How to use getMeta method of regression Package

Best Keploy code snippet using regression.getMeta

pls_test.go

Source:pls_test.go Github

copy

Full Screen

1// Copyright 2015 The LUCI Authors.2//3// Licensed under the Apache License, Version 2.0 (the "License");4// you may not use this file except in compliance with the License.5// You may obtain a copy of the License at6//7// http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// distributed under the License is distributed on an "AS IS" BASIS,11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12// See the License for the specific language governing permissions and13// limitations under the License.14// adapted from github.com/golang/appengine/datastore15package datastore16import (17 "bytes"18 "encoding/json"19 "fmt"20 "math"21 "reflect"22 "strconv"23 "strings"24 "testing"25 "time"26 . "github.com/smartystreets/goconvey/convey"27 "go.chromium.org/gae/service/blobstore"28 . "go.chromium.org/luci/common/testing/assertions"29)30var (31 mp = MkProperty32 mpNI = MkPropertyNI33)34const testAppID = "testApp"35type (36 myBlob []byte37 myByte byte38 myString string39)40func makeMyByteSlice(n int) []myByte {41 b := make([]myByte, n)42 for i := range b {43 b[i] = myByte(i)44 }45 return b46}47func makeInt8Slice(n int) []int8 {48 b := make([]int8, n)49 for i := range b {50 b[i] = int8(i)51 }52 return b53}54func makeUint8Slice(n int) []uint8 {55 b := make([]uint8, n)56 for i := range b {57 b[i] = uint8(i)58 }59 return b60}61var (62 testKey0 = mkKey("kind", "name0")63 testKey1a = mkKey("kind", "name1")64 testKey1b = mkKey("kind", "name1")65 testKey2a = mkKey("kind", "name0", "kind", "name2")66 testKey2b = mkKey("kind", "name0", "kind", "name2")67 testGeoPt0 = GeoPoint{Lat: 1.2, Lng: 3.4}68 testGeoPt1 = GeoPoint{Lat: 5, Lng: 10}69 testBadGeoPt = GeoPoint{Lat: 1000, Lng: 34}70)71type B0 struct {72 B []byte `gae:",noindex"`73}74type B1 struct {75 B []int876}77type B2 struct {78 B myBlob79}80type B3 struct {81 B []myByte82}83type B4 struct {84 B [][]byte `gae:",noindex"`85}86type B5 struct {87 B []byte88}89type C0 struct {90 I int91 C chan int92}93type C1 struct {94 I int95 C *chan int96}97type C2 struct {98 I int99 C []chan int100}101type C3 struct {102 C string103}104type E struct{}105type G0 struct {106 G GeoPoint107}108type G1 struct {109 G []GeoPoint110}111type K0 struct {112 K *Key113}114type K1 struct {115 K []*Key116}117type N0 struct {118 X0119 ID int64 `gae:"$id"`120 _kind string `gae:"$kind,whatnow"`121 Nonymous X0122 Ignore string `gae:"-"`123 Other string124}125type N1 struct {126 X0127 Nonymous []X0128 Ignore string `gae:"-"`129 Other string130}131type N2 struct {132 N1 `gae:"red"`133 Green N1 `gae:"green"`134 Blue N1135 White N1 `gae:"-"`136}137type N3 struct {138 ID uint32 `gae:"$id,200"`139}140type O0 struct {141 I int64142}143type O1 struct {144 I int32145}146type U0 struct {147 U uint32148}149type U1 struct {150 U byte151}152type U2 struct {153 U int64154}155type T struct {156 T time.Time157}158type X0 struct {159 S string160 I int161 i int162}163type X1 struct {164 S myString165 I int32166 J int64167}168type X2 struct {169 Z string170 i int171}172type X3 struct {173 S bool174 I int175}176type Y0 struct {177 B bool178 F []float64179 G []float64180}181type Y1 struct {182 B bool183 F float64184}185type Y2 struct {186 B bool187 F []int64188}189type Y3 struct {190 B bool191 F int64192}193type Tagged struct {194 A int `gae:"a,noindex"`195 B []int `gae:"b1"`196 C int `gae:",noindex"`197 D int `gae:""`198 E int199 I int `gae:"-"`200 J int `gae:",noindex" json:"j"`201 Y0 `gae:"-"`202 Z chan int `gae:"-,"`203}204type InvalidTagged1 struct {205 I int `gae:"\t"`206}207type InvalidTagged2 struct {208 I int209 J int `gae:"I"`210}211type InvalidTagged3 struct {212 I int `gae:"a\t"`213}214type InvalidTagged4 struct {215 I int `gae:"a."`216}217type InvalidTaggedSub struct {218 I int219}220type InvalidTagged5 struct {221 I int `gae:"V.I"`222 V []InvalidTaggedSub223}224type Inner1 struct {225 W int32226 X string227}228type Inner2 struct {229 Y float64230}231type Inner3 struct {232 Z bool233}234type Outer struct {235 A int16236 I []Inner1237 J Inner2238 Inner3239}240type OuterEquivalent struct {241 A int16242 IDotW []int32 `gae:"I.W"`243 IDotX []string `gae:"I.X"`244 JDotY float64 `gae:"J.Y"`245 Z bool246}247type Dotted struct {248 A DottedA `gae:"A0.A1.A2"`249}250type DottedA struct {251 B DottedB `gae:"B3"`252}253type DottedB struct {254 C int `gae:"C4.C5"`255}256type SliceOfSlices struct {257 I int258 S []struct {259 J int260 F []float64261 }262}263type Recursive struct {264 I int265 R []Recursive266}267type MutuallyRecursive0 struct {268 I int269 R []MutuallyRecursive1270}271type MutuallyRecursive1 struct {272 I int273 R []MutuallyRecursive0274}275type ExoticTypes struct {276 BS blobstore.Key277}278type Underspecified struct {279 Iface PropertyConverter280}281type MismatchTypes struct {282 S string283 B bool284 F float32285 K *Key286 T time.Time287 G GeoPoint288 IS []int289}290type BadMeta struct {291 ID int64 `gae:"$id"`292 id string `gae:"$id"`293}294type Doubler struct {295 S string296 I int64297 B bool298}299func (d *Doubler) Load(props PropertyMap) error {300 return GetPLS(d).Load(props)301}302func (d *Doubler) Save(withMeta bool) (PropertyMap, error) {303 pls := GetPLS(d)304 propMap, err := pls.Save(withMeta)305 if err != nil {306 return nil, err307 }308 double := func(prop *Property) {309 switch v := prop.Value().(type) {310 case string:311 // + means string concatenation.312 So(prop.SetValue(v+v, prop.IndexSetting()), ShouldBeNil)313 case int64:314 // + means integer addition.315 So(prop.SetValue(v+v, prop.IndexSetting()), ShouldBeNil)316 }317 }318 // Edit that map and send it on.319 for k, v := range propMap {320 if prop, ok := v.(Property); ok {321 double(&prop)322 propMap[k] = prop323 }324 }325 return propMap, nil326}327func (d *Doubler) Problem() error { return nil }328var _ PropertyLoadSaver = (*Doubler)(nil)329type Deriver struct {330 S, Derived, Ignored string331}332func (d *Deriver) Load(props PropertyMap) error {333 for name := range props {334 if name != "S" {335 continue336 }337 d.S = props.Slice(name)[0].Value().(string)338 d.Derived = "derived+" + d.S339 }340 return nil341}342func (d *Deriver) Save(withMeta bool) (PropertyMap, error) {343 return map[string]PropertyData{344 "S": mp(d.S),345 }, nil346}347func (d *Deriver) Problem() error { return nil }348var _ PropertyLoadSaver = (*Deriver)(nil)349type Augmenter struct {350 S string351 g string `gae:"-"`352}353func (a *Augmenter) Load(props PropertyMap) error {354 if e := props.Slice("Extra"); len(e) > 0 {355 a.g = e[0].Value().(string)356 delete(props, "Extra")357 }358 if err := GetPLS(a).Load(props); err != nil {359 return err360 }361 return nil362}363func (a *Augmenter) Save(withMeta bool) (PropertyMap, error) {364 props, err := GetPLS(a).Save(withMeta)365 if err != nil {366 return nil, err367 }368 props["Extra"] = MkProperty("ohai!")369 return props, nil370}371func (a *Augmenter) Problem() error { return nil }372var _ PropertyLoadSaver = (*Augmenter)(nil)373type BK struct {374 Key blobstore.Key375}376type Convertable []int64377var _ PropertyConverter = (*Convertable)(nil)378func (c *Convertable) ToProperty() (ret Property, err error) {379 buf := make([]string, len(*c))380 for i, v := range *c {381 buf[i] = strconv.FormatInt(v, 10)382 }383 err = ret.SetValue(strings.Join(buf, ","), NoIndex)384 return385}386func (c *Convertable) FromProperty(pv Property) error {387 if sval, ok := pv.Value().(string); ok {388 for _, t := range strings.Split(sval, ",") {389 ival, err := strconv.ParseInt(t, 10, 64)390 if err != nil {391 return err392 }393 *c = append(*c, ival)394 }395 return nil396 }397 return fmt.Errorf("nope")398}399type Impossible struct {400 Nested []ImpossibleInner401}402type ImpossibleInner struct {403 Ints Convertable `gae:"wot"`404}405type Convertable2 struct {406 Data string407 Exploded []string408}409func (c *Convertable2) ToProperty() (ret Property, err error) {410 err = ret.SetValue(c.Data, ShouldIndex)411 return412}413func (c *Convertable2) FromProperty(pv Property) error {414 if sval, ok := pv.Value().(string); ok {415 c.Data = sval416 c.Exploded = []string{"turn", "down", "for", "what"}417 return nil418 }419 return fmt.Errorf("nope")420}421type Impossible2 struct {422 Nested []ImpossibleInner2423}424type ImpossibleInner2 struct {425 Thingy Convertable2 `gae:"nerb"`426}427type JSONKVProp map[string]interface{}428var _ PropertyConverter = (*JSONKVProp)(nil)429func (j *JSONKVProp) ToProperty() (ret Property, err error) {430 data, err := json.Marshal(map[string]interface{}(*j))431 if err != nil {432 return433 }434 err = ret.SetValue(data, NoIndex)435 return436}437func (j *JSONKVProp) FromProperty(pv Property) error {438 if bval, ok := pv.Value().([]byte); ok {439 dec := json.NewDecoder(bytes.NewBuffer(bval))440 dec.UseNumber()441 return dec.Decode((*map[string]interface{})(j))442 }443 return fmt.Errorf("nope")444}445type Impossible3 struct {446 KMap JSONKVProp `gae:"kewelmap"`447}448type Complex complex128449var _ PropertyConverter = (*Complex)(nil)450func (c *Complex) ToProperty() (ret Property, err error) {451 // cheat hardkore and usurp GeoPoint so datastore will index these suckers452 // (note that this won't REALLY work, since GeoPoints are limited to a very453 // limited range of values, but it's nice to pretend ;)). You'd probably454 // really end up with a packed binary representation.455 err = ret.SetValue(GeoPoint{Lat: real(*c), Lng: imag(*c)}, ShouldIndex)456 return457}458func (c *Complex) FromProperty(p Property) error {459 if gval, ok := p.Value().(GeoPoint); ok {460 *c = Complex(complex(gval.Lat, gval.Lng))461 return nil462 }463 return fmt.Errorf("nope")464}465type Impossible4 struct {466 Values []Complex467}468type DerivedKey struct {469 K *Key470}471type IfaceKey struct {472 K *Key473}474type IDParser struct {475 _kind string `gae:"$kind,CoolKind"`476 // real $id is myParentName|myID477 parent string `gae:"-"`478 id int64 `gae:"-"`479}480var _ MetaGetterSetter = (*IDParser)(nil)481func (i *IDParser) getFullID() string {482 return fmt.Sprintf("%s|%d", i.parent, i.id)483}484func (i *IDParser) GetAllMeta() PropertyMap {485 pm := GetPLS(i).GetAllMeta()486 pm.SetMeta("id", i.getFullID())487 return pm488}489func (i *IDParser) GetMeta(key string) (interface{}, bool) {490 if key == "id" {491 return i.getFullID(), true492 }493 return GetPLS(i).GetMeta(key)494}495func (i *IDParser) SetMeta(key string, value interface{}) bool {496 if key == "id" {497 // let the panics flooowwww498 vS := strings.SplitN(value.(string), "|", 2)499 i.parent = vS[0]500 var err error501 i.id, err = strconv.ParseInt(vS[1], 10, 64)502 if err != nil {503 panic(err)504 }505 return true506 }507 return GetPLS(i).SetMeta(key, value)508}509type KindOverride struct {510 ID int64 `gae:"$id"`511 customKind string `gae:"-"`512}513var _ MetaGetterSetter = (*KindOverride)(nil)514func (i *KindOverride) GetAllMeta() PropertyMap {515 pm := GetPLS(i).GetAllMeta()516 if i.customKind != "" {517 pm.SetMeta("kind", i.customKind)518 }519 return pm520}521func (i *KindOverride) GetMeta(key string) (interface{}, bool) {522 if key == "kind" && i.customKind != "" {523 return i.customKind, true524 }525 return GetPLS(i).GetMeta(key)526}527func (i *KindOverride) SetMeta(key string, value interface{}) bool {528 if key == "kind" {529 kind := value.(string)530 if kind != "KindOverride" {531 i.customKind = kind532 } else {533 i.customKind = ""534 }535 return true536 }537 return GetPLS(i).SetMeta(key, value)538}539type EmbeddedID struct {540 Thing string541 Val int542}543var _ PropertyConverter = (*EmbeddedID)(nil)544func (e *EmbeddedID) ToProperty() (ret Property, err error) {545 return mpNI(fmt.Sprintf("%s|%d", e.Thing, e.Val)), nil546}547func (e *EmbeddedID) FromProperty(val Property) error {548 if val.Type() != PTString {549 return fmt.Errorf("gotta have a string")550 }551 toks := strings.SplitN(val.Value().(string), "|", 2)552 if len(toks) != 2 {553 return fmt.Errorf("gotta have two parts")554 }555 v, err := strconv.Atoi(toks[1])556 if err != nil {557 return err558 }559 e.Thing = toks[0]560 e.Val = v561 return nil562}563type IDEmbedder struct {564 EmbeddedID `gae:"$id"`565}566type Simple struct{}567type testCase struct {568 desc string569 src interface{}570 want interface{}571 plsErr string572 saveErr string573 plsLoadErr string574 loadErr string575}576var testCases = []testCase{577 {578 desc: "chan save fails",579 src: &C0{I: -1},580 plsErr: `field "C" has invalid type: chan int`,581 },582 {583 desc: "*chan save fails",584 src: &C1{I: -1},585 plsErr: `field "C" has invalid type: *chan int`,586 },587 {588 desc: "[]chan save fails",589 src: &C2{I: -1, C: make([]chan int, 8)},590 plsErr: `field "C" has invalid type: []chan int`,591 },592 {593 desc: "chan load fails",594 src: &C3{C: "not a chan"},595 want: &C0{},596 plsLoadErr: `field "C" has invalid type: chan int`,597 },598 {599 desc: "*chan load fails",600 src: &C3{C: "not a *chan"},601 want: &C1{},602 plsLoadErr: `field "C" has invalid type: *chan int`,603 },604 {605 desc: "[]chan load fails",606 src: &C3{C: "not a []chan"},607 want: &C2{},608 plsLoadErr: `field "C" has invalid type: []chan int`,609 },610 {611 desc: "empty struct",612 src: &E{},613 want: &E{},614 },615 {616 desc: "geopoint",617 src: &G0{G: testGeoPt0},618 want: &G0{G: testGeoPt0},619 },620 {621 desc: "geopoint invalid",622 src: &G0{G: testBadGeoPt},623 saveErr: "invalid GeoPoint value",624 },625 {626 desc: "geopoint as props",627 src: &G0{G: testGeoPt0},628 want: PropertyMap{629 "G": mp(testGeoPt0),630 },631 },632 {633 desc: "geopoint slice",634 src: &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}},635 want: &G1{G: []GeoPoint{testGeoPt0, testGeoPt1}},636 },637 {638 desc: "key",639 src: &K0{K: testKey1a},640 want: &K0{K: testKey1b},641 },642 {643 desc: "key with parent",644 src: &K0{K: testKey2a},645 want: &K0{K: testKey2b},646 },647 {648 desc: "nil key",649 src: &K0{},650 want: &K0{},651 },652 {653 desc: "all nil keys in slice",654 src: &K1{[]*Key{nil, nil}},655 want: &K1{[]*Key{nil, nil}},656 },657 {658 desc: "some nil keys in slice",659 src: &K1{[]*Key{testKey1a, nil, testKey2a}},660 want: &K1{[]*Key{testKey1b, nil, testKey2b}},661 },662 {663 desc: "overflow",664 src: &O0{I: 1 << 48},665 want: &O1{},666 loadErr: "overflow",667 },668 {669 desc: "underflow",670 src: &O0{I: math.MaxInt64},671 want: &O1{},672 loadErr: "overflow",673 },674 {675 desc: "time",676 src: &T{T: time.Unix(1e9, 0).UTC()},677 want: &T{T: time.Unix(1e9, 0).UTC()},678 },679 {680 desc: "time as props",681 src: &T{T: time.Unix(1e9, 0).UTC()},682 want: PropertyMap{683 "T": mp(time.Unix(1e9, 0).UTC()),684 },685 },686 {687 desc: "uint32 save",688 src: &U0{U: 1},689 want: PropertyMap{690 "U": mp(1),691 },692 },693 {694 desc: "uint32 load",695 src: &U2{U: 100},696 want: &U0{U: 100},697 },698 {699 desc: "uint32 load oob (neg)",700 src: &U2{U: -1},701 want: &U0{},702 loadErr: "overflow",703 },704 {705 desc: "uint32 load oob (huge)",706 src: &U2{U: math.MaxInt64},707 want: &U0{},708 loadErr: "overflow",709 },710 {711 desc: "byte save",712 src: &U1{U: 1},713 want: PropertyMap{714 "U": mp(1),715 },716 },717 {718 desc: "byte load",719 src: &U2{U: 100},720 want: &U1{U: 100},721 },722 {723 desc: "byte load oob (neg)",724 src: &U2{U: -1},725 want: &U1{},726 loadErr: "overflow",727 },728 {729 desc: "byte load oob (huge)",730 src: &U2{U: math.MaxInt64},731 want: &U1{},732 loadErr: "overflow",733 },734 {735 desc: "zero",736 src: &X0{},737 want: &X0{},738 },739 {740 desc: "basic",741 src: &X0{S: "one", I: 2, i: 3},742 want: &X0{S: "one", I: 2},743 },744 {745 desc: "save string/int load myString/int32",746 src: &X0{S: "one", I: 2, i: 3},747 want: &X1{S: "one", I: 2},748 },749 {750 desc: "missing fields",751 src: &X0{S: "one", I: 2, i: 3},752 want: &X2{},753 loadErr: "no such struct field",754 },755 {756 desc: "save string load bool",757 src: &X0{S: "one", I: 2, i: 3},758 want: &X3{I: 2},759 loadErr: "type mismatch",760 },761 {762 desc: "basic slice",763 src: &Y0{B: true, F: []float64{7, 8, 9}},764 want: &Y0{B: true, F: []float64{7, 8, 9}},765 },766 {767 desc: "save []float64 load float64",768 src: &Y0{B: true, F: []float64{7, 8, 9}},769 want: &Y1{B: true},770 loadErr: "requires a slice",771 },772 {773 desc: "save single []int64 load int64",774 src: &Y2{B: true, F: []int64{7}},775 want: &Y3{B: true, F: 7},776 },777 {778 desc: "save int64 load single []int64",779 src: &Y3{B: true, F: 7},780 want: &Y2{B: true, F: []int64{7}},781 },782 {783 desc: "use convertable slice",784 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Convertable{2, 4, 6}}}},785 want: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Convertable{2, 4, 6}}}},786 },787 {788 desc: "use convertable slice (to map)",789 src: &Impossible{[]ImpossibleInner{{Convertable{1, 5, 9}}, {Convertable{2, 4, 6}}}},790 want: PropertyMap{791 "Nested.wot": PropertySlice{mpNI("1,5,9"), mpNI("2,4,6")},792 },793 },794 {795 desc: "convertable slice (bad load)",796 src: PropertyMap{"Nested.wot": mpNI([]byte("ohai"))},797 want: &Impossible{[]ImpossibleInner{{}}},798 loadErr: "nope",799 },800 {801 desc: "use convertable struct",802 src: &Impossible2{803 []ImpossibleInner2{804 {Convertable2{"nerb", nil}},805 },806 },807 want: &Impossible2{808 []ImpossibleInner2{809 {Convertable2{"nerb", []string{"turn", "down", "for", "what"}}},810 },811 },812 },813 {814 desc: "convertable json KVMap",815 src: &Impossible3{816 JSONKVProp{817 "epic": "success",818 "no_way!": []interface{}{true, "story"},819 "what": []interface{}{"is", "really", 100},820 },821 },822 want: &Impossible3{823 JSONKVProp{824 "epic": "success",825 "no_way!": []interface{}{true, "story"},826 "what": []interface{}{"is", "really", json.Number("100")},827 },828 },829 },830 {831 desc: "convertable json KVMap (to map)",832 src: &Impossible3{833 JSONKVProp{834 "epic": "success",835 "no_way!": []interface{}{true, "story"},836 "what": []interface{}{"is", "really", 100},837 },838 },839 want: PropertyMap{840 "kewelmap": mpNI([]byte(841 `{"epic":"success","no_way!":[true,"story"],"what":["is","really",100]}`)),842 },843 },844 {845 desc: "convertable complex slice",846 src: &Impossible4{847 []Complex{complex(1, 2), complex(3, 4)},848 },849 want: &Impossible4{850 []Complex{complex(1, 2), complex(3, 4)},851 },852 },853 {854 desc: "convertable complex slice (to map)",855 src: &Impossible4{856 []Complex{complex(1, 2), complex(3, 4)},857 },858 want: PropertyMap{859 "Values": PropertySlice{mp(GeoPoint{Lat: 1, Lng: 2}), mp(GeoPoint{Lat: 3, Lng: 4})},860 },861 },862 {863 desc: "convertable complex slice (bad load)",864 src: PropertyMap{"Values": mp("hello")},865 want: &Impossible4{[]Complex(nil)},866 loadErr: "nope",867 },868 {869 desc: "allow concrete *Key implementors (save)",870 src: &DerivedKey{testKey2a},871 want: &IfaceKey{testKey2b},872 },873 {874 desc: "allow concrete *Key implementors (load)",875 src: &IfaceKey{testKey2b},876 want: &DerivedKey{testKey2a},877 },878 {879 desc: "save []float64 load []int64",880 src: &Y0{B: true, F: []float64{7, 8, 9}},881 want: &Y2{B: true},882 loadErr: "type mismatch",883 },884 {885 desc: "single slice is too long",886 src: &Y0{F: make([]float64, maxIndexedProperties+1)},887 want: &Y0{},888 saveErr: "gae: too many indexed properties",889 },890 {891 desc: "two slices are too long",892 src: &Y0{F: make([]float64, maxIndexedProperties), G: make([]float64, maxIndexedProperties)},893 want: &Y0{},894 saveErr: "gae: too many indexed properties",895 },896 {897 desc: "one slice and one scalar are too long",898 src: &Y0{F: make([]float64, maxIndexedProperties), B: true},899 want: &Y0{},900 saveErr: "gae: too many indexed properties",901 },902 {903 desc: "long blob",904 src: &B0{B: makeUint8Slice(maxIndexedProperties + 1)},905 want: &B0{B: makeUint8Slice(maxIndexedProperties + 1)},906 },907 {908 desc: "long []int8 is too long",909 src: &B1{B: makeInt8Slice(maxIndexedProperties + 1)},910 want: &B1{},911 saveErr: "gae: too many indexed properties",912 },913 {914 desc: "short []int8",915 src: &B1{B: makeInt8Slice(3)},916 want: &B1{B: makeInt8Slice(3)},917 },918 {919 desc: "long myBlob",920 src: &B2{B: makeUint8Slice(maxIndexedProperties + 1)},921 want: &B2{B: makeUint8Slice(maxIndexedProperties + 1)},922 },923 {924 desc: "short myBlob",925 src: &B2{B: makeUint8Slice(3)},926 want: &B2{B: makeUint8Slice(3)},927 },928 {929 desc: "long []myByte",930 src: &B3{B: makeMyByteSlice(maxIndexedProperties + 1)},931 want: &B3{B: makeMyByteSlice(maxIndexedProperties + 1)},932 },933 {934 desc: "short []myByte",935 src: &B3{B: makeMyByteSlice(3)},936 want: &B3{B: makeMyByteSlice(3)},937 },938 {939 desc: "slice of blobs",940 src: &B4{B: [][]byte{941 makeUint8Slice(3),942 makeUint8Slice(4),943 makeUint8Slice(5),944 }},945 want: &B4{B: [][]byte{946 makeUint8Slice(3),947 makeUint8Slice(4),948 makeUint8Slice(5),949 }},950 },951 {952 desc: "short []byte",953 src: &B5{B: makeUint8Slice(3)},954 want: &B5{B: makeUint8Slice(3)},955 },956 {957 desc: "short ByteString as props",958 src: &B5{B: makeUint8Slice(3)},959 want: PropertyMap{960 "B": mp(makeUint8Slice(3)),961 },962 },963 {964 desc: "save tagged load props",965 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6, J: 7},966 want: PropertyMap{967 // A and B are renamed to a and b; A and C are noindex, I is ignored.968 // Indexed properties are loaded before raw properties. Thus, the969 // result is: b, b, b, D, E, a, c.970 "b1": PropertySlice{971 mp(21),972 mp(22),973 mp(23),974 },975 "D": mp(4),976 "E": mp(5),977 "a": mpNI(1),978 "C": mpNI(3),979 "J": mpNI(7),980 },981 },982 {983 desc: "save tagged load tagged",984 src: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, I: 6, J: 7},985 want: &Tagged{A: 1, B: []int{21, 22, 23}, C: 3, D: 4, E: 5, J: 7},986 },987 {988 desc: "save props load tagged",989 src: PropertyMap{990 "A": mpNI(11),991 "a": mpNI(12),992 },993 want: &Tagged{A: 12},994 loadErr: `cannot load field "A"`,995 },996 {997 desc: "invalid tagged1",998 src: &InvalidTagged1{I: 1},999 plsErr: `struct tag has invalid property name: "\t"`,1000 },1001 {1002 desc: "invalid tagged2",1003 src: &InvalidTagged2{I: 1, J: 2},1004 want: &InvalidTagged2{},1005 plsErr: `struct tag has repeated property name: "I"`,1006 },1007 {1008 desc: "invalid tagged3",1009 src: &InvalidTagged3{I: 1},1010 plsErr: `struct tag has invalid property name: "a\t"`,1011 },1012 {1013 desc: "invalid tagged4",1014 src: &InvalidTagged4{I: 1},1015 plsErr: `struct tag has invalid property name: "a."`,1016 },1017 {1018 desc: "invalid tagged5",1019 src: &InvalidTagged5{I: 19, V: []InvalidTaggedSub{{1}}},1020 plsErr: `struct tag has repeated property name: "V.I"`,1021 },1022 {1023 desc: "doubler",1024 src: &Doubler{S: "s", I: 1, B: true},1025 want: &Doubler{S: "ss", I: 2, B: true},1026 },1027 {1028 desc: "save struct load props",1029 src: &X0{S: "s", I: 1},1030 want: PropertyMap{1031 "S": mp("s"),1032 "I": mp(1),1033 },1034 },1035 {1036 desc: "save props load struct",1037 src: PropertyMap{1038 "S": mp("s"),1039 "I": mp(1),1040 },1041 want: &X0{S: "s", I: 1},1042 },1043 {1044 desc: "nil-value props",1045 src: PropertyMap{1046 "I": mp(nil),1047 "B": mp(nil),1048 "S": mp(nil),1049 "F": mp(nil),1050 "K": mp(nil),1051 "T": mp(nil),1052 "J": PropertySlice{1053 mp(nil),1054 mp(7),1055 mp(nil),1056 },1057 },1058 want: &struct {1059 I int641060 B bool1061 S string1062 F float641063 K *Key1064 T time.Time1065 J []int641066 }{1067 J: []int64{0, 7, 0},1068 },1069 },1070 {1071 desc: "save outer load props",1072 src: &Outer{1073 A: 1,1074 I: []Inner1{1075 {10, "ten"},1076 {20, "twenty"},1077 {30, "thirty"},1078 },1079 J: Inner2{1080 Y: 3.14,1081 },1082 Inner3: Inner3{1083 Z: true,1084 },1085 },1086 want: PropertyMap{1087 "A": mp(1),1088 "I.W": PropertySlice{1089 mp(10),1090 mp(20),1091 mp(30),1092 },1093 "I.X": PropertySlice{1094 mp("ten"),1095 mp("twenty"),1096 mp("thirty"),1097 },1098 "J.Y": mp(3.14),1099 "Z": mp(true),1100 },1101 },1102 {1103 desc: "save props load outer-equivalent",1104 src: PropertyMap{1105 "A": mp(1),1106 "I.W": PropertySlice{1107 mp(10),1108 mp(20),1109 mp(30),1110 },1111 "I.X": PropertySlice{1112 mp("ten"),1113 mp("twenty"),1114 mp("thirty"),1115 },1116 "J.Y": mp(3.14),1117 "Z": mp(true),1118 },1119 want: &OuterEquivalent{1120 A: 1,1121 IDotW: []int32{10, 20, 30},1122 IDotX: []string{"ten", "twenty", "thirty"},1123 JDotY: 3.14,1124 Z: true,1125 },1126 },1127 {1128 desc: "save outer-equivalent load outer",1129 src: &OuterEquivalent{1130 A: 1,1131 IDotW: []int32{10, 20, 30},1132 IDotX: []string{"ten", "twenty", "thirty"},1133 JDotY: 3.14,1134 Z: true,1135 },1136 want: &Outer{1137 A: 1,1138 I: []Inner1{1139 {10, "ten"},1140 {20, "twenty"},1141 {30, "thirty"},1142 },1143 J: Inner2{1144 Y: 3.14,1145 },1146 Inner3: Inner3{1147 Z: true,1148 },1149 },1150 },1151 {1152 desc: "dotted names save",1153 src: &Dotted{A: DottedA{B: DottedB{C: 88}}},1154 want: PropertyMap{1155 "A0.A1.A2.B3.C4.C5": mp(88),1156 },1157 },1158 {1159 desc: "dotted names load",1160 src: PropertyMap{1161 "A0.A1.A2.B3.C4.C5": mp(99),1162 },1163 want: &Dotted{A: DottedA{B: DottedB{C: 99}}},1164 },1165 {1166 desc: "save struct load deriver",1167 src: &X0{S: "s", I: 1},1168 want: &Deriver{S: "s", Derived: "derived+s"},1169 },1170 {1171 desc: "save deriver load struct",1172 src: &Deriver{S: "s", Derived: "derived+s", Ignored: "ignored"},1173 want: &X0{S: "s"},1174 },1175 {1176 desc: "augmenter save",1177 src: &Augmenter{S: "s"},1178 want: PropertyMap{1179 "S": mp("s"),1180 "Extra": mp("ohai!"),1181 },1182 },1183 {1184 desc: "augmenter load",1185 src: PropertyMap{1186 "S": mp("s"),1187 "Extra": mp("kthxbye!"),1188 },1189 want: &Augmenter{S: "s", g: "kthxbye!"},1190 },1191 // Regression: CL 25062824 broke handling of appengine.BlobKey fields.1192 {1193 desc: "appengine.BlobKey",1194 src: &BK{Key: "blah"},1195 want: &BK{Key: "blah"},1196 },1197 {1198 desc: "zero time.Time",1199 src: &T{T: time.Time{}},1200 want: &T{T: time.Time{}},1201 },1202 {1203 desc: "time.Time near Unix zero time",1204 src: &T{T: time.Unix(0, 4e3).UTC()},1205 want: &T{T: time.Unix(0, 4e3).UTC()},1206 },1207 {1208 desc: "time.Time, far in the future",1209 src: &T{T: time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC)},1210 want: &T{T: time.Date(99999, 1, 1, 0, 0, 0, 0, time.UTC)},1211 },1212 {1213 desc: "time.Time, very far in the past",1214 src: &T{T: time.Date(-300000, 1, 1, 0, 0, 0, 0, time.UTC)},1215 want: &T{},1216 saveErr: "time value out of range",1217 },1218 {1219 desc: "time.Time, very far in the future",1220 src: &T{T: time.Date(294248, 1, 1, 0, 0, 0, 0, time.UTC)},1221 want: &T{},1222 saveErr: "time value out of range",1223 },1224 {1225 desc: "structs",1226 src: &N0{1227 X0: X0{S: "one", I: 2, i: 3},1228 Nonymous: X0{S: "four", I: 5, i: 6},1229 Ignore: "ignore",1230 Other: "other",1231 },1232 want: &N0{1233 X0: X0{S: "one", I: 2},1234 Nonymous: X0{S: "four", I: 5},1235 Other: "other",1236 },1237 },1238 {1239 desc: "exotic types",1240 src: &ExoticTypes{1241 BS: "sup",1242 },1243 want: &ExoticTypes{1244 BS: "sup",1245 },1246 },1247 {1248 desc: "exotic type projection",1249 src: PropertyMap{1250 "BS": mp([]byte("I'mABlobKey")),1251 },1252 want: &ExoticTypes{1253 BS: "I'mABlobKey",1254 },1255 },1256 {1257 desc: "underspecified types",1258 src: &Underspecified{},1259 plsErr: "non-concrete interface",1260 },1261 {1262 desc: "mismatch (string)",1263 src: PropertyMap{1264 "K": mp(199),1265 "S": mp([]byte("cats")),1266 "F": mp("nurbs"),1267 },1268 want: &MismatchTypes{},1269 loadErr: "type mismatch",1270 },1271 {1272 desc: "mismatch (float)",1273 src: PropertyMap{"F": mp(blobstore.Key("wot"))},1274 want: &MismatchTypes{},1275 loadErr: "type mismatch",1276 },1277 {1278 desc: "mismatch (float/overflow)",1279 src: PropertyMap{"F": mp(math.MaxFloat64)},1280 want: &MismatchTypes{},1281 loadErr: "overflows",1282 },1283 {1284 desc: "mismatch (key)",1285 src: PropertyMap{"K": mp(false)},1286 want: &MismatchTypes{},1287 loadErr: "type mismatch",1288 },1289 {1290 desc: "mismatch (bool)",1291 src: PropertyMap{"B": mp(testKey0)},1292 want: &MismatchTypes{},1293 loadErr: "type mismatch",1294 },1295 {1296 desc: "mismatch (time)",1297 src: PropertyMap{"T": mp(GeoPoint{})},1298 want: &MismatchTypes{},1299 loadErr: "type mismatch",1300 },1301 {1302 desc: "mismatch (geopoint)",1303 src: PropertyMap{"G": mp(time.Now().UTC())},1304 want: &MismatchTypes{},1305 loadErr: "type mismatch",1306 },1307 {1308 desc: "slice of structs",1309 src: &N1{1310 X0: X0{S: "one", I: 2, i: 3},1311 Nonymous: []X0{1312 {S: "four", I: 5, i: 6},1313 {S: "seven", I: 8, i: 9},1314 {S: "ten", I: 11, i: 12},1315 {S: "thirteen", I: 14, i: 15},1316 },1317 Ignore: "ignore",1318 Other: "other",1319 },1320 want: &N1{1321 X0: X0{S: "one", I: 2},1322 Nonymous: []X0{1323 {S: "four", I: 5},1324 {S: "seven", I: 8},1325 {S: "ten", I: 11},1326 {S: "thirteen", I: 14},1327 },1328 Other: "other",1329 },1330 },1331 {1332 desc: "structs with slices of structs",1333 src: &N2{1334 N1: N1{1335 X0: X0{S: "rouge"},1336 Nonymous: []X0{1337 {S: "rosso0"},1338 {S: "rosso1"},1339 },1340 },1341 Green: N1{1342 X0: X0{S: "vert"},1343 Nonymous: []X0{1344 {S: "verde0"},1345 {S: "verde1"},1346 {S: "verde2"},1347 },1348 },1349 Blue: N1{1350 X0: X0{S: "bleu"},1351 Nonymous: []X0{1352 {S: "blu0"},1353 {S: "blu1"},1354 {S: "blu2"},1355 {S: "blu3"},1356 },1357 },1358 },1359 want: &N2{1360 N1: N1{1361 X0: X0{S: "rouge"},1362 Nonymous: []X0{1363 {S: "rosso0"},1364 {S: "rosso1"},1365 },1366 },1367 Green: N1{1368 X0: X0{S: "vert"},1369 Nonymous: []X0{1370 {S: "verde0"},1371 {S: "verde1"},1372 {S: "verde2"},1373 },1374 },1375 Blue: N1{1376 X0: X0{S: "bleu"},1377 Nonymous: []X0{1378 {S: "blu0"},1379 {S: "blu1"},1380 {S: "blu2"},1381 {S: "blu3"},1382 },1383 },1384 },1385 },1386 {1387 desc: "save structs load props",1388 src: &N2{1389 N1: N1{1390 X0: X0{S: "rouge"},1391 Nonymous: []X0{1392 {S: "rosso0"},1393 {S: "rosso1"},1394 },1395 },1396 Green: N1{1397 X0: X0{S: "vert"},1398 Nonymous: []X0{1399 {S: "verde0"},1400 {S: "verde1"},1401 {S: "verde2"},1402 },1403 },1404 Blue: N1{1405 X0: X0{S: "bleu"},1406 Nonymous: []X0{1407 {S: "blu0"},1408 {S: "blu1"},1409 {S: "blu2"},1410 {S: "blu3"},1411 },1412 },1413 },1414 want: PropertyMap{1415 "red.S": mp("rouge"),1416 "red.I": mp(0),1417 "red.Nonymous.S": PropertySlice{mp("rosso0"), mp("rosso1")},1418 "red.Nonymous.I": PropertySlice{mp(0), mp(0)},1419 "red.Other": mp(""),1420 "green.S": mp("vert"),1421 "green.I": mp(0),1422 "green.Nonymous.S": PropertySlice{mp("verde0"), mp("verde1"), mp("verde2")},1423 "green.Nonymous.I": PropertySlice{mp(0), mp(0), mp(0)},1424 "green.Other": mp(""),1425 "Blue.S": mp("bleu"),1426 "Blue.I": mp(0),1427 "Blue.Nonymous.S": PropertySlice{mp("blu0"), mp("blu1"), mp("blu2"), mp("blu3")},1428 "Blue.Nonymous.I": PropertySlice{mp(0), mp(0), mp(0), mp(0)},1429 "Blue.Other": mp(""),1430 },1431 },1432 {1433 desc: "save props load structs with ragged fields",1434 src: PropertyMap{1435 "red.S": mp("rot"),1436 "green.Nonymous.I": PropertySlice{mp(10), mp(11), mp(12), mp(13)},1437 "Blue.Nonymous.S": PropertySlice{mp("blau0"), mp("blau1"), mp("blau2")},1438 "Blue.Nonymous.I": PropertySlice{mp(20), mp(21)},1439 },1440 want: &N2{1441 N1: N1{1442 X0: X0{S: "rot"},1443 },1444 Green: N1{1445 Nonymous: []X0{1446 {I: 10},1447 {I: 11},1448 {I: 12},1449 {I: 13},1450 },1451 },1452 Blue: N1{1453 Nonymous: []X0{1454 {S: "blau0", I: 20},1455 {S: "blau1", I: 21},1456 {S: "blau2"},1457 },1458 },1459 },1460 },1461 {1462 desc: "save structs with noindex tags",1463 src: &struct {1464 A struct {1465 X string `gae:",noindex"`1466 Y string1467 } `gae:",noindex"`1468 B struct {1469 X string `gae:",noindex"`1470 Y string1471 }1472 }{},1473 want: PropertyMap{1474 "B.Y": mp(""),1475 "A.X": mpNI(""),1476 "A.Y": mpNI(""),1477 "B.X": mpNI(""),1478 },1479 },1480 {1481 desc: "embedded struct with name override",1482 src: &struct {1483 Inner1 `gae:"foo"`1484 }{},1485 want: PropertyMap{1486 "foo.W": mp(0),1487 "foo.X": mp(""),1488 },1489 },1490 {1491 desc: "slice of slices",1492 src: &SliceOfSlices{},1493 plsErr: `flattening nested structs leads to a slice of slices: field "S"`,1494 },1495 {1496 desc: "recursive struct",1497 src: &Recursive{},1498 plsErr: `field "R" is recursively defined`,1499 },1500 {1501 desc: "mutually recursive struct",1502 src: &MutuallyRecursive0{},1503 plsErr: `field "R" has problem: field "R" is recursively defined`,1504 },1505 {1506 desc: "non-exported struct fields",1507 src: &struct {1508 i, J int641509 }{i: 1, J: 2},1510 want: PropertyMap{1511 "J": mp(2),1512 },1513 },1514 {1515 desc: "json.RawMessage",1516 src: &struct {1517 J json.RawMessage1518 }{1519 J: json.RawMessage("rawr"),1520 },1521 want: PropertyMap{1522 "J": mp([]byte("rawr")),1523 },1524 },1525 {1526 desc: "json.RawMessage to myBlob",1527 src: &struct {1528 B json.RawMessage1529 }{1530 B: json.RawMessage("rawr"),1531 },1532 want: &B2{B: myBlob("rawr")},1533 },1534}1535func TestRoundTrip(t *testing.T) {1536 t.Parallel()1537 getPLSErr := func(obj interface{}) (pls PropertyLoadSaver, err error) {1538 defer func() {1539 if v := recover(); v != nil {1540 err = v.(error)1541 }1542 }()1543 pls = GetPLS(obj)1544 return1545 }1546 Convey("Test round-trip", t, func() {1547 for _, tc := range testCases {1548 tc := tc1549 Convey(tc.desc, func() {1550 pls, ok := tc.src.(PropertyLoadSaver)1551 if !ok {1552 var err error1553 pls, err = getPLSErr(tc.src)1554 if tc.plsErr != "" {1555 So(err, ShouldErrLike, tc.plsErr)1556 return1557 }1558 }1559 So(pls, ShouldNotBeNil)1560 savedProps, err := pls.Save(false)1561 if tc.saveErr != "" {1562 So(err, ShouldErrLike, tc.saveErr)1563 return1564 }1565 So(err, ShouldBeNil)1566 So(savedProps, ShouldNotBeNil)1567 var got interface{}1568 if _, ok := tc.want.(PropertyMap); ok {1569 pls = PropertyMap{}1570 got = pls1571 } else {1572 got = reflect.New(reflect.TypeOf(tc.want).Elem()).Interface()1573 if pls, ok = got.(PropertyLoadSaver); !ok {1574 var err error1575 pls, err = getPLSErr(got)1576 if tc.plsLoadErr != "" {1577 So(err, ShouldErrLike, tc.plsLoadErr)1578 return1579 }1580 }1581 }1582 So(pls, ShouldNotBeNil)1583 err = pls.Load(savedProps)1584 if tc.loadErr != "" {1585 So(err, ShouldErrLike, tc.loadErr)1586 return1587 }1588 if tc.want == nil {1589 return1590 }1591 if gotT, ok := got.(*T); ok {1592 // Round tripping a time.Time can result in a different time.Location: Local instead of UTC.1593 // We therefore test equality explicitly, instead of relying on reflect.DeepEqual.1594 So(gotT.T.Equal(tc.want.(*T).T), ShouldBeTrue)1595 } else {1596 So(got, ShouldResemble, tc.want)1597 }1598 })1599 }1600 })1601}1602func TestMeta(t *testing.T) {1603 t.Parallel()1604 Convey("Test meta fields", t, func() {1605 Convey("Can retrieve from struct", func() {1606 o := &N0{ID: 100}1607 mgs := getMGS(o)1608 val, ok := mgs.GetMeta("id")1609 So(ok, ShouldBeTrue)1610 So(val, ShouldEqual, 100)1611 val, ok = mgs.GetMeta("kind")1612 So(ok, ShouldBeTrue)1613 So(val, ShouldEqual, "whatnow")1614 So(GetMetaDefault(mgs, "kind", "zappo"), ShouldEqual, "whatnow")1615 So(GetMetaDefault(mgs, "id", "stringID"), ShouldEqual, "stringID")1616 So(GetMetaDefault(mgs, "id", 6), ShouldEqual, 100)1617 })1618 Convey("Getting something not there is an error", func() {1619 o := &N0{ID: 100}1620 mgs := getMGS(o)1621 _, ok := mgs.GetMeta("wat")1622 So(ok, ShouldBeFalse)1623 })1624 Convey("Default works for missing fields", func() {1625 o := &N0{ID: 100}1626 mgs := getMGS(o)1627 So(GetMetaDefault(mgs, "whozit", 10), ShouldEqual, 10)1628 })1629 Convey("getting mgs for bad struct is an error", func() {1630 So(func() { getMGS(&Recursive{}) }, ShouldPanicLike,1631 `field "R" is recursively defined`)1632 })1633 Convey("can assign values to exported meta fields", func() {1634 o := &N0{ID: 100}1635 mgs := getMGS(o)1636 So(mgs.SetMeta("id", int64(200)), ShouldBeTrue)1637 So(o.ID, ShouldEqual, 200)1638 })1639 Convey("assigning to unsassiagnable fields returns !ok", func() {1640 o := &N0{ID: 100}1641 mgs := getMGS(o)1642 So(mgs.SetMeta("kind", "hi"), ShouldBeFalse)1643 So(mgs.SetMeta("noob", "hi"), ShouldBeFalse)1644 })1645 Convey("unsigned int meta fields work", func() {1646 o := &N3{}1647 mgs := getMGS(o)1648 v, ok := mgs.GetMeta("id")1649 So(v, ShouldEqual, int64(200))1650 So(ok, ShouldBeTrue)1651 So(mgs.SetMeta("id", 20), ShouldBeTrue)1652 So(o.ID, ShouldEqual, 20)1653 So(mgs.SetMeta("id", math.MaxInt64), ShouldBeFalse)1654 So(o.ID, ShouldEqual, 20)1655 So(mgs.SetMeta("id", math.MaxUint32), ShouldBeTrue)1656 So(o.ID, ShouldEqual, math.MaxUint32)1657 })1658 })1659 Convey("StructPLS Miscellaneous", t, func() {1660 Convey("a simple struct has a default $kind", func() {1661 So(GetPLS(&Simple{}).GetAllMeta(), ShouldResemble, PropertyMap{1662 "$kind": mpNI("Simple"),1663 })1664 })1665 Convey("multiple overlapping fields is an error", func() {1666 o := &BadMeta{}1667 So(func() { GetPLS(o) }, ShouldPanicLike, "multiple times")1668 })1669 Convey("empty property names are invalid", func() {1670 So(validPropertyName(""), ShouldBeFalse)1671 })1672 Convey("attempting to get a PLS for a non *struct is an error", func() {1673 s := []string{}1674 So(func() { GetPLS(&s) }, ShouldPanicLike,1675 "cannot GetPLS(*[]string): not a pointer-to-struct")1676 })1677 Convey("attempting to get a PLS for a nil pointer-to-struct is an error", func() {1678 var s *Simple1679 So(func() { GetPLS(s) }, ShouldPanicLike,1680 "cannot GetPLS(*datastore.Simple): pointer is nil")1681 })1682 Convey("convertible meta default types", func() {1683 type OKDefaults struct {1684 When string `gae:"$when,tomorrow"`1685 Amount int64 `gae:"$amt,100"`1686 DoIt Toggle `gae:"$doit,on"`1687 }1688 okd := &OKDefaults{}1689 mgs := getMGS(okd)1690 v, ok := mgs.GetMeta("when")1691 So(ok, ShouldBeTrue)1692 So(v, ShouldEqual, "tomorrow")1693 v, ok = mgs.GetMeta("amt")1694 So(ok, ShouldBeTrue)1695 So(v, ShouldEqual, int64(100))1696 So(okd.DoIt, ShouldEqual, Auto)1697 v, ok = mgs.GetMeta("doit")1698 So(ok, ShouldBeTrue)1699 So(v, ShouldBeTrue)1700 So(mgs.SetMeta("doit", false), ShouldBeTrue)1701 v, ok = mgs.GetMeta("doit")1702 So(ok, ShouldBeTrue)1703 So(v, ShouldBeFalse)1704 So(okd.DoIt, ShouldEqual, Off)1705 So(mgs.SetMeta("doit", true), ShouldBeTrue)1706 v, ok = mgs.GetMeta("doit")1707 So(ok, ShouldBeTrue)1708 So(v, ShouldBeTrue)1709 So(okd.DoIt, ShouldEqual, On)1710 Convey("Toggle fields REQUIRE a default", func() {1711 type BadToggle struct {1712 Bad Toggle `gae:"$wut"`1713 }1714 So(func() { GetPLS(&BadToggle{}) }, ShouldPanicLike, "bad/missing default")1715 })1716 })1717 Convey("meta fields can be saved", func() {1718 type OKDefaults struct {1719 When string `gae:"$when,tomorrow"`1720 Amount int64 `gae:"$amt,100"`1721 }1722 pls := GetPLS(&OKDefaults{})1723 pm, err := pls.Save(true)1724 So(err, ShouldBeNil)1725 So(pm, ShouldResemble, PropertyMap{1726 "$when": mpNI("tomorrow"),1727 "$amt": mpNI(100),1728 "$kind": mpNI("OKDefaults"),1729 })1730 v, ok := pm.GetMeta("when")1731 So(ok, ShouldBeTrue)1732 So(v, ShouldEqual, "tomorrow")1733 v, ok = pm.GetMeta("amt")1734 So(ok, ShouldBeTrue)1735 So(v, ShouldEqual, int64(100))1736 })1737 Convey("default are optional", func() {1738 type OverrideDefault struct {1739 Val int64 `gae:"$val"`1740 }1741 o := &OverrideDefault{}1742 mgs := getMGS(o)1743 v, ok := mgs.GetMeta("val")1744 So(ok, ShouldBeTrue)1745 So(v, ShouldEqual, int64(0))1746 })1747 Convey("overridable defaults", func() {1748 type OverrideDefault struct {1749 Val int64 `gae:"$val,100"`1750 }1751 o := &OverrideDefault{}1752 mgs := getMGS(o)1753 v, ok := mgs.GetMeta("val")1754 So(ok, ShouldBeTrue)1755 So(v, ShouldEqual, int64(100))1756 o.Val = 101757 v, ok = mgs.GetMeta("val")1758 So(ok, ShouldBeTrue)1759 So(v, ShouldEqual, int64(10))1760 })1761 Convey("underflow", func() {1762 type UnderflowMeta struct {1763 ID int16 `gae:"$id"`1764 }1765 um := &UnderflowMeta{}1766 mgs := getMGS(um)1767 So(mgs.SetMeta("id", -20), ShouldBeTrue)1768 So(mgs.SetMeta("id", math.MinInt64), ShouldBeFalse)1769 })1770 Convey("negative default", func() {1771 type UnderflowMeta struct {1772 ID int16 `gae:"$id,-30"`1773 }1774 um := &UnderflowMeta{}1775 mgs := getMGS(um)1776 val, ok := mgs.GetMeta("id")1777 So(ok, ShouldBeTrue)1778 So(val, ShouldEqual, -30)1779 })1780 Convey("Derived metadata fields", func() {1781 type DerivedString string1782 type DerivedInt int161783 type DerivedStruct struct {1784 ID DerivedString `gae:"$id"`1785 Foo DerivedInt `gae:"$foo"`1786 }1787 o := &DerivedStruct{"hello", 10}1788 mgs := getMGS(o)1789 v, ok := mgs.GetMeta("id")1790 So(ok, ShouldBeTrue)1791 So(v, ShouldEqual, "hello")1792 v, ok = mgs.GetMeta("foo")1793 So(ok, ShouldBeTrue)1794 So(v, ShouldEqual, int64(10))1795 So(mgs.SetMeta("id", "nerds"), ShouldBeTrue)1796 So(mgs.SetMeta("foo", 20), ShouldBeTrue)1797 So(o.ID, ShouldEqual, DerivedString("nerds"))1798 So(o.Foo, ShouldEqual, DerivedInt(20))1799 })1800 Convey("Bad default meta type", func() {1801 type BadDefault struct {1802 Val time.Time `gae:"$meta,tomorrow"`1803 }1804 So(func() { GetPLS(&BadDefault{}) }, ShouldPanicLike, "bad type")1805 })1806 Convey("MetaGetterSetter implementation (IDParser)", func() {1807 idp := &IDParser{parent: "moo", id: 100}1808 mgs := getMGS(idp)1809 So(GetMetaDefault(mgs, "id", ""), ShouldEqual, "moo|100")1810 So(GetMetaDefault(mgs, "kind", ""), ShouldEqual, "CoolKind")1811 So(mgs.SetMeta("kind", "Something"), ShouldBeFalse)1812 So(mgs.SetMeta("id", "happy|27"), ShouldBeTrue)1813 So(idp.parent, ShouldEqual, "happy")1814 So(idp.id, ShouldEqual, 27)1815 So(mgs.GetAllMeta(), ShouldResemble, PropertyMap{1816 "$id": mpNI("happy|27"),1817 "$kind": mpNI("CoolKind"),1818 })1819 })1820 Convey("MetaGetterSetter implementation (KindOverride)", func() {1821 ko := &KindOverride{ID: 20}1822 mgs := getMGS(ko)1823 So(GetMetaDefault(mgs, "kind", ""), ShouldEqual, "KindOverride")1824 ko.customKind = "something"1825 So(GetMetaDefault(mgs, "kind", ""), ShouldEqual, "something")1826 So(mgs.SetMeta("kind", "Nerp"), ShouldBeTrue)1827 So(ko.customKind, ShouldEqual, "Nerp")1828 So(mgs.SetMeta("kind", "KindOverride"), ShouldBeTrue)1829 So(ko.customKind, ShouldEqual, "")1830 So(mgs.GetAllMeta(), ShouldResemble, PropertyMap{1831 "$id": mpNI(20),1832 "$kind": mpNI("KindOverride"),1833 })1834 ko.customKind = "wut"1835 So(mgs.GetAllMeta(), ShouldResemble, PropertyMap{1836 "$id": mpNI(20),1837 "$kind": mpNI("wut"),1838 })1839 props, err := GetPLS(ko).Save(true)1840 So(err, ShouldBeNil)1841 So(props, ShouldResemble, PropertyMap{1842 "$id": mpNI(20),1843 "$kind": mpNI("wut"),1844 })1845 })1846 Convey("Embeddable Metadata structs", func() {1847 ide := &IDEmbedder{EmbeddedID{"hello", 10}}1848 pls := GetPLS(ide)1849 val, ok := pls.GetMeta("id")1850 So(ok, ShouldBeTrue)1851 So(val, ShouldEqual, "hello|10")1852 So(pls.SetMeta("id", "sup|1337"), ShouldBeTrue)1853 So(ide.EmbeddedID, ShouldResemble, EmbeddedID{"sup", 1337})1854 So(pls.GetAllMeta(), ShouldResemble, PropertyMap{1855 "$id": mpNI("sup|1337"),1856 "$kind": mpNI("IDEmbedder"),1857 })1858 })1859 })1860}...

