// roundTripSame verifies the same source object is tested in all API versions // yielded by codecsToTest func roundTripSame(t *testing.T, group testapi.TestGroup, item runtime.Object, except ...string) { set := sets.NewString(except...) seed := rand.Int63() fuzzInternalObject(t, group.InternalGroupVersion(), item, seed) version := *group.GroupVersion() codecs := []runtime.Codec{} for _, fn := range codecsToTest { codec, ok, err := fn(version, item) if err != nil { t.Errorf("unable to get codec: %v", err) return } if !ok { continue } codecs = append(codecs, codec) } if !set.Has(version.String()) { fuzzInternalObject(t, version, item, seed) for _, codec := range codecs { roundTrip(t, codec, item) } } }
func doRoundTripTest(group testapi.TestGroup, kind string, t *testing.T) { item, err := api.Scheme.New(group.InternalGroupVersion().WithKind(kind)) if err != nil { t.Fatalf("Couldn't make a %v? %v", kind, err) } if _, err := meta.TypeAccessor(item); err != nil { t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableTypes: %v", kind, err) } if api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) { roundTripSame(t, group, item, nonRoundTrippableTypesByVersion[kind]...) } if !nonInternalRoundTrippableTypes.Has(kind) && api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) { roundTrip(t, group.Codec(), fuzzInternalObject(t, group.InternalGroupVersion(), item, rand.Int63())) } }
func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) { // We do fuzzing on the internal version of the object, and only then // convert to the external version. This is because custom fuzzing // function are only supported for internal objects. internalObj, err := api.Scheme.New(group.InternalGroupVersion().WithKind(kind)) if err != nil { t.Fatalf("Couldn't create internal object %v: %v", kind, err) } seed := rand.Int63() apitesting.FuzzerFor(t, group.InternalGroupVersion(), rand.NewSource(seed)). // We are explicitly overwriting custom fuzzing functions, to ensure // that InitContainers and their statuses are not generated. This is // because in thise test we are simply doing json operations, in which // those disappear. Funcs( func(s *api.PodSpec, c fuzz.Continue) { c.FuzzNoCustom(s) s.InitContainers = nil }, func(s *api.PodStatus, c fuzz.Continue) { c.FuzzNoCustom(s) s.InitContainerStatuses = nil }, ).Fuzz(internalObj) item, err := api.Scheme.New(group.GroupVersion().WithKind(kind)) if err != nil { t.Fatalf("Couldn't create external object %v: %v", kind, err) } if err := api.Scheme.Convert(internalObj, item, nil); err != nil { t.Fatalf("Conversion for %v failed: %v", kind, err) } data, err := json.Marshal(item) if err != nil { t.Errorf("Error when marshaling object: %v", err) return } unstr := make(map[string]interface{}) err = json.Unmarshal(data, &unstr) if err != nil { t.Errorf("Error when unmarshaling to unstructured: %v", err) return } data, err = json.Marshal(unstr) if err != nil { t.Errorf("Error when marshaling unstructured: %v", err) return } unmarshalledObj := reflect.New(reflect.TypeOf(item).Elem()).Interface() err = json.Unmarshal(data, &unmarshalledObj) if err != nil { t.Errorf("Error when unmarshaling to object: %v", err) return } if !api.Semantic.DeepEqual(item, unmarshalledObj) { t.Errorf("Object changed during JSON operations, diff: %v", diff.ObjectReflectDiff(item, unmarshalledObj)) return } // TODO; Enable the following part of test once to/from unstructured // format conversions are implemented. /* newUnstr := make(map[string]interface{}) err = unstructured.NewConverter().ToUnstructured(item, &newUnstr) if err != nil { t.Errorf("ToUnstructured failed: %v", err) return } newObj := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) err = unstructured.NewConverter().FromUnstructured(newUnstr, newObj) if err != nil { t.Errorf("FromUnstructured failed: %v", err) return } if !api.Semantic.DeepEqual(item, newObj) { t.Errorf("Object changed, diff: %v", diff.ObjectReflectDiff(item, newObj)) } */ }