...

Source file src/github.com/go-kivik/kivik/v4/kiviktest/db/find.go

Documentation: github.com/go-kivik/kivik/v4/kiviktest/db

     1  // Licensed under the Apache License, Version 2.0 (the "License"); you may not
     2  // use this file except in compliance with the License. You may obtain a copy of
     3  // the License at
     4  //
     5  //  http://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     9  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    10  // License for the specific language governing permissions and limitations under
    11  // the License.
    12  
    13  package db
    14  
    15  import (
    16  	"context"
    17  	"fmt"
    18  	"sort"
    19  
    20  	"gitlab.com/flimzy/testy"
    21  
    22  	"github.com/go-kivik/kivik/v4"
    23  	"github.com/go-kivik/kivik/v4/kiviktest/kt"
    24  )
    25  
    26  func init() {
    27  	kt.Register("Find", find)
    28  }
    29  
    30  func find(ctx *kt.Context) {
    31  	ctx.RunAdmin(func(ctx *kt.Context) {
    32  		testFind(ctx, ctx.Admin)
    33  	})
    34  	ctx.RunNoAuth(func(ctx *kt.Context) {
    35  		testFind(ctx, ctx.NoAuth)
    36  	})
    37  	ctx.RunRW(func(ctx *kt.Context) {
    38  		testFindRW(ctx)
    39  	})
    40  }
    41  
    42  func testFindRW(ctx *kt.Context) {
    43  	if ctx.Admin == nil {
    44  		// Can't do anything here without admin access
    45  		return
    46  	}
    47  	dbName, expected, err := setUpFindTest(ctx)
    48  	if err != nil {
    49  		ctx.Errorf("Failed to set up temp db: %s", err)
    50  	}
    51  	ctx.Run("group", func(ctx *kt.Context) {
    52  		ctx.RunAdmin(func(ctx *kt.Context) {
    53  			doFindTest(ctx, ctx.Admin, dbName, 0, expected)
    54  		})
    55  		ctx.RunNoAuth(func(ctx *kt.Context) {
    56  			doFindTest(ctx, ctx.NoAuth, dbName, 0, expected)
    57  		})
    58  	})
    59  }
    60  
    61  func setUpFindTest(ctx *kt.Context) (dbName string, docIDs []string, err error) {
    62  	dbName = ctx.TestDB()
    63  	db := ctx.Admin.DB(dbName, ctx.Options("db"))
    64  	if err := db.Err(); err != nil {
    65  		return dbName, nil, fmt.Errorf("failed to connect to db: %w", err)
    66  	}
    67  	const maxDocs = 10
    68  	docIDs = make([]string, maxDocs)
    69  	for i := range docIDs {
    70  		id := ctx.TestDBName()
    71  		doc := struct {
    72  			ID string `json:"id"`
    73  		}{
    74  			ID: id,
    75  		}
    76  		if _, err := db.Put(context.Background(), doc.ID, doc); err != nil {
    77  			return dbName, nil, fmt.Errorf("failed to create doc: %w", err)
    78  		}
    79  		docIDs[i] = id
    80  	}
    81  	sort.Strings(docIDs)
    82  	return dbName, docIDs, nil
    83  }
    84  
    85  func testFind(ctx *kt.Context, client *kivik.Client) {
    86  	if !ctx.IsSet("databases") {
    87  		ctx.Errorf("databases not set; Did you configure this test?")
    88  		return
    89  	}
    90  	for _, dbName := range ctx.StringSlice("databases") {
    91  		func(dbName string) {
    92  			ctx.Run(dbName, func(ctx *kt.Context) {
    93  				doFindTest(ctx, client, dbName, int64(ctx.Int("offset")), ctx.StringSlice("expected"))
    94  			})
    95  		}(dbName)
    96  	}
    97  }
    98  
    99  func doFindTest(ctx *kt.Context, client *kivik.Client, dbName string, expOffset int64, expected []string) {
   100  	ctx.Parallel()
   101  	db := client.DB(dbName, ctx.Options("db"))
   102  	// Errors may be deferred here, so only return if we actually get
   103  	// an error.
   104  	if err := db.Err(); err != nil && !ctx.IsExpectedSuccess(err) {
   105  		return
   106  	}
   107  
   108  	var rows *kivik.ResultSet
   109  	err := kt.Retry(func() error {
   110  		rows = db.Find(context.Background(), `{"selector":{"_id":{"$gt":null}}}`)
   111  		return rows.Err()
   112  	})
   113  
   114  	if !ctx.IsExpectedSuccess(err) {
   115  		return
   116  	}
   117  	docIDs := make([]string, 0, len(expected))
   118  	for rows.Next() {
   119  		var doc struct {
   120  			DocID string `json:"_id"`
   121  			Rev   string `json:"_rev"`
   122  			ID    string `json:"id"`
   123  		}
   124  		if err := rows.ScanDoc(&doc); err != nil {
   125  			ctx.Errorf("Failed to scan doc: %s", err)
   126  		}
   127  		docIDs = append(docIDs, doc.DocID)
   128  	}
   129  	meta, err := rows.Metadata()
   130  	if err != nil {
   131  		ctx.Fatalf("Failed to fetch row: %s", rows.Err())
   132  	}
   133  	sort.Strings(docIDs) // normalize order
   134  	if d := testy.DiffTextSlices(expected, docIDs); d != nil {
   135  		ctx.Errorf("Unexpected document IDs returned:\n%s\n", d)
   136  	}
   137  	if meta.Offset != expOffset {
   138  		ctx.Errorf("Unexpected offset: %v", meta.Offset)
   139  	}
   140  	ctx.Run("Warning", func(ctx *kt.Context) {
   141  		rows := db.Find(context.Background(), `{"selector":{"foo":{"$gt":null}}}`)
   142  		if !ctx.IsExpectedSuccess(rows.Err()) {
   143  			return
   144  		}
   145  		for rows.Next() {
   146  		}
   147  		if w := ctx.String("warning"); w != meta.Warning {
   148  			ctx.Errorf("Warning:\nExpected: %s\n  Actual: %s", w, meta.Warning)
   149  		}
   150  	})
   151  }
   152  

View as plain text