Full Screen

Full Screen

regression.go

Source:regression.go Github

copy

Full Screen

...59 if err != nil {60 render.Render(w, r, ErrInvalidRequest(err))61 return62 }63 app := rg.getMeta(w, r, true)64 if app == "" {65 return66 }67 id := uuid.New().String()68 now := time.Now().Unix()69 // user := "default"70 err = rg.run.Put(r.Context(), run.TestRun{71 ID: id,72 Created: now,73 Updated: now,74 Status: run.TestRunStatusRunning,75 CID: graph.DEFAULT_COMPANY,76 App: app,77 User: graph.DEFAULT_USER,78 Total: total,79 })80 if err != nil {81 render.Render(w, r, ErrInvalidRequest(err))82 return83 }84 render.Status(r, http.StatusOK)85 render.JSON(w, r, map[string]string{86 "id": id,87 })88}89func (rg *regression) GetTC(w http.ResponseWriter, r *http.Request) {90 id := chi.URLParam(r, "id")91 app := rg.getMeta(w, r, false)92 tcs, err := rg.svc.Get(r.Context(), graph.DEFAULT_COMPANY, app, id)93 if err != nil {94 render.Render(w, r, ErrInvalidRequest(err))95 return96 }97 render.Status(r, http.StatusOK)98 render.JSON(w, r, tcs)99}100func (rg *regression) getMeta(w http.ResponseWriter, r *http.Request, appRequired bool) string {101 app := r.URL.Query().Get("app")102 if app == "" && appRequired {103 rg.logger.Error("request for fetching testcases should include app id")104 render.Render(w, r, ErrInvalidRequest(errors.New("missing app id")))105 return ""106 }107 return app108}109func (rg *regression) GetTCS(w http.ResponseWriter, r *http.Request) {110 app := rg.getMeta(w, r, true)111 if app == "" {112 return113 }114 offsetStr := r.URL.Query().Get("offset")115 limitStr := r.URL.Query().Get("limit")116 var (117 offset int118 limit int119 err error120 )121 if offsetStr != "" {122 offset, err = strconv.Atoi(offsetStr)123 if err != nil {124 rg.logger.Error("request for fetching testcases in converting offset to integer")...

Full Screen

Full Screen

vault_test.go

Source:vault_test.go Github

copy

Full Screen

1// Copyright © 2014-2021 Thomas Rabaix <thomas.rabaix@gmail.com>.2//3// Use of this source code is governed by an MIT-style4// license that can be found in the LICENSE file.5package vault6import (7 "bytes"8 "crypto/rand"9 "io"10 "testing"11 "github.com/stretchr/testify/assert"12)13var xSmallMessage []byte14var smallMessage []byte15var largeMessage []byte16var xLargeMessage []byte17var key = []byte("de4d3ae8cf578c971b39ab5f21b2435483a3654f63b9f3777925c77e9492a141")18func init() {19 xSmallMessage = []byte("1")20 smallMessage = []byte("Comment ca va ??")21 largeMessage = make([]byte, 1024*1024*1+2)22 io.ReadFull(rand.Reader, largeMessage)23 xLargeMessage = make([]byte, 1024*1024*10+3)24 io.ReadFull(rand.Reader, xLargeMessage)25}26// write/encrypted file27func RunTestVault(t *testing.T, v *Vault, plaintext []byte, msgPrefix string) {28 var read int6429 file := "this-is-a-test"30 meta := NewVaultMetadata()31 meta["foo"] = "bar"32 reader := bytes.NewBuffer(plaintext)33 written, err := v.Put(file, meta, reader)34 assert.NoError(t, err, msgPrefix+": err returned")35 assert.True(t, written >= int64(len(plaintext)), msgPrefix) // some cipher might add extra data36 assert.True(t, written > 0, msgPrefix) // some cipher might add extra data37 assert.True(t, v.Has(file), msgPrefix+": has file should be true")38 invalid := []byte("Another invalid message with the same key")39 // test overwrite40 written, err = v.Put(file, meta, bytes.NewBuffer(invalid))41 assert.Error(t, err, msgPrefix)42 assert.Equal(t, written, int64(0), msgPrefix)43 // get metadata44 meta, err = v.GetMeta(file)45 assert.NoError(t, err, msgPrefix)46 assert.Equal(t, meta["foo"].(string), "bar", msgPrefix)47 // get file48 writer := bytes.NewBuffer([]byte(""))49 read, err = v.Get(file, writer)50 assert.Equal(t, read, int64(len(plaintext)), msgPrefix)51 assert.True(t, len(plaintext) > 0, "plaintext length should not be empty", msgPrefix)52 assert.NoError(t, err, msgPrefix)53 assert.Equal(t, plaintext, writer.Bytes(), msgPrefix)54 // remove file55 err = v.Remove(file)56 assert.NoError(t, err, msgPrefix)57}58// read stored encrypted files59func RunRegressionTest(t *testing.T, v *Vault) {60 file := "The-secret-file"61 assert.True(t, v.Has(file))62 meta, err := v.GetMeta(file)63 assert.NoError(t, err)64 assert.Equal(t, meta["foo"].(string), "bar")65 writer := bytes.NewBufferString("")66 _, err = v.Get(file, writer)67 assert.NoError(t, err)68 assert.Equal(t, writer.String(), "The secret message")69}70func Test_VaultElement(t *testing.T) {71 ve := NewVaultElement()72 assert.Equal(t, ve.Algo, "aes_ctr") // default value73 assert.NotEmpty(t, ve.BinKey)74 assert.NotEmpty(t, ve.MetaKey)75}...

Full Screen

Full Screen

getMeta

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 reg := linear.NewRegression(linear.WithStep(0.01), linear.WithIterations(1000), linear.WithRegParam(0.1), linear.WithEpsilon(0.00001))4 tfidf := text.NewTFIDF(2, nil)5 vectorizer := text.NewVectorizer()6 data := base.NewDataset()7 data.CSV("../data/iris.csv")8 vectorizer.FitTransform(features)9 tfidf.FitTransform(features)10 reg.Fit(features, labels)11 predictions := reg.Predict(features)12 fmt.Println(predictions)

Full Screen

Full Screen

getMeta

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 r := new(regression.Regression)4 r.SetObserved("Y")5 r.SetVar(0, "X")6 r.Train(regression.Data{7 {Y: 10, X: 10},8 {Y: 20, X: 20},9 {Y: 30, X: 30},10 })11 r.Run()12 fmt.Printf("GetMeta: %v13", r.GetMeta())14}15Golang: GetMeta() Method

Full Screen

Full Screen

getMeta

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 irisFile, err := os.Open("iris_data.csv")4 if err != nil {5 log.Fatal(err)6 }7 defer irisFile.Close()8 irisDF := dataframe.ReadCSV(irisFile)9 yVals := irisDF.Col("species").Records()10 xVals := irisDF.Drop("species").Records()11 r := new(regression.Regression)12 r.SetObserved("species")13 for idx, xVal := range xVals {14 r.Train(regression.DataPoint(yVals[idx][0].(float64), xVal))15 }16 r.Run()17 summary := r.Summary()18 fmt.Println(summary)19}20 | (intercept) | 2.625 | 0.335 | 7.825 | 0.000 |

