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

Side by Side Diff: service/datastore/pls_test.go

Issue 2342063003: Differentiate between single- and multi- props. (Closed)
Patch Set: Slice is now always a clone. This is marginally worse performance, but a much safer UI. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « service/datastore/pls_impl.go ('k') | service/datastore/properties.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 // adapted from github.com/golang/appengine/datastore 5 // adapted from github.com/golang/appengine/datastore
6 6
7 package datastore 7 package datastore
8 8
9 import ( 9 import (
10 "bytes" 10 "bytes"
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 return GetPLS(d).Load(props) 360 return GetPLS(d).Load(props)
361 } 361 }
362 362
363 func (d *Doubler) Save(withMeta bool) (PropertyMap, error) { 363 func (d *Doubler) Save(withMeta bool) (PropertyMap, error) {
364 pls := GetPLS(d) 364 pls := GetPLS(d)
365 propMap, err := pls.Save(withMeta) 365 propMap, err := pls.Save(withMeta)
366 if err != nil { 366 if err != nil {
367 return nil, err 367 return nil, err
368 } 368 }
369 369
370 double := func(prop *Property) {
371 switch v := prop.Value().(type) {
372 case string:
373 // + means string concatenation.
374 So(prop.SetValue(v+v, prop.IndexSetting()), ShouldBeNil)
375 case int64:
376 // + means integer addition.
377 So(prop.SetValue(v+v, prop.IndexSetting()), ShouldBeNil)
378 }
379 }
380
370 // Edit that map and send it on. 381 // Edit that map and send it on.
371 » for _, props := range propMap { 382 » for k, v := range propMap {
372 » » for i := range props { 383 » » if prop, ok := v.(Property); ok {
373 » » » switch v := props[i].Value().(type) { 384 » » » double(&prop)
374 » » » case string: 385 » » » propMap[k] = prop
375 » » » » // + means string concatenation.
376 » » » » So(props[i].SetValue(v+v, props[i].IndexSetting( )), ShouldBeNil)
377 » » » case int64:
378 » » » » // + means integer addition.
379 » » » » So(props[i].SetValue(v+v, props[i].IndexSetting( )), ShouldBeNil)
380 » » » }
381 } 386 }
382 } 387 }
383 return propMap, nil 388 return propMap, nil
384 } 389 }
385 390
386 func (d *Doubler) Problem() error { return nil } 391 func (d *Doubler) Problem() error { return nil }
387 392
388 var _ PropertyLoadSaver = (*Doubler)(nil) 393 var _ PropertyLoadSaver = (*Doubler)(nil)
389 394
390 type Deriver struct { 395 type Deriver struct {
391 S, Derived, Ignored string 396 S, Derived, Ignored string
392 } 397 }
393 398
394 func (d *Deriver) Load(props PropertyMap) error { 399 func (d *Deriver) Load(props PropertyMap) error {
395 » for name, p := range props { 400 » for name := range props {
396 if name != "S" { 401 if name != "S" {
397 continue 402 continue
398 } 403 }
399 » » d.S = p[0].Value().(string) 404 » » d.S = props.Slice(name)[0].Value().(string)
400 d.Derived = "derived+" + d.S 405 d.Derived = "derived+" + d.S
401 } 406 }
402 return nil 407 return nil
403 } 408 }
404 409
405 func (d *Deriver) Save(withMeta bool) (PropertyMap, error) { 410 func (d *Deriver) Save(withMeta bool) (PropertyMap, error) {
406 » return map[string][]Property{ 411 » return map[string]PropertyData{
407 » » "S": {mp(d.S)}, 412 » » "S": mp(d.S),
408 }, nil 413 }, nil
409 } 414 }
410 415
411 func (d *Deriver) Problem() error { return nil } 416 func (d *Deriver) Problem() error { return nil }
412 417
413 var _ PropertyLoadSaver = (*Deriver)(nil) 418 var _ PropertyLoadSaver = (*Deriver)(nil)
414 419
415 type Augmenter struct { 420 type Augmenter struct {
416 S string 421 S string
417 422
418 g string `gae:"-"` 423 g string `gae:"-"`
419 } 424 }
420 425
421 func (a *Augmenter) Load(props PropertyMap) error { 426 func (a *Augmenter) Load(props PropertyMap) error {
422 » if e := props["Extra"]; len(e) > 0 { 427 » if e := props.Slice("Extra"); len(e) > 0 {
423 a.g = e[0].Value().(string) 428 a.g = e[0].Value().(string)
424 delete(props, "Extra") 429 delete(props, "Extra")
425 } 430 }
426 if err := GetPLS(a).Load(props); err != nil { 431 if err := GetPLS(a).Load(props); err != nil {
427 return err 432 return err
428 } 433 }
429 return nil 434 return nil
430 } 435 }
431 436
432 func (a *Augmenter) Save(withMeta bool) (PropertyMap, error) { 437 func (a *Augmenter) Save(withMeta bool) (PropertyMap, error) {
433 props, err := GetPLS(a).Save(withMeta) 438 props, err := GetPLS(a).Save(withMeta)
434 if err != nil { 439 if err != nil {
435 return nil, err 440 return nil, err
436 } 441 }
437 » props["Extra"] = []Property{MkProperty("ohai!")} 442 » props["Extra"] = MkProperty("ohai!")
438 return props, nil 443 return props, nil
439 } 444 }
440 445
441 func (a *Augmenter) Problem() error { return nil } 446 func (a *Augmenter) Problem() error { return nil }
442 447
443 var _ PropertyLoadSaver = (*Augmenter)(nil) 448 var _ PropertyLoadSaver = (*Augmenter)(nil)
444 449
445 type BK struct { 450 type BK struct {
446 Key blobstore.Key 451 Key blobstore.Key
447 } 452 }
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 }, 741 },
737 { 742 {
738 desc: "geopoint invalid", 743 desc: "geopoint invalid",
739 src: &G0{G: testBadGeoPt}, 744 src: &G0{G: testBadGeoPt},
740 saveErr: "invalid GeoPoint value", 745 saveErr: "invalid GeoPoint value",
741 }, 746 },
742 { 747 {
743 desc: "geopoint as props", 748 desc: "geopoint as props",
744 src: &G0{G: testGeoPt0}, 749 src: &G0{G: testGeoPt0},
745 want: PropertyMap{ 750 want: PropertyMap{
746 » » » "G": {mp(testGeoPt0)}, 751 » » » "G": mp(testGeoPt0),
747 }, 752 },
748 }, 753 },
749 { 754 {
750 desc: "geopoint slice", 755 desc: "geopoint slice",
751 src: &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}}, 756 src: &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}},
752 want: &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}}, 757 want: &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}},
753 }, 758 },
754 { 759 {
755 desc: "key", 760 desc: "key",
756 src: &K0{K: testKey1a}, 761 src: &K0{K: testKey1a},
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 }, 795 },
791 { 796 {
792 desc: "time", 797 desc: "time",
793 src: &T{T: time.Unix(1e9, 0).UTC()}, 798 src: &T{T: time.Unix(1e9, 0).UTC()},
794 want: &T{T: time.Unix(1e9, 0).UTC()}, 799 want: &T{T: time.Unix(1e9, 0).UTC()},
795 }, 800 },
796 { 801 {
797 desc: "time as props", 802 desc: "time as props",
798 src: &T{T: time.Unix(1e9, 0).UTC()}, 803 src: &T{T: time.Unix(1e9, 0).UTC()},
799 want: PropertyMap{ 804 want: PropertyMap{
800 » » » "T": {mp(time.Unix(1e9, 0).UTC())}, 805 » » » "T": mp(time.Unix(1e9, 0).UTC()),
801 }, 806 },
802 }, 807 },
803 { 808 {
804 desc: "uint32 save", 809 desc: "uint32 save",
805 src: &U0{U: 1}, 810 src: &U0{U: 1},
806 want: PropertyMap{ 811 want: PropertyMap{
807 » » » "U": {mp(1)}, 812 » » » "U": mp(1),
808 }, 813 },
809 }, 814 },
810 { 815 {
811 desc: "uint32 load", 816 desc: "uint32 load",
812 src: &U2{U: 100}, 817 src: &U2{U: 100},
813 want: &U0{U: 100}, 818 want: &U0{U: 100},
814 }, 819 },
815 { 820 {
816 desc: "uint32 load oob (neg)", 821 desc: "uint32 load oob (neg)",
817 src: &U2{U: -1}, 822 src: &U2{U: -1},
818 want: &U0{}, 823 want: &U0{},
819 loadErr: "overflow", 824 loadErr: "overflow",
820 }, 825 },
821 { 826 {
822 desc: "uint32 load oob (huge)", 827 desc: "uint32 load oob (huge)",
823 src: &U2{U: math.MaxInt64}, 828 src: &U2{U: math.MaxInt64},
824 want: &U0{}, 829 want: &U0{},
825 loadErr: "overflow", 830 loadErr: "overflow",
826 }, 831 },
827 { 832 {
828 desc: "byte save", 833 desc: "byte save",
829 src: &U1{U: 1}, 834 src: &U1{U: 1},
830 want: PropertyMap{ 835 want: PropertyMap{
831 » » » "U": {mp(1)}, 836 » » » "U": mp(1),
832 }, 837 },
833 }, 838 },
834 { 839 {
835 desc: "byte load", 840 desc: "byte load",
836 src: &U2{U: 100}, 841 src: &U2{U: 100},
837 want: &U1{U: 100}, 842 want: &U1{U: 100},
838 }, 843 },
839 { 844 {
840 desc: "byte load oob (neg)", 845 desc: "byte load oob (neg)",
841 src: &U2{U: -1}, 846 src: &U2{U: -1},
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 }, 903 },
899 { 904 {
900 desc: "use convertable slice", 905 desc: "use convertable slice",
901 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}}, 906 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}},
902 want: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}}, 907 want: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}},
903 }, 908 },
904 { 909 {
905 desc: "use convertable slice (to map)", 910 desc: "use convertable slice (to map)",
906 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}}, 911 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Con vertable{2, 4, 6}}}},
907 want: PropertyMap{ 912 want: PropertyMap{
908 » » » "Nested.wot": {mpNI("1,5,9"), mpNI("2,4,6")}, 913 » » » "Nested.wot": PropertySlice{mpNI("1,5,9"), mpNI("2,4,6") },
909 }, 914 },
910 }, 915 },
911 { 916 {
912 desc: "convertable slice (bad load)", 917 desc: "convertable slice (bad load)",
913 » » src: PropertyMap{"Nested.wot": {mpNI([]byte("ohai"))}}, 918 » » src: PropertyMap{"Nested.wot": mpNI([]byte("ohai"))},
914 want: &Impossible{[]ImpossibleInner{{}}}, 919 want: &Impossible{[]ImpossibleInner{{}}},
915 loadErr: "nope", 920 loadErr: "nope",
916 }, 921 },
917 { 922 {
918 desc: "use convertable struct", 923 desc: "use convertable struct",
919 src: &Impossible2{ 924 src: &Impossible2{
920 []ImpossibleInner2{ 925 []ImpossibleInner2{
921 {Convertable2{"nerb", nil}}, 926 {Convertable2{"nerb", nil}},
922 }, 927 },
923 }, 928 },
(...skipping 23 matching lines...) Expand all
947 { 952 {
948 desc: "convertable json KVMap (to map)", 953 desc: "convertable json KVMap (to map)",
949 src: &Impossible3{ 954 src: &Impossible3{
950 JSONKVProp{ 955 JSONKVProp{
951 "epic": "success", 956 "epic": "success",
952 "no_way!": []interface{}{true, "story"}, 957 "no_way!": []interface{}{true, "story"},
953 "what": []interface{}{"is", "really", 100}, 958 "what": []interface{}{"is", "really", 100},
954 }, 959 },
955 }, 960 },
956 want: PropertyMap{ 961 want: PropertyMap{
957 » » » "kewelmap": { 962 » » » "kewelmap": mpNI([]byte(
958 » » » » mpNI([]byte( 963 » » » » `{"epic":"success","no_way!":[true,"story"],"wha t":["is","really",100]}`)),
959 » » » » » `{"epic":"success","no_way!":[true,"stor y"],"what":["is","really",100]}`))},
960 }, 964 },
961 }, 965 },
962 { 966 {
963 desc: "convertable complex slice", 967 desc: "convertable complex slice",
964 src: &Impossible4{ 968 src: &Impossible4{
965 []Complex{complex(1, 2), complex(3, 4)}, 969 []Complex{complex(1, 2), complex(3, 4)},
966 }, 970 },
967 want: &Impossible4{ 971 want: &Impossible4{
968 []Complex{complex(1, 2), complex(3, 4)}, 972 []Complex{complex(1, 2), complex(3, 4)},
969 }, 973 },
970 }, 974 },
971 { 975 {
972 desc: "convertable complex slice (to map)", 976 desc: "convertable complex slice (to map)",
973 src: &Impossible4{ 977 src: &Impossible4{
974 []Complex{complex(1, 2), complex(3, 4)}, 978 []Complex{complex(1, 2), complex(3, 4)},
975 }, 979 },
976 want: PropertyMap{ 980 want: PropertyMap{
977 » » » "Values": { 981 » » » "Values": PropertySlice{mp(GeoPoint{Lat: 1, Lng: 2}), mp (GeoPoint{Lat: 3, Lng: 4})},
978 » » » » mp(GeoPoint{Lat: 1, Lng: 2}), mp(GeoPoint{Lat: 3 , Lng: 4})},
979 }, 982 },
980 }, 983 },
981 { 984 {
982 desc: "convertable complex slice (bad load)", 985 desc: "convertable complex slice (bad load)",
983 » » src: PropertyMap{"Values": {mp("hello")}}, 986 » » src: PropertyMap{"Values": mp("hello")},
984 want: &Impossible4{[]Complex(nil)}, 987 want: &Impossible4{[]Complex(nil)},
985 loadErr: "nope", 988 loadErr: "nope",
986 }, 989 },
987 { 990 {
988 desc: "allow concrete *Key implementors (save)", 991 desc: "allow concrete *Key implementors (save)",
989 src: &DerivedKey{testKey2a}, 992 src: &DerivedKey{testKey2a},
990 want: &IfaceKey{testKey2b}, 993 want: &IfaceKey{testKey2b},
991 }, 994 },
992 { 995 {
993 desc: "allow concrete *Key implementors (load)", 996 desc: "allow concrete *Key implementors (load)",
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1069 }, 1072 },
1070 { 1073 {
1071 desc: "short []byte", 1074 desc: "short []byte",
1072 src: &B5{B: makeUint8Slice(3)}, 1075 src: &B5{B: makeUint8Slice(3)},
1073 want: &B5{B: makeUint8Slice(3)}, 1076 want: &B5{B: makeUint8Slice(3)},
1074 }, 1077 },
1075 { 1078 {
1076 desc: "short ByteString as props", 1079 desc: "short ByteString as props",
1077 src: &B5{B: makeUint8Slice(3)}, 1080 src: &B5{B: makeUint8Slice(3)},
1078 want: PropertyMap{ 1081 want: PropertyMap{
1079 » » » "B": {mp(makeUint8Slice(3))}, 1082 » » » "B": mp(makeUint8Slice(3)),
1080 }, 1083 },
1081 }, 1084 },
1082 { 1085 {
1083 desc: "save tagged load props", 1086 desc: "save tagged load props",
1084 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6 , J: 7}, 1087 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6 , J: 7},
1085 want: PropertyMap{ 1088 want: PropertyMap{
1086 // A and B are renamed to a and b; A and C are noindex, I is ignored. 1089 // A and B are renamed to a and b; A and C are noindex, I is ignored.
1087 // Indexed properties are loaded before raw properties. Thus, the 1090 // Indexed properties are loaded before raw properties. Thus, the
1088 // result is: b, b, b, D, E, a, c. 1091 // result is: b, b, b, D, E, a, c.
1089 » » » "b1": { 1092 » » » "b1": PropertySlice{
1090 mp(21), 1093 mp(21),
1091 mp(22), 1094 mp(22),
1092 mp(23), 1095 mp(23),
1093 }, 1096 },
1094 » » » "D": {mp(4)}, 1097 » » » "D": mp(4),
1095 » » » "E": {mp(5)}, 1098 » » » "E": mp(5),
1096 » » » "a": {mpNI(1)}, 1099 » » » "a": mpNI(1),
1097 » » » "C": {mpNI(3)}, 1100 » » » "C": mpNI(3),
1098 » » » "J": {mpNI(7)}, 1101 » » » "J": mpNI(7),
1099 }, 1102 },
1100 }, 1103 },
1101 { 1104 {
1102 desc: "save tagged load tagged", 1105 desc: "save tagged load tagged",
1103 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6 , J: 7}, 1106 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6 , J: 7},
1104 want: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, J: 7 }, 1107 want: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, J: 7 },
1105 }, 1108 },
1106 { 1109 {
1107 desc: "save props load tagged", 1110 desc: "save props load tagged",
1108 src: PropertyMap{ 1111 src: PropertyMap{
1109 » » » "A": {mpNI(11)}, 1112 » » » "A": mpNI(11),
1110 » » » "a": {mpNI(12)}, 1113 » » » "a": mpNI(12),
1111 }, 1114 },
1112 want: &Tagged{A: 12}, 1115 want: &Tagged{A: 12},
1113 loadErr: `cannot load field "A"`, 1116 loadErr: `cannot load field "A"`,
1114 }, 1117 },
1115 { 1118 {
1116 desc: "invalid tagged1", 1119 desc: "invalid tagged1",
1117 src: &InvalidTagged1{I: 1}, 1120 src: &InvalidTagged1{I: 1},
1118 plsErr: `struct tag has invalid property name: "\t"`, 1121 plsErr: `struct tag has invalid property name: "\t"`,
1119 }, 1122 },
1120 { 1123 {
(...skipping 19 matching lines...) Expand all
1140 }, 1143 },
1141 { 1144 {
1142 desc: "doubler", 1145 desc: "doubler",
1143 src: &Doubler{S: "s", I: 1, B: true}, 1146 src: &Doubler{S: "s", I: 1, B: true},
1144 want: &Doubler{S: "ss", I: 2, B: true}, 1147 want: &Doubler{S: "ss", I: 2, B: true},
1145 }, 1148 },
1146 { 1149 {
1147 desc: "save struct load props", 1150 desc: "save struct load props",
1148 src: &X0{S: "s", I: 1}, 1151 src: &X0{S: "s", I: 1},
1149 want: PropertyMap{ 1152 want: PropertyMap{
1150 » » » "S": {mp("s")}, 1153 » » » "S": mp("s"),
1151 » » » "I": {mp(1)}, 1154 » » » "I": mp(1),
1152 }, 1155 },
1153 }, 1156 },
1154 { 1157 {
1155 desc: "save props load struct", 1158 desc: "save props load struct",
1156 src: PropertyMap{ 1159 src: PropertyMap{
1157 » » » "S": {mp("s")}, 1160 » » » "S": mp("s"),
1158 » » » "I": {mp(1)}, 1161 » » » "I": mp(1),
1159 }, 1162 },
1160 want: &X0{S: "s", I: 1}, 1163 want: &X0{S: "s", I: 1},
1161 }, 1164 },
1162 { 1165 {
1163 desc: "nil-value props", 1166 desc: "nil-value props",
1164 src: PropertyMap{ 1167 src: PropertyMap{
1165 » » » "I": {mp(nil)}, 1168 » » » "I": mp(nil),
1166 » » » "B": {mp(nil)}, 1169 » » » "B": mp(nil),
1167 » » » "S": {mp(nil)}, 1170 » » » "S": mp(nil),
1168 » » » "F": {mp(nil)}, 1171 » » » "F": mp(nil),
1169 » » » "K": {mp(nil)}, 1172 » » » "K": mp(nil),
1170 » » » "T": {mp(nil)}, 1173 » » » "T": mp(nil),
1171 » » » "J": { 1174 » » » "J": PropertySlice{
1172 mp(nil), 1175 mp(nil),
1173 mp(7), 1176 mp(7),
1174 mp(nil), 1177 mp(nil),
1175 }, 1178 },
1176 }, 1179 },
1177 want: &struct { 1180 want: &struct {
1178 I int64 1181 I int64
1179 B bool 1182 B bool
1180 S string 1183 S string
1181 F float64 1184 F float64
(...skipping 14 matching lines...) Expand all
1196 {30, "thirty"}, 1199 {30, "thirty"},
1197 }, 1200 },
1198 J: Inner2{ 1201 J: Inner2{
1199 Y: 3.14, 1202 Y: 3.14,
1200 }, 1203 },
1201 Inner3: Inner3{ 1204 Inner3: Inner3{
1202 Z: true, 1205 Z: true,
1203 }, 1206 },
1204 }, 1207 },
1205 want: PropertyMap{ 1208 want: PropertyMap{
1206 » » » "A": {mp(1)}, 1209 » » » "A": mp(1),
1207 » » » "I.W": { 1210 » » » "I.W": PropertySlice{
1208 mp(10), 1211 mp(10),
1209 mp(20), 1212 mp(20),
1210 mp(30), 1213 mp(30),
1211 }, 1214 },
1212 » » » "I.X": { 1215 » » » "I.X": PropertySlice{
1213 mp("ten"), 1216 mp("ten"),
1214 mp("twenty"), 1217 mp("twenty"),
1215 mp("thirty"), 1218 mp("thirty"),
1216 }, 1219 },
1217 » » » "J.Y": {mp(3.14)}, 1220 » » » "J.Y": mp(3.14),
1218 » » » "Z": {mp(true)}, 1221 » » » "Z": mp(true),
1219 }, 1222 },
1220 }, 1223 },
1221 { 1224 {
1222 desc: "save props load outer-equivalent", 1225 desc: "save props load outer-equivalent",
1223 src: PropertyMap{ 1226 src: PropertyMap{
1224 » » » "A": {mp(1)}, 1227 » » » "A": mp(1),
1225 » » » "I.W": { 1228 » » » "I.W": PropertySlice{
1226 mp(10), 1229 mp(10),
1227 mp(20), 1230 mp(20),
1228 mp(30), 1231 mp(30),
1229 }, 1232 },
1230 » » » "I.X": { 1233 » » » "I.X": PropertySlice{
1231 mp("ten"), 1234 mp("ten"),
1232 mp("twenty"), 1235 mp("twenty"),
1233 mp("thirty"), 1236 mp("thirty"),
1234 }, 1237 },
1235 » » » "J.Y": {mp(3.14)}, 1238 » » » "J.Y": mp(3.14),
1236 » » » "Z": {mp(true)}, 1239 » » » "Z": mp(true),
1237 }, 1240 },
1238 want: &OuterEquivalent{ 1241 want: &OuterEquivalent{
1239 A: 1, 1242 A: 1,
1240 IDotW: []int32{10, 20, 30}, 1243 IDotW: []int32{10, 20, 30},
1241 IDotX: []string{"ten", "twenty", "thirty"}, 1244 IDotX: []string{"ten", "twenty", "thirty"},
1242 JDotY: 3.14, 1245 JDotY: 3.14,
1243 Z: true, 1246 Z: true,
1244 }, 1247 },
1245 }, 1248 },
1246 { 1249 {
(...skipping 17 matching lines...) Expand all
1264 }, 1267 },
1265 Inner3: Inner3{ 1268 Inner3: Inner3{
1266 Z: true, 1269 Z: true,
1267 }, 1270 },
1268 }, 1271 },
1269 }, 1272 },
1270 { 1273 {
1271 desc: "dotted names save", 1274 desc: "dotted names save",
1272 src: &Dotted{A: DottedA{B: DottedB{C: 88}}}, 1275 src: &Dotted{A: DottedA{B: DottedB{C: 88}}},
1273 want: PropertyMap{ 1276 want: PropertyMap{
1274 » » » "A0.A1.A2.B3.C4.C5": {mp(88)}, 1277 » » » "A0.A1.A2.B3.C4.C5": mp(88),
1275 }, 1278 },
1276 }, 1279 },
1277 { 1280 {
1278 desc: "dotted names load", 1281 desc: "dotted names load",
1279 src: PropertyMap{ 1282 src: PropertyMap{
1280 » » » "A0.A1.A2.B3.C4.C5": {mp(99)}, 1283 » » » "A0.A1.A2.B3.C4.C5": mp(99),
1281 }, 1284 },
1282 want: &Dotted{A: DottedA{B: DottedB{C: 99}}}, 1285 want: &Dotted{A: DottedA{B: DottedB{C: 99}}},
1283 }, 1286 },
1284 { 1287 {
1285 desc: "save struct load deriver", 1288 desc: "save struct load deriver",
1286 src: &X0{S: "s", I: 1}, 1289 src: &X0{S: "s", I: 1},
1287 want: &Deriver{S: "s", Derived: "derived+s"}, 1290 want: &Deriver{S: "s", Derived: "derived+s"},
1288 }, 1291 },
1289 { 1292 {
1290 desc: "save deriver load struct", 1293 desc: "save deriver load struct",
1291 src: &Deriver{S: "s", Derived: "derived+s", Ignored: "ignored"} , 1294 src: &Deriver{S: "s", Derived: "derived+s", Ignored: "ignored"} ,
1292 want: &X0{S: "s"}, 1295 want: &X0{S: "s"},
1293 }, 1296 },
1294 { 1297 {
1295 desc: "augmenter save", 1298 desc: "augmenter save",
1296 src: &Augmenter{S: "s"}, 1299 src: &Augmenter{S: "s"},
1297 want: PropertyMap{ 1300 want: PropertyMap{
1298 » » » "S": {mp("s")}, 1301 » » » "S": mp("s"),
1299 » » » "Extra": {mp("ohai!")}, 1302 » » » "Extra": mp("ohai!"),
1300 }, 1303 },
1301 }, 1304 },
1302 { 1305 {
1303 desc: "augmenter load", 1306 desc: "augmenter load",
1304 src: PropertyMap{ 1307 src: PropertyMap{
1305 » » » "S": {mp("s")}, 1308 » » » "S": mp("s"),
1306 » » » "Extra": {mp("kthxbye!")}, 1309 » » » "Extra": mp("kthxbye!"),
1307 }, 1310 },
1308 want: &Augmenter{S: "s", g: "kthxbye!"}, 1311 want: &Augmenter{S: "s", g: "kthxbye!"},
1309 }, 1312 },
1310 // Regression: CL 25062824 broke handling of appengine.BlobKey fields. 1313 // Regression: CL 25062824 broke handling of appengine.BlobKey fields.
1311 { 1314 {
1312 desc: "appengine.BlobKey", 1315 desc: "appengine.BlobKey",
1313 src: &BK{Key: "blah"}, 1316 src: &BK{Key: "blah"},
1314 want: &BK{Key: "blah"}, 1317 want: &BK{Key: "blah"},
1315 }, 1318 },
1316 { 1319 {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1359 src: &ExoticTypes{ 1362 src: &ExoticTypes{
1360 BS: "sup", 1363 BS: "sup",
1361 }, 1364 },
1362 want: &ExoticTypes{ 1365 want: &ExoticTypes{
1363 BS: "sup", 1366 BS: "sup",
1364 }, 1367 },
1365 }, 1368 },
1366 { 1369 {
1367 desc: "exotic type projection", 1370 desc: "exotic type projection",
1368 src: PropertyMap{ 1371 src: PropertyMap{
1369 » » » "BS": {mp([]byte("I'mABlobKey"))}, 1372 » » » "BS": mp([]byte("I'mABlobKey")),
1370 }, 1373 },
1371 want: &ExoticTypes{ 1374 want: &ExoticTypes{
1372 BS: "I'mABlobKey", 1375 BS: "I'mABlobKey",
1373 }, 1376 },
1374 }, 1377 },
1375 { 1378 {
1376 desc: "underspecified types", 1379 desc: "underspecified types",
1377 src: &Underspecified{}, 1380 src: &Underspecified{},
1378 plsErr: "non-concrete interface", 1381 plsErr: "non-concrete interface",
1379 }, 1382 },
1380 { 1383 {
1381 desc: "mismatch (string)", 1384 desc: "mismatch (string)",
1382 src: PropertyMap{ 1385 src: PropertyMap{
1383 » » » "K": {mp(199)}, 1386 » » » "K": mp(199),
1384 » » » "S": {mp([]byte("cats"))}, 1387 » » » "S": mp([]byte("cats")),
1385 » » » "F": {mp("nurbs")}, 1388 » » » "F": mp("nurbs"),
1386 }, 1389 },
1387 want: &MismatchTypes{}, 1390 want: &MismatchTypes{},
1388 loadErr: "type mismatch", 1391 loadErr: "type mismatch",
1389 }, 1392 },
1390 { 1393 {
1391 desc: "mismatch (float)", 1394 desc: "mismatch (float)",
1392 » » src: PropertyMap{"F": {mp(blobstore.Key("wot"))}}, 1395 » » src: PropertyMap{"F": mp(blobstore.Key("wot"))},
1393 want: &MismatchTypes{}, 1396 want: &MismatchTypes{},
1394 loadErr: "type mismatch", 1397 loadErr: "type mismatch",
1395 }, 1398 },
1396 { 1399 {
1397 desc: "mismatch (float/overflow)", 1400 desc: "mismatch (float/overflow)",
1398 » » src: PropertyMap{"F": {mp(math.MaxFloat64)}}, 1401 » » src: PropertyMap{"F": mp(math.MaxFloat64)},
1399 want: &MismatchTypes{}, 1402 want: &MismatchTypes{},
1400 loadErr: "overflows", 1403 loadErr: "overflows",
1401 }, 1404 },
1402 { 1405 {
1403 desc: "mismatch (key)", 1406 desc: "mismatch (key)",
1404 » » src: PropertyMap{"K": {mp(false)}}, 1407 » » src: PropertyMap{"K": mp(false)},
1405 want: &MismatchTypes{}, 1408 want: &MismatchTypes{},
1406 loadErr: "type mismatch", 1409 loadErr: "type mismatch",
1407 }, 1410 },
1408 { 1411 {
1409 desc: "mismatch (bool)", 1412 desc: "mismatch (bool)",
1410 » » src: PropertyMap{"B": {mp(testKey0)}}, 1413 » » src: PropertyMap{"B": mp(testKey0)},
1411 want: &MismatchTypes{}, 1414 want: &MismatchTypes{},
1412 loadErr: "type mismatch", 1415 loadErr: "type mismatch",
1413 }, 1416 },
1414 { 1417 {
1415 desc: "mismatch (time)", 1418 desc: "mismatch (time)",
1416 » » src: PropertyMap{"T": {mp(GeoPoint{})}}, 1419 » » src: PropertyMap{"T": mp(GeoPoint{})},
1417 want: &MismatchTypes{}, 1420 want: &MismatchTypes{},
1418 loadErr: "type mismatch", 1421 loadErr: "type mismatch",
1419 }, 1422 },
1420 { 1423 {
1421 desc: "mismatch (geopoint)", 1424 desc: "mismatch (geopoint)",
1422 » » src: PropertyMap{"G": {mp(time.Now().UTC())}}, 1425 » » src: PropertyMap{"G": mp(time.Now().UTC())},
1423 want: &MismatchTypes{}, 1426 want: &MismatchTypes{},
1424 loadErr: "type mismatch", 1427 loadErr: "type mismatch",
1425 }, 1428 },
1426 { 1429 {
1427 desc: "slice of structs", 1430 desc: "slice of structs",
1428 src: &N1{ 1431 src: &N1{
1429 X0: X0{S: "one", I: 2, i: 3}, 1432 X0: X0{S: "one", I: 2, i: 3},
1430 Nonymous: []X0{ 1433 Nonymous: []X0{
1431 {S: "four", I: 5, i: 6}, 1434 {S: "four", I: 5, i: 6},
1432 {S: "seven", I: 8, i: 9}, 1435 {S: "seven", I: 8, i: 9},
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1524 X0: X0{S: "bleu"}, 1527 X0: X0{S: "bleu"},
1525 Nonymous: []X0{ 1528 Nonymous: []X0{
1526 {S: "blu0"}, 1529 {S: "blu0"},
1527 {S: "blu1"}, 1530 {S: "blu1"},
1528 {S: "blu2"}, 1531 {S: "blu2"},
1529 {S: "blu3"}, 1532 {S: "blu3"},
1530 }, 1533 },
1531 }, 1534 },
1532 }, 1535 },
1533 want: PropertyMap{ 1536 want: PropertyMap{
1534 » » » "red.S": {mp("rouge")}, 1537 » » » "red.S": mp("rouge"),
1535 » » » "red.I": {mp(0)}, 1538 » » » "red.I": mp(0),
1536 » » » "red.Nonymous.S": {mp("rosso0"), mp("rosso1")}, 1539 » » » "red.Nonymous.S": PropertySlice{mp("rosso0"), mp("ross o1")},
1537 » » » "red.Nonymous.I": {mp(0), mp(0)}, 1540 » » » "red.Nonymous.I": PropertySlice{mp(0), mp(0)},
1538 » » » "red.Other": {mp("")}, 1541 » » » "red.Other": mp(""),
1539 » » » "green.S": {mp("vert")}, 1542 » » » "green.S": mp("vert"),
1540 » » » "green.I": {mp(0)}, 1543 » » » "green.I": mp(0),
1541 » » » "green.Nonymous.S": {mp("verde0"), mp("verde1"), mp("ver de2")}, 1544 » » » "green.Nonymous.S": PropertySlice{mp("verde0"), mp("verd e1"), mp("verde2")},
1542 » » » "green.Nonymous.I": {mp(0), mp(0), mp(0)}, 1545 » » » "green.Nonymous.I": PropertySlice{mp(0), mp(0), mp(0)},
1543 » » » "green.Other": {mp("")}, 1546 » » » "green.Other": mp(""),
1544 » » » "Blue.S": {mp("bleu")}, 1547 » » » "Blue.S": mp("bleu"),
1545 » » » "Blue.I": {mp(0)}, 1548 » » » "Blue.I": mp(0),
1546 » » » "Blue.Nonymous.S": {mp("blu0"), mp("blu1"), mp("blu2"), mp("blu3")}, 1549 » » » "Blue.Nonymous.S": PropertySlice{mp("blu0"), mp("blu1") , mp("blu2"), mp("blu3")},
1547 » » » "Blue.Nonymous.I": {mp(0), mp(0), mp(0), mp(0)}, 1550 » » » "Blue.Nonymous.I": PropertySlice{mp(0), mp(0), mp(0), m p(0)},
1548 » » » "Blue.Other": {mp("")}, 1551 » » » "Blue.Other": mp(""),
1549 }, 1552 },
1550 }, 1553 },
1551 { 1554 {
1552 desc: "save props load structs with ragged fields", 1555 desc: "save props load structs with ragged fields",
1553 src: PropertyMap{ 1556 src: PropertyMap{
1554 » » » "red.S": {mp("rot")}, 1557 » » » "red.S": mp("rot"),
1555 » » » "green.Nonymous.I": {mp(10), mp(11), mp(12), mp(13)}, 1558 » » » "green.Nonymous.I": PropertySlice{mp(10), mp(11), mp(12) , mp(13)},
1556 » » » "Blue.Nonymous.S": {mp("blau0"), mp("blau1"), mp("blau2 ")}, 1559 » » » "Blue.Nonymous.S": PropertySlice{mp("blau0"), mp("blau1 "), mp("blau2")},
1557 » » » "Blue.Nonymous.I": {mp(20), mp(21)}, 1560 » » » "Blue.Nonymous.I": PropertySlice{mp(20), mp(21)},
1558 }, 1561 },
1559 want: &N2{ 1562 want: &N2{
1560 N1: N1{ 1563 N1: N1{
1561 X0: X0{S: "rot"}, 1564 X0: X0{S: "rot"},
1562 }, 1565 },
1563 Green: N1{ 1566 Green: N1{
1564 Nonymous: []X0{ 1567 Nonymous: []X0{
1565 {I: 10}, 1568 {I: 10},
1566 {I: 11}, 1569 {I: 11},
1567 {I: 12}, 1570 {I: 12},
(...skipping 15 matching lines...) Expand all
1583 A struct { 1586 A struct {
1584 X string `gae:",noindex"` 1587 X string `gae:",noindex"`
1585 Y string 1588 Y string
1586 } `gae:",noindex"` 1589 } `gae:",noindex"`
1587 B struct { 1590 B struct {
1588 X string `gae:",noindex"` 1591 X string `gae:",noindex"`
1589 Y string 1592 Y string
1590 } 1593 }
1591 }{}, 1594 }{},
1592 want: PropertyMap{ 1595 want: PropertyMap{
1593 » » » "B.Y": {mp("")}, 1596 » » » "B.Y": mp(""),
1594 » » » "A.X": {mpNI("")}, 1597 » » » "A.X": mpNI(""),
1595 » » » "A.Y": {mpNI("")}, 1598 » » » "A.Y": mpNI(""),
1596 » » » "B.X": {mpNI("")}, 1599 » » » "B.X": mpNI(""),
1597 }, 1600 },
1598 }, 1601 },
1599 { 1602 {
1600 desc: "embedded struct with name override", 1603 desc: "embedded struct with name override",
1601 src: &struct { 1604 src: &struct {
1602 Inner1 `gae:"foo"` 1605 Inner1 `gae:"foo"`
1603 }{}, 1606 }{},
1604 want: PropertyMap{ 1607 want: PropertyMap{
1605 » » » "foo.W": {mp(0)}, 1608 » » » "foo.W": mp(0),
1606 » » » "foo.X": {mp("")}, 1609 » » » "foo.X": mp(""),
1607 }, 1610 },
1608 }, 1611 },
1609 { 1612 {
1610 desc: "slice of slices", 1613 desc: "slice of slices",
1611 src: &SliceOfSlices{}, 1614 src: &SliceOfSlices{},
1612 plsErr: `flattening nested structs leads to a slice of slices: f ield "S"`, 1615 plsErr: `flattening nested structs leads to a slice of slices: f ield "S"`,
1613 }, 1616 },
1614 { 1617 {
1615 desc: "recursive struct", 1618 desc: "recursive struct",
1616 src: &Recursive{}, 1619 src: &Recursive{},
1617 plsErr: `field "R" is recursively defined`, 1620 plsErr: `field "R" is recursively defined`,
1618 }, 1621 },
1619 { 1622 {
1620 desc: "mutually recursive struct", 1623 desc: "mutually recursive struct",
1621 src: &MutuallyRecursive0{}, 1624 src: &MutuallyRecursive0{},
1622 plsErr: `field "R" has problem: field "R" is recursively defined `, 1625 plsErr: `field "R" has problem: field "R" is recursively defined `,
1623 }, 1626 },
1624 { 1627 {
1625 desc: "non-exported struct fields", 1628 desc: "non-exported struct fields",
1626 src: &struct { 1629 src: &struct {
1627 i, J int64 1630 i, J int64
1628 }{i: 1, J: 2}, 1631 }{i: 1, J: 2},
1629 want: PropertyMap{ 1632 want: PropertyMap{
1630 » » » "J": {mp(2)}, 1633 » » » "J": mp(2),
1631 }, 1634 },
1632 }, 1635 },
1633 { 1636 {
1634 desc: "json.RawMessage", 1637 desc: "json.RawMessage",
1635 src: &struct { 1638 src: &struct {
1636 J json.RawMessage 1639 J json.RawMessage
1637 }{ 1640 }{
1638 J: json.RawMessage("rawr"), 1641 J: json.RawMessage("rawr"),
1639 }, 1642 },
1640 want: PropertyMap{ 1643 want: PropertyMap{
1641 » » » "J": {mp([]byte("rawr"))}, 1644 » » » "J": mp([]byte("rawr")),
1642 }, 1645 },
1643 }, 1646 },
1644 { 1647 {
1645 desc: "json.RawMessage to myBlob", 1648 desc: "json.RawMessage to myBlob",
1646 src: &struct { 1649 src: &struct {
1647 B json.RawMessage 1650 B json.RawMessage
1648 }{ 1651 }{
1649 B: json.RawMessage("rawr"), 1652 B: json.RawMessage("rawr"),
1650 }, 1653 },
1651 want: &B2{B: myBlob("rawr")}, 1654 want: &B2{B: myBlob("rawr")},
(...skipping 26 matching lines...) Expand all
1678 return 1681 return
1679 } 1682 }
1680 } 1683 }
1681 So(pls, ShouldNotBeNil) 1684 So(pls, ShouldNotBeNil)
1682 1685
1683 savedProps, err := pls.Save(false) 1686 savedProps, err := pls.Save(false)
1684 if tc.saveErr != "" { 1687 if tc.saveErr != "" {
1685 So(err, ShouldErrLike, tc.saveErr) 1688 So(err, ShouldErrLike, tc.saveErr)
1686 return 1689 return
1687 } 1690 }
1691 So(err, ShouldBeNil)
1688 So(savedProps, ShouldNotBeNil) 1692 So(savedProps, ShouldNotBeNil)
1689 1693
1690 var got interface{} 1694 var got interface{}
1691 if _, ok := tc.want.(PropertyMap); ok { 1695 if _, ok := tc.want.(PropertyMap); ok {
1692 pls = PropertyMap{} 1696 pls = PropertyMap{}
1693 got = pls 1697 got = pls
1694 } else { 1698 } else {
1695 got = reflect.New(reflect.TypeOf(tc.want ).Elem()).Interface() 1699 got = reflect.New(reflect.TypeOf(tc.want ).Elem()).Interface()
1696 if pls, ok = got.(PropertyLoadSaver); !o k { 1700 if pls, ok = got.(PropertyLoadSaver); !o k {
1697 var err error 1701 var err error
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 So(o.ID, ShouldEqual, 20) 1796 So(o.ID, ShouldEqual, 20)
1793 1797
1794 So(mgs.SetMeta("id", math.MaxUint32), ShouldBeTrue) 1798 So(mgs.SetMeta("id", math.MaxUint32), ShouldBeTrue)
1795 So(o.ID, ShouldEqual, math.MaxUint32) 1799 So(o.ID, ShouldEqual, math.MaxUint32)
1796 }) 1800 })
1797 }) 1801 })
1798 1802
1799 Convey("StructPLS Miscellaneous", t, func() { 1803 Convey("StructPLS Miscellaneous", t, func() {
1800 Convey("a simple struct has a default $kind", func() { 1804 Convey("a simple struct has a default $kind", func() {
1801 So(GetPLS(&Simple{}).GetAllMeta(), ShouldResemble, Prope rtyMap{ 1805 So(GetPLS(&Simple{}).GetAllMeta(), ShouldResemble, Prope rtyMap{
1802 » » » » "$kind": []Property{mpNI("Simple")}, 1806 » » » » "$kind": mpNI("Simple"),
1803 }) 1807 })
1804 }) 1808 })
1805 1809
1806 Convey("multiple overlapping fields is an error", func() { 1810 Convey("multiple overlapping fields is an error", func() {
1807 o := &BadMeta{} 1811 o := &BadMeta{}
1808 So(func() { GetPLS(o) }, ShouldPanicLike, "multiple time s") 1812 So(func() { GetPLS(o) }, ShouldPanicLike, "multiple time s")
1809 }) 1813 })
1810 1814
1811 Convey("empty property names are invalid", func() { 1815 Convey("empty property names are invalid", func() {
1812 So(validPropertyName(""), ShouldBeFalse) 1816 So(validPropertyName(""), ShouldBeFalse)
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1868 1872
1869 Convey("meta fields can be saved", func() { 1873 Convey("meta fields can be saved", func() {
1870 type OKDefaults struct { 1874 type OKDefaults struct {
1871 When string `gae:"$when,tomorrow"` 1875 When string `gae:"$when,tomorrow"`
1872 Amount int64 `gae:"$amt,100"` 1876 Amount int64 `gae:"$amt,100"`
1873 } 1877 }
1874 pls := GetPLS(&OKDefaults{}) 1878 pls := GetPLS(&OKDefaults{})
1875 pm, err := pls.Save(true) 1879 pm, err := pls.Save(true)
1876 So(err, ShouldBeNil) 1880 So(err, ShouldBeNil)
1877 So(pm, ShouldResemble, PropertyMap{ 1881 So(pm, ShouldResemble, PropertyMap{
1878 » » » » "$when": {mpNI("tomorrow")}, 1882 » » » » "$when": mpNI("tomorrow"),
1879 » » » » "$amt": {mpNI(100)}, 1883 » » » » "$amt": mpNI(100),
1880 » » » » "$kind": {mpNI("OKDefaults")}, 1884 » » » » "$kind": mpNI("OKDefaults"),
1881 }) 1885 })
1882 1886
1883 v, ok := pm.GetMeta("when") 1887 v, ok := pm.GetMeta("when")
1884 So(ok, ShouldBeTrue) 1888 So(ok, ShouldBeTrue)
1885 So(v, ShouldEqual, "tomorrow") 1889 So(v, ShouldEqual, "tomorrow")
1886 1890
1887 v, ok = pm.GetMeta("amt") 1891 v, ok = pm.GetMeta("amt")
1888 So(ok, ShouldBeTrue) 1892 So(ok, ShouldBeTrue)
1889 So(v, ShouldEqual, int64(100)) 1893 So(v, ShouldEqual, int64(100))
1890 }) 1894 })
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1976 1980
1977 So(GetMetaDefault(mgs, "kind", ""), ShouldEqual, "CoolKi nd") 1981 So(GetMetaDefault(mgs, "kind", ""), ShouldEqual, "CoolKi nd")
1978 1982
1979 So(mgs.SetMeta("kind", "Something"), ShouldBeFalse) 1983 So(mgs.SetMeta("kind", "Something"), ShouldBeFalse)
1980 So(mgs.SetMeta("id", "happy|27"), ShouldBeTrue) 1984 So(mgs.SetMeta("id", "happy|27"), ShouldBeTrue)
1981 1985
1982 So(idp.parent, ShouldEqual, "happy") 1986 So(idp.parent, ShouldEqual, "happy")
1983 So(idp.id, ShouldEqual, 27) 1987 So(idp.id, ShouldEqual, 27)
1984 1988
1985 So(mgs.GetAllMeta(), ShouldResemble, PropertyMap{ 1989 So(mgs.GetAllMeta(), ShouldResemble, PropertyMap{
1986 » » » » "$id": {mpNI("happy|27")}, 1990 » » » » "$id": mpNI("happy|27"),
1987 » » » » "$kind": {mpNI("CoolKind")}, 1991 » » » » "$kind": mpNI("CoolKind"),
1988 }) 1992 })
1989 }) 1993 })
1990 1994
1991 Convey("MetaGetterSetter implementation (KindOverride)", func() { 1995 Convey("MetaGetterSetter implementation (KindOverride)", func() {
1992 ko := &KindOverride{ID: 20} 1996 ko := &KindOverride{ID: 20}
1993 mgs := getMGS(ko) 1997 mgs := getMGS(ko)
1994 So(GetMetaDefault(mgs, "kind", ""), ShouldEqual, "KindOv erride") 1998 So(GetMetaDefault(mgs, "kind", ""), ShouldEqual, "KindOv erride")
1995 1999
1996 ko.customKind = "something" 2000 ko.customKind = "something"
1997 So(GetMetaDefault(mgs, "kind", ""), ShouldEqual, "someth ing") 2001 So(GetMetaDefault(mgs, "kind", ""), ShouldEqual, "someth ing")
1998 2002
1999 So(mgs.SetMeta("kind", "Nerp"), ShouldBeTrue) 2003 So(mgs.SetMeta("kind", "Nerp"), ShouldBeTrue)
2000 So(ko.customKind, ShouldEqual, "Nerp") 2004 So(ko.customKind, ShouldEqual, "Nerp")
2001 2005
2002 So(mgs.SetMeta("kind", "KindOverride"), ShouldBeTrue) 2006 So(mgs.SetMeta("kind", "KindOverride"), ShouldBeTrue)
2003 So(ko.customKind, ShouldEqual, "") 2007 So(ko.customKind, ShouldEqual, "")
2004 2008
2005 So(mgs.GetAllMeta(), ShouldResemble, PropertyMap{ 2009 So(mgs.GetAllMeta(), ShouldResemble, PropertyMap{
2006 » » » » "$id": {mpNI(20)}, 2010 » » » » "$id": mpNI(20),
2007 » » » » "$kind": {mpNI("KindOverride")}, 2011 » » » » "$kind": mpNI("KindOverride"),
2008 }) 2012 })
2009 ko.customKind = "wut" 2013 ko.customKind = "wut"
2010 So(mgs.GetAllMeta(), ShouldResemble, PropertyMap{ 2014 So(mgs.GetAllMeta(), ShouldResemble, PropertyMap{
2011 » » » » "$id": {mpNI(20)}, 2015 » » » » "$id": mpNI(20),
2012 » » » » "$kind": {mpNI("wut")}, 2016 » » » » "$kind": mpNI("wut"),
2013 }) 2017 })
2014 2018
2015 props, err := GetPLS(ko).Save(true) 2019 props, err := GetPLS(ko).Save(true)
2016 So(err, ShouldBeNil) 2020 So(err, ShouldBeNil)
2017 So(props, ShouldResemble, PropertyMap{ 2021 So(props, ShouldResemble, PropertyMap{
2018 » » » » "$id": {mpNI(20)}, 2022 » » » » "$id": mpNI(20),
2019 » » » » "$kind": {mpNI("wut")}, 2023 » » » » "$kind": mpNI("wut"),
2020 }) 2024 })
2021 }) 2025 })
2022 2026
2023 Convey("Embeddable Metadata structs", func() { 2027 Convey("Embeddable Metadata structs", func() {
2024 ide := &IDEmbedder{EmbeddedID{"hello", 10}} 2028 ide := &IDEmbedder{EmbeddedID{"hello", 10}}
2025 pls := GetPLS(ide) 2029 pls := GetPLS(ide)
2026 val, ok := pls.GetMeta("id") 2030 val, ok := pls.GetMeta("id")
2027 So(ok, ShouldBeTrue) 2031 So(ok, ShouldBeTrue)
2028 So(val, ShouldEqual, "hello|10") 2032 So(val, ShouldEqual, "hello|10")
2029 2033
2030 So(pls.SetMeta("id", "sup|1337"), ShouldBeTrue) 2034 So(pls.SetMeta("id", "sup|1337"), ShouldBeTrue)
2031 So(ide.EmbeddedID, ShouldResemble, EmbeddedID{"sup", 133 7}) 2035 So(ide.EmbeddedID, ShouldResemble, EmbeddedID{"sup", 133 7})
2032 2036
2033 So(pls.GetAllMeta(), ShouldResemble, PropertyMap{ 2037 So(pls.GetAllMeta(), ShouldResemble, PropertyMap{
2034 » » » » "$id": {mpNI("sup|1337")}, 2038 » » » » "$id": mpNI("sup|1337"),
2035 » » » » "$kind": {mpNI("IDEmbedder")}, 2039 » » » » "$kind": mpNI("IDEmbedder"),
2036 }) 2040 })
2037 }) 2041 })
2038 }) 2042 })
2039 } 2043 }
OLDNEW
« no previous file with comments | « service/datastore/pls_impl.go ('k') | service/datastore/properties.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698