1
2
3
4
5
6
7
8
9
10
11
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
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
103
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)
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