Full Screen

Full Screen

getMeta

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 r := new(regression.Regression)4 r.SetObserved("y")5 r.SetVar(0, "x")6 r.Train(regression.DataPoint(1, []float64{1}, []string{"x"}, 10))7 r.Train(regression.DataPoint(1, []float64{2}, []string{"x"}, 20))8 r.Train(regression.DataPoint(1, []float64{3}, []string{"x"}, 30))9 r.Train(regression.DataPoint(1, []float64{4}, []string{"x"}, 40))10 fmt.Println(r.GetMeta("x"))11}12How to get the Coefficient of Determination (R-Squared) value of a regression model in

Full Screen

Full Screen

getMeta

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 r.SetObserved("y")4 r.SetVar(0, "x")5 r.Train(regression.Data{6 X: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9},7 Y: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9},8 })9 fmt.Printf("Parameters: %0.2f\n", r.Coeff(0))10 fmt.Printf("Intercept: %0.2f\n", r.Intercept)11 fmt.Printf("R2: %0.2f\n", r.R2)12 fmt.Printf("Predicted (%0.2f, %0.2f)\n", 5.0, r.Predict([]float64{5.0}))13}14Predicted (5.00, 5.00)15import (16func main() {17 r.SetObserved("y")18 r.SetVar(0, "x")19 r.Train(regression.Data{20 X: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9},21 Y: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9},22 })23 fmt.Printf("Parameters: %0.2f\n", r.Coeff(0))24 fmt.Printf("Intercept: %0.2f\n", r.Intercept)

