1
2
3
4
5
6
7
8
9
10
11
12
13 package memorydb
14
15 import (
16 "bytes"
17 "context"
18 "encoding/json"
19 "strings"
20 "testing"
21
22 "gitlab.com/flimzy/testy"
23
24 "github.com/go-kivik/kivik/v4/driver"
25 )
26
27 func TestIndexSpecUnmarshalJSON(t *testing.T) {
28 type isuTest struct {
29 name string
30 input string
31 expected *indexSpec
32 err string
33 }
34 tests := []isuTest{
35 {
36 name: "ddoc only",
37 input: `"foo"`,
38 expected: &indexSpec{ddoc: "foo"},
39 },
40 {
41 name: "ddoc and index",
42 input: `["foo","bar"]`,
43 expected: &indexSpec{ddoc: "foo", index: "bar"},
44 },
45 {
46 name: "invalid json",
47 input: "asdf",
48 err: "invalid character 'a' looking for beginning of value",
49 },
50 {
51 name: "extra fields",
52 input: `["foo","bar","baz"]`,
53 err: "invalid index specification",
54 },
55 {
56 name: "One field",
57 input: `["foo"]`,
58 expected: &indexSpec{ddoc: "foo"},
59 },
60 {
61 name: "Empty array",
62 input: `[]`,
63 err: "invalid index specification",
64 },
65 }
66 for _, test := range tests {
67 t.Run(test.name, func(t *testing.T) {
68 result := &indexSpec{}
69 err := result.UnmarshalJSON([]byte(test.input))
70 var msg string
71 if err != nil {
72 msg = err.Error()
73 }
74 if msg != test.err {
75 t.Errorf("Unexpected error: %s", err)
76 }
77 if err != nil {
78 return
79 }
80 if d := testy.DiffInterface(test.expected, result); d != nil {
81 t.Error(d)
82 }
83 })
84 }
85 }
86
87 func TestCreateIndex(t *testing.T) {
88 d := &db{}
89 err := d.CreateIndex(context.Background(), "foo", "bar", "baz", nil)
90 if err != errFindNotImplemented {
91 t.Errorf("Unexpected error: %s", err)
92 }
93 }
94
95 func TestGetIndexes(t *testing.T) {
96 d := &db{}
97 _, err := d.GetIndexes(context.Background(), nil)
98 if err != errFindNotImplemented {
99 t.Errorf("Unexpected error: %s", err)
100 }
101 }
102
103 func TestDeleteIndex(t *testing.T) {
104 d := &db{}
105 err := d.DeleteIndex(context.Background(), "foo", "bar", nil)
106 if err != errFindNotImplemented {
107 t.Errorf("Unexpected error: %s", err)
108 }
109 }
110
111
112 func TestFind(t *testing.T) {
113 type findTest struct {
114 name string
115 db *db
116 query interface{}
117 expectedIDs []string
118 err string
119 rowsErr string
120 }
121 tests := []findTest{
122 {
123 name: "invalid query",
124 query: make(chan int),
125 err: "json: unsupported type: chan int",
126 },
127 {
128 name: "Invalid JSON query",
129 query: "asdf",
130 err: "invalid character 'a' looking for beginning of value",
131 },
132 {
133 name: "No query",
134 err: "Missing required key: selector",
135 },
136 {
137 name: "empty selector",
138 query: `{"selector":{}}`,
139 db: func() *db {
140 db := setupDB(t)
141 for _, id := range []string{"a", "c", "z", "q", "chicken"} {
142 if _, err := db.Put(context.Background(), id, map[string]string{"value": id}, nil); err != nil {
143 t.Fatal(err)
144 }
145 }
146 return db
147 }(),
148 expectedIDs: []string{"a", "c", "chicken", "q", "z"},
149 },
150 {
151 name: "simple selector",
152 query: `{"selector":{"value":"chicken"}}`,
153 db: func() *db {
154 db := setupDB(t)
155 for _, id := range []string{"a", "c", "z", "q", "chicken"} {
156 if _, err := db.Put(context.Background(), id, map[string]string{"value": id}, nil); err != nil {
157 t.Fatal(err)
158 }
159 }
160 return db
161 }(),
162 expectedIDs: []string{"chicken"},
163 },
164 }
165 for _, test := range tests {
166 t.Run(test.name, func(t *testing.T) {
167 db := test.db
168 if db == nil {
169 db = setupDB(t)
170 }
171 rows, err := db.Find(context.Background(), test.query, nil)
172 var msg string
173 if err != nil {
174 msg = err.Error()
175 }
176 if msg != test.err {
177 t.Errorf("Unexpected error: %s", err)
178 }
179 if err != nil {
180 return
181 }
182 checkRows(t, rows, test.expectedIDs, test.rowsErr)
183 })
184 }
185 }
186
187
188
189 func TestFindDoc(t *testing.T) {
190 type fdTest struct {
191 name string
192 db *db
193 query interface{}
194 expected interface{}
195 }
196 tests := []fdTest{
197 {
198 name: "simple selector",
199 query: `{"selector":{}}`,
200 db: func() *db {
201 db := setupDB(t)
202 id := "chicken"
203 if _, err := db.Put(context.Background(), id, map[string]string{"value": id}, nil); err != nil {
204 t.Fatal(err)
205 }
206 return db
207 }(),
208 expected: map[string]interface{}{
209 "_id": "chicken",
210 "_rev": "1-xxx",
211 "value": "chicken",
212 },
213 },
214 {
215 name: "fields",
216 query: `{"selector":{}, "fields":["value","_rev"]}`,
217 db: func() *db {
218 db := setupDB(t)
219 if _, err := db.Put(context.Background(), "foo", map[string]string{"value": "foo"}, nil); err != nil {
220 t.Fatal(err)
221 }
222 return db
223 }(),
224 expected: map[string]interface{}{
225 "value": "foo",
226 "_rev": "1-xxx",
227 },
228 },
229 }
230 for _, test := range tests {
231 t.Run(test.name, func(t *testing.T) {
232 db := test.db
233 if db == nil {
234 db = setupDB(t)
235 }
236 rows, err := db.Find(context.Background(), test.query, nil)
237 if err != nil {
238 t.Fatal(err)
239 }
240 var row driver.Row
241 if e := rows.Next(&row); e != nil {
242 t.Fatal(e)
243 }
244 _ = rows.Close()
245 var result map[string]interface{}
246 if e := json.NewDecoder(row.Doc).Decode(&result); e != nil {
247 t.Fatal(e)
248 }
249 parts := strings.Split(result["_rev"].(string), "-")
250 result["_rev"] = parts[0] + "-xxx"
251 if d := testy.DiffAsJSON(test.expected, result); d != nil {
252 t.Error(d)
253 }
254 })
255 }
256 }
257
258 func TestResultWarning(t *testing.T) {
259 rows := &findResults{}
260 expected := "no matching index found, create an index to optimize query time"
261 if w := rows.Warning(); w != expected {
262 t.Errorf("Unexpected warning: %s", w)
263 }
264 }
265
266 func TestFilterDoc(t *testing.T) {
267 type fdTest struct {
268 name string
269 rows *findResults
270 data string
271 expected string
272 err string
273 }
274 tests := []fdTest{
275 {
276 name: "no filter",
277 rows: &findResults{},
278 data: `{"foo":"bar"}`,
279 expected: `{"foo":"bar"}`,
280 },
281 {
282 name: "with filter",
283 rows: &findResults{fields: map[string]struct{}{"foo": {}}},
284 data: `{"foo":"bar", "baz":"qux"}`,
285 expected: `{"foo":"bar"}`,
286 },
287 {
288 name: "invalid json",
289 rows: &findResults{fields: map[string]struct{}{"foo": {}}},
290 data: `{"foo":"bar", "baz":"qux}`,
291 err: "unexpected end of JSON input",
292 },
293 }
294 for _, test := range tests {
295 t.Run(test.name, func(t *testing.T) {
296 result, err := test.rows.filterDoc([]byte(test.data))
297 var msg string
298 if err != nil {
299 msg = err.Error()
300 }
301 if msg != test.err {
302 t.Errorf("Unexpected error: %s", msg)
303 }
304 if err != nil {
305 return
306 }
307 if d := testy.DiffJSON([]byte(test.expected), result); d != nil {
308 t.Error(d)
309 }
310 })
311 }
312 }
313
314 func TestToJSON(t *testing.T) {
315 type tjTest struct {
316 Name string
317 Input interface{}
318 Expected string
319 }
320 tests := []tjTest{
321 {
322 Name: "Null",
323 Expected: "null",
324 },
325 {
326 Name: "String",
327 Input: `{"foo":"bar"}`,
328 Expected: `{"foo":"bar"}`,
329 },
330 {
331 Name: "ByteSlice",
332 Input: []byte(`{"foo":"bar"}`),
333 Expected: `{"foo":"bar"}`,
334 },
335 {
336 Name: "RawMessage",
337 Input: json.RawMessage(`{"foo":"bar"}`),
338 Expected: `{"foo":"bar"}`,
339 },
340 {
341 Name: "Interface",
342 Input: map[string]string{"foo": "bar"},
343 Expected: `{"foo":"bar"}`,
344 },
345 }
346 for _, test := range tests {
347 t.Run(test.Name, func(t *testing.T) {
348 r, err := toJSON(test.Input)
349 if err != nil {
350 t.Fatalf("jsonify failed: %s", err)
351 }
352 buf := &bytes.Buffer{}
353 _, _ = buf.ReadFrom(r)
354 result := strings.TrimSpace(buf.String())
355 if result != test.Expected {
356 t.Errorf("Expected: `%s`\n Actual: `%s`", test.Expected, result)
357 }
358 })
359 }
360 }
361
View as plain text