OLD | NEW |
---|---|
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package memory | 5 package memory |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "strings" | 9 "strings" |
10 "testing" | 10 "testing" |
11 "time" | 11 "time" |
12 | 12 |
13 "github.com/luci/gae/service/blobstore" | 13 "github.com/luci/gae/service/blobstore" |
14 ds "github.com/luci/gae/service/datastore" | 14 ds "github.com/luci/gae/service/datastore" |
15 "github.com/luci/gae/service/info" | 15 "github.com/luci/gae/service/info" |
16 "golang.org/x/net/context" | 16 "golang.org/x/net/context" |
17 | 17 |
18 . "github.com/luci/luci-go/common/testing/assertions" | 18 . "github.com/luci/luci-go/common/testing/assertions" |
19 . "github.com/smartystreets/goconvey/convey" | 19 . "github.com/smartystreets/goconvey/convey" |
20 ) | 20 ) |
21 | 21 |
22 func mkKey(appID, namespace string, elems ...interface{}) *ds.Key { | 22 func mkKey(appID, namespace string, elems ...interface{}) *ds.Key { |
23 return ds.MkKeyContext(appID, namespace).MakeKey(elems...) | 23 return ds.MkKeyContext(appID, namespace).MakeKey(elems...) |
24 } | 24 } |
25 | 25 |
26 var enableOnly = false | |
27 | |
28 func enable() bool { | |
dnj
2016/11/11 08:37:53
This is something useful for debugging specific te
| |
29 enableOnly = true | |
30 return true | |
31 } | |
32 | |
26 type qExpect struct { | 33 type qExpect struct { |
27 q *ds.Query | 34 q *ds.Query |
28 inTxn bool | 35 inTxn bool |
29 | 36 |
30 get []ds.PropertyMap | 37 get []ds.PropertyMap |
31 keys []*ds.Key | 38 keys []*ds.Key |
32 count int | 39 count int |
40 | |
41 enable bool | |
33 } | 42 } |
34 | 43 |
35 type qExStage struct { | 44 type qExStage struct { |
36 addIdxs []*ds.IndexDefinition | 45 addIdxs []*ds.IndexDefinition |
37 putEnts []ds.PropertyMap | 46 putEnts []ds.PropertyMap |
38 delEnts []*ds.Key | 47 delEnts []*ds.Key |
39 | 48 |
40 expect []qExpect | 49 expect []qExpect |
41 | 50 |
42 extraFns []func(context.Context) | 51 extraFns []func(context.Context) |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 | 254 |
246 {q: nq("Kind").Gt("Val", 2).Lte("Val", 5), get: []ds.PropertyMap{ | 255 {q: nq("Kind").Gt("Val", 2).Lte("Val", 5), get: []ds.PropertyMap{ |
247 stage1Data[0], stage1Data[3], | 256 stage1Data[0], stage1Data[3], |
248 }}, | 257 }}, |
249 | 258 |
250 {q: nq("Kind").Gt("Val", 2).Lte("Val", 5).Order( "-Val"), get: []ds.PropertyMap{ | 259 {q: nq("Kind").Gt("Val", 2).Lte("Val", 5).Order( "-Val"), get: []ds.PropertyMap{ |
251 stage1Data[3], stage1Data[0], | 260 stage1Data[3], stage1Data[0], |
252 }}, | 261 }}, |
253 | 262 |
254 {q: nq("").Gt("__key__", key("Kind", 2)), | 263 {q: nq("").Gt("__key__", key("Kind", 2)), |
255 » » » » » // count counts from the index with Keys Only and so counts the deleted | 264 » » » » » count: 7, |
dnj
2016/11/11 08:37:53
(This is no longer true, since we don't auto-KeysO
| |
256 » » » » » // entity Unique/1. | |
257 » » » » » count: 8, | |
258 get: []ds.PropertyMap{ | 265 get: []ds.PropertyMap{ |
259 // TODO(riannucci): determine if the real datastore shows metadata | 266 // TODO(riannucci): determine if the real datastore shows metadata |
260 // during kindless queries. The documentation seems to imply so, but | 267 // during kindless queries. The documentation seems to imply so, but |
261 // I'd like to be sure. | 268 // I'd like to be sure. |
262 pmap("$key", key("Kind", 2, "__e ntity_group__", 1), Next, | 269 pmap("$key", key("Kind", 2, "__e ntity_group__", 1), Next, |
263 "__version__", 1), | 270 "__version__", 1), |
264 stage1Data[2], | 271 stage1Data[2], |
265 stage1Data[4], | 272 stage1Data[4], |
266 // this is 5 because the value i s retrieved from HEAD and not from | 273 // this is 5 because the value i s retrieved from HEAD and not from |
267 // the index snapshot! | 274 // the index snapshot! |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 " - name: Val", | 423 " - name: Val", |
417 }, "\n")) | 424 }, "\n")) |
418 }, | 425 }, |
419 }, | 426 }, |
420 }, | 427 }, |
421 | 428 |
422 { | 429 { |
423 expect: []qExpect{ | 430 expect: []qExpect{ |
424 // eventual consistency; Unique/1 is deleted at HEAD. Keysonly finds it, | 431 // eventual consistency; Unique/1 is deleted at HEAD. Keysonly finds it, |
425 // but 'normal' doesn't. | 432 // but 'normal' doesn't. |
433 {q: nq("Unique").Gt("__key__", key("AKind", 5)). Lte("__key__", key("Zeta", "prime")).KeysOnly(true), | |
434 keys: []*ds.Key{key("Unique", 1)}}, | |
426 {q: nq("Unique").Gt("__key__", key("AKind", 5)). Lte("__key__", key("Zeta", "prime")), | 435 {q: nq("Unique").Gt("__key__", key("AKind", 5)). Lte("__key__", key("Zeta", "prime")), |
427 » » » » » keys: []*ds.Key{key("Unique", 1)}, | 436 » » » » » get: []ds.PropertyMap{}}, |
428 » » » » » get: []ds.PropertyMap{}}, | |
429 | 437 |
430 {q: nq("Kind").Eq("Val", 1, 3), get: []ds.Proper tyMap{ | 438 {q: nq("Kind").Eq("Val", 1, 3), get: []ds.Proper tyMap{ |
431 stage1Data[0], stage2Data[2], | 439 stage1Data[0], stage2Data[2], |
432 }}, | 440 }}, |
433 }, | 441 }, |
434 }, | 442 }, |
435 }}, | 443 }}, |
436 {"collapsed types", []qExStage{ | 444 {"collapsed types", []qExStage{ |
437 { | 445 { |
438 putEnts: collapsedData, | 446 putEnts: collapsedData, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
476 }, | 484 }, |
477 { | 485 { |
478 q: nq("Kind").Eq("Val", []byte("uwutm8") ), | 486 q: nq("Kind").Eq("Val", []byte("uwutm8") ), |
479 get: []ds.PropertyMap{ | 487 get: []ds.PropertyMap{ |
480 collapsedData[5], | 488 collapsedData[5], |
481 }, | 489 }, |
482 }, | 490 }, |
483 }, | 491 }, |
484 }, | 492 }, |
485 }}, | 493 }}, |
494 | |
495 {"regression: tombstones and limit/offset queries", []qExStage{ | |
496 { | |
497 putEnts: []ds.PropertyMap{ | |
498 pmap("$key", key("Kind", 1)), | |
499 pmap("$key", key("Kind", 2)), | |
500 pmap("$key", key("Kind", 3)), | |
501 }, | |
502 delEnts: []*ds.Key{key("Kind", 2)}, | |
503 }, | |
504 { | |
505 expect: []qExpect{ | |
506 { | |
507 q: nq("Kind").Limit(2), | |
508 get: []ds.PropertyMap{ | |
509 pmap("$key", key("Kind", 1)), | |
510 pmap("$key", key("Kind", 3)), | |
511 }, | |
512 }, | |
513 | |
514 { | |
515 q: nq("Kind").Offset(2), | |
516 get: []ds.PropertyMap{}, | |
517 }, | |
518 }, | |
519 }, | |
520 }}, | |
486 } | 521 } |
487 | 522 |
488 func TestQueryExecution(t *testing.T) { | 523 func TestQueryExecution(t *testing.T) { |
489 t.Parallel() | 524 t.Parallel() |
490 | 525 |
491 Convey("Test query execution", t, func() { | 526 Convey("Test query execution", t, func() { |
492 c, err := info.Namespace(Use(context.Background()), "ns") | 527 c, err := info.Namespace(Use(context.Background()), "ns") |
493 if err != nil { | 528 if err != nil { |
494 panic(err) | 529 panic(err) |
495 } | 530 } |
(...skipping 23 matching lines...) Expand all Loading... | |
519 panic(err) | 554 panic(err) |
520 } | 555 } |
521 } | 556 } |
522 | 557 |
523 if err := ds.Delete(c, stage.delEnts); e rr != nil { | 558 if err := ds.Delete(c, stage.delEnts); e rr != nil { |
524 panic(err) | 559 panic(err) |
525 } | 560 } |
526 | 561 |
527 Convey(fmt.Sprintf("stage %d", i), func( ) { | 562 Convey(fmt.Sprintf("stage %d", i), func( ) { |
528 for j, expect := range stage.exp ect { | 563 for j, expect := range stage.exp ect { |
564 if enableOnly && !expect .enable { | |
565 continue | |
566 } | |
529 runner := func(c context .Context, f func(ic context.Context) error, _ *ds.TransactionOptions) error { | 567 runner := func(c context .Context, f func(ic context.Context) error, _ *ds.TransactionOptions) error { |
530 return f(c) | 568 return f(c) |
531 } | 569 } |
532 if expect.inTxn { | 570 if expect.inTxn { |
533 runner = ds.RunI nTransaction | 571 runner = ds.RunI nTransaction |
534 } | 572 } |
535 | 573 |
536 if expect.count == 0 { | 574 if expect.count == 0 { |
537 if len(expect.ke ys) > 0 { | 575 if len(expect.ke ys) > 0 { |
538 expect.c ount = len(expect.keys) | 576 expect.c ount = len(expect.keys) |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
633 | 671 |
634 v, ok := actual.(error) | 672 v, ok := actual.(error) |
635 if !ok { | 673 if !ok { |
636 return fmt.Sprintf("type of 'actual' must be error, not %T", act ual) | 674 return fmt.Sprintf("type of 'actual' must be error, not %T", act ual) |
637 } | 675 } |
638 if v == nil || v == ds.Stop { | 676 if v == nil || v == ds.Stop { |
639 return "" | 677 return "" |
640 } | 678 } |
641 return fmt.Sprintf("expected success value, not %v", v) | 679 return fmt.Sprintf("expected success value, not %v", v) |
642 } | 680 } |
OLD | NEW |