OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // adapted from github.com/golang/appengine/datastore |
| 6 |
| 7 package datastore |
| 8 |
| 9 import ( |
| 10 "fmt" |
| 11 "testing" |
| 12 |
| 13 "github.com/luci/gae/service/info" |
| 14 "github.com/luci/luci-go/common/errors" |
| 15 . "github.com/smartystreets/goconvey/convey" |
| 16 "golang.org/x/net/context" |
| 17 ) |
| 18 |
| 19 func fakeDatastoreFactory(c context.Context) RawInterface { |
| 20 i := info.Get(c) |
| 21 return &fakeDatastore{ |
| 22 aid: i.AppID(), |
| 23 ns: i.GetNamespace(), |
| 24 } |
| 25 } |
| 26 |
| 27 type fakeQuery struct { |
| 28 Query |
| 29 |
| 30 limit int |
| 31 |
| 32 err error |
| 33 errSingle error |
| 34 errSingleIdx int |
| 35 } |
| 36 |
| 37 func (q *fakeQuery) KeysOnly() Query { |
| 38 return q |
| 39 } |
| 40 |
| 41 func (q *fakeQuery) Limit(i int) Query { |
| 42 q.limit = i |
| 43 return q |
| 44 } |
| 45 |
| 46 func (q *fakeQuery) FailAll() Query { |
| 47 q.err = errors.New("Query fail all") |
| 48 return q |
| 49 } |
| 50 |
| 51 func (q *fakeQuery) Fail(i int) Query { |
| 52 q.errSingleIdx = i |
| 53 q.errSingle = errors.New("Query fail") |
| 54 return q |
| 55 } |
| 56 |
| 57 type fakeDatastore struct { |
| 58 RawInterface |
| 59 aid string |
| 60 ns string |
| 61 } |
| 62 |
| 63 func (f *fakeDatastore) NewKey(kind, stringID string, intID int64, parent Key) K
ey { |
| 64 return NewKey(f.aid, f.ns, kind, stringID, intID, parent) |
| 65 } |
| 66 |
| 67 func (f *fakeDatastore) NewQuery(string) Query { |
| 68 return &fakeQuery{} |
| 69 } |
| 70 |
| 71 func (f *fakeDatastore) Run(q Query, cb RawRunCB) error { |
| 72 rq := q.(*fakeQuery) |
| 73 if rq.err != nil { |
| 74 return rq.err |
| 75 } |
| 76 for i := 0; i < rq.limit; i++ { |
| 77 if rq.errSingle != nil && i == rq.errSingleIdx { |
| 78 return rq.errSingle |
| 79 } else { |
| 80 k := f.NewKey("Kind", "", int64(i+1), nil) |
| 81 if i == 10 { |
| 82 k = f.NewKey("Kind", "eleven", 0, nil) |
| 83 } |
| 84 pm := PropertyMap{"Value": {MkProperty(i)}} |
| 85 if !cb(k, pm, nil) { |
| 86 break |
| 87 } |
| 88 } |
| 89 } |
| 90 return nil |
| 91 } |
| 92 |
| 93 func (f *fakeDatastore) PutMulti(keys []Key, vals []PropertyMap, cb PutMultiCB)
error { |
| 94 if keys[0].Kind() == "FailAll" { |
| 95 return errors.New("PutMulti fail all") |
| 96 } |
| 97 assertExtra := false |
| 98 if _, err := vals[0].GetMeta("assertExtra"); err == nil { |
| 99 assertExtra = true |
| 100 } |
| 101 for i, k := range keys { |
| 102 err := error(nil) |
| 103 if k.Kind() == "Fail" { |
| 104 err = errors.New("PutMulti fail") |
| 105 } else { |
| 106 So(vals[i]["Value"], ShouldResemble, []Property{MkProper
ty(i)}) |
| 107 if assertExtra { |
| 108 So(vals[i]["Extra"], ShouldResemble, []Property{
MkProperty("whoa")}) |
| 109 } |
| 110 if KeyIncomplete(k) { |
| 111 k = NewKey(k.AppID(), k.Namespace(), k.Kind(), "
", int64(i+1), k.Parent()) |
| 112 } |
| 113 } |
| 114 cb(k, err) |
| 115 } |
| 116 return nil |
| 117 } |
| 118 |
| 119 func (f *fakeDatastore) GetMulti(keys []Key, cb GetMultiCB) error { |
| 120 if keys[0].Kind() == "FailAll" { |
| 121 return errors.New("GetMulti fail all") |
| 122 } |
| 123 for i, k := range keys { |
| 124 if k.Kind() == "Fail" { |
| 125 cb(nil, errors.New("GetMulti fail")) |
| 126 } else { |
| 127 cb(PropertyMap{"Value": {MkProperty(i + 1)}}, nil) |
| 128 } |
| 129 } |
| 130 return nil |
| 131 } |
| 132 |
| 133 func (f *fakeDatastore) DeleteMulti(keys []Key, cb DeleteMultiCB) error { |
| 134 if keys[0].Kind() == "FailAll" { |
| 135 return errors.New("DeleteMulti fail all") |
| 136 } |
| 137 for _, k := range keys { |
| 138 if k.Kind() == "Fail" { |
| 139 cb(errors.New("DeleteMulti fail")) |
| 140 } else { |
| 141 cb(nil) |
| 142 } |
| 143 } |
| 144 return nil |
| 145 } |
| 146 |
| 147 type badStruct struct { |
| 148 ID int64 `gae:"$id"` |
| 149 Compy complex64 // bad type |
| 150 } |
| 151 |
| 152 type CommonStruct struct { |
| 153 ID int64 `gae:"$id"` |
| 154 Parent Key `gae:"$parent"` |
| 155 |
| 156 Value int64 |
| 157 } |
| 158 |
| 159 type permaBad struct { |
| 160 PropertyLoadSaver |
| 161 } |
| 162 |
| 163 func (f *permaBad) Load(pm PropertyMap) error { |
| 164 return errors.New("permaBad") |
| 165 } |
| 166 |
| 167 type FakePLS struct { |
| 168 IntID int64 |
| 169 StringID string |
| 170 Kind string |
| 171 |
| 172 Value int64 |
| 173 gotLoaded bool |
| 174 |
| 175 failGetMeta bool |
| 176 failLoad bool |
| 177 failProblem bool |
| 178 failSave bool |
| 179 failSaveMeta bool |
| 180 } |
| 181 |
| 182 func (f *FakePLS) Load(pm PropertyMap) error { |
| 183 if f.failLoad { |
| 184 return errors.New("FakePLS.Load") |
| 185 } |
| 186 f.gotLoaded = true |
| 187 f.Value = pm["Value"][0].Value().(int64) |
| 188 return nil |
| 189 } |
| 190 |
| 191 func (f *FakePLS) Save(withMeta bool) (PropertyMap, error) { |
| 192 if f.failSave { |
| 193 return nil, errors.New("FakePLS.Save") |
| 194 } |
| 195 ret := PropertyMap{ |
| 196 "Value": {MkProperty(f.Value)}, |
| 197 "Extra": {MkProperty("whoa")}, |
| 198 } |
| 199 if withMeta { |
| 200 id, _ := f.GetMeta("id") |
| 201 ret.SetMeta("id", id) |
| 202 if f.Kind == "" { |
| 203 ret.SetMeta("kind", "FakePLS") |
| 204 } else { |
| 205 ret.SetMeta("kind", f.Kind) |
| 206 } |
| 207 ret.SetMeta("assertExtra", true) |
| 208 } |
| 209 return ret, nil |
| 210 } |
| 211 |
| 212 func (f *FakePLS) GetMeta(key string) (interface{}, error) { |
| 213 if f.failGetMeta { |
| 214 return nil, errors.New("FakePLS.GetMeta") |
| 215 } |
| 216 switch key { |
| 217 case "id": |
| 218 if f.StringID != "" { |
| 219 return f.StringID, nil |
| 220 } |
| 221 return f.IntID, nil |
| 222 case "kind": |
| 223 if f.Kind == "" { |
| 224 return "FakePLS", nil |
| 225 } |
| 226 return f.Kind, nil |
| 227 } |
| 228 return nil, ErrMetaFieldUnset |
| 229 } |
| 230 |
| 231 func (f *FakePLS) SetMeta(key string, val interface{}) error { |
| 232 if f.failSaveMeta { |
| 233 return errors.New("FakePL.SetMeta") |
| 234 } |
| 235 if key == "id" { |
| 236 switch x := val.(type) { |
| 237 case int64: |
| 238 f.IntID = x |
| 239 case string: |
| 240 f.StringID = x |
| 241 } |
| 242 return nil |
| 243 } |
| 244 if key == "kind" { |
| 245 f.Kind = val.(string) |
| 246 return nil |
| 247 } |
| 248 return ErrMetaFieldUnset |
| 249 } |
| 250 |
| 251 func (f *FakePLS) Problem() error { |
| 252 if f.failProblem { |
| 253 return errors.New("FakePLS.Problem") |
| 254 } |
| 255 return nil |
| 256 } |
| 257 |
| 258 func TestKeyForObj(t *testing.T) { |
| 259 t.Parallel() |
| 260 |
| 261 Convey("Test interface.KeyForObj", t, func() { |
| 262 c := info.Set(context.Background(), fakeInfo{}) |
| 263 c = SetRawFactory(c, fakeDatastoreFactory) |
| 264 ds := Get(c) |
| 265 |
| 266 k := ds.NewKey("Hello", "world", 0, nil) |
| 267 |
| 268 Convey("good", func() { |
| 269 Convey("struct containing $key", func() { |
| 270 type keyStruct struct { |
| 271 Key Key `gae:"$key"` |
| 272 } |
| 273 |
| 274 ks := &keyStruct{k} |
| 275 So(ds.KeyForObj(ks), ShouldEqual, k) |
| 276 }) |
| 277 |
| 278 Convey("struct containing default $id and $kind", func()
{ |
| 279 type idStruct struct { |
| 280 id string `gae:"$id,wut"` |
| 281 knd string `gae:"$kind,SuperKind"` |
| 282 } |
| 283 |
| 284 So(ds.KeyForObj(&idStruct{}).String(), ShouldEqu
al, `/SuperKind,wut`) |
| 285 }) |
| 286 |
| 287 Convey("struct containing $id and $parent", func() { |
| 288 So(ds.KeyForObj(&CommonStruct{ID: 4}).String(),
ShouldEqual, `/CommonStruct,4`) |
| 289 |
| 290 So(ds.KeyForObj(&CommonStruct{ID: 4, Parent: k})
.String(), ShouldEqual, `/Hello,world/CommonStruct,4`) |
| 291 }) |
| 292 |
| 293 Convey("a propmap with $key", func() { |
| 294 pm := PropertyMap{} |
| 295 pm.SetMeta("key", k) |
| 296 So(ds.KeyForObj(pm).String(), ShouldEqual, `/Hel
lo,world`) |
| 297 }) |
| 298 |
| 299 Convey("a propmap with $id, $kind, $parent", func() { |
| 300 pm := PropertyMap{} |
| 301 pm.SetMeta("id", 100) |
| 302 pm.SetMeta("kind", "Sup") |
| 303 So(ds.KeyForObj(pm).String(), ShouldEqual, `/Sup
,100`) |
| 304 |
| 305 pm.SetMeta("parent", k) |
| 306 So(ds.KeyForObj(pm).String(), ShouldEqual, `/Hel
lo,world/Sup,100`) |
| 307 }) |
| 308 |
| 309 Convey("a pls with $id, $parent", func() { |
| 310 pls := GetPLS(&CommonStruct{ID: 1}) |
| 311 So(ds.KeyForObj(pls).String(), ShouldEqual, `/Co
mmonStruct,1`) |
| 312 |
| 313 pls.SetMeta("parent", k) |
| 314 So(ds.KeyForObj(pls).String(), ShouldEqual, `/He
llo,world/CommonStruct,1`) |
| 315 }) |
| 316 |
| 317 }) |
| 318 |
| 319 Convey("bad", func() { |
| 320 Convey("a propmap without $kind", func() { |
| 321 pm := PropertyMap{} |
| 322 pm.SetMeta("id", 100) |
| 323 So(func() { ds.KeyForObj(pm) }, ShouldPanic) |
| 324 }) |
| 325 }) |
| 326 }) |
| 327 } |
| 328 |
| 329 func TestPut(t *testing.T) { |
| 330 t.Parallel() |
| 331 |
| 332 Convey("Test Put/PutMulti", t, func() { |
| 333 c := info.Set(context.Background(), fakeInfo{}) |
| 334 c = SetRawFactory(c, fakeDatastoreFactory) |
| 335 ds := Get(c) |
| 336 |
| 337 Convey("bad", func() { |
| 338 Convey("static can't serialize", func() { |
| 339 bss := []badStruct{{}, {}} |
| 340 So(ds.PutMulti(bss).Error(), ShouldContainSubstr
ing, "invalid PutMulti input") |
| 341 }) |
| 342 |
| 343 Convey("static ptr can't serialize", func() { |
| 344 bss := []*badStruct{{}, {}} |
| 345 So(ds.PutMulti(bss).Error(), ShouldContainSubstr
ing, "invalid PutMulti input") |
| 346 }) |
| 347 |
| 348 Convey("static bad type (non-slice)", func() { |
| 349 So(ds.PutMulti(100).Error(), ShouldContainSubstr
ing, "invalid PutMulti input") |
| 350 }) |
| 351 |
| 352 Convey("static bad type (slice of bad type)", func() { |
| 353 So(ds.PutMulti([]int{}).Error(), ShouldContainSu
bstring, "invalid PutMulti input") |
| 354 }) |
| 355 |
| 356 Convey("dynamic can't serialize", func() { |
| 357 fplss := []FakePLS{{failSave: true}, {}} |
| 358 So(ds.PutMulti(fplss).Error(), ShouldContainSubs
tring, "FakePLS.Save") |
| 359 }) |
| 360 |
| 361 Convey("can't get keys", func() { |
| 362 fplss := []FakePLS{{failGetMeta: true}, {}} |
| 363 So(ds.PutMulti(fplss).Error(), ShouldContainSubs
tring, "unable to extract $kind") |
| 364 }) |
| 365 |
| 366 Convey("get single error for RPC failure", func() { |
| 367 fplss := []FakePLS{{Kind: "FailAll"}, {}} |
| 368 So(ds.PutMulti(fplss).Error(), ShouldEqual, "Put
Multi fail all") |
| 369 }) |
| 370 |
| 371 Convey("get multi error for individual failures", func()
{ |
| 372 fplss := []FakePLS{{}, {Kind: "Fail"}} |
| 373 So(ds.PutMulti(fplss), ShouldResemble, errors.Mu
ltiError{nil, errors.New("PutMulti fail")}) |
| 374 }) |
| 375 |
| 376 Convey("put with non-modifyable type is an error", func(
) { |
| 377 cs := CommonStruct{} |
| 378 So(ds.Put(cs).Error(), ShouldContainSubstring, "
invalid Put input type") |
| 379 }) |
| 380 }) |
| 381 |
| 382 Convey("ok", func() { |
| 383 Convey("[]S", func() { |
| 384 css := make([]CommonStruct, 7) |
| 385 for i := range css { |
| 386 if i == 4 { |
| 387 css[i].ID = 200 |
| 388 } |
| 389 css[i].Value = int64(i) |
| 390 } |
| 391 So(ds.PutMulti(css), ShouldBeNil) |
| 392 for i, cs := range css { |
| 393 expect := int64(i + 1) |
| 394 if i == 4 { |
| 395 expect = 200 |
| 396 } |
| 397 So(cs.ID, ShouldEqual, expect) |
| 398 } |
| 399 }) |
| 400 |
| 401 Convey("[]*S", func() { |
| 402 css := make([]*CommonStruct, 7) |
| 403 for i := range css { |
| 404 css[i] = &CommonStruct{Value: int64(i)} |
| 405 if i == 4 { |
| 406 css[i].ID = 200 |
| 407 } |
| 408 } |
| 409 So(ds.PutMulti(css), ShouldBeNil) |
| 410 for i, cs := range css { |
| 411 expect := int64(i + 1) |
| 412 if i == 4 { |
| 413 expect = 200 |
| 414 } |
| 415 So(cs.ID, ShouldEqual, expect) |
| 416 } |
| 417 |
| 418 s := &CommonStruct{} |
| 419 So(ds.Put(s), ShouldBeNil) |
| 420 So(s.ID, ShouldEqual, 1) |
| 421 }) |
| 422 |
| 423 Convey("[]P", func() { |
| 424 fplss := make([]FakePLS, 7) |
| 425 for i := range fplss { |
| 426 fplss[i].Value = int64(i) |
| 427 if i == 4 { |
| 428 fplss[i].IntID = int64(200) |
| 429 } |
| 430 } |
| 431 So(ds.PutMulti(fplss), ShouldBeNil) |
| 432 for i, fpls := range fplss { |
| 433 expect := int64(i + 1) |
| 434 if i == 4 { |
| 435 expect = 200 |
| 436 } |
| 437 So(fpls.IntID, ShouldEqual, expect) |
| 438 } |
| 439 |
| 440 pm := PropertyMap{"Value": {MkProperty(0)}, "$ki
nd": {MkPropertyNI("Pmap")}} |
| 441 So(ds.Put(pm), ShouldBeNil) |
| 442 So(ds.KeyForObj(pm).IntID(), ShouldEqual, 1) |
| 443 }) |
| 444 |
| 445 Convey("[]P (map)", func() { |
| 446 pms := make([]PropertyMap, 7) |
| 447 for i := range pms { |
| 448 pms[i] = PropertyMap{ |
| 449 "$kind": {MkProperty("Pmap")}, |
| 450 "Value": {MkProperty(i)}, |
| 451 } |
| 452 if i == 4 { |
| 453 pms[i].SetMeta("id", int64(200)) |
| 454 } |
| 455 } |
| 456 So(ds.PutMulti(pms), ShouldBeNil) |
| 457 for i, pm := range pms { |
| 458 expect := int64(i + 1) |
| 459 if i == 4 { |
| 460 expect = 200 |
| 461 } |
| 462 So(ds.KeyForObj(pm).String(), ShouldEqua
l, fmt.Sprintf("/Pmap,%d", expect)) |
| 463 } |
| 464 }) |
| 465 |
| 466 Convey("[]*P", func() { |
| 467 fplss := make([]*FakePLS, 7) |
| 468 for i := range fplss { |
| 469 fplss[i] = &FakePLS{Value: int64(i)} |
| 470 if i == 4 { |
| 471 fplss[i].IntID = int64(200) |
| 472 } |
| 473 } |
| 474 So(ds.PutMulti(fplss), ShouldBeNil) |
| 475 for i, fpls := range fplss { |
| 476 expect := int64(i + 1) |
| 477 if i == 4 { |
| 478 expect = 200 |
| 479 } |
| 480 So(fpls.IntID, ShouldEqual, expect) |
| 481 } |
| 482 }) |
| 483 |
| 484 Convey("[]*P (map)", func() { |
| 485 pms := make([]*PropertyMap, 7) |
| 486 for i := range pms { |
| 487 pms[i] = &PropertyMap{ |
| 488 "$kind": {MkProperty("Pmap")}, |
| 489 "Value": {MkProperty(i)}, |
| 490 } |
| 491 if i == 4 { |
| 492 pms[i].SetMeta("id", int64(200)) |
| 493 } |
| 494 } |
| 495 So(ds.PutMulti(pms), ShouldBeNil) |
| 496 for i, pm := range pms { |
| 497 expect := int64(i + 1) |
| 498 if i == 4 { |
| 499 expect = 200 |
| 500 } |
| 501 So(ds.KeyForObj(*pm).String(), ShouldEqu
al, fmt.Sprintf("/Pmap,%d", expect)) |
| 502 } |
| 503 }) |
| 504 |
| 505 Convey("[]I", func() { |
| 506 ifs := []interface{}{ |
| 507 &CommonStruct{Value: 0}, |
| 508 &FakePLS{Value: 1}, |
| 509 PropertyMap{"Value": {MkProperty(2)}, "$
kind": {MkPropertyNI("Pmap")}}, |
| 510 &PropertyMap{"Value": {MkProperty(3)}, "
$kind": {MkPropertyNI("Pmap")}}, |
| 511 } |
| 512 So(ds.PutMulti(ifs), ShouldBeNil) |
| 513 for i := range ifs { |
| 514 switch i { |
| 515 case 0: |
| 516 So(ifs[i].(*CommonStruct).ID, Sh
ouldEqual, 1) |
| 517 case 1: |
| 518 fpls := ifs[i].(*FakePLS) |
| 519 So(fpls.IntID, ShouldEqual, 2) |
| 520 case 2: |
| 521 So(ds.KeyForObj(ifs[i].(Property
Map)).String(), ShouldEqual, "/Pmap,3") |
| 522 case 3: |
| 523 So(ds.KeyForObj(*ifs[i].(*Proper
tyMap)).String(), ShouldEqual, "/Pmap,4") |
| 524 } |
| 525 } |
| 526 }) |
| 527 |
| 528 }) |
| 529 |
| 530 }) |
| 531 } |
| 532 |
| 533 func TestDelete(t *testing.T) { |
| 534 t.Parallel() |
| 535 |
| 536 Convey("Test Delete/DeleteMulti", t, func() { |
| 537 c := info.Set(context.Background(), fakeInfo{}) |
| 538 c = SetRawFactory(c, fakeDatastoreFactory) |
| 539 ds := Get(c) |
| 540 So(ds, ShouldNotBeNil) |
| 541 |
| 542 Convey("bad", func() { |
| 543 Convey("get single error for RPC failure", func() { |
| 544 keys := []Key{ |
| 545 NewKey("aid", "ns", "FailAll", "", 1, ni
l), |
| 546 NewKey("aid", "ns", "Ok", "", 1, nil), |
| 547 } |
| 548 So(ds.DeleteMulti(keys).Error(), ShouldEqual, "D
eleteMulti fail all") |
| 549 }) |
| 550 |
| 551 Convey("get multi error for individual failure", func()
{ |
| 552 keys := []Key{ |
| 553 ds.NewKey("Ok", "", 1, nil), |
| 554 ds.NewKey("Fail", "", 2, nil), |
| 555 } |
| 556 So(ds.DeleteMulti(keys).Error(), ShouldEqual, "D
eleteMulti fail") |
| 557 }) |
| 558 |
| 559 Convey("get single error when deleting a single", func()
{ |
| 560 k := ds.NewKey("Fail", "", 1, nil) |
| 561 So(ds.Delete(k).Error(), ShouldEqual, "DeleteMul
ti fail") |
| 562 }) |
| 563 }) |
| 564 |
| 565 }) |
| 566 } |
| 567 |
| 568 func TestGet(t *testing.T) { |
| 569 t.Parallel() |
| 570 |
| 571 Convey("Test Get/GetMulti", t, func() { |
| 572 c := info.Set(context.Background(), fakeInfo{}) |
| 573 c = SetRawFactory(c, fakeDatastoreFactory) |
| 574 ds := Get(c) |
| 575 So(ds, ShouldNotBeNil) |
| 576 |
| 577 Convey("bad", func() { |
| 578 Convey("static can't serialize", func() { |
| 579 toGet := []badStruct{{}, {}} |
| 580 So(ds.GetMulti(toGet).Error(), ShouldContainSubs
tring, "invalid GetMulti input") |
| 581 }) |
| 582 |
| 583 Convey("can't get keys", func() { |
| 584 fplss := []FakePLS{{failGetMeta: true}, {}} |
| 585 So(ds.GetMulti(fplss).Error(), ShouldContainSubs
tring, "unable to extract $kind") |
| 586 }) |
| 587 |
| 588 Convey("get single error for RPC failure", func() { |
| 589 fplss := []FakePLS{ |
| 590 {IntID: 1, Kind: "FailAll"}, |
| 591 {IntID: 2}, |
| 592 } |
| 593 So(ds.GetMulti(fplss).Error(), ShouldEqual, "Get
Multi fail all") |
| 594 }) |
| 595 |
| 596 Convey("get multi error for individual failures", func()
{ |
| 597 fplss := []FakePLS{{IntID: 1}, {IntID: 2, Kind:
"Fail"}} |
| 598 So(ds.GetMulti(fplss), ShouldResemble, errors.Mu
ltiError{nil, errors.New("GetMulti fail")}) |
| 599 }) |
| 600 |
| 601 Convey("get with non-modifiable type is an error", func(
) { |
| 602 cs := CommonStruct{} |
| 603 So(ds.Get(cs).Error(), ShouldContainSubstring, "
invalid Get input type") |
| 604 }) |
| 605 }) |
| 606 |
| 607 Convey("ok", func() { |
| 608 Convey("Get", func() { |
| 609 cs := &CommonStruct{ID: 1} |
| 610 So(ds.Get(cs), ShouldBeNil) |
| 611 So(cs.Value, ShouldEqual, 1) |
| 612 }) |
| 613 |
| 614 Convey("Raw access too", func() { |
| 615 rds := ds.Raw() |
| 616 So(rds.GetMulti([]Key{rds.NewKey("Kind", "", 1,
nil)}, func(pm PropertyMap, err error) { |
| 617 So(err, ShouldBeNil) |
| 618 So(pm["Value"][0].Value(), ShouldEqual,
1) |
| 619 }), ShouldBeNil) |
| 620 }) |
| 621 }) |
| 622 |
| 623 }) |
| 624 } |
| 625 |
| 626 func TestGetAll(t *testing.T) { |
| 627 t.Parallel() |
| 628 |
| 629 Convey("Test GetAll", t, func() { |
| 630 c := info.Set(context.Background(), fakeInfo{}) |
| 631 c = SetRawFactory(c, fakeDatastoreFactory) |
| 632 ds := Get(c) |
| 633 So(ds, ShouldNotBeNil) |
| 634 |
| 635 q := ds.NewQuery("").Limit(5) |
| 636 |
| 637 Convey("bad", func() { |
| 638 Convey("nil target", func() { |
| 639 So(ds.GetAll(q, (*[]PropertyMap)(nil)).Error(),
ShouldContainSubstring, "dst: <nil>") |
| 640 }) |
| 641 |
| 642 Convey("bad type", func() { |
| 643 output := 100 |
| 644 So(ds.GetAll(q, &output).Error(), ShouldContainS
ubstring, "invalid GetAll input type") |
| 645 }) |
| 646 |
| 647 Convey("bad type (non pointer)", func() { |
| 648 So(ds.GetAll(q, "moo").Error(), ShouldContainSub
string, "must have a ptr-to-slice") |
| 649 }) |
| 650 |
| 651 Convey("bad type (underspecified)", func() { |
| 652 output := []PropertyLoadSaver(nil) |
| 653 So(ds.GetAll(q, &output).Error(), ShouldContainS
ubstring, "invalid GetAll input type") |
| 654 }) |
| 655 }) |
| 656 |
| 657 Convey("ok", func() { |
| 658 Convey("*[]S", func() { |
| 659 output := []CommonStruct(nil) |
| 660 So(ds.GetAll(q, &output), ShouldBeNil) |
| 661 So(len(output), ShouldEqual, 5) |
| 662 for i, o := range output { |
| 663 So(o.ID, ShouldEqual, i+1) |
| 664 So(o.Value, ShouldEqual, i) |
| 665 } |
| 666 }) |
| 667 |
| 668 Convey("*[]*S", func() { |
| 669 output := []*CommonStruct(nil) |
| 670 So(ds.GetAll(q, &output), ShouldBeNil) |
| 671 So(len(output), ShouldEqual, 5) |
| 672 for i, o := range output { |
| 673 So(o.ID, ShouldEqual, i+1) |
| 674 So(o.Value, ShouldEqual, i) |
| 675 } |
| 676 }) |
| 677 |
| 678 Convey("*[]P", func() { |
| 679 output := []FakePLS(nil) |
| 680 So(ds.GetAll(q, &output), ShouldBeNil) |
| 681 So(len(output), ShouldEqual, 5) |
| 682 for i, o := range output { |
| 683 So(o.gotLoaded, ShouldBeTrue) |
| 684 So(o.IntID, ShouldEqual, i+1) |
| 685 So(o.Value, ShouldEqual, i) |
| 686 } |
| 687 }) |
| 688 |
| 689 Convey("*[]P (map)", func() { |
| 690 output := []PropertyMap(nil) |
| 691 So(ds.GetAll(q, &output), ShouldBeNil) |
| 692 So(len(output), ShouldEqual, 5) |
| 693 for i, o := range output { |
| 694 k, err := o.GetMeta("key") |
| 695 So(err, ShouldBeNil) |
| 696 So(k.(Key).IntID(), ShouldEqual, i+1) |
| 697 So(o["Value"][0].Value().(int64), Should
Equal, i) |
| 698 } |
| 699 }) |
| 700 |
| 701 Convey("*[]*P", func() { |
| 702 output := []*FakePLS(nil) |
| 703 So(ds.GetAll(q, &output), ShouldBeNil) |
| 704 So(len(output), ShouldEqual, 5) |
| 705 for i, o := range output { |
| 706 So(o.gotLoaded, ShouldBeTrue) |
| 707 So(o.IntID, ShouldEqual, i+1) |
| 708 So(o.Value, ShouldEqual, i) |
| 709 } |
| 710 }) |
| 711 |
| 712 Convey("*[]*P (map)", func() { |
| 713 output := []*PropertyMap(nil) |
| 714 So(ds.GetAll(q, &output), ShouldBeNil) |
| 715 So(len(output), ShouldEqual, 5) |
| 716 for i, op := range output { |
| 717 o := *op |
| 718 k, err := o.GetMeta("key") |
| 719 So(err, ShouldBeNil) |
| 720 So(k.(Key).IntID(), ShouldEqual, i+1) |
| 721 So(o["Value"][0].Value().(int64), Should
Equal, i) |
| 722 } |
| 723 }) |
| 724 |
| 725 Convey("*[]Key", func() { |
| 726 output := []Key(nil) |
| 727 So(ds.GetAll(q, &output), ShouldBeNil) |
| 728 So(len(output), ShouldEqual, 5) |
| 729 for i, k := range output { |
| 730 So(k.IntID(), ShouldEqual, i+1) |
| 731 } |
| 732 }) |
| 733 |
| 734 }) |
| 735 }) |
| 736 } |
| 737 |
| 738 func TestRun(t *testing.T) { |
| 739 t.Parallel() |
| 740 |
| 741 Convey("Test Run", t, func() { |
| 742 c := info.Set(context.Background(), fakeInfo{}) |
| 743 c = SetRawFactory(c, fakeDatastoreFactory) |
| 744 ds := Get(c) |
| 745 So(ds, ShouldNotBeNil) |
| 746 |
| 747 q := ds.NewQuery("").Limit(5) |
| 748 |
| 749 Convey("bad", func() { |
| 750 Convey("bad proto type", func() { |
| 751 So(ds.Run(q, 100, func(obj interface{}, _ func()
(Cursor, error)) bool { |
| 752 panic("never here!") |
| 753 }).Error(), ShouldContainSubstring, "invalid Run
proto type") |
| 754 }) |
| 755 |
| 756 Convey("early abort on error", func() { |
| 757 rq := q.(*fakeQuery).Fail(3) |
| 758 i := 0 |
| 759 So(ds.Run(rq, CommonStruct{}, func(_ interface{}
, _ func() (Cursor, error)) bool { |
| 760 i++ |
| 761 return true |
| 762 }).Error(), ShouldEqual, "Query fail") |
| 763 So(i, ShouldEqual, 3) |
| 764 }) |
| 765 |
| 766 Convey("return error on serialization failure", func() { |
| 767 So(ds.Run(q, permaBad{}, func(_ interface{}, _ f
unc() (Cursor, error)) bool { |
| 768 panic("never here") |
| 769 }).Error(), ShouldEqual, "permaBad") |
| 770 }) |
| 771 }) |
| 772 |
| 773 Convey("ok", func() { |
| 774 Convey("*S", func() { |
| 775 i := 0 |
| 776 So(ds.Run(q, (*CommonStruct)(nil), func(obj inte
rface{}, _ func() (Cursor, error)) bool { |
| 777 cs := obj.(*CommonStruct) |
| 778 So(cs.ID, ShouldEqual, i+1) |
| 779 So(cs.Value, ShouldEqual, i) |
| 780 i++ |
| 781 return true |
| 782 }), ShouldBeNil) |
| 783 }) |
| 784 |
| 785 Convey("*P", func() { |
| 786 i := 0 |
| 787 So(ds.Run(q.Limit(12), (*FakePLS)(nil), func(obj
interface{}, _ func() (Cursor, error)) bool { |
| 788 fpls := obj.(*FakePLS) |
| 789 So(fpls.gotLoaded, ShouldBeTrue) |
| 790 if i == 10 { |
| 791 So(fpls.StringID, ShouldEqual, "
eleven") |
| 792 } else { |
| 793 So(fpls.IntID, ShouldEqual, i+1) |
| 794 } |
| 795 So(fpls.Value, ShouldEqual, i) |
| 796 i++ |
| 797 return true |
| 798 }), ShouldBeNil) |
| 799 }) |
| 800 |
| 801 Convey("*P (map)", func() { |
| 802 i := 0 |
| 803 So(ds.Run(q, (*PropertyMap)(nil), func(obj inter
face{}, _ func() (Cursor, error)) bool { |
| 804 pm := *obj.(*PropertyMap) |
| 805 k, err := pm.GetMeta("key") |
| 806 So(err, ShouldBeNil) |
| 807 So(k.(Key).IntID(), ShouldEqual, i+1) |
| 808 So(pm["Value"][0].Value(), ShouldEqual,
i) |
| 809 i++ |
| 810 return true |
| 811 }), ShouldBeNil) |
| 812 }) |
| 813 |
| 814 Convey("S", func() { |
| 815 i := 0 |
| 816 So(ds.Run(q, CommonStruct{}, func(obj interface{
}, _ func() (Cursor, error)) bool { |
| 817 cs := obj.(CommonStruct) |
| 818 So(cs.ID, ShouldEqual, i+1) |
| 819 So(cs.Value, ShouldEqual, i) |
| 820 i++ |
| 821 return true |
| 822 }), ShouldBeNil) |
| 823 }) |
| 824 |
| 825 Convey("P", func() { |
| 826 i := 0 |
| 827 So(ds.Run(q, FakePLS{}, func(obj interface{}, _
func() (Cursor, error)) bool { |
| 828 fpls := obj.(FakePLS) |
| 829 So(fpls.gotLoaded, ShouldBeTrue) |
| 830 So(fpls.IntID, ShouldEqual, i+1) |
| 831 So(fpls.Value, ShouldEqual, i) |
| 832 i++ |
| 833 return true |
| 834 }), ShouldBeNil) |
| 835 }) |
| 836 |
| 837 Convey("P (map)", func() { |
| 838 i := 0 |
| 839 So(ds.Run(q, (PropertyMap)(nil), func(obj interf
ace{}, _ func() (Cursor, error)) bool { |
| 840 pm := obj.(PropertyMap) |
| 841 k, err := pm.GetMeta("key") |
| 842 So(err, ShouldBeNil) |
| 843 So(k.(Key).IntID(), ShouldEqual, i+1) |
| 844 So(pm["Value"][0].Value(), ShouldEqual,
i) |
| 845 i++ |
| 846 return true |
| 847 }), ShouldBeNil) |
| 848 }) |
| 849 |
| 850 Convey("*Key", func() { |
| 851 i := 0 |
| 852 So(ds.Run(q, (*Key)(nil), func(obj interface{},
_ func() (Cursor, error)) bool { |
| 853 So(obj.(Key).IntID(), ShouldEqual, i+1) |
| 854 i++ |
| 855 return true |
| 856 }), ShouldBeNil) |
| 857 }) |
| 858 |
| 859 }) |
| 860 }) |
| 861 } |
OLD | NEW |