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

Side by Side Diff: service/rawdatastore/datastore_test.go

Issue 1243323002: Refactor a bit. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix golint Created 5 years, 5 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 | « service/rawdatastore/datastore_key_test.go ('k') | service/rawdatastore/errors.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 Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // adapted from github.com/golang/appengine/datastore 5 // adapted from github.com/golang/appengine/datastore
6 6
7 package helper 7 package rawdatastore
8 8
9 import ( 9 import (
10 "bytes" 10 "bytes"
11 "encoding/json" 11 "encoding/json"
12 "fmt" 12 "fmt"
13 "math" 13 "math"
14 "reflect" 14 "reflect"
15 "strconv" 15 "strconv"
16 "strings" 16 "strings"
17 "testing" 17 "testing"
18 "time" 18 "time"
19 19
20 » "github.com/luci/gae" 20 » "github.com/luci/gae/service/blobstore"
21 . "github.com/smartystreets/goconvey/convey" 21 . "github.com/smartystreets/goconvey/convey"
22 ) 22 )
23 23
24 var ( 24 var (
25 » mp = gae.MkDSProperty 25 » mp = MkProperty
26 » mpNI = gae.MkDSPropertyNI 26 » mpNI = MkPropertyNI
27 ) 27 )
28 28
29 const testAppID = "testApp" 29 const testAppID = "testApp"
30 30
31 type ( 31 type (
32 myBlob []byte 32 myBlob []byte
33 myByte byte 33 myByte byte
34 myString string 34 myString string
35 ) 35 )
36 36
(...skipping 20 matching lines...) Expand all
57 } 57 }
58 return b 58 return b
59 } 59 }
60 60
61 var ( 61 var (
62 testKey0 = mkKey("aid", "", "kind", "name0") 62 testKey0 = mkKey("aid", "", "kind", "name0")
63 testKey1a = mkKey("aid", "", "kind", "name1") 63 testKey1a = mkKey("aid", "", "kind", "name1")
64 testKey1b = mkKey("aid", "", "kind", "name1") 64 testKey1b = mkKey("aid", "", "kind", "name1")
65 testKey2a = mkKey("aid", "", "kind", "name0", "kind", "name2") 65 testKey2a = mkKey("aid", "", "kind", "name0", "kind", "name2")
66 testKey2b = mkKey("aid", "", "kind", "name0", "kind", "name2") 66 testKey2b = mkKey("aid", "", "kind", "name0", "kind", "name2")
67 » testGeoPt0 = gae.DSGeoPoint{Lat: 1.2, Lng: 3.4} 67 » testGeoPt0 = GeoPoint{Lat: 1.2, Lng: 3.4}
68 » testGeoPt1 = gae.DSGeoPoint{Lat: 5, Lng: 10} 68 » testGeoPt1 = GeoPoint{Lat: 5, Lng: 10}
69 » testBadGeoPt = gae.DSGeoPoint{Lat: 1000, Lng: 34} 69 » testBadGeoPt = GeoPoint{Lat: 1000, Lng: 34}
70 ) 70 )
71 71
72 type B0 struct { 72 type B0 struct {
73 B []byte 73 B []byte
74 } 74 }
75 75
76 type B1 struct { 76 type B1 struct {
77 B []int8 77 B []int8
78 } 78 }
79 79
80 type B2 struct { 80 type B2 struct {
81 B myBlob 81 B myBlob
82 } 82 }
83 83
84 type B3 struct { 84 type B3 struct {
85 B []myByte 85 B []myByte
86 } 86 }
87 87
88 type B4 struct { 88 type B4 struct {
89 B [][]byte 89 B [][]byte
90 } 90 }
91 91
92 type B5 struct { 92 type B5 struct {
93 » B gae.DSByteString 93 » B ByteString
94 } 94 }
95 95
96 type C0 struct { 96 type C0 struct {
97 I int 97 I int
98 C chan int 98 C chan int
99 } 99 }
100 100
101 type C1 struct { 101 type C1 struct {
102 I int 102 I int
103 C *chan int 103 C *chan int
104 } 104 }
105 105
106 type C2 struct { 106 type C2 struct {
107 I int 107 I int
108 C []chan int 108 C []chan int
109 } 109 }
110 110
111 type C3 struct { 111 type C3 struct {
112 C string 112 C string
113 } 113 }
114 114
115 type E struct{} 115 type E struct{}
116 116
117 type G0 struct { 117 type G0 struct {
118 » G gae.DSGeoPoint 118 » G GeoPoint
119 } 119 }
120 120
121 type G1 struct { 121 type G1 struct {
122 » G []gae.DSGeoPoint 122 » G []GeoPoint
123 } 123 }
124 124
125 type K0 struct { 125 type K0 struct {
126 » K gae.DSKey 126 » K Key
127 } 127 }
128 128
129 type K1 struct { 129 type K1 struct {
130 » K []gae.DSKey 130 » K []Key
131 } 131 }
132 132
133 type N0 struct { 133 type N0 struct {
134 X0 134 X0
135 ID int64 `gae:"$id"` 135 ID int64 `gae:"$id"`
136 _kind string `gae:"$kind,whatnow"` 136 _kind string `gae:"$kind,whatnow"`
137 Nonymous X0 137 Nonymous X0
138 Ignore string `gae:"-"` 138 Ignore string `gae:"-"`
139 Other string 139 Other string
140 } 140 }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 I int 312 I int
313 R []MutuallyRecursive1 313 R []MutuallyRecursive1
314 } 314 }
315 315
316 type MutuallyRecursive1 struct { 316 type MutuallyRecursive1 struct {
317 I int 317 I int
318 R []MutuallyRecursive0 318 R []MutuallyRecursive0
319 } 319 }
320 320
321 type ExoticTypes struct { 321 type ExoticTypes struct {
322 » BS gae.BSKey 322 » BS blobstore.Key
323 » DSBS gae.DSByteString 323 » DSBS ByteString
324 } 324 }
325 325
326 type Underspecified struct { 326 type Underspecified struct {
327 » Iface gae.DSPropertyConverter 327 » Iface PropertyConverter
328 } 328 }
329 329
330 type MismatchTypes struct { 330 type MismatchTypes struct {
331 S string 331 S string
332 B bool 332 B bool
333 F float32 333 F float32
334 » K gae.DSKey 334 » K Key
335 T time.Time 335 T time.Time
336 » G gae.DSGeoPoint 336 » G GeoPoint
337 IS []int 337 IS []int
338 } 338 }
339 339
340 type BadSpecial struct { 340 type BadSpecial struct {
341 ID int64 `gae:"$id"` 341 ID int64 `gae:"$id"`
342 id string `gae:"$id"` 342 id string `gae:"$id"`
343 } 343 }
344 344
345 type Doubler struct { 345 type Doubler struct {
346 S string 346 S string
347 I int64 347 I int64
348 B bool 348 B bool
349 } 349 }
350 350
351 func (d *Doubler) Load(props gae.DSPropertyMap) error { 351 func (d *Doubler) Load(props PropertyMap) error {
352 return GetPLS(d).Load(props) 352 return GetPLS(d).Load(props)
353 } 353 }
354 354
355 func (d *Doubler) Save(withMeta bool) (gae.DSPropertyMap, error) { 355 func (d *Doubler) Save(withMeta bool) (PropertyMap, error) {
356 pls := GetPLS(d) 356 pls := GetPLS(d)
357 propMap, err := pls.Save(withMeta) 357 propMap, err := pls.Save(withMeta)
358 if err != nil { 358 if err != nil {
359 return nil, err 359 return nil, err
360 } 360 }
361 361
362 // Edit that map and send it on. 362 // Edit that map and send it on.
363 for _, props := range propMap { 363 for _, props := range propMap {
364 for i := range props { 364 for i := range props {
365 switch v := props[i].Value().(type) { 365 switch v := props[i].Value().(type) {
366 case string: 366 case string:
367 // + means string concatenation. 367 // + means string concatenation.
368 props[i].SetValue(v+v, props[i].IndexSetting()) 368 props[i].SetValue(v+v, props[i].IndexSetting())
369 case int64: 369 case int64:
370 // + means integer addition. 370 // + means integer addition.
371 props[i].SetValue(v+v, props[i].IndexSetting()) 371 props[i].SetValue(v+v, props[i].IndexSetting())
372 } 372 }
373 } 373 }
374 } 374 }
375 return propMap, nil 375 return propMap, nil
376 } 376 }
377 377
378 func (d *Doubler) GetMeta(string) (interface{}, error) { return nil, gae.ErrDSMe taFieldUnset } 378 func (d *Doubler) GetMeta(string) (interface{}, error) { return nil, ErrMetaFiel dUnset }
379 func (d *Doubler) SetMeta(string, interface{}) error { return gae.ErrDSMetaFie ldUnset } 379 func (d *Doubler) SetMeta(string, interface{}) error { return ErrMetaFieldUnse t }
380 func (d *Doubler) Problem() error { return nil } 380 func (d *Doubler) Problem() error { return nil }
381 381
382 var _ gae.DSPropertyLoadSaver = (*Doubler)(nil) 382 var _ PropertyLoadSaver = (*Doubler)(nil)
383 383
384 type Deriver struct { 384 type Deriver struct {
385 S, Derived, Ignored string 385 S, Derived, Ignored string
386 } 386 }
387 387
388 func (d *Deriver) Load(props gae.DSPropertyMap) error { 388 func (d *Deriver) Load(props PropertyMap) error {
389 for name, p := range props { 389 for name, p := range props {
390 if name != "S" { 390 if name != "S" {
391 continue 391 continue
392 } 392 }
393 d.S = p[0].Value().(string) 393 d.S = p[0].Value().(string)
394 d.Derived = "derived+" + d.S 394 d.Derived = "derived+" + d.S
395 } 395 }
396 return nil 396 return nil
397 } 397 }
398 398
399 func (d *Deriver) Save(withMeta bool) (gae.DSPropertyMap, error) { 399 func (d *Deriver) Save(withMeta bool) (PropertyMap, error) {
400 » return map[string][]gae.DSProperty{ 400 » return map[string][]Property{
401 "S": {mp(d.S)}, 401 "S": {mp(d.S)},
402 }, nil 402 }, nil
403 } 403 }
404 404
405 func (d *Deriver) GetMeta(string) (interface{}, error) { return nil, gae.ErrDSMe taFieldUnset } 405 func (d *Deriver) GetMeta(string) (interface{}, error) { return nil, ErrMetaFiel dUnset }
406 func (d *Deriver) SetMeta(string, interface{}) error { return gae.ErrDSMetaFie ldUnset } 406 func (d *Deriver) SetMeta(string, interface{}) error { return ErrMetaFieldUnse t }
407 func (d *Deriver) Problem() error { return nil } 407 func (d *Deriver) Problem() error { return nil }
408 408
409 var _ gae.DSPropertyLoadSaver = (*Deriver)(nil) 409 var _ PropertyLoadSaver = (*Deriver)(nil)
410 410
411 type BK struct { 411 type BK struct {
412 » Key gae.BSKey 412 » Key blobstore.Key
413 } 413 }
414 414
415 type Convertable []int64 415 type Convertable []int64
416 416
417 var _ gae.DSPropertyConverter = (*Convertable)(nil) 417 var _ PropertyConverter = (*Convertable)(nil)
418 418
419 func (c *Convertable) ToDSProperty() (ret gae.DSProperty, err error) { 419 func (c *Convertable) ToProperty() (ret Property, err error) {
420 buf := make([]string, len(*c)) 420 buf := make([]string, len(*c))
421 for i, v := range *c { 421 for i, v := range *c {
422 buf[i] = strconv.FormatInt(v, 10) 422 buf[i] = strconv.FormatInt(v, 10)
423 } 423 }
424 » err = ret.SetValue(strings.Join(buf, ","), gae.NoIndex) 424 » err = ret.SetValue(strings.Join(buf, ","), NoIndex)
425 return 425 return
426 } 426 }
427 427
428 func (c *Convertable) FromDSProperty(pv gae.DSProperty) error { 428 func (c *Convertable) FromProperty(pv Property) error {
429 if sval, ok := pv.Value().(string); ok { 429 if sval, ok := pv.Value().(string); ok {
430 for _, t := range strings.Split(sval, ",") { 430 for _, t := range strings.Split(sval, ",") {
431 ival, err := strconv.ParseInt(t, 10, 64) 431 ival, err := strconv.ParseInt(t, 10, 64)
432 if err != nil { 432 if err != nil {
433 return err 433 return err
434 } 434 }
435 *c = append(*c, ival) 435 *c = append(*c, ival)
436 } 436 }
437 return nil 437 return nil
438 } 438 }
439 return fmt.Errorf("nope") 439 return fmt.Errorf("nope")
440 } 440 }
441 441
442 type Impossible struct { 442 type Impossible struct {
443 Nested []ImpossibleInner 443 Nested []ImpossibleInner
444 } 444 }
445 445
446 type ImpossibleInner struct { 446 type ImpossibleInner struct {
447 Ints Convertable `gae:"wot"` 447 Ints Convertable `gae:"wot"`
448 } 448 }
449 449
450 type Convertable2 struct { 450 type Convertable2 struct {
451 Data string 451 Data string
452 Exploded []string 452 Exploded []string
453 } 453 }
454 454
455 func (c *Convertable2) ToDSProperty() (ret gae.DSProperty, err error) { 455 func (c *Convertable2) ToProperty() (ret Property, err error) {
456 » err = ret.SetValue(c.Data, gae.ShouldIndex) 456 » err = ret.SetValue(c.Data, ShouldIndex)
457 return 457 return
458 } 458 }
459 459
460 func (c *Convertable2) FromDSProperty(pv gae.DSProperty) error { 460 func (c *Convertable2) FromProperty(pv Property) error {
461 if sval, ok := pv.Value().(string); ok { 461 if sval, ok := pv.Value().(string); ok {
462 c.Data = sval 462 c.Data = sval
463 c.Exploded = []string{"turn", "down", "for", "what"} 463 c.Exploded = []string{"turn", "down", "for", "what"}
464 return nil 464 return nil
465 } 465 }
466 return fmt.Errorf("nope") 466 return fmt.Errorf("nope")
467 } 467 }
468 468
469 type Impossible2 struct { 469 type Impossible2 struct {
470 Nested []ImpossibleInner2 470 Nested []ImpossibleInner2
471 } 471 }
472 472
473 type ImpossibleInner2 struct { 473 type ImpossibleInner2 struct {
474 Thingy Convertable2 `gae:"nerb"` 474 Thingy Convertable2 `gae:"nerb"`
475 } 475 }
476 476
477 type JSONKVProp map[string]interface{} 477 type JSONKVProp map[string]interface{}
478 478
479 var _ gae.DSPropertyConverter = (*JSONKVProp)(nil) 479 var _ PropertyConverter = (*JSONKVProp)(nil)
480 480
481 func (j *JSONKVProp) ToDSProperty() (ret gae.DSProperty, err error) { 481 func (j *JSONKVProp) ToProperty() (ret Property, err error) {
482 data, err := json.Marshal(map[string]interface{}(*j)) 482 data, err := json.Marshal(map[string]interface{}(*j))
483 if err != nil { 483 if err != nil {
484 return 484 return
485 } 485 }
486 » err = ret.SetValue(data, gae.NoIndex) 486 » err = ret.SetValue(data, NoIndex)
487 return 487 return
488 } 488 }
489 489
490 func (j *JSONKVProp) FromDSProperty(pv gae.DSProperty) error { 490 func (j *JSONKVProp) FromProperty(pv Property) error {
491 if bval, ok := pv.Value().([]byte); ok { 491 if bval, ok := pv.Value().([]byte); ok {
492 dec := json.NewDecoder(bytes.NewBuffer(bval)) 492 dec := json.NewDecoder(bytes.NewBuffer(bval))
493 dec.UseNumber() 493 dec.UseNumber()
494 return dec.Decode((*map[string]interface{})(j)) 494 return dec.Decode((*map[string]interface{})(j))
495 } 495 }
496 return fmt.Errorf("nope") 496 return fmt.Errorf("nope")
497 } 497 }
498 498
499 type Impossible3 struct { 499 type Impossible3 struct {
500 KMap JSONKVProp `gae:"kewelmap"` 500 KMap JSONKVProp `gae:"kewelmap"`
501 } 501 }
502 502
503 type Complex complex128 503 type Complex complex128
504 504
505 var _ gae.DSPropertyConverter = (*Complex)(nil) 505 var _ PropertyConverter = (*Complex)(nil)
506 506
507 func (c *Complex) ToDSProperty() (ret gae.DSProperty, err error) { 507 func (c *Complex) ToProperty() (ret Property, err error) {
508 // cheat hardkore and usurp GeoPoint so datastore will index these sucke rs 508 // cheat hardkore and usurp GeoPoint so datastore will index these sucke rs
509 // (note that this won't REALLY work, since GeoPoints are limited to a v ery 509 // (note that this won't REALLY work, since GeoPoints are limited to a v ery
510 // limited range of values, but it's nice to pretend ;)). You'd probably 510 // limited range of values, but it's nice to pretend ;)). You'd probably
511 // really end up with a packed binary representation. 511 // really end up with a packed binary representation.
512 » err = ret.SetValue(gae.DSGeoPoint{Lat: real(*c), Lng: imag(*c)}, gae.Sho uldIndex) 512 » err = ret.SetValue(GeoPoint{Lat: real(*c), Lng: imag(*c)}, ShouldIndex)
513 return 513 return
514 } 514 }
515 515
516 func (c *Complex) FromDSProperty(p gae.DSProperty) error { 516 func (c *Complex) FromProperty(p Property) error {
517 » if gval, ok := p.Value().(gae.DSGeoPoint); ok { 517 » if gval, ok := p.Value().(GeoPoint); ok {
518 *c = Complex(complex(gval.Lat, gval.Lng)) 518 *c = Complex(complex(gval.Lat, gval.Lng))
519 return nil 519 return nil
520 } 520 }
521 return fmt.Errorf("nope") 521 return fmt.Errorf("nope")
522 } 522 }
523 523
524 type Impossible4 struct { 524 type Impossible4 struct {
525 Values []Complex 525 Values []Complex
526 } 526 }
527 527
528 type DerivedKey struct { 528 type DerivedKey struct {
529 » K *GenericDSKey 529 » K *GenericKey
530 } 530 }
531 531
532 type IfaceKey struct { 532 type IfaceKey struct {
533 » K gae.DSKey 533 » K Key
534 } 534 }
535 535
536 type testCase struct { 536 type testCase struct {
537 desc string 537 desc string
538 src interface{} 538 src interface{}
539 want interface{} 539 want interface{}
540 plsErr string 540 plsErr string
541 saveErr string 541 saveErr string
542 actualNoIndex bool 542 actualNoIndex bool
543 plsLoadErr string 543 plsLoadErr string
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 want: &G0{G: testGeoPt0}, 589 want: &G0{G: testGeoPt0},
590 }, 590 },
591 { 591 {
592 desc: "geopoint invalid", 592 desc: "geopoint invalid",
593 src: &G0{G: testBadGeoPt}, 593 src: &G0{G: testBadGeoPt},
594 saveErr: "invalid GeoPoint value", 594 saveErr: "invalid GeoPoint value",
595 }, 595 },
596 { 596 {
597 desc: "geopoint as props", 597 desc: "geopoint as props",
598 src: &G0{G: testGeoPt0}, 598 src: &G0{G: testGeoPt0},
599 » » want: gae.DSPropertyMap{ 599 » » want: PropertyMap{
600 "G": {mp(testGeoPt0)}, 600 "G": {mp(testGeoPt0)},
601 }, 601 },
602 }, 602 },
603 { 603 {
604 desc: "geopoint slice", 604 desc: "geopoint slice",
605 » » src: &G1{G: []gae.DSGeoPoint{testGeoPt0, testGeoPt1}}, 605 » » src: &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}},
606 » » want: &G1{G: []gae.DSGeoPoint{testGeoPt0, testGeoPt1}}, 606 » » want: &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}},
607 }, 607 },
608 { 608 {
609 desc: "key", 609 desc: "key",
610 src: &K0{K: testKey1a}, 610 src: &K0{K: testKey1a},
611 want: &K0{K: testKey1b}, 611 want: &K0{K: testKey1b},
612 }, 612 },
613 { 613 {
614 desc: "key with parent", 614 desc: "key with parent",
615 src: &K0{K: testKey2a}, 615 src: &K0{K: testKey2a},
616 want: &K0{K: testKey2b}, 616 want: &K0{K: testKey2b},
617 }, 617 },
618 { 618 {
619 desc: "nil key", 619 desc: "nil key",
620 src: &K0{}, 620 src: &K0{},
621 want: &K0{}, 621 want: &K0{},
622 }, 622 },
623 { 623 {
624 desc: "all nil keys in slice", 624 desc: "all nil keys in slice",
625 » » src: &K1{[]gae.DSKey{nil, nil}}, 625 » » src: &K1{[]Key{nil, nil}},
626 » » want: &K1{[]gae.DSKey{nil, nil}}, 626 » » want: &K1{[]Key{nil, nil}},
627 }, 627 },
628 { 628 {
629 desc: "some nil keys in slice", 629 desc: "some nil keys in slice",
630 » » src: &K1{[]gae.DSKey{testKey1a, nil, testKey2a}}, 630 » » src: &K1{[]Key{testKey1a, nil, testKey2a}},
631 » » want: &K1{[]gae.DSKey{testKey1b, nil, testKey2b}}, 631 » » want: &K1{[]Key{testKey1b, nil, testKey2b}},
632 }, 632 },
633 { 633 {
634 desc: "overflow", 634 desc: "overflow",
635 src: &O0{I: 1 << 48}, 635 src: &O0{I: 1 << 48},
636 want: &O1{}, 636 want: &O1{},
637 loadErr: "overflow", 637 loadErr: "overflow",
638 }, 638 },
639 { 639 {
640 desc: "time", 640 desc: "time",
641 src: &T{T: time.Unix(1e9, 0).UTC()}, 641 src: &T{T: time.Unix(1e9, 0).UTC()},
642 want: &T{T: time.Unix(1e9, 0).UTC()}, 642 want: &T{T: time.Unix(1e9, 0).UTC()},
643 }, 643 },
644 { 644 {
645 desc: "time as props", 645 desc: "time as props",
646 src: &T{T: time.Unix(1e9, 0).UTC()}, 646 src: &T{T: time.Unix(1e9, 0).UTC()},
647 » » want: gae.DSPropertyMap{ 647 » » want: PropertyMap{
648 "T": {mp(time.Unix(1e9, 0).UTC())}, 648 "T": {mp(time.Unix(1e9, 0).UTC())},
649 }, 649 },
650 }, 650 },
651 { 651 {
652 desc: "uint save", 652 desc: "uint save",
653 src: &U0{U: 1}, 653 src: &U0{U: 1},
654 plsErr: `field "U" has invalid type: uint`, 654 plsErr: `field "U" has invalid type: uint`,
655 }, 655 },
656 { 656 {
657 desc: "uint load", 657 desc: "uint load",
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 want: &Y2{B: true, F: []int64{7}}, 708 want: &Y2{B: true, F: []int64{7}},
709 }, 709 },
710 { 710 {
711 desc: "use convertable slice", 711 desc: "use convertable slice",
712 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}}, 712 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}},
713 want: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}}, 713 want: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}},
714 }, 714 },
715 { 715 {
716 desc: "use convertable slice (to map)", 716 desc: "use convertable slice (to map)",
717 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}}, 717 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}},
718 » » want: gae.DSPropertyMap{ 718 » » want: PropertyMap{
719 "Nested.wot": {mpNI("1,5,9"), mpNI("2,4,6")}, 719 "Nested.wot": {mpNI("1,5,9"), mpNI("2,4,6")},
720 }, 720 },
721 }, 721 },
722 { 722 {
723 desc: "convertable slice (bad load)", 723 desc: "convertable slice (bad load)",
724 » » src: gae.DSPropertyMap{"Nested.wot": {mpNI([]byte("ohai"))}} , 724 » » src: PropertyMap{"Nested.wot": {mpNI([]byte("ohai"))}},
725 want: &Impossible{[]ImpossibleInner{{}}}, 725 want: &Impossible{[]ImpossibleInner{{}}},
726 loadErr: "nope", 726 loadErr: "nope",
727 }, 727 },
728 { 728 {
729 desc: "use convertable struct", 729 desc: "use convertable struct",
730 src: &Impossible2{ 730 src: &Impossible2{
731 []ImpossibleInner2{ 731 []ImpossibleInner2{
732 {Convertable2{"nerb", nil}}, 732 {Convertable2{"nerb", nil}},
733 }, 733 },
734 }, 734 },
(...skipping 22 matching lines...) Expand all
757 }, 757 },
758 { 758 {
759 desc: "convertable json KVMap (to map)", 759 desc: "convertable json KVMap (to map)",
760 src: &Impossible3{ 760 src: &Impossible3{
761 JSONKVProp{ 761 JSONKVProp{
762 "epic": "success", 762 "epic": "success",
763 "no_way!": []interface{}{true, "story"}, 763 "no_way!": []interface{}{true, "story"},
764 "what": []interface{}{"is", "really", 100}, 764 "what": []interface{}{"is", "really", 100},
765 }, 765 },
766 }, 766 },
767 » » want: gae.DSPropertyMap{ 767 » » want: PropertyMap{
768 "kewelmap": { 768 "kewelmap": {
769 mpNI([]byte( 769 mpNI([]byte(
770 `{"epic":"success","no_way!":[true,"stor y"],"what":["is","really",100]}`))}, 770 `{"epic":"success","no_way!":[true,"stor y"],"what":["is","really",100]}`))},
771 }, 771 },
772 }, 772 },
773 { 773 {
774 desc: "convertable complex slice", 774 desc: "convertable complex slice",
775 src: &Impossible4{ 775 src: &Impossible4{
776 []Complex{complex(1, 2), complex(3, 4)}, 776 []Complex{complex(1, 2), complex(3, 4)},
777 }, 777 },
778 want: &Impossible4{ 778 want: &Impossible4{
779 []Complex{complex(1, 2), complex(3, 4)}, 779 []Complex{complex(1, 2), complex(3, 4)},
780 }, 780 },
781 }, 781 },
782 { 782 {
783 desc: "convertable complex slice (to map)", 783 desc: "convertable complex slice (to map)",
784 src: &Impossible4{ 784 src: &Impossible4{
785 []Complex{complex(1, 2), complex(3, 4)}, 785 []Complex{complex(1, 2), complex(3, 4)},
786 }, 786 },
787 » » want: gae.DSPropertyMap{ 787 » » want: PropertyMap{
788 "Values": { 788 "Values": {
789 » » » » mp(gae.DSGeoPoint{Lat: 1, Lng: 2}), mp(gae.DSGeo Point{Lat: 3, Lng: 4})}, 789 » » » » mp(GeoPoint{Lat: 1, Lng: 2}), mp(GeoPoint{Lat: 3 , Lng: 4})},
790 }, 790 },
791 }, 791 },
792 { 792 {
793 desc: "convertable complex slice (bad load)", 793 desc: "convertable complex slice (bad load)",
794 » » src: gae.DSPropertyMap{"Values": {mp("hello")}}, 794 » » src: PropertyMap{"Values": {mp("hello")}},
795 want: &Impossible4{[]Complex(nil)}, 795 want: &Impossible4{[]Complex(nil)},
796 loadErr: "nope", 796 loadErr: "nope",
797 }, 797 },
798 { 798 {
799 » » desc: "allow concrete gae.DSKey implementors (save)", 799 » » desc: "allow concrete Key implementors (save)",
800 » » src: &DerivedKey{testKey2a.(*GenericDSKey)}, 800 » » src: &DerivedKey{testKey2a.(*GenericKey)},
801 want: &IfaceKey{testKey2b}, 801 want: &IfaceKey{testKey2b},
802 }, 802 },
803 { 803 {
804 » » desc: "allow concrete gae.DSKey implementors (load)", 804 » » desc: "allow concrete Key implementors (load)",
805 src: &IfaceKey{testKey2b}, 805 src: &IfaceKey{testKey2b},
806 » » want: &DerivedKey{testKey2a.(*GenericDSKey)}, 806 » » want: &DerivedKey{testKey2a.(*GenericKey)},
807 }, 807 },
808 { 808 {
809 desc: "save []float64 load []int64", 809 desc: "save []float64 load []int64",
810 src: &Y0{B: true, F: []float64{7, 8, 9}}, 810 src: &Y0{B: true, F: []float64{7, 8, 9}},
811 want: &Y2{B: true}, 811 want: &Y2{B: true},
812 loadErr: "type mismatch", 812 loadErr: "type mismatch",
813 }, 813 },
814 { 814 {
815 desc: "single slice is too long", 815 desc: "single slice is too long",
816 src: &Y0{F: make([]float64, maxIndexedProperties+1)}, 816 src: &Y0{F: make([]float64, maxIndexedProperties+1)},
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 makeUint8Slice(4), 872 makeUint8Slice(4),
873 makeUint8Slice(5), 873 makeUint8Slice(5),
874 }}, 874 }},
875 want: &B4{B: [][]byte{ 875 want: &B4{B: [][]byte{
876 makeUint8Slice(3), 876 makeUint8Slice(3),
877 makeUint8Slice(4), 877 makeUint8Slice(4),
878 makeUint8Slice(5), 878 makeUint8Slice(5),
879 }}, 879 }},
880 }, 880 },
881 { 881 {
882 » » desc: "short gae.DSByteString", 882 » » desc: "short ByteString",
883 » » src: &B5{B: gae.DSByteString(makeUint8Slice(3))}, 883 » » src: &B5{B: ByteString(makeUint8Slice(3))},
884 » » want: &B5{B: gae.DSByteString(makeUint8Slice(3))}, 884 » » want: &B5{B: ByteString(makeUint8Slice(3))},
885 }, 885 },
886 { 886 {
887 » » desc: "short gae.DSByteString as props", 887 » » desc: "short ByteString as props",
888 » » src: &B5{B: gae.DSByteString(makeUint8Slice(3))}, 888 » » src: &B5{B: ByteString(makeUint8Slice(3))},
889 » » want: gae.DSPropertyMap{ 889 » » want: PropertyMap{
890 » » » "B": {mp(gae.DSByteString(makeUint8Slice(3)))}, 890 » » » "B": {mp(ByteString(makeUint8Slice(3)))},
891 }, 891 },
892 }, 892 },
893 { 893 {
894 desc: "[]byte must be noindex", 894 desc: "[]byte must be noindex",
895 » » src: gae.DSPropertyMap{ 895 » » src: PropertyMap{
896 "B": {mp(makeUint8Slice(3))}, 896 "B": {mp(makeUint8Slice(3))},
897 }, 897 },
898 actualNoIndex: true, 898 actualNoIndex: true,
899 }, 899 },
900 { 900 {
901 desc: "save tagged load props", 901 desc: "save tagged load props",
902 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6 , J: 7}, 902 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6 , J: 7},
903 » » want: gae.DSPropertyMap{ 903 » » want: PropertyMap{
904 // A and B are renamed to a and b; A and C are noindex, I is ignored. 904 // A and B are renamed to a and b; A and C are noindex, I is ignored.
905 // Indexed properties are loaded before raw properties. Thus, the 905 // Indexed properties are loaded before raw properties. Thus, the
906 // result is: b, b, b, D, E, a, c. 906 // result is: b, b, b, D, E, a, c.
907 "b1": { 907 "b1": {
908 mp(21), 908 mp(21),
909 mp(22), 909 mp(22),
910 mp(23), 910 mp(23),
911 }, 911 },
912 "D": {mp(4)}, 912 "D": {mp(4)},
913 "E": {mp(5)}, 913 "E": {mp(5)},
914 "a": {mpNI(1)}, 914 "a": {mpNI(1)},
915 "C": {mpNI(3)}, 915 "C": {mpNI(3)},
916 "J": {mpNI(7)}, 916 "J": {mpNI(7)},
917 }, 917 },
918 }, 918 },
919 { 919 {
920 desc: "save tagged load tagged", 920 desc: "save tagged load tagged",
921 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6 , J: 7}, 921 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6 , J: 7},
922 want: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, J: 7 }, 922 want: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, J: 7 },
923 }, 923 },
924 { 924 {
925 desc: "save props load tagged", 925 desc: "save props load tagged",
926 » » src: gae.DSPropertyMap{ 926 » » src: PropertyMap{
927 "A": {mpNI(11)}, 927 "A": {mpNI(11)},
928 "a": {mpNI(12)}, 928 "a": {mpNI(12)},
929 }, 929 },
930 want: &Tagged{A: 12}, 930 want: &Tagged{A: 12},
931 loadErr: `cannot load field "A"`, 931 loadErr: `cannot load field "A"`,
932 }, 932 },
933 { 933 {
934 desc: "invalid tagged1", 934 desc: "invalid tagged1",
935 src: &InvalidTagged1{I: 1}, 935 src: &InvalidTagged1{I: 1},
936 plsErr: `struct tag has invalid property name: "\t"`, 936 plsErr: `struct tag has invalid property name: "\t"`,
(...skipping 20 matching lines...) Expand all
957 plsErr: `struct tag has repeated property name: "V.I"`, 957 plsErr: `struct tag has repeated property name: "V.I"`,
958 }, 958 },
959 { 959 {
960 desc: "doubler", 960 desc: "doubler",
961 src: &Doubler{S: "s", I: 1, B: true}, 961 src: &Doubler{S: "s", I: 1, B: true},
962 want: &Doubler{S: "ss", I: 2, B: true}, 962 want: &Doubler{S: "ss", I: 2, B: true},
963 }, 963 },
964 { 964 {
965 desc: "save struct load props", 965 desc: "save struct load props",
966 src: &X0{S: "s", I: 1}, 966 src: &X0{S: "s", I: 1},
967 » » want: gae.DSPropertyMap{ 967 » » want: PropertyMap{
968 "S": {mp("s")}, 968 "S": {mp("s")},
969 "I": {mp(1)}, 969 "I": {mp(1)},
970 }, 970 },
971 }, 971 },
972 { 972 {
973 desc: "save props load struct", 973 desc: "save props load struct",
974 » » src: gae.DSPropertyMap{ 974 » » src: PropertyMap{
975 "S": {mp("s")}, 975 "S": {mp("s")},
976 "I": {mp(1)}, 976 "I": {mp(1)},
977 }, 977 },
978 want: &X0{S: "s", I: 1}, 978 want: &X0{S: "s", I: 1},
979 }, 979 },
980 { 980 {
981 desc: "nil-value props", 981 desc: "nil-value props",
982 » » src: gae.DSPropertyMap{ 982 » » src: PropertyMap{
983 "I": {mp(nil)}, 983 "I": {mp(nil)},
984 "B": {mp(nil)}, 984 "B": {mp(nil)},
985 "S": {mp(nil)}, 985 "S": {mp(nil)},
986 "F": {mp(nil)}, 986 "F": {mp(nil)},
987 "K": {mp(nil)}, 987 "K": {mp(nil)},
988 "T": {mp(nil)}, 988 "T": {mp(nil)},
989 "J": { 989 "J": {
990 mp(nil), 990 mp(nil),
991 mp(7), 991 mp(7),
992 mp(nil), 992 mp(nil),
993 }, 993 },
994 }, 994 },
995 want: &struct { 995 want: &struct {
996 I int64 996 I int64
997 B bool 997 B bool
998 S string 998 S string
999 F float64 999 F float64
1000 » » » K gae.DSKey 1000 » » » K Key
1001 T time.Time 1001 T time.Time
1002 J []int64 1002 J []int64
1003 }{ 1003 }{
1004 J: []int64{0, 7, 0}, 1004 J: []int64{0, 7, 0},
1005 }, 1005 },
1006 }, 1006 },
1007 { 1007 {
1008 desc: "save outer load props", 1008 desc: "save outer load props",
1009 src: &Outer{ 1009 src: &Outer{
1010 A: 1, 1010 A: 1,
1011 I: []Inner1{ 1011 I: []Inner1{
1012 {10, "ten"}, 1012 {10, "ten"},
1013 {20, "twenty"}, 1013 {20, "twenty"},
1014 {30, "thirty"}, 1014 {30, "thirty"},
1015 }, 1015 },
1016 J: Inner2{ 1016 J: Inner2{
1017 Y: 3.14, 1017 Y: 3.14,
1018 }, 1018 },
1019 Inner3: Inner3{ 1019 Inner3: Inner3{
1020 Z: true, 1020 Z: true,
1021 }, 1021 },
1022 }, 1022 },
1023 » » want: gae.DSPropertyMap{ 1023 » » want: PropertyMap{
1024 "A": {mp(1)}, 1024 "A": {mp(1)},
1025 "I.W": { 1025 "I.W": {
1026 mp(10), 1026 mp(10),
1027 mp(20), 1027 mp(20),
1028 mp(30), 1028 mp(30),
1029 }, 1029 },
1030 "I.X": { 1030 "I.X": {
1031 mp("ten"), 1031 mp("ten"),
1032 mp("twenty"), 1032 mp("twenty"),
1033 mp("thirty"), 1033 mp("thirty"),
1034 }, 1034 },
1035 "J.Y": {mp(3.14)}, 1035 "J.Y": {mp(3.14)},
1036 "Z": {mp(true)}, 1036 "Z": {mp(true)},
1037 }, 1037 },
1038 }, 1038 },
1039 { 1039 {
1040 desc: "save props load outer-equivalent", 1040 desc: "save props load outer-equivalent",
1041 » » src: gae.DSPropertyMap{ 1041 » » src: PropertyMap{
1042 "A": {mp(1)}, 1042 "A": {mp(1)},
1043 "I.W": { 1043 "I.W": {
1044 mp(10), 1044 mp(10),
1045 mp(20), 1045 mp(20),
1046 mp(30), 1046 mp(30),
1047 }, 1047 },
1048 "I.X": { 1048 "I.X": {
1049 mp("ten"), 1049 mp("ten"),
1050 mp("twenty"), 1050 mp("twenty"),
1051 mp("thirty"), 1051 mp("thirty"),
(...skipping 29 matching lines...) Expand all
1081 Y: 3.14, 1081 Y: 3.14,
1082 }, 1082 },
1083 Inner3: Inner3{ 1083 Inner3: Inner3{
1084 Z: true, 1084 Z: true,
1085 }, 1085 },
1086 }, 1086 },
1087 }, 1087 },
1088 { 1088 {
1089 desc: "dotted names save", 1089 desc: "dotted names save",
1090 src: &Dotted{A: DottedA{B: DottedB{C: 88}}}, 1090 src: &Dotted{A: DottedA{B: DottedB{C: 88}}},
1091 » » want: gae.DSPropertyMap{ 1091 » » want: PropertyMap{
1092 "A0.A1.A2.B3.C4.C5": {mp(88)}, 1092 "A0.A1.A2.B3.C4.C5": {mp(88)},
1093 }, 1093 },
1094 }, 1094 },
1095 { 1095 {
1096 desc: "dotted names load", 1096 desc: "dotted names load",
1097 » » src: gae.DSPropertyMap{ 1097 » » src: PropertyMap{
1098 "A0.A1.A2.B3.C4.C5": {mp(99)}, 1098 "A0.A1.A2.B3.C4.C5": {mp(99)},
1099 }, 1099 },
1100 want: &Dotted{A: DottedA{B: DottedB{C: 99}}}, 1100 want: &Dotted{A: DottedA{B: DottedB{C: 99}}},
1101 }, 1101 },
1102 { 1102 {
1103 desc: "save struct load deriver", 1103 desc: "save struct load deriver",
1104 src: &X0{S: "s", I: 1}, 1104 src: &X0{S: "s", I: 1},
1105 want: &Deriver{S: "s", Derived: "derived+s"}, 1105 want: &Deriver{S: "s", Derived: "derived+s"},
1106 }, 1106 },
1107 { 1107 {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 want: &N0{ 1153 want: &N0{
1154 X0: X0{S: "one", I: 2}, 1154 X0: X0{S: "one", I: 2},
1155 Nonymous: X0{S: "four", I: 5}, 1155 Nonymous: X0{S: "four", I: 5},
1156 Other: "other", 1156 Other: "other",
1157 }, 1157 },
1158 }, 1158 },
1159 { 1159 {
1160 desc: "exotic types", 1160 desc: "exotic types",
1161 src: &ExoticTypes{ 1161 src: &ExoticTypes{
1162 BS: "sup", 1162 BS: "sup",
1163 » » » DSBS: gae.DSByteString("nerds"), 1163 » » » DSBS: ByteString("nerds"),
1164 }, 1164 },
1165 want: &ExoticTypes{ 1165 want: &ExoticTypes{
1166 BS: "sup", 1166 BS: "sup",
1167 » » » DSBS: gae.DSByteString("nerds"), 1167 » » » DSBS: ByteString("nerds"),
1168 }, 1168 },
1169 }, 1169 },
1170 { 1170 {
1171 desc: "underspecified types", 1171 desc: "underspecified types",
1172 src: &Underspecified{}, 1172 src: &Underspecified{},
1173 plsErr: "non-concrete interface", 1173 plsErr: "non-concrete interface",
1174 }, 1174 },
1175 { 1175 {
1176 desc: "mismatch (string)", 1176 desc: "mismatch (string)",
1177 » » src: gae.DSPropertyMap{ 1177 » » src: PropertyMap{
1178 "K": {mp(199)}, 1178 "K": {mp(199)},
1179 "S": {mp([]byte("cats"))}, 1179 "S": {mp([]byte("cats"))},
1180 » » » "F": {mp(gae.DSByteString("nurbs"))}, 1180 » » » "F": {mp(ByteString("nurbs"))},
1181 }, 1181 },
1182 want: &MismatchTypes{}, 1182 want: &MismatchTypes{},
1183 loadErr: "type mismatch", 1183 loadErr: "type mismatch",
1184 }, 1184 },
1185 { 1185 {
1186 desc: "mismatch (float)", 1186 desc: "mismatch (float)",
1187 » » src: gae.DSPropertyMap{"F": {mp(gae.BSKey("wot"))}}, 1187 » » src: PropertyMap{"F": {mp(blobstore.Key("wot"))}},
1188 want: &MismatchTypes{}, 1188 want: &MismatchTypes{},
1189 loadErr: "type mismatch", 1189 loadErr: "type mismatch",
1190 }, 1190 },
1191 { 1191 {
1192 desc: "mismatch (float/overflow)", 1192 desc: "mismatch (float/overflow)",
1193 » » src: gae.DSPropertyMap{"F": {mp(math.MaxFloat64)}}, 1193 » » src: PropertyMap{"F": {mp(math.MaxFloat64)}},
1194 want: &MismatchTypes{}, 1194 want: &MismatchTypes{},
1195 loadErr: "overflows", 1195 loadErr: "overflows",
1196 }, 1196 },
1197 { 1197 {
1198 desc: "mismatch (key)", 1198 desc: "mismatch (key)",
1199 » » src: gae.DSPropertyMap{"K": {mp(false)}}, 1199 » » src: PropertyMap{"K": {mp(false)}},
1200 want: &MismatchTypes{}, 1200 want: &MismatchTypes{},
1201 loadErr: "type mismatch", 1201 loadErr: "type mismatch",
1202 }, 1202 },
1203 { 1203 {
1204 desc: "mismatch (bool)", 1204 desc: "mismatch (bool)",
1205 » » src: gae.DSPropertyMap{"B": {mp(testKey0)}}, 1205 » » src: PropertyMap{"B": {mp(testKey0)}},
1206 want: &MismatchTypes{}, 1206 want: &MismatchTypes{},
1207 loadErr: "type mismatch", 1207 loadErr: "type mismatch",
1208 }, 1208 },
1209 { 1209 {
1210 desc: "mismatch (time)", 1210 desc: "mismatch (time)",
1211 » » src: gae.DSPropertyMap{"T": {mp(gae.DSGeoPoint{})}}, 1211 » » src: PropertyMap{"T": {mp(GeoPoint{})}},
1212 want: &MismatchTypes{}, 1212 want: &MismatchTypes{},
1213 loadErr: "type mismatch", 1213 loadErr: "type mismatch",
1214 }, 1214 },
1215 { 1215 {
1216 desc: "mismatch (geopoint)", 1216 desc: "mismatch (geopoint)",
1217 » » src: gae.DSPropertyMap{"G": {mp(time.Now().UTC())}}, 1217 » » src: PropertyMap{"G": {mp(time.Now().UTC())}},
1218 want: &MismatchTypes{}, 1218 want: &MismatchTypes{},
1219 loadErr: "type mismatch", 1219 loadErr: "type mismatch",
1220 }, 1220 },
1221 { 1221 {
1222 desc: "slice of structs", 1222 desc: "slice of structs",
1223 src: &N1{ 1223 src: &N1{
1224 X0: X0{S: "one", I: 2, i: 3}, 1224 X0: X0{S: "one", I: 2, i: 3},
1225 Nonymous: []X0{ 1225 Nonymous: []X0{
1226 {S: "four", I: 5, i: 6}, 1226 {S: "four", I: 5, i: 6},
1227 {S: "seven", I: 8, i: 9}, 1227 {S: "seven", I: 8, i: 9},
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 Blue: N1{ 1318 Blue: N1{
1319 X0: X0{S: "bleu"}, 1319 X0: X0{S: "bleu"},
1320 Nonymous: []X0{ 1320 Nonymous: []X0{
1321 {S: "blu0"}, 1321 {S: "blu0"},
1322 {S: "blu1"}, 1322 {S: "blu1"},
1323 {S: "blu2"}, 1323 {S: "blu2"},
1324 {S: "blu3"}, 1324 {S: "blu3"},
1325 }, 1325 },
1326 }, 1326 },
1327 }, 1327 },
1328 » » want: gae.DSPropertyMap{ 1328 » » want: PropertyMap{
1329 "red.S": {mp("rouge")}, 1329 "red.S": {mp("rouge")},
1330 "red.I": {mp(0)}, 1330 "red.I": {mp(0)},
1331 "red.Nonymous.S": {mp("rosso0"), mp("rosso1")}, 1331 "red.Nonymous.S": {mp("rosso0"), mp("rosso1")},
1332 "red.Nonymous.I": {mp(0), mp(0)}, 1332 "red.Nonymous.I": {mp(0), mp(0)},
1333 "red.Other": {mp("")}, 1333 "red.Other": {mp("")},
1334 "green.S": {mp("vert")}, 1334 "green.S": {mp("vert")},
1335 "green.I": {mp(0)}, 1335 "green.I": {mp(0)},
1336 "green.Nonymous.S": {mp("verde0"), mp("verde1"), mp("ver de2")}, 1336 "green.Nonymous.S": {mp("verde0"), mp("verde1"), mp("ver de2")},
1337 "green.Nonymous.I": {mp(0), mp(0), mp(0)}, 1337 "green.Nonymous.I": {mp(0), mp(0), mp(0)},
1338 "green.Other": {mp("")}, 1338 "green.Other": {mp("")},
1339 "Blue.S": {mp("bleu")}, 1339 "Blue.S": {mp("bleu")},
1340 "Blue.I": {mp(0)}, 1340 "Blue.I": {mp(0)},
1341 "Blue.Nonymous.S": {mp("blu0"), mp("blu1"), mp("blu2"), mp("blu3")}, 1341 "Blue.Nonymous.S": {mp("blu0"), mp("blu1"), mp("blu2"), mp("blu3")},
1342 "Blue.Nonymous.I": {mp(0), mp(0), mp(0), mp(0)}, 1342 "Blue.Nonymous.I": {mp(0), mp(0), mp(0), mp(0)},
1343 "Blue.Other": {mp("")}, 1343 "Blue.Other": {mp("")},
1344 }, 1344 },
1345 }, 1345 },
1346 { 1346 {
1347 desc: "save props load structs with ragged fields", 1347 desc: "save props load structs with ragged fields",
1348 » » src: gae.DSPropertyMap{ 1348 » » src: PropertyMap{
1349 "red.S": {mp("rot")}, 1349 "red.S": {mp("rot")},
1350 "green.Nonymous.I": {mp(10), mp(11), mp(12), mp(13)}, 1350 "green.Nonymous.I": {mp(10), mp(11), mp(12), mp(13)},
1351 "Blue.Nonymous.S": {mp("blau0"), mp("blau1"), mp("blau2 ")}, 1351 "Blue.Nonymous.S": {mp("blau0"), mp("blau1"), mp("blau2 ")},
1352 "Blue.Nonymous.I": {mp(20), mp(21)}, 1352 "Blue.Nonymous.I": {mp(20), mp(21)},
1353 }, 1353 },
1354 want: &N2{ 1354 want: &N2{
1355 N1: N1{ 1355 N1: N1{
1356 X0: X0{S: "rot"}, 1356 X0: X0{S: "rot"},
1357 }, 1357 },
1358 Green: N1{ 1358 Green: N1{
(...skipping 18 matching lines...) Expand all
1377 src: &struct { 1377 src: &struct {
1378 A struct { 1378 A struct {
1379 X string `gae:",noindex"` 1379 X string `gae:",noindex"`
1380 Y string 1380 Y string
1381 } `gae:",noindex"` 1381 } `gae:",noindex"`
1382 B struct { 1382 B struct {
1383 X string `gae:",noindex"` 1383 X string `gae:",noindex"`
1384 Y string 1384 Y string
1385 } 1385 }
1386 }{}, 1386 }{},
1387 » » want: gae.DSPropertyMap{ 1387 » » want: PropertyMap{
1388 "B.Y": {mp("")}, 1388 "B.Y": {mp("")},
1389 "A.X": {mpNI("")}, 1389 "A.X": {mpNI("")},
1390 "A.Y": {mpNI("")}, 1390 "A.Y": {mpNI("")},
1391 "B.X": {mpNI("")}, 1391 "B.X": {mpNI("")},
1392 }, 1392 },
1393 }, 1393 },
1394 { 1394 {
1395 desc: "embedded struct with name override", 1395 desc: "embedded struct with name override",
1396 src: &struct { 1396 src: &struct {
1397 Inner1 `gae:"foo"` 1397 Inner1 `gae:"foo"`
1398 }{}, 1398 }{},
1399 » » want: gae.DSPropertyMap{ 1399 » » want: PropertyMap{
1400 "foo.W": {mp(0)}, 1400 "foo.W": {mp(0)},
1401 "foo.X": {mp("")}, 1401 "foo.X": {mp("")},
1402 }, 1402 },
1403 }, 1403 },
1404 { 1404 {
1405 desc: "slice of slices", 1405 desc: "slice of slices",
1406 src: &SliceOfSlices{}, 1406 src: &SliceOfSlices{},
1407 plsErr: `flattening nested structs leads to a slice of slices: f ield "S"`, 1407 plsErr: `flattening nested structs leads to a slice of slices: f ield "S"`,
1408 }, 1408 },
1409 { 1409 {
1410 desc: "recursive struct", 1410 desc: "recursive struct",
1411 src: &Recursive{}, 1411 src: &Recursive{},
1412 plsErr: `field "R" is recursively defined`, 1412 plsErr: `field "R" is recursively defined`,
1413 }, 1413 },
1414 { 1414 {
1415 desc: "mutually recursive struct", 1415 desc: "mutually recursive struct",
1416 src: &MutuallyRecursive0{}, 1416 src: &MutuallyRecursive0{},
1417 plsErr: `field "R" has problem: field "R" is recursively defined `, 1417 plsErr: `field "R" has problem: field "R" is recursively defined `,
1418 }, 1418 },
1419 { 1419 {
1420 desc: "non-exported struct fields", 1420 desc: "non-exported struct fields",
1421 src: &struct { 1421 src: &struct {
1422 i, J int64 1422 i, J int64
1423 }{i: 1, J: 2}, 1423 }{i: 1, J: 2},
1424 » » want: gae.DSPropertyMap{ 1424 » » want: PropertyMap{
1425 "J": {mp(2)}, 1425 "J": {mp(2)},
1426 }, 1426 },
1427 }, 1427 },
1428 { 1428 {
1429 desc: "json.RawMessage", 1429 desc: "json.RawMessage",
1430 src: &struct { 1430 src: &struct {
1431 J json.RawMessage 1431 J json.RawMessage
1432 }{ 1432 }{
1433 J: json.RawMessage("rawr"), 1433 J: json.RawMessage("rawr"),
1434 }, 1434 },
1435 » » want: gae.DSPropertyMap{ 1435 » » want: PropertyMap{
1436 "J": {mp([]byte("rawr"))}, 1436 "J": {mp([]byte("rawr"))},
1437 }, 1437 },
1438 }, 1438 },
1439 { 1439 {
1440 desc: "json.RawMessage to myBlob", 1440 desc: "json.RawMessage to myBlob",
1441 src: &struct { 1441 src: &struct {
1442 B json.RawMessage 1442 B json.RawMessage
1443 }{ 1443 }{
1444 B: json.RawMessage("rawr"), 1444 B: json.RawMessage("rawr"),
1445 }, 1445 },
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1498 1498
1499 checkErr := func(actual interface{}, expected string) bool { 1499 checkErr := func(actual interface{}, expected string) bool {
1500 So(actual, ShouldErrLike, expected) 1500 So(actual, ShouldErrLike, expected)
1501 return expected != "" 1501 return expected != ""
1502 } 1502 }
1503 1503
1504 Convey("Test round-trip", t, func() { 1504 Convey("Test round-trip", t, func() {
1505 for _, tc := range testCases { 1505 for _, tc := range testCases {
1506 tc := tc 1506 tc := tc
1507 Convey(tc.desc, func() { 1507 Convey(tc.desc, func() {
1508 » » » » pls, ok := tc.src.(gae.DSPropertyLoadSaver) 1508 » » » » pls, ok := tc.src.(PropertyLoadSaver)
1509 if !ok { 1509 if !ok {
1510 pls = GetPLS(tc.src) 1510 pls = GetPLS(tc.src)
1511 } 1511 }
1512 if checkErr(pls.Problem(), tc.plsErr) { 1512 if checkErr(pls.Problem(), tc.plsErr) {
1513 return 1513 return
1514 } 1514 }
1515 So(pls, ShouldNotBeNil) 1515 So(pls, ShouldNotBeNil)
1516 1516
1517 savedProps, err := pls.Save(false) 1517 savedProps, err := pls.Save(false)
1518 if checkErr(err, tc.saveErr) { 1518 if checkErr(err, tc.saveErr) {
1519 return 1519 return
1520 } 1520 }
1521 So(savedProps, ShouldNotBeNil) 1521 So(savedProps, ShouldNotBeNil)
1522 1522
1523 if tc.actualNoIndex { 1523 if tc.actualNoIndex {
1524 for _, props := range savedProps { 1524 for _, props := range savedProps {
1525 » » » » » » So(props[0].IndexSetting(), Shou ldEqual, gae.NoIndex) 1525 » » » » » » So(props[0].IndexSetting(), Shou ldEqual, NoIndex)
1526 return 1526 return
1527 } 1527 }
1528 So(true, ShouldBeFalse) // shouldn't get here 1528 So(true, ShouldBeFalse) // shouldn't get here
1529 } 1529 }
1530 1530
1531 var got interface{} 1531 var got interface{}
1532 » » » » if _, ok := tc.want.(gae.DSPropertyMap); ok { 1532 » » » » if _, ok := tc.want.(PropertyMap); ok {
1533 » » » » » pls = gae.DSPropertyMap{} 1533 » » » » » pls = PropertyMap{}
1534 got = pls 1534 got = pls
1535 } else { 1535 } else {
1536 got = reflect.New(reflect.TypeOf(tc.want ).Elem()).Interface() 1536 got = reflect.New(reflect.TypeOf(tc.want ).Elem()).Interface()
1537 » » » » » if pls, ok = got.(gae.DSPropertyLoadSave r); !ok { 1537 » » » » » if pls, ok = got.(PropertyLoadSaver); !o k {
1538 pls = GetPLS(got) 1538 pls = GetPLS(got)
1539 } 1539 }
1540 } 1540 }
1541 1541
1542 if checkErr(pls.Problem(), tc.plsLoadErr) { 1542 if checkErr(pls.Problem(), tc.plsLoadErr) {
1543 return 1543 return
1544 } 1544 }
1545 So(pls, ShouldNotBeNil) 1545 So(pls, ShouldNotBeNil)
1546 1546
1547 err = pls.Load(savedProps) 1547 err = pls.Load(savedProps)
(...skipping 29 matching lines...) Expand all
1577 1577
1578 val, err = pls.GetMeta("kind") 1578 val, err = pls.GetMeta("kind")
1579 So(err, ShouldBeNil) 1579 So(err, ShouldBeNil)
1580 So(val, ShouldEqual, "whatnow") 1580 So(val, ShouldEqual, "whatnow")
1581 }) 1581 })
1582 1582
1583 Convey("Getting something not there is an error", func() { 1583 Convey("Getting something not there is an error", func() {
1584 o := &N0{ID: 100} 1584 o := &N0{ID: 100}
1585 pls := GetPLS(o) 1585 pls := GetPLS(o)
1586 _, err := pls.GetMeta("wat") 1586 _, err := pls.GetMeta("wat")
1587 » » » So(err, ShouldEqual, gae.ErrDSMetaFieldUnset) 1587 » » » So(err, ShouldEqual, ErrMetaFieldUnset)
1588 }) 1588 })
1589 1589
1590 Convey("getting/setting from a bad struct is an error", func() { 1590 Convey("getting/setting from a bad struct is an error", func() {
1591 o := &Recursive{} 1591 o := &Recursive{}
1592 pls := GetPLS(o) 1592 pls := GetPLS(o)
1593 _, err := pls.GetMeta("wat") 1593 _, err := pls.GetMeta("wat")
1594 So(err, ShouldNotBeNil) 1594 So(err, ShouldNotBeNil)
1595 1595
1596 err = pls.SetMeta("wat", 100) 1596 err = pls.SetMeta("wat", 100)
1597 So(err, ShouldNotBeNil) 1597 So(err, ShouldNotBeNil)
1598 }) 1598 })
1599 1599
1600 Convey("can assign values to exported special fields", func() { 1600 Convey("can assign values to exported special fields", func() {
1601 o := &N0{ID: 100} 1601 o := &N0{ID: 100}
1602 pls := GetPLS(o) 1602 pls := GetPLS(o)
1603 err := pls.SetMeta("id", int64(200)) 1603 err := pls.SetMeta("id", int64(200))
1604 So(err, ShouldBeNil) 1604 So(err, ShouldBeNil)
1605 So(o.ID, ShouldEqual, 200) 1605 So(o.ID, ShouldEqual, 200)
1606 1606
1607 }) 1607 })
1608 1608
1609 Convey("assigning to unsassiagnable fields is a simple error", f unc() { 1609 Convey("assigning to unsassiagnable fields is a simple error", f unc() {
1610 o := &N0{ID: 100} 1610 o := &N0{ID: 100}
1611 pls := GetPLS(o) 1611 pls := GetPLS(o)
1612 err := pls.SetMeta("kind", "hi") 1612 err := pls.SetMeta("kind", "hi")
1613 So(err.Error(), ShouldContainSubstring, "unexported fiel d") 1613 So(err.Error(), ShouldContainSubstring, "unexported fiel d")
1614 1614
1615 err = pls.SetMeta("noob", "hi") 1615 err = pls.SetMeta("noob", "hi")
1616 » » » So(err, ShouldEqual, gae.ErrDSMetaFieldUnset) 1616 » » » So(err, ShouldEqual, ErrMetaFieldUnset)
1617 }) 1617 })
1618 }) 1618 })
1619 1619
1620 Convey("StructPLS Miscellaneous", t, func() { 1620 Convey("StructPLS Miscellaneous", t, func() {
1621 Convey("multiple overlapping fields is an error", func() { 1621 Convey("multiple overlapping fields is an error", func() {
1622 o := &BadSpecial{} 1622 o := &BadSpecial{}
1623 pls := GetPLS(o) 1623 pls := GetPLS(o)
1624 err := pls.Load(nil) 1624 err := pls.Load(nil)
1625 So(err, ShouldErrLike, "multiple times") 1625 So(err, ShouldErrLike, "multiple times")
1626 e := pls.Problem() 1626 e := pls.Problem()
1627 _, err = pls.Save(true) 1627 _, err = pls.Save(true)
1628 So(err, ShouldEqual, e) 1628 So(err, ShouldEqual, e)
1629 err = pls.Load(nil) 1629 err = pls.Load(nil)
1630 So(err, ShouldEqual, e) 1630 So(err, ShouldEqual, e)
1631 }) 1631 })
1632 1632
1633 Convey("empty property names are invalid", func() { 1633 Convey("empty property names are invalid", func() {
1634 So(validPropertyName(""), ShouldBeFalse) 1634 So(validPropertyName(""), ShouldBeFalse)
1635 }) 1635 })
1636 1636
1637 Convey("attempting to get a PLS for a non *struct is an error", func() { 1637 Convey("attempting to get a PLS for a non *struct is an error", func() {
1638 pls := GetPLS((*[]string)(nil)) 1638 pls := GetPLS((*[]string)(nil))
1639 » » » So(pls.Problem(), ShouldEqual, gae.ErrDSInvalidEntityTyp e) 1639 » » » So(pls.Problem(), ShouldEqual, ErrInvalidEntityType)
1640 }) 1640 })
1641 1641
1642 Convey("convertible meta default types", func() { 1642 Convey("convertible meta default types", func() {
1643 type OKDefaults struct { 1643 type OKDefaults struct {
1644 When string `gae:"$when,tomorrow"` 1644 When string `gae:"$when,tomorrow"`
1645 Amount int64 `gae:"$amt,100"` 1645 Amount int64 `gae:"$amt,100"`
1646 } 1646 }
1647 pls := GetPLS(&OKDefaults{}) 1647 pls := GetPLS(&OKDefaults{})
1648 So(pls.Problem(), ShouldBeNil) 1648 So(pls.Problem(), ShouldBeNil)
1649 1649
1650 v, err := pls.GetMeta("when") 1650 v, err := pls.GetMeta("when")
1651 So(err, ShouldBeNil) 1651 So(err, ShouldBeNil)
1652 So(v, ShouldEqual, "tomorrow") 1652 So(v, ShouldEqual, "tomorrow")
1653 1653
1654 v, err = pls.GetMeta("amt") 1654 v, err = pls.GetMeta("amt")
1655 So(err, ShouldBeNil) 1655 So(err, ShouldBeNil)
1656 So(v, ShouldEqual, int64(100)) 1656 So(v, ShouldEqual, int64(100))
1657 }) 1657 })
1658 1658
1659 Convey("meta fields can be saved", func() { 1659 Convey("meta fields can be saved", func() {
1660 type OKDefaults struct { 1660 type OKDefaults struct {
1661 When string `gae:"$when,tomorrow"` 1661 When string `gae:"$when,tomorrow"`
1662 Amount int64 `gae:"$amt,100"` 1662 Amount int64 `gae:"$amt,100"`
1663 } 1663 }
1664 pls := GetPLS(&OKDefaults{}) 1664 pls := GetPLS(&OKDefaults{})
1665 pm, err := pls.Save(true) 1665 pm, err := pls.Save(true)
1666 So(err, ShouldBeNil) 1666 So(err, ShouldBeNil)
1667 » » » So(pm, ShouldResemble, gae.DSPropertyMap{ 1667 » » » So(pm, ShouldResemble, PropertyMap{
1668 » » » » "$when": {gae.MkDSPropertyNI("tomorrow")}, 1668 » » » » "$when": {mpNI("tomorrow")},
1669 » » » » "$amt": {gae.MkDSPropertyNI(100)}, 1669 » » » » "$amt": {mpNI(100)},
1670 }) 1670 })
1671 1671
1672 v, err := pm.GetMeta("when") 1672 v, err := pm.GetMeta("when")
1673 So(err, ShouldBeNil) 1673 So(err, ShouldBeNil)
1674 So(v, ShouldEqual, "tomorrow") 1674 So(v, ShouldEqual, "tomorrow")
1675 1675
1676 v, err = pm.GetMeta("amt") 1676 v, err = pm.GetMeta("amt")
1677 So(err, ShouldBeNil) 1677 So(err, ShouldBeNil)
1678 So(v, ShouldEqual, int64(100)) 1678 So(v, ShouldEqual, int64(100))
1679 }) 1679 })
(...skipping 29 matching lines...) Expand all
1709 1709
1710 Convey("Bad default meta type", func() { 1710 Convey("Bad default meta type", func() {
1711 type BadDefault struct { 1711 type BadDefault struct {
1712 Val time.Time `gae:"$meta,tomorrow"` 1712 Val time.Time `gae:"$meta,tomorrow"`
1713 } 1713 }
1714 pls := GetPLS(&BadDefault{}) 1714 pls := GetPLS(&BadDefault{})
1715 So(pls.Problem().Error(), ShouldContainSubstring, "bad t ype") 1715 So(pls.Problem().Error(), ShouldContainSubstring, "bad t ype")
1716 }) 1716 })
1717 }) 1717 })
1718 } 1718 }
OLDNEW
« no previous file with comments | « service/rawdatastore/datastore_key_test.go ('k') | service/rawdatastore/errors.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698