OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 // 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |