| 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 { |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |