1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package server
16
17 import (
18 "net/http"
19 "strings"
20 "testing"
21 "time"
22
23 "github.com/go-kivik/kivik/v4"
24 "github.com/go-kivik/kivik/v4/driver"
25 "github.com/go-kivik/kivik/v4/mockdb"
26 )
27
28 func Test_dbUpdates(t *testing.T) {
29 tests := serverTests{
30 {
31 name: "db updates, unauthorized",
32 method: http.MethodGet,
33 path: "/_db_updates",
34 wantStatus: http.StatusUnauthorized,
35 wantJSON: map[string]interface{}{
36 "error": "unauthorized",
37 "reason": "User not authenticated",
38 },
39 },
40 {
41 name: "db updates, two updates",
42 client: func() *kivik.Client {
43 client, mock, err := mockdb.New()
44 if err != nil {
45 t.Fatal(err)
46 }
47 mock.ExpectDBUpdates().WillReturn(mockdb.NewDBUpdates().
48 AddUpdate(&driver.DBUpdate{
49 DBName: "foo",
50 Type: "created",
51 Seq: "1-aaa",
52 }).
53 AddUpdate(&driver.DBUpdate{
54 DBName: "foo",
55 Type: "deleted",
56 Seq: "2-aaa",
57 }).LastSeq("2-aaa"))
58 return client
59 }(),
60 authUser: userAdmin,
61 method: http.MethodGet,
62 path: "/_db_updates",
63 wantStatus: http.StatusOK,
64 wantJSON: map[string]interface{}{
65 "results": []interface{}{
66 map[string]interface{}{
67 "db_name": "foo",
68 "type": "created",
69 "seq": "1-aaa",
70 },
71 map[string]interface{}{
72 "db_name": "foo",
73 "type": "deleted",
74 "seq": "2-aaa",
75 },
76 },
77 "last_seq": "2-aaa",
78 },
79 },
80 {
81 name: "continuous, invalid heartbeat",
82 method: http.MethodGet,
83 authUser: userAdmin,
84 path: "/_db_updates?feed=continuous&heartbeat=chicken",
85 wantStatus: http.StatusBadRequest,
86 wantJSON: map[string]interface{}{
87 "error": "bad_request",
88 "reason": "strconv.Atoi: parsing \"chicken\": invalid syntax",
89 },
90 },
91 {
92 name: "continuous, with heartbeat",
93 client: func() *kivik.Client {
94 client, mock, err := mockdb.New()
95 if err != nil {
96 t.Fatal(err)
97 }
98 mock.ExpectDBUpdates().WillReturn(mockdb.NewDBUpdates().
99 AddUpdate(&driver.DBUpdate{
100 DBName: "foo",
101 Type: "created",
102 Seq: "1-aaa",
103 }).
104 AddDelay(500 * time.Millisecond).
105 AddUpdate(&driver.DBUpdate{
106 DBName: "foo",
107 Type: "deleted",
108 Seq: "2-aaa",
109 }))
110 return client
111 }(),
112 authUser: userAdmin,
113 method: http.MethodGet,
114 path: "/_db_updates?feed=continuous&heartbeat=100",
115 wantStatus: http.StatusOK,
116 wantBodyRE: "}\n+\n{",
117 },
118 }
119
120 tests.Run(t)
121 }
122
123 func Test_allDocs(t *testing.T) {
124 tests := serverTests{
125 {
126 name: "GET defaults",
127 authUser: userAdmin,
128 method: http.MethodGet,
129 path: "/db1/_all_docs",
130 client: func() *kivik.Client {
131 client, mock, err := mockdb.New()
132 if err != nil {
133 t.Fatal(err)
134 }
135 db := mock.NewDB()
136 mock.ExpectDB().WillReturn(db)
137 db.ExpectSecurity().WillReturn(&driver.Security{})
138 mock.ExpectDB().WillReturn(db)
139 db.ExpectAllDocs().WillReturn(mockdb.NewRows().
140 AddRow(&driver.Row{
141 ID: "foo",
142 Key: []byte(`"foo"`),
143 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
144 }).
145 TotalRows(99),
146 )
147 return client
148 }(),
149 wantStatus: http.StatusOK,
150 wantJSON: map[string]interface{}{
151 "offset": 0,
152 "rows": []interface{}{
153 map[string]interface{}{
154 "id": "foo",
155 "key": "foo",
156 "value": map[string]interface{}{
157 "rev": "1-beea34a62a215ab051862d1e5d93162e",
158 },
159 },
160 },
161 "total_rows": 99,
162 },
163 },
164 {
165 name: "multi queries",
166 authUser: userAdmin,
167 method: http.MethodPost,
168 path: "/db1/_all_docs/queries",
169 headers: map[string]string{
170 "Content-Type": "application/json",
171 },
172 body: strings.NewReader(`{"queries": [{"keys": ["foo", "bar"]}]}`),
173 client: func() *kivik.Client {
174 client, mock, err := mockdb.New()
175 if err != nil {
176 t.Fatal(err)
177 }
178 db := mock.NewDB()
179 mock.ExpectDB().WillReturn(db)
180 db.ExpectSecurity().WillReturn(&driver.Security{})
181 mock.ExpectDB().WillReturn(db)
182 db.ExpectAllDocs().WillReturn(mockdb.NewRows().
183 AddRow(&driver.Row{
184 ID: "foo",
185 Key: []byte(`"foo"`),
186 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
187 }).
188 TotalRows(99),
189 )
190 return client
191 }(),
192 wantStatus: http.StatusOK,
193 wantJSON: map[string]interface{}{
194 "offset": 0,
195 "rows": []interface{}{
196 map[string]interface{}{
197 "id": "foo",
198 "key": "foo",
199 "value": map[string]interface{}{
200 "rev": "1-beea34a62a215ab051862d1e5d93162e",
201 },
202 },
203 },
204 "total_rows": 99,
205 },
206 },
207 {
208 name: "POST _all_docs",
209 authUser: userAdmin,
210 method: http.MethodPost,
211 path: "/db1/_all_docs",
212 headers: map[string]string{
213 "Content-Type": "application/json",
214 },
215 body: strings.NewReader(`{"keys": ["foo", "bar"]}`),
216 client: func() *kivik.Client {
217 client, mock, err := mockdb.New()
218 if err != nil {
219 t.Fatal(err)
220 }
221 db := mock.NewDB()
222 mock.ExpectDB().WillReturn(db)
223 db.ExpectSecurity().WillReturn(&driver.Security{})
224 mock.ExpectDB().WillReturn(db)
225 db.ExpectAllDocs().WillReturn(mockdb.NewRows().
226 AddRow(&driver.Row{
227 ID: "foo",
228 Key: []byte(`"foo"`),
229 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
230 }).
231 TotalRows(99),
232 )
233 return client
234 }(),
235 wantStatus: http.StatusOK,
236 wantJSON: map[string]interface{}{
237 "offset": 0,
238 "rows": []interface{}{
239 map[string]interface{}{
240 "id": "foo",
241 "key": "foo",
242 "value": map[string]interface{}{
243 "rev": "1-beea34a62a215ab051862d1e5d93162e",
244 },
245 },
246 },
247 "total_rows": 99,
248 },
249 },
250 }
251
252 tests.Run(t)
253 }
254
255 func Test_localDocs(t *testing.T) {
256 tests := serverTests{
257 {
258 name: "GET defaults",
259 authUser: userAdmin,
260 method: http.MethodGet,
261 path: "/db1/_local_docs",
262 client: func() *kivik.Client {
263 client, mock, err := mockdb.New()
264 if err != nil {
265 t.Fatal(err)
266 }
267 db := mock.NewDB()
268 mock.ExpectDB().WillReturn(db)
269 db.ExpectSecurity().WillReturn(&driver.Security{})
270 mock.ExpectDB().WillReturn(db)
271 db.ExpectLocalDocs().WillReturn(mockdb.NewRows().
272 AddRow(&driver.Row{
273 ID: "foo",
274 Key: []byte(`"foo"`),
275 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
276 }).
277 TotalRows(99),
278 )
279 return client
280 }(),
281 wantStatus: http.StatusOK,
282 wantJSON: map[string]interface{}{
283 "offset": 0,
284 "rows": []interface{}{
285 map[string]interface{}{
286 "id": "foo",
287 "key": "foo",
288 "value": map[string]interface{}{
289 "rev": "1-beea34a62a215ab051862d1e5d93162e",
290 },
291 },
292 },
293 "total_rows": 99,
294 },
295 },
296 {
297 name: "multi queries",
298 authUser: userAdmin,
299 method: http.MethodPost,
300 path: "/db1/_local_docs/queries",
301 headers: map[string]string{
302 "Content-Type": "application/json",
303 },
304 body: strings.NewReader(`{"queries": [{"keys": ["foo", "bar"]}]}`),
305 client: func() *kivik.Client {
306 client, mock, err := mockdb.New()
307 if err != nil {
308 t.Fatal(err)
309 }
310 db := mock.NewDB()
311 mock.ExpectDB().WillReturn(db)
312 db.ExpectSecurity().WillReturn(&driver.Security{})
313 mock.ExpectDB().WillReturn(db)
314 db.ExpectLocalDocs().WillReturn(mockdb.NewRows().
315 AddRow(&driver.Row{
316 ID: "foo",
317 Key: []byte(`"foo"`),
318 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
319 }).
320 TotalRows(99),
321 )
322 return client
323 }(),
324 wantStatus: http.StatusOK,
325 wantJSON: map[string]interface{}{
326 "offset": 0,
327 "rows": []interface{}{
328 map[string]interface{}{
329 "id": "foo",
330 "key": "foo",
331 "value": map[string]interface{}{
332 "rev": "1-beea34a62a215ab051862d1e5d93162e",
333 },
334 },
335 },
336 "total_rows": 99,
337 },
338 },
339 {
340 name: "POST _local_docs",
341 authUser: userAdmin,
342 method: http.MethodPost,
343 path: "/db1/_local_docs",
344 headers: map[string]string{
345 "Content-Type": "application/json",
346 },
347 body: strings.NewReader(`{"keys": ["foo", "bar"]}`),
348 client: func() *kivik.Client {
349 client, mock, err := mockdb.New()
350 if err != nil {
351 t.Fatal(err)
352 }
353 db := mock.NewDB()
354 mock.ExpectDB().WillReturn(db)
355 db.ExpectSecurity().WillReturn(&driver.Security{})
356 mock.ExpectDB().WillReturn(db)
357 db.ExpectLocalDocs().WillReturn(mockdb.NewRows().
358 AddRow(&driver.Row{
359 ID: "foo",
360 Key: []byte(`"foo"`),
361 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
362 }).
363 TotalRows(99),
364 )
365 return client
366 }(),
367 wantStatus: http.StatusOK,
368 wantJSON: map[string]interface{}{
369 "offset": 0,
370 "rows": []interface{}{
371 map[string]interface{}{
372 "id": "foo",
373 "key": "foo",
374 "value": map[string]interface{}{
375 "rev": "1-beea34a62a215ab051862d1e5d93162e",
376 },
377 },
378 },
379 "total_rows": 99,
380 },
381 },
382 }
383
384 tests.Run(t)
385 }
386
387 func Test_designDocs(t *testing.T) {
388 tests := serverTests{
389 {
390 name: "GET defaults",
391 authUser: userAdmin,
392 method: http.MethodGet,
393 path: "/db1/_design_docs",
394 client: func() *kivik.Client {
395 client, mock, err := mockdb.New()
396 if err != nil {
397 t.Fatal(err)
398 }
399 db := mock.NewDB()
400 mock.ExpectDB().WillReturn(db)
401 db.ExpectSecurity().WillReturn(&driver.Security{})
402 mock.ExpectDB().WillReturn(db)
403 db.ExpectDesignDocs().WillReturn(mockdb.NewRows().
404 AddRow(&driver.Row{
405 ID: "foo",
406 Key: []byte(`"foo"`),
407 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
408 }).
409 TotalRows(99),
410 )
411 return client
412 }(),
413 wantStatus: http.StatusOK,
414 wantJSON: map[string]interface{}{
415 "offset": 0,
416 "rows": []interface{}{
417 map[string]interface{}{
418 "id": "foo",
419 "key": "foo",
420 "value": map[string]interface{}{
421 "rev": "1-beea34a62a215ab051862d1e5d93162e",
422 },
423 },
424 },
425 "total_rows": 99,
426 },
427 },
428 {
429 name: "multi queries",
430 authUser: userAdmin,
431 method: http.MethodPost,
432 path: "/db1/_design_docs/queries",
433 headers: map[string]string{
434 "Content-Type": "application/json",
435 },
436 body: strings.NewReader(`{"queries": [{"keys": ["foo", "bar"]}]}`),
437 client: func() *kivik.Client {
438 client, mock, err := mockdb.New()
439 if err != nil {
440 t.Fatal(err)
441 }
442 db := mock.NewDB()
443 mock.ExpectDB().WillReturn(db)
444 db.ExpectSecurity().WillReturn(&driver.Security{})
445 mock.ExpectDB().WillReturn(db)
446 db.ExpectDesignDocs().WillReturn(mockdb.NewRows().
447 AddRow(&driver.Row{
448 ID: "foo",
449 Key: []byte(`"foo"`),
450 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
451 }).
452 TotalRows(99),
453 )
454 return client
455 }(),
456 wantStatus: http.StatusOK,
457 wantJSON: map[string]interface{}{
458 "offset": 0,
459 "rows": []interface{}{
460 map[string]interface{}{
461 "id": "foo",
462 "key": "foo",
463 "value": map[string]interface{}{
464 "rev": "1-beea34a62a215ab051862d1e5d93162e",
465 },
466 },
467 },
468 "total_rows": 99,
469 },
470 },
471 {
472 name: "POST _design_docs",
473 authUser: userAdmin,
474 method: http.MethodPost,
475 path: "/db1/_design_docs",
476 headers: map[string]string{
477 "Content-Type": "application/json",
478 },
479 body: strings.NewReader(`{"keys": ["foo", "bar"]}`),
480 client: func() *kivik.Client {
481 client, mock, err := mockdb.New()
482 if err != nil {
483 t.Fatal(err)
484 }
485 db := mock.NewDB()
486 mock.ExpectDB().WillReturn(db)
487 db.ExpectSecurity().WillReturn(&driver.Security{})
488 mock.ExpectDB().WillReturn(db)
489 db.ExpectDesignDocs().WillReturn(mockdb.NewRows().
490 AddRow(&driver.Row{
491 ID: "foo",
492 Key: []byte(`"foo"`),
493 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
494 }).
495 TotalRows(99),
496 )
497 return client
498 }(),
499 wantStatus: http.StatusOK,
500 wantJSON: map[string]interface{}{
501 "offset": 0,
502 "rows": []interface{}{
503 map[string]interface{}{
504 "id": "foo",
505 "key": "foo",
506 "value": map[string]interface{}{
507 "rev": "1-beea34a62a215ab051862d1e5d93162e",
508 },
509 },
510 },
511 "total_rows": 99,
512 },
513 },
514 }
515
516 tests.Run(t)
517 }
518
519 func Test_queryView(t *testing.T) {
520 tests := serverTests{
521 {
522 name: "GET defaults",
523 authUser: userAdmin,
524 method: http.MethodGet,
525 path: "/db1/_design/foo/_view/bar",
526 client: func() *kivik.Client {
527 client, mock, err := mockdb.New()
528 if err != nil {
529 t.Fatal(err)
530 }
531 db := mock.NewDB()
532 mock.ExpectDB().WillReturn(db)
533 db.ExpectSecurity().WillReturn(&driver.Security{})
534 mock.ExpectDB().WillReturn(db)
535 db.ExpectQuery().WillReturn(mockdb.NewRows().
536 AddRow(&driver.Row{
537 ID: "foo",
538 Key: []byte(`"foo"`),
539 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
540 }).
541 TotalRows(99),
542 )
543 return client
544 }(),
545 wantStatus: http.StatusOK,
546 wantJSON: map[string]interface{}{
547 "offset": 0,
548 "rows": []interface{}{
549 map[string]interface{}{
550 "id": "foo",
551 "key": "foo",
552 "value": map[string]interface{}{
553 "rev": "1-beea34a62a215ab051862d1e5d93162e",
554 },
555 },
556 },
557 "total_rows": 99,
558 },
559 },
560 {
561 name: "multi queries",
562 authUser: userAdmin,
563 method: http.MethodPost,
564 path: "/db1/_design/foo/_view/bar/queries",
565 headers: map[string]string{
566 "Content-Type": "application/json",
567 },
568 body: strings.NewReader(`{"queries": [{"keys": ["foo", "bar"]}]}`),
569 client: func() *kivik.Client {
570 client, mock, err := mockdb.New()
571 if err != nil {
572 t.Fatal(err)
573 }
574 db := mock.NewDB()
575 mock.ExpectDB().WillReturn(db)
576 db.ExpectSecurity().WillReturn(&driver.Security{})
577 mock.ExpectDB().WillReturn(db)
578 db.ExpectQuery().WillReturn(mockdb.NewRows().
579 AddRow(&driver.Row{
580 ID: "foo",
581 Key: []byte(`"foo"`),
582 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
583 }).
584 TotalRows(99),
585 )
586 return client
587 }(),
588 wantStatus: http.StatusOK,
589 wantJSON: map[string]interface{}{
590 "offset": 0,
591 "rows": []interface{}{
592 map[string]interface{}{
593 "id": "foo",
594 "key": "foo",
595 "value": map[string]interface{}{
596 "rev": "1-beea34a62a215ab051862d1e5d93162e",
597 },
598 },
599 },
600 "total_rows": 99,
601 },
602 },
603 {
604 name: "POST _design/foo/_view/bar",
605 authUser: userAdmin,
606 method: http.MethodPost,
607 path: "/db1/_design/foo/_view/bar",
608 headers: map[string]string{
609 "Content-Type": "application/json",
610 },
611 body: strings.NewReader(`{"keys": ["foo", "bar"]}`),
612 client: func() *kivik.Client {
613 client, mock, err := mockdb.New()
614 if err != nil {
615 t.Fatal(err)
616 }
617 db := mock.NewDB()
618 mock.ExpectDB().WillReturn(db)
619 db.ExpectSecurity().WillReturn(&driver.Security{})
620 mock.ExpectDB().WillReturn(db)
621 db.ExpectQuery().WillReturn(mockdb.NewRows().
622 AddRow(&driver.Row{
623 ID: "foo",
624 Key: []byte(`"foo"`),
625 Value: strings.NewReader(`{"rev": "1-beea34a62a215ab051862d1e5d93162e"}`),
626 }).
627 TotalRows(99),
628 )
629 return client
630 }(),
631 wantStatus: http.StatusOK,
632 wantJSON: map[string]interface{}{
633 "offset": 0,
634 "rows": []interface{}{
635 map[string]interface{}{
636 "id": "foo",
637 "key": "foo",
638 "value": map[string]interface{}{
639 "rev": "1-beea34a62a215ab051862d1e5d93162e",
640 },
641 },
642 },
643 "total_rows": 99,
644 },
645 },
646 }
647
648 tests.Run(t)
649 }
650
View as plain text