func TestConverter_fuzz(t *testing.T) { newAnonType := func() interface{} { return reflect.New(reflect.TypeOf(externalTypeReturn())).Interface() } // Use the same types from the scheme test. table := []struct { from, to, check interface{} }{ {&TestType1{}, newAnonType(), &TestType1{}}, {newAnonType(), &TestType1{}, newAnonType()}, } f := util.NewFuzzer() c := NewConverter() for i, item := range table { for j := 0; j < *fuzzIters; j++ { f.Fuzz(item.from) err := c.Convert(item.from, item.to, 0) if err != nil { t.Errorf("(%v, %v): unexpected error: %v", i, j, err) continue } err = c.Convert(item.to, item.check, 0) if err != nil { t.Errorf("(%v, %v): unexpected error: %v", i, j, err) continue } if e, a := item.from, item.check; !reflect.DeepEqual(e, a) { t.Errorf("(%v, %v): unexpected diff: %v", i, j, objDiff(e, a)) } } } }
var apiObjectFuzzer = util.NewFuzzer( func(j *JSONBase) { // We have to customize the randomization of JSONBases because their // APIVersion and Kind must remain blank in memory. j.APIVersion = "" j.Kind = "" j.ID = util.RandString() // TODO: Fix JSON/YAML packages and/or write custom encoding // for uint64's. Somehow the LS *byte* of this is lost, but // only when all 8 bytes are set. j.ResourceVersion = util.RandUint64() >> 8 j.SelfLink = util.RandString() j.CreationTimestamp = util.RandString() }, func(intstr *util.IntOrString) { // util.IntOrString will panic if its kind is set wrong. if util.RandBool() { intstr.Kind = util.IntstrInt intstr.IntVal = int(util.RandUint64()) intstr.StrVal = "" } else { intstr.Kind = util.IntstrString intstr.IntVal = 0 intstr.StrVal = util.RandString() } }, func(p *PodInfo) { // The docker container type doesn't survive fuzzing. // TODO: fix this. *p = nil }, )
var apiObjectFuzzer = util.NewFuzzer( func(j *JSONBase) { // We have to customize the randomization of JSONBases because their // APIVersion and Kind must remain blank in memory. j.APIVersion = "" j.Kind = "" j.ID = util.RandString() // TODO: Fix JSON/YAML packages and/or write custom encoding // for uint64's. Somehow the LS *byte* of this is lost, but // only when all 8 bytes are set. j.ResourceVersion = util.RandUint64() >> 8 j.SelfLink = util.RandString() j.CreationTimestamp = util.RandString() }, func(intstr *util.IntOrString) { // util.IntOrString will panic if its kind is set wrong. if util.RandBool() { intstr.Kind = util.IntstrInt intstr.IntVal = int(util.RandUint64()) intstr.StrVal = "" } else { intstr.Kind = util.IntstrString intstr.IntVal = 0 intstr.StrVal = util.RandString() } }, func(u64 *uint64) { // TODO: uint64's are NOT handled right. *u64 = util.RandUint64() >> 8 }, func(pb map[docker.Port][]docker.PortBinding) { // This is necessary because keys with nil values get omitted. // TODO: Is this a bug? pb[docker.Port(util.RandString())] = []docker.PortBinding{ {util.RandString(), util.RandString()}, {util.RandString(), util.RandString()}, } }, func(pm map[string]docker.PortMapping) { // This is necessary because keys with nil values get omitted. // TODO: Is this a bug? pm[util.RandString()] = docker.PortMapping{ util.RandString(): util.RandString(), } }, )
MyWeirdCustomEmbeddedVersionKindField `json:",inline" yaml:",inline"` A TestType2 `yaml:"A,omitempty" json:"A,omitempty"` } // TestObjectFuzzer can randomly populate all the above objects. var TestObjectFuzzer = util.NewFuzzer( func(j *MyWeirdCustomEmbeddedVersionKindField) { // We have to customize the randomization of MyWeirdCustomEmbeddedVersionKindFields because their // APIVersion and Kind must remain blank in memory. j.APIVersion = "" j.ObjectKind = "" j.ID = util.RandString() }, func(u *uint64) { // TODO: Fix JSON/YAML packages and/or write custom encoding // for uint64's. Somehow the LS *byte* of this is lost, but // only when all 8 bytes are set. *u = util.RandUint64() >> 8 }, func(u *uint) { // TODO: Fix JSON/YAML packages and/or write custom encoding // for uint64's. Somehow the LS *byte* of this is lost, but // only when all 8 bytes are set. *u = uint(util.RandUint64() >> 8) }, ) // Returns a new Scheme set up with the test objects. func GetTestScheme() *Scheme { s := NewScheme() s.AddKnownTypes("", TestType1{}, ExternalInternalSame{})
func TestConverter_flags(t *testing.T) { type Foo struct{ A string } type Bar struct{ A string } table := []struct { from, to interface{} flags FieldMatchingFlags shouldSucceed bool }{ // Check that DestFromSource allows extra fields only in source. { from: &struct{ A string }{}, to: &struct{ A, B string }{}, flags: DestFromSource, shouldSucceed: false, }, { from: &struct{ A, B string }{}, to: &struct{ A string }{}, flags: DestFromSource, shouldSucceed: true, }, // Check that SourceToDest allows for extra fields only in dest. { from: &struct{ A string }{}, to: &struct{ A, B string }{}, flags: SourceToDest, shouldSucceed: true, }, { from: &struct{ A, B string }{}, to: &struct{ A string }{}, flags: SourceToDest, shouldSucceed: false, }, // Check that IgnoreMissingFields makes the above failure cases pass. { from: &struct{ A string }{}, to: &struct{ A, B string }{}, flags: DestFromSource | IgnoreMissingFields, shouldSucceed: true, }, { from: &struct{ A, B string }{}, to: &struct{ A string }{}, flags: SourceToDest | IgnoreMissingFields, shouldSucceed: true, }, // Check that the field type name must match unless // AllowDifferentFieldTypeNames is specified. { from: &struct{ A, B Foo }{}, to: &struct{ A Bar }{}, flags: DestFromSource, shouldSucceed: false, }, { from: &struct{ A Foo }{}, to: &struct{ A, B Bar }{}, flags: SourceToDest, shouldSucceed: false, }, { from: &struct{ A, B Foo }{}, to: &struct{ A Bar }{}, flags: DestFromSource | AllowDifferentFieldTypeNames, shouldSucceed: true, }, { from: &struct{ A Foo }{}, to: &struct{ A, B Bar }{}, flags: SourceToDest | AllowDifferentFieldTypeNames, shouldSucceed: true, }, } f := util.NewFuzzer() c := NewConverter() for i, item := range table { for j := 0; j < *fuzzIters; j++ { f.Fuzz(item.from) err := c.Convert(item.from, item.to, item.flags) if item.shouldSucceed && err != nil { t.Errorf("(%v, %v): unexpected error: %v", i, j, err) continue } if !item.shouldSucceed && err == nil { t.Errorf("(%v, %v): unexpected non-error", i, j) continue } } } }