Full Screen

Full Screen

getMeta

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 r.Train(regression.DataPoint(1, []float64{1}))4 r.Train(regression.DataPoint(2, []float64{2}))5 r.Train(regression.DataPoint(3, []float64{3}))6 m := r.GetMeta()7 fmt.Printf("Meta data: %v8}9Meta data: {NumFeatures:1 NumData:3}10import (11func main() {12 r.Train(regression.DataPoint(1, []float64{1}))13 r.Train(regression.DataPoint(2, []float64{2}))14 r.Train(regression.DataPoint(3, []float64{3}))15 res := r.GetResiduals()16 fmt.Printf("Residuals: %v17}18import (19func main() {20 r.Train(regression.DataPoint(1, []float64{1}))21 r.Train(regression.DataPoint(2, []float64{2}))22 r.Train(regression.DataPoint(3, []float64{3}))23 rs := r.GetRSquared()

Full Screen

Full Screen

getMeta

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 r := rand.New(rand.NewSource(time.Now().UnixNano()))4 reg.SetObserved("Y")5 reg.SetVar(0, "X")6 for i := 0; i < 100; i++ {7 x := r.Float64()8 y := 2*x + 1 + r.Float64()9 reg.Train(regression.DataPoint(y, []float64{x}))10 }11 reg.Run()12 fmt.Printf("\nRegression Formula:\n")13 fmt.Printf("%v\n\n", reg.Formula)14 fmt.Printf("Parameters:\n")15 fmt.Printf("X: %v\n", reg.Coeff(0))16 fmt.Printf("Y: %v\n", reg.Coeff(1))17 fmt.Printf("\nStandard Error: %0.2f\n\n", reg.StdErr)18 fmt.Printf("R^2: %0.2f\n\n", reg.R2)19 fmt.Printf("Meta Data:\n")20 fmt.Printf("Y: %v\n", reg.GetMeta("Y"))21 fmt.Printf("X: %v\n", reg.GetMeta("X"))22 fmt.Printf("\nPredict:\n")23 fmt.Printf("X: %0.2f\n", 1.0)24 fmt.Printf("Y: %0.2f\n", reg.Predict([]float64{1.0}))25}

Full Screen

Full Screen

getMeta

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 r := new(regression.Regression)4 r.Train(regression.DataPoint(2.0, []float64{1.0}))5 r.Train(regression.DataPoint(3.0, []float64{2.0}))6 r.Train(regression.DataPoint(4.0, []float64{3.0}))7 r.Train(regression.DataPoint(5.0, []float64{4.0}))8 r.Train(regression.DataPoint(6.0, []float64{5.0}))9 r.Run()10 fmt.Printf("\nRegression Formula:\n%v\n", r.Formula)11 fmt.Printf("\nR2: %v\n", r.R2)12 fmt.Printf("\nMeta: %v\n", r.GetMeta())13}14import (15func main() {16 r := new(regression.Regression)17 r.Train(regression.DataPoint(2.0, []float64{1.0}))18 r.Train(regression.DataPoint(3.0, []float64{2.0}))19 r.Train(regression.DataPoint(4.0, []float64{3.0}))20 r.Train(regression.DataPoint(5.0, []float64{4.0}))21 r.Train(regression.DataPoint(6.0, []float64{5.0}))22 r.Run()23 fmt.Printf("\nRegression Formula:\n%v\n", r.Formula)

Full Screen

Full Screen

getMeta

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 train := utils.ReadCsv("data/train.csv")4 test := utils.ReadCsv("data/test.csv")5 model := new(ML.Regression)6 model.Fit(train, "SalePrice", 1.0)7 meta := model.GetMeta()8 fmt.Println(meta)9 predictions := model.Predict(test)10 fmt.Println(predictions)11}

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Keploy automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful