Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(564)

Side by Side Diff: impl/memory/datastore_query_execution_test.go

Issue 2302743002: Interface update, per-method Contexts. (Closed)
Patch Set: Lightning talk licenses. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « impl/memory/datastore_query_execution.go ('k') | impl/memory/datastore_query_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 {
23 return ds.KeyContext{appID, namespace}.MakeKey(elems...)
24 }
25
22 type qExpect struct { 26 type qExpect struct {
23 q *ds.Query 27 q *ds.Query
24 inTxn bool 28 inTxn bool
25 29
26 get []ds.PropertyMap 30 get []ds.PropertyMap
27 keys []*ds.Key 31 keys []*ds.Key
28 count int 32 count int
29 } 33 }
30 34
31 type qExStage struct { 35 type qExStage struct {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 "Extra", "hello", "waffle", 82 "Extra", "hello", "waffle",
79 ), 83 ),
80 pmap("$key", key("Kind", 3, "Kind", 2), Next, 84 pmap("$key", key("Kind", 3, "Kind", 2), Next,
81 "Val", 3, 4, Next, 85 "Val", 3, 4, Next,
82 "Extra", "hello", "waffle", 86 "Extra", "hello", "waffle",
83 ), 87 ),
84 pmap("$key", key("Kind", 3, "Kind", 3), Next, 88 pmap("$key", key("Kind", 3, "Kind", 3), Next,
85 "Val", 3, 4, 2, 1, Next, 89 "Val", 3, 4, 2, 1, Next,
86 "Extra", "nuts", 90 "Extra", "nuts",
87 ), 91 ),
88 » pmap("$key", ds.MakeKey("dev~app", "", "Kind", "id")), 92 » pmap("$key", mkKey("dev~app", "", "Kind", "id")),
89 » pmap("$key", ds.MakeKey("dev~app", "bob", "Kind", "id")), 93 » pmap("$key", mkKey("dev~app", "bob", "Kind", "id")),
90 } 94 }
91 95
92 var collapsedData = []ds.PropertyMap{ 96 var collapsedData = []ds.PropertyMap{
93 // PTTime 97 // PTTime
94 pmap("$key", key("Kind", 1), Next, 98 pmap("$key", key("Kind", 1), Next,
95 "Date", time.Date(2000, time.January, 1, 1, 1, 1, 1, time.UTC), Next, 99 "Date", time.Date(2000, time.January, 1, 1, 1, 1, 1, time.UTC), Next,
96 ), 100 ),
97 pmap("$key", key("Kind", 2), Next, 101 pmap("$key", key("Kind", 2), Next,
98 "Date", time.Date(2000, time.March, 1, 1, 1, 1, 1, time.UTC), Ne xt, 102 "Date", time.Date(2000, time.March, 1, 1, 1, 1, 1, time.UTC), Ne xt,
99 ), 103 ),
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 key("Kind", 3, "Child", "seven"), 146 key("Kind", 3, "Child", "seven"),
143 }}, 147 }},
144 {q: nq("Child").Ancestor(key("Kind", 3)).Eventua lConsistency(true), keys: []*ds.Key{}}, 148 {q: nq("Child").Ancestor(key("Kind", 3)).Eventua lConsistency(true), keys: []*ds.Key{}},
145 {q: nq("Child").Ancestor(key("Kind", 3)).Eventua lConsistency(true), keys: []*ds.Key{ 149 {q: nq("Child").Ancestor(key("Kind", 3)).Eventua lConsistency(true), keys: []*ds.Key{
146 key("Kind", 3, "Child", "seven"), 150 key("Kind", 3, "Child", "seven"),
147 }, inTxn: true}, 151 }, inTxn: true},
148 {q: nq("Child").Ancestor(key("Kind", 3)), keys: []*ds.Key{ 152 {q: nq("Child").Ancestor(key("Kind", 3)), keys: []*ds.Key{
149 key("Kind", 3, "Child", "seven"), 153 key("Kind", 3, "Child", "seven"),
150 }, inTxn: true}, 154 }, inTxn: true},
151 {q: nq("__namespace__"), get: []ds.PropertyMap{ 155 {q: nq("__namespace__"), get: []ds.PropertyMap{
152 » » » » » pmap("$key", ds.MakeKey("dev~app", "", " __namespace__", "ns")), 156 » » » » » pmap("$key", mkKey("dev~app", "", "__nam espace__", "ns")),
153 }}, 157 }},
154 {q: nq("__namespace__").Offset(1), get: []ds.Pro pertyMap{}}, 158 {q: nq("__namespace__").Offset(1), get: []ds.Pro pertyMap{}},
155 {q: nq("__namespace__").Offset(1).Limit(1), get: []ds.PropertyMap{}}, 159 {q: nq("__namespace__").Offset(1).Limit(1), get: []ds.PropertyMap{}},
156 }, 160 },
157 }, 161 },
158 162
159 { 163 {
160 putEnts: stage2Data, 164 putEnts: stage2Data,
161 delEnts: []*ds.Key{key("Unique", 1)}, 165 delEnts: []*ds.Key{key("Unique", 1)},
162 addIdxs: []*ds.IndexDefinition{ 166 addIdxs: []*ds.IndexDefinition{
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 "When", 996688461000000), 348 "When", 996688461000000),
345 }}, 349 }},
346 350
347 // Original (complex) types are retained when ge tting the full value. 351 // Original (complex) types are retained when ge tting the full value.
348 {q: nq("Kind").Order("When"), get: []ds.Property Map{ 352 {q: nq("Kind").Order("When"), get: []ds.Property Map{
349 stage1Data[1], 353 stage1Data[1],
350 stage1Data[3], 354 stage1Data[3],
351 stage1Data[2], 355 stage1Data[2],
352 }}, 356 }},
353 {q: nq("__namespace__"), get: []ds.PropertyMap{ 357 {q: nq("__namespace__"), get: []ds.PropertyMap{
354 » » » » » pmap("$key", ds.MakeKey("dev~app", "", " __namespace__", 1)), 358 » » » » » pmap("$key", mkKey("dev~app", "", "__nam espace__", 1)),
355 » » » » » pmap("$key", ds.MakeKey("dev~app", "", " __namespace__", "bob")), 359 » » » » » pmap("$key", mkKey("dev~app", "", "__nam espace__", "bob")),
356 » » » » » pmap("$key", ds.MakeKey("dev~app", "", " __namespace__", "ns")), 360 » » » » » pmap("$key", mkKey("dev~app", "", "__nam espace__", "ns")),
357 }}, 361 }},
358 {q: nq("__namespace__").Offset(1), get: []ds.Pro pertyMap{ 362 {q: nq("__namespace__").Offset(1), get: []ds.Pro pertyMap{
359 » » » » » pmap("$key", ds.MakeKey("dev~app", "", " __namespace__", "bob")), 363 » » » » » pmap("$key", mkKey("dev~app", "", "__nam espace__", "bob")),
360 » » » » » pmap("$key", ds.MakeKey("dev~app", "", " __namespace__", "ns")), 364 » » » » » pmap("$key", mkKey("dev~app", "", "__nam espace__", "ns")),
361 }}, 365 }},
362 {q: nq("__namespace__").Offset(1).Limit(1), get: []ds.PropertyMap{ 366 {q: nq("__namespace__").Offset(1).Limit(1), get: []ds.PropertyMap{
363 » » » » » pmap("$key", ds.MakeKey("dev~app", "", " __namespace__", "bob")), 367 » » » » » pmap("$key", mkKey("dev~app", "", "__nam espace__", "bob")),
364 }}, 368 }},
365 }, 369 },
366 370
367 extraFns: []func(context.Context){ 371 extraFns: []func(context.Context){
368 func(c context.Context) { 372 func(c context.Context) {
369 data := ds.Get(c)
370 curs := ds.Cursor(nil) 373 curs := ds.Cursor(nil)
371 374
372 q := nq("").Gt("__key__", key("Kind", 2) ) 375 q := nq("").Gt("__key__", key("Kind", 2) )
373 376
374 » » » » » err := data.Run(q, func(pm ds.PropertyMa p, gc ds.CursorCB) error { 377 » » » » » err := ds.Run(c, q, func(pm ds.PropertyM ap, gc ds.CursorCB) error {
375 So(pm, ShouldResemble, pmap( 378 So(pm, ShouldResemble, pmap(
376 "$key", key("Kind", 2, " __entity_group__", 1), Next, 379 "$key", key("Kind", 2, " __entity_group__", 1), Next,
377 "__version__", 1)) 380 "__version__", 1))
378 381
379 err := error(nil) 382 err := error(nil)
380 curs, err = gc() 383 curs, err = gc()
381 So(err, ShouldBeNil) 384 So(err, ShouldBeNil)
382 return ds.Stop 385 return ds.Stop
383 }) 386 })
384 So(err, shouldBeSuccessful) 387 So(err, shouldBeSuccessful)
385 388
386 » » » » » err = data.Run(q.Start(curs), func(pm ds .PropertyMap) error { 389 » » » » » err = ds.Run(c, q.Start(curs), func(pm d s.PropertyMap) error {
387 So(pm, ShouldResemble, stage1Dat a[2]) 390 So(pm, ShouldResemble, stage1Dat a[2])
388 return ds.Stop 391 return ds.Stop
389 }) 392 })
390 So(err, shouldBeSuccessful) 393 So(err, shouldBeSuccessful)
391 }, 394 },
392 395
393 func(c context.Context) { 396 func(c context.Context) {
394 data := ds.Get(c)
395 q := nq("Something").Eq("Does", 2).Order ("Not", "-Work") 397 q := nq("Something").Eq("Does", 2).Order ("Not", "-Work")
396 » » » » » So(data.Run(q, func(ds.Key) {}), ShouldE rrLike, strings.Join([]string{ 398 » » » » » So(ds.Run(c, q, func(ds.Key) {}), Should ErrLike, strings.Join([]string{
397 "Consider adding:", 399 "Consider adding:",
398 "- kind: Something", 400 "- kind: Something",
399 " properties:", 401 " properties:",
400 " - name: Does", 402 " - name: Does",
401 " - name: Not", 403 " - name: Not",
402 " - name: Work", 404 " - name: Work",
403 " direction: desc", 405 " direction: desc",
404 }, "\n")) 406 }, "\n"))
405 }, 407 },
406 408
407 func(c context.Context) { 409 func(c context.Context) {
408 data := ds.Get(c)
409 q := nq("Something").Ancestor(key("Kind" , 3)).Order("Val") 410 q := nq("Something").Ancestor(key("Kind" , 3)).Order("Val")
410 » » » » » So(data.Run(q, func(ds.Key) {}), ShouldE rrLike, strings.Join([]string{ 411 » » » » » So(ds.Run(c, q, func(ds.Key) {}), Should ErrLike, strings.Join([]string{
411 "Consider adding:", 412 "Consider adding:",
412 "- kind: Something", 413 "- kind: Something",
413 " ancestor: yes", 414 " ancestor: yes",
414 " properties:", 415 " properties:",
415 " - name: Val", 416 " - name: Val",
416 }, "\n")) 417 }, "\n"))
417 }, 418 },
418 }, 419 },
419 }, 420 },
420 421
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 }, 482 },
482 }, 483 },
483 }, 484 },
484 }}, 485 }},
485 } 486 }
486 487
487 func TestQueryExecution(t *testing.T) { 488 func TestQueryExecution(t *testing.T) {
488 t.Parallel() 489 t.Parallel()
489 490
490 Convey("Test query execution", t, func() { 491 Convey("Test query execution", t, func() {
491 » » c, err := info.Get(Use(context.Background())).Namespace("ns") 492 » » c, err := info.Namespace(Use(context.Background()), "ns")
492 if err != nil { 493 if err != nil {
493 panic(err) 494 panic(err)
494 } 495 }
495 496
496 » » So(info.Get(c).FullyQualifiedAppID(), ShouldEqual, "dev~app") 497 » » So(info.FullyQualifiedAppID(c), ShouldEqual, "dev~app")
497 » » ns, has := info.Get(c).GetNamespace() 498 » » So(info.GetNamespace(c), ShouldEqual, "ns")
498 » » So(ns, ShouldEqual, "ns")
499 » » So(has, ShouldBeTrue)
500 499
501 » » data := ds.Get(c) 500 » » testing := ds.GetTestable(c)
502 » » testing := data.Testable()
503 501
504 for _, tc := range queryExecutionTests { 502 for _, tc := range queryExecutionTests {
505 Convey(tc.name, func() { 503 Convey(tc.name, func() {
506 for i, stage := range tc.test { 504 for i, stage := range tc.test {
507 // outside of Convey, since these must a lways happen 505 // outside of Convey, since these must a lways happen
508 testing.CatchupIndexes() 506 testing.CatchupIndexes()
509 507
510 testing.AddIndexes(stage.addIdxs...) 508 testing.AddIndexes(stage.addIdxs...)
511 byNs := map[string][]ds.PropertyMap{} 509 byNs := map[string][]ds.PropertyMap{}
512 for _, ent := range stage.putEnts { 510 for _, ent := range stage.putEnts {
513 k := ds.GetMetaDefault(ent, "key ", nil).(*ds.Key) 511 k := ds.GetMetaDefault(ent, "key ", nil).(*ds.Key)
514 byNs[k.Namespace()] = append(byN s[k.Namespace()], ent) 512 byNs[k.Namespace()] = append(byN s[k.Namespace()], ent)
515 } 513 }
516 for ns, ents := range byNs { 514 for ns, ents := range byNs {
517 » » » » » » c := info.Get(c).MustNamespace(n s) 515 » » » » » » c := info.MustNamespace(c, ns)
518 » » » » » » data := ds.Get(c) 516 » » » » » » if err := ds.Put(c, ents); err ! = nil {
519 » » » » » » if err := data.PutMulti(ents); e rr != nil {
520 // prevent Convey from t hinking this assertion should show up in 517 // prevent Convey from t hinking this assertion should show up in
521 // every test loop. 518 // every test loop.
522 panic(err) 519 panic(err)
523 } 520 }
524 } 521 }
525 522
526 » » » » » if err := data.DeleteMulti(stage.delEnts ); err != nil { 523 » » » » » if err := ds.Delete(c, stage.delEnts); e rr != nil {
527 panic(err) 524 panic(err)
528 } 525 }
529 526
530 Convey(fmt.Sprintf("stage %d", i), func( ) { 527 Convey(fmt.Sprintf("stage %d", i), func( ) {
531 for j, expect := range stage.exp ect { 528 for j, expect := range stage.exp ect {
532 » » » » » » » runner := func(f func(ic context.Context) error, _ *ds.TransactionOptions) error { 529 » » » » » » » runner := func(c context .Context, f func(ic context.Context) error, _ *ds.TransactionOptions) error {
533 return f(c) 530 return f(c)
534 } 531 }
535 if expect.inTxn { 532 if expect.inTxn {
536 » » » » » » » » runner = data.Ru nInTransaction 533 » » » » » » » » runner = ds.RunI nTransaction
537 } 534 }
538 535
539 if expect.count == 0 { 536 if expect.count == 0 {
540 if len(expect.ke ys) > 0 { 537 if len(expect.ke ys) > 0 {
541 expect.c ount = len(expect.keys) 538 expect.c ount = len(expect.keys)
542 } else { 539 } else {
543 expect.c ount = len(expect.get) 540 expect.c ount = len(expect.get)
544 } 541 }
545 } 542 }
546 543
547 if expect.keys != nil { 544 if expect.keys != nil {
548 Convey(fmt.Sprin tf("expect %d (keys)", j), func() { 545 Convey(fmt.Sprin tf("expect %d (keys)", j), func() {
549 » » » » » » » » » err := r unner(func(c context.Context) error { 546 » » » » » » » » » err := r unner(c, func(c context.Context) error {
550 » » » » » » » » » » data := ds.Get(c) 547 » » » » » » » » » » count, err := ds.Count(c, expect.q)
551 » » » » » » » » » » count, err := data.Count(expect.q)
552 So(err, shouldBeSuccessful) 548 So(err, shouldBeSuccessful)
553 So(count, ShouldEqual, expect.count) 549 So(count, ShouldEqual, expect.count)
554 550
555 rslt := []*ds.Key(nil) 551 rslt := []*ds.Key(nil)
556 » » » » » » » » » » So(data.GetAll(expect.q, &rslt), shouldBeSuccessful) 552 » » » » » » » » » » So(ds.GetAll(c, expect.q, &rslt), shouldBeSuccessful)
557 So(len(rslt), ShouldEqual, len(expect.keys)) 553 So(len(rslt), ShouldEqual, len(expect.keys))
558 for i, r := range rslt { 554 for i, r := range rslt {
559 So(r, ShouldResemble, expect.keys[i]) 555 So(r, ShouldResemble, expect.keys[i])
560 } 556 }
561 return nil 557 return nil
562 }, &ds.T ransactionOptions{XG: true}) 558 }, &ds.T ransactionOptions{XG: true})
563 So(err, shouldBeSuccessful) 559 So(err, shouldBeSuccessful)
564 }) 560 })
565 } 561 }
566 562
567 if expect.get != nil { 563 if expect.get != nil {
568 Convey(fmt.Sprin tf("expect %d (data)", j), func() { 564 Convey(fmt.Sprin tf("expect %d (data)", j), func() {
569 » » » » » » » » » err := r unner(func(c context.Context) error { 565 » » » » » » » » » err := r unner(c, func(c context.Context) error {
570 » » » » » » » » » » data := ds.Get(c) 566 » » » » » » » » » » count, err := ds.Count(c, expect.q)
571 » » » » » » » » » » count, err := data.Count(expect.q)
572 So(err, shouldBeSuccessful) 567 So(err, shouldBeSuccessful)
573 So(count, ShouldEqual, expect.count) 568 So(count, ShouldEqual, expect.count)
574 569
575 rslt := []ds.PropertyMap(nil) 570 rslt := []ds.PropertyMap(nil)
576 » » » » » » » » » » So(data.GetAll(expect.q, &rslt), shouldBeSuccessful) 571 » » » » » » » » » » So(ds.GetAll(c, expect.q, &rslt), shouldBeSuccessful)
577 So(len(rslt), ShouldEqual, len(expect.get)) 572 So(len(rslt), ShouldEqual, len(expect.get))
578 for i, r := range rslt { 573 for i, r := range rslt {
579 So(r, ShouldResemble, expect.get[i]) 574 So(r, ShouldResemble, expect.get[i])
580 } 575 }
581 return nil 576 return nil
582 }, &ds.T ransactionOptions{XG: true}) 577 }, &ds.T ransactionOptions{XG: true})
583 So(err, shouldBeSuccessful) 578 So(err, shouldBeSuccessful)
584 }) 579 })
585 } 580 }
586 } 581 }
587 582
588 for j, fn := range stage.extraFn s { 583 for j, fn := range stage.extraFn s {
589 Convey(fmt.Sprintf("extr aFn %d", j), func() { 584 Convey(fmt.Sprintf("extr aFn %d", j), func() {
590 fn(c) 585 fn(c)
591 }) 586 })
592 } 587 }
593 }) 588 })
594 } 589 }
595 }) 590 })
596 } 591 }
597 }) 592 })
598 593
599 Convey("Test AutoIndex", t, func() { 594 Convey("Test AutoIndex", t, func() {
600 » » c, err := info.Get(Use(context.Background())).Namespace("ns") 595 » » c, err := info.Namespace(Use(context.Background()), "ns")
601 if err != nil { 596 if err != nil {
602 panic(err) 597 panic(err)
603 } 598 }
604 599
605 » » data := ds.Get(c) 600 » » testing := ds.GetTestable(c)
606 » » testing := data.Testable()
607 testing.Consistent(true) 601 testing.Consistent(true)
608 602
609 » » So(data.Put(pmap("$key", key("Kind", 1), Next, 603 » » So(ds.Put(c, pmap("$key", key("Kind", 1), Next,
610 "Val", 1, 2, 3, Next, 604 "Val", 1, 2, 3, Next,
611 "Extra", "hello", 605 "Extra", "hello",
612 )), shouldBeSuccessful) 606 )), shouldBeSuccessful)
613 607
614 » » So(data.Put(pmap("$key", key("Kind", 2), Next, 608 » » So(ds.Put(c, pmap("$key", key("Kind", 2), Next,
615 "Val", 2, 3, 9, Next, 609 "Val", 2, 3, 9, Next,
616 "Extra", "ace", "hello", "there", 610 "Extra", "ace", "hello", "there",
617 )), shouldBeSuccessful) 611 )), shouldBeSuccessful)
618 612
619 q := nq("Kind").Gt("Val", 2).Order("Val", "Extra") 613 q := nq("Kind").Gt("Val", 2).Order("Val", "Extra")
620 614
621 » » count, err := data.Count(q) 615 » » count, err := ds.Count(c, q)
622 So(err, ShouldErrLike, "Insufficient indexes") 616 So(err, ShouldErrLike, "Insufficient indexes")
623 617
624 testing.AutoIndex(true) 618 testing.AutoIndex(true)
625 619
626 » » count, err = data.Count(q) 620 » » count, err = ds.Count(c, q)
627 So(err, shouldBeSuccessful) 621 So(err, shouldBeSuccessful)
628 So(count, ShouldEqual, 2) 622 So(count, ShouldEqual, 2)
629 }) 623 })
630 } 624 }
631 625
632 func shouldBeSuccessful(actual interface{}, expected ...interface{}) string { 626 func shouldBeSuccessful(actual interface{}, expected ...interface{}) string {
633 if len(expected) != 0 { 627 if len(expected) != 0 {
634 return "no expected values permitted" 628 return "no expected values permitted"
635 } 629 }
636 if actual == nil { 630 if actual == nil {
637 return "" 631 return ""
638 } 632 }
639 633
640 v, ok := actual.(error) 634 v, ok := actual.(error)
641 if !ok { 635 if !ok {
642 return fmt.Sprintf("type of 'actual' must be error, not %T", act ual) 636 return fmt.Sprintf("type of 'actual' must be error, not %T", act ual)
643 } 637 }
644 if v == nil || v == ds.Stop { 638 if v == nil || v == ds.Stop {
645 return "" 639 return ""
646 } 640 }
647 return fmt.Sprintf("expected success value, not %v", v) 641 return fmt.Sprintf("expected success value, not %v", v)
648 } 642 }
OLDNEW
« no previous file with comments | « impl/memory/datastore_query_execution.go ('k') | impl/memory/datastore_query_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698