Extract RoundtripToUnstructured to apimachinery apitesting library.
This will allow the same scenarios to be exercised on types defined in staging modules, like apiextensions-apiserver, without importing them all from the root module.
This commit is contained in:
		| @@ -17,30 +17,24 @@ limitations under the License. | ||||
| package testing | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"math/rand" | ||||
| 	"os" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/google/go-cmp/cmp" | ||||
| 	fuzz "github.com/google/gofuzz" | ||||
|  | ||||
| 	v1 "k8s.io/api/core/v1" | ||||
| 	"k8s.io/apimachinery/pkg/api/apitesting/fuzzer" | ||||
| 	"k8s.io/apimachinery/pkg/api/apitesting/roundtrip" | ||||
| 	apiequality "k8s.io/apimachinery/pkg/api/equality" | ||||
| 	"k8s.io/apimachinery/pkg/api/meta" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	metaunstruct "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	cborserializer "k8s.io/apimachinery/pkg/runtime/serializer/cbor" | ||||
| 	cbor "k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct" | ||||
| 	jsonserializer "k8s.io/apimachinery/pkg/runtime/serializer/json" | ||||
| 	"k8s.io/apimachinery/pkg/util/json" | ||||
| 	"k8s.io/apimachinery/pkg/util/sets" | ||||
| 	"k8s.io/kubernetes/pkg/api/legacyscheme" | ||||
| 	api "k8s.io/kubernetes/pkg/apis/core" | ||||
| ) | ||||
| @@ -142,182 +136,33 @@ func TestRoundTrip(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // TestRoundtripToUnstructured verifies the roundtrip faithfulness of all external types from native | ||||
| // to unstructured and back using both the JSON and CBOR serializers. The intermediate unstructured | ||||
| // objects produced by both encodings must be identical and be themselves roundtrippable to JSON and | ||||
| // CBOR. | ||||
| func TestRoundtripToUnstructured(t *testing.T) { | ||||
| 	// These are GVKs that whose CBOR roundtrippability is blocked by a known issue that must be | ||||
| 	// resolved as a prerequisite for alpha. | ||||
| 	knownFailureReasons := map[string][]schema.GroupVersionKind{ | ||||
| 		// If a RawExtension's bytes are invalid JSON, its containing object can't be encoded to JSON. | ||||
| 		"rawextension needs to work in programs that assume json": { | ||||
| 			{Version: "v1", Kind: "List"}, | ||||
| 			{Group: "apps", Version: "v1beta1", Kind: "ControllerRevision"}, | ||||
| 			{Group: "apps", Version: "v1beta1", Kind: "ControllerRevisionList"}, | ||||
| 			{Group: "apps", Version: "v1beta2", Kind: "ControllerRevision"}, | ||||
| 			{Group: "apps", Version: "v1beta2", Kind: "ControllerRevisionList"}, | ||||
| 			{Group: "apps", Version: "v1", Kind: "ControllerRevision"}, | ||||
| 			{Group: "apps", Version: "v1", Kind: "ControllerRevisionList"}, | ||||
| 			{Group: "admission.k8s.io", Version: "v1beta1", Kind: "AdmissionReview"}, | ||||
| 			{Group: "admission.k8s.io", Version: "v1", Kind: "AdmissionReview"}, | ||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaim"}, | ||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimList"}, | ||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimParameters"}, | ||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimParametersList"}, | ||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClassParameters"}, | ||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClassParametersList"}, | ||||
| 		}, | ||||
| 	} | ||||
| 	skipped := sets.New( | ||||
| 		// TODO: Support cross-protocol RawExtension roundtrips. | ||||
| 		schema.GroupVersionKind{Version: "v1", Kind: "List"}, | ||||
| 		schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "ControllerRevision"}, | ||||
| 		schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "ControllerRevisionList"}, | ||||
| 		schema.GroupVersionKind{Group: "apps", Version: "v1beta2", Kind: "ControllerRevision"}, | ||||
| 		schema.GroupVersionKind{Group: "apps", Version: "v1beta2", Kind: "ControllerRevisionList"}, | ||||
| 		schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ControllerRevision"}, | ||||
| 		schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ControllerRevisionList"}, | ||||
| 		schema.GroupVersionKind{Group: "admission.k8s.io", Version: "v1beta1", Kind: "AdmissionReview"}, | ||||
| 		schema.GroupVersionKind{Group: "admission.k8s.io", Version: "v1", Kind: "AdmissionReview"}, | ||||
| 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaim"}, | ||||
| 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimList"}, | ||||
| 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimParameters"}, | ||||
| 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimParametersList"}, | ||||
| 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClassParameters"}, | ||||
| 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClassParametersList"}, | ||||
| 	) | ||||
|  | ||||
| 	seed := int64(time.Now().Nanosecond()) | ||||
| 	if override := os.Getenv("TEST_RAND_SEED"); len(override) > 0 { | ||||
| 		overrideSeed, err := strconv.ParseInt(override, 10, 64) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		seed = overrideSeed | ||||
| 		t.Logf("using overridden seed: %d", seed) | ||||
| 	} else { | ||||
| 		t.Logf("seed (override with TEST_RAND_SEED if desired): %d", seed) | ||||
| 	} | ||||
|  | ||||
| 	var buf bytes.Buffer | ||||
| 	for gvk := range legacyscheme.Scheme.AllKnownTypes() { | ||||
| 		if nonRoundTrippableTypes.Has(gvk.Kind) { | ||||
| 			continue | ||||
| 		} | ||||
| 		if gvk.Version == runtime.APIVersionInternal { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		subtestName := fmt.Sprintf("%s.%s/%s", gvk.Version, gvk.Group, gvk.Kind) | ||||
| 		if gvk.Group == "" { | ||||
| 			subtestName = fmt.Sprintf("%s/%s", gvk.Version, gvk.Kind) | ||||
| 		} | ||||
|  | ||||
| 		t.Run(subtestName, func(t *testing.T) { | ||||
| 			for reason, gvks := range knownFailureReasons { | ||||
| 				for _, each := range gvks { | ||||
| 					if gvk == each { | ||||
| 						t.Skip(reason) | ||||
| 					} | ||||
| 			skipped.Insert(gvk) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 			fuzzer := fuzzer.FuzzerFor(FuzzerFuncs, rand.NewSource(seed), legacyscheme.Codecs) | ||||
|  | ||||
| 			for i := 0; i < 50; i++ { | ||||
| 				// 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 := legacyscheme.Scheme.New(schema.GroupVersion{Group: gvk.Group, Version: runtime.APIVersionInternal}.WithKind(gvk.Kind)) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("couldn't create internal object %v: %v", gvk.Kind, err) | ||||
| 				} | ||||
| 				fuzzer.Fuzz(internalObj) | ||||
|  | ||||
| 				item, err := legacyscheme.Scheme.New(gvk) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("couldn't create external object %v: %v", gvk.Kind, err) | ||||
| 				} | ||||
| 				if err := legacyscheme.Scheme.Convert(internalObj, item, nil); err != nil { | ||||
| 					t.Fatalf("conversion for %v failed: %v", gvk.Kind, err) | ||||
| 				} | ||||
|  | ||||
| 				// Decoding into Unstructured requires that apiVersion and kind be | ||||
| 				// serialized, so populate TypeMeta. | ||||
| 				item.GetObjectKind().SetGroupVersionKind(gvk) | ||||
|  | ||||
| 				jsonSerializer := jsonserializer.NewSerializerWithOptions(jsonserializer.DefaultMetaFactory, legacyscheme.Scheme, legacyscheme.Scheme, jsonserializer.SerializerOptions{}) | ||||
| 				cborSerializer := cborserializer.NewSerializer(legacyscheme.Scheme, legacyscheme.Scheme) | ||||
|  | ||||
| 				// original->JSON->Unstructured | ||||
| 				buf.Reset() | ||||
| 				if err := jsonSerializer.Encode(item, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding native to json: %v", err) | ||||
| 				} | ||||
| 				var uJSON runtime.Object = &metaunstruct.Unstructured{} | ||||
| 				uJSON, _, err = jsonSerializer.Decode(buf.Bytes(), &gvk, uJSON) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("error decoding json to unstructured: %v", err) | ||||
| 				} | ||||
|  | ||||
| 				// original->CBOR->Unstructured | ||||
| 				buf.Reset() | ||||
| 				if err := cborSerializer.Encode(item, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding native to cbor: %v", err) | ||||
| 				} | ||||
| 				var uCBOR runtime.Object = &metaunstruct.Unstructured{} | ||||
| 				uCBOR, _, err = cborSerializer.Decode(buf.Bytes(), &gvk, uCBOR) | ||||
| 				if err != nil { | ||||
| 					diag, _ := cbor.Diagnose(buf.Bytes()) | ||||
| 					t.Fatalf("error decoding cbor to unstructured: %v, diag: %s", err, diag) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON->Unstructured == original->CBOR->Unstructured | ||||
| 				if !apiequality.Semantic.DeepEqual(uJSON, uCBOR) { | ||||
| 					t.Fatalf("unstructured via json differed from unstructured via cbor: %v", cmp.Diff(uJSON, uCBOR)) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON/CBOR->Unstructured == original->JSON/CBOR->Unstructured->JSON->Unstructured | ||||
| 				buf.Reset() | ||||
| 				if err := jsonSerializer.Encode(uJSON, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding unstructured to json: %v", err) | ||||
| 				} | ||||
| 				var uJSON2 runtime.Object = &metaunstruct.Unstructured{} | ||||
| 				uJSON2, _, err = jsonSerializer.Decode(buf.Bytes(), &gvk, uJSON2) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("error decoding json to unstructured: %v", err) | ||||
| 				} | ||||
| 				if !apiequality.Semantic.DeepEqual(uJSON, uJSON2) { | ||||
| 					t.Errorf("object changed during native-json-unstructured-json-unstructured roundtrip, diff: %s", cmp.Diff(uJSON, uJSON2)) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON/CBOR->Unstructured == original->JSON/CBOR->Unstructured->CBOR->Unstructured | ||||
| 				buf.Reset() | ||||
| 				if err := cborSerializer.Encode(uCBOR, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding unstructured to cbor: %v", err) | ||||
| 				} | ||||
| 				var uCBOR2 runtime.Object = &metaunstruct.Unstructured{} | ||||
| 				uCBOR2, _, err = cborSerializer.Decode(buf.Bytes(), &gvk, uCBOR2) | ||||
| 				if err != nil { | ||||
| 					diag, _ := cbor.Diagnose(buf.Bytes()) | ||||
| 					t.Fatalf("error decoding cbor to unstructured: %v, diag: %s", err, diag) | ||||
| 				} | ||||
| 				if !apiequality.Semantic.DeepEqual(uCBOR, uCBOR2) { | ||||
| 					t.Errorf("object changed during native-cbor-unstructured-cbor-unstructured roundtrip, diff: %s", cmp.Diff(uCBOR, uCBOR2)) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON/CBOR->Unstructured->JSON->final == original | ||||
| 				buf.Reset() | ||||
| 				if err := jsonSerializer.Encode(uJSON, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding unstructured to json: %v", err) | ||||
| 				} | ||||
| 				finalJSON, _, err := jsonSerializer.Decode(buf.Bytes(), &gvk, nil) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("error decoding json to native: %v", err) | ||||
| 				} | ||||
| 				if !apiequality.Semantic.DeepEqual(item, finalJSON) { | ||||
| 					t.Errorf("object changed during native-json-unstructured-json-native roundtrip, diff: %s", cmp.Diff(item, finalJSON)) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON/CBOR->Unstructured->CBOR->final == original | ||||
| 				buf.Reset() | ||||
| 				if err := cborSerializer.Encode(uCBOR, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding unstructured to cbor: %v", err) | ||||
| 				} | ||||
| 				finalCBOR, _, err := cborSerializer.Decode(buf.Bytes(), &gvk, nil) | ||||
| 				if err != nil { | ||||
| 					diag, _ := cbor.Diagnose(buf.Bytes()) | ||||
| 					t.Fatalf("error decoding cbor to native: %v, diag: %s", err, diag) | ||||
| 				} | ||||
| 				if !apiequality.Semantic.DeepEqual(item, finalCBOR) { | ||||
| 					t.Errorf("object changed during native-cbor-unstructured-cbor-native roundtrip, diff: %s", cmp.Diff(item, finalCBOR)) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| 	roundtrip.RoundtripToUnstructured(t, legacyscheme.Scheme, FuzzerFuncs, skipped) | ||||
| } | ||||
|  | ||||
| func TestRoundTripWithEmptyCreationTimestamp(t *testing.T) { | ||||
|   | ||||
| @@ -0,0 +1,193 @@ | ||||
| /* | ||||
| Copyright 2024 The Kubernetes Authors. | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
|  | ||||
| package roundtrip | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"math/rand" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"k8s.io/apimachinery/pkg/api/apitesting/fuzzer" | ||||
| 	apiequality "k8s.io/apimachinery/pkg/api/equality" | ||||
| 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/serializer" | ||||
| 	cborserializer "k8s.io/apimachinery/pkg/runtime/serializer/cbor" | ||||
| 	cbor "k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct" | ||||
| 	jsonserializer "k8s.io/apimachinery/pkg/runtime/serializer/json" | ||||
| 	"k8s.io/apimachinery/pkg/util/sets" | ||||
|  | ||||
| 	"github.com/google/go-cmp/cmp" | ||||
| ) | ||||
|  | ||||
| // RoundtripToUnstructured verifies the roundtrip faithfulness of all external types in a scheme | ||||
| // from native to unstructured and back using both the JSON and CBOR serializers. The intermediate | ||||
| // unstructured objects produced by both encodings must be identical and be themselves | ||||
| // roundtrippable to JSON and CBOR. | ||||
| func RoundtripToUnstructured(t *testing.T, scheme *runtime.Scheme, funcs fuzzer.FuzzerFuncs, skipped sets.Set[schema.GroupVersionKind]) { | ||||
| 	codecs := serializer.NewCodecFactory(scheme) | ||||
|  | ||||
| 	seed := int64(time.Now().Nanosecond()) | ||||
| 	if override := os.Getenv("TEST_RAND_SEED"); len(override) > 0 { | ||||
| 		overrideSeed, err := strconv.ParseInt(override, 10, 64) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		seed = overrideSeed | ||||
| 		t.Logf("using overridden seed: %d", seed) | ||||
| 	} else { | ||||
| 		t.Logf("seed (override with TEST_RAND_SEED if desired): %d", seed) | ||||
| 	} | ||||
|  | ||||
| 	var buf bytes.Buffer | ||||
| 	for gvk := range scheme.AllKnownTypes() { | ||||
| 		if globalNonRoundTrippableTypes.Has(gvk.Kind) { | ||||
| 			continue | ||||
| 		} | ||||
| 		if gvk.Version == runtime.APIVersionInternal { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		subtestName := fmt.Sprintf("%s.%s/%s", gvk.Version, gvk.Group, gvk.Kind) | ||||
| 		if gvk.Group == "" { | ||||
| 			subtestName = fmt.Sprintf("%s/%s", gvk.Version, gvk.Kind) | ||||
| 		} | ||||
|  | ||||
| 		t.Run(subtestName, func(t *testing.T) { | ||||
| 			if skipped.Has(gvk) { | ||||
| 				t.Skip() | ||||
| 			} | ||||
|  | ||||
| 			fuzzer := fuzzer.FuzzerFor(funcs, rand.NewSource(seed), codecs) | ||||
|  | ||||
| 			for i := 0; i < 50; i++ { | ||||
| 				// 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 := scheme.New(schema.GroupVersion{Group: gvk.Group, Version: runtime.APIVersionInternal}.WithKind(gvk.Kind)) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("couldn't create internal object %v: %v", gvk.Kind, err) | ||||
| 				} | ||||
| 				fuzzer.Fuzz(internalObj) | ||||
|  | ||||
| 				item, err := scheme.New(gvk) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("couldn't create external object %v: %v", gvk.Kind, err) | ||||
| 				} | ||||
| 				if err := scheme.Convert(internalObj, item, nil); err != nil { | ||||
| 					t.Fatalf("conversion for %v failed: %v", gvk.Kind, err) | ||||
| 				} | ||||
|  | ||||
| 				// Decoding into Unstructured requires that apiVersion and kind be | ||||
| 				// serialized, so populate TypeMeta. | ||||
| 				item.GetObjectKind().SetGroupVersionKind(gvk) | ||||
|  | ||||
| 				jsonSerializer := jsonserializer.NewSerializerWithOptions(jsonserializer.DefaultMetaFactory, scheme, scheme, jsonserializer.SerializerOptions{}) | ||||
| 				cborSerializer := cborserializer.NewSerializer(scheme, scheme) | ||||
|  | ||||
| 				// original->JSON->Unstructured | ||||
| 				buf.Reset() | ||||
| 				if err := jsonSerializer.Encode(item, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding native to json: %v", err) | ||||
| 				} | ||||
| 				var uJSON runtime.Object = &unstructured.Unstructured{} | ||||
| 				uJSON, _, err = jsonSerializer.Decode(buf.Bytes(), &gvk, uJSON) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("error decoding json to unstructured: %v", err) | ||||
| 				} | ||||
|  | ||||
| 				// original->CBOR->Unstructured | ||||
| 				buf.Reset() | ||||
| 				if err := cborSerializer.Encode(item, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding native to cbor: %v", err) | ||||
| 				} | ||||
| 				var uCBOR runtime.Object = &unstructured.Unstructured{} | ||||
| 				uCBOR, _, err = cborSerializer.Decode(buf.Bytes(), &gvk, uCBOR) | ||||
| 				if err != nil { | ||||
| 					diag, _ := cbor.Diagnose(buf.Bytes()) | ||||
| 					t.Fatalf("error decoding cbor to unstructured: %v, diag: %s", err, diag) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON->Unstructured == original->CBOR->Unstructured | ||||
| 				if !apiequality.Semantic.DeepEqual(uJSON, uCBOR) { | ||||
| 					t.Fatalf("unstructured via json differed from unstructured via cbor: %v", cmp.Diff(uJSON, uCBOR)) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON/CBOR->Unstructured == original->JSON/CBOR->Unstructured->JSON->Unstructured | ||||
| 				buf.Reset() | ||||
| 				if err := jsonSerializer.Encode(uJSON, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding unstructured to json: %v", err) | ||||
| 				} | ||||
| 				var uJSON2 runtime.Object = &unstructured.Unstructured{} | ||||
| 				uJSON2, _, err = jsonSerializer.Decode(buf.Bytes(), &gvk, uJSON2) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("error decoding json to unstructured: %v", err) | ||||
| 				} | ||||
| 				if !apiequality.Semantic.DeepEqual(uJSON, uJSON2) { | ||||
| 					t.Errorf("object changed during native-json-unstructured-json-unstructured roundtrip, diff: %s", cmp.Diff(uJSON, uJSON2)) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON/CBOR->Unstructured == original->JSON/CBOR->Unstructured->CBOR->Unstructured | ||||
| 				buf.Reset() | ||||
| 				if err := cborSerializer.Encode(uCBOR, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding unstructured to cbor: %v", err) | ||||
| 				} | ||||
| 				var uCBOR2 runtime.Object = &unstructured.Unstructured{} | ||||
| 				uCBOR2, _, err = cborSerializer.Decode(buf.Bytes(), &gvk, uCBOR2) | ||||
| 				if err != nil { | ||||
| 					diag, _ := cbor.Diagnose(buf.Bytes()) | ||||
| 					t.Fatalf("error decoding cbor to unstructured: %v, diag: %s", err, diag) | ||||
| 				} | ||||
| 				if !apiequality.Semantic.DeepEqual(uCBOR, uCBOR2) { | ||||
| 					t.Errorf("object changed during native-cbor-unstructured-cbor-unstructured roundtrip, diff: %s", cmp.Diff(uCBOR, uCBOR2)) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON/CBOR->Unstructured->JSON->final == original | ||||
| 				buf.Reset() | ||||
| 				if err := jsonSerializer.Encode(uJSON, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding unstructured to json: %v", err) | ||||
| 				} | ||||
| 				finalJSON, _, err := jsonSerializer.Decode(buf.Bytes(), &gvk, nil) | ||||
| 				if err != nil { | ||||
| 					t.Fatalf("error decoding json to native: %v", err) | ||||
| 				} | ||||
| 				if !apiequality.Semantic.DeepEqual(item, finalJSON) { | ||||
| 					t.Errorf("object changed during native-json-unstructured-json-native roundtrip, diff: %s", cmp.Diff(item, finalJSON)) | ||||
| 				} | ||||
|  | ||||
| 				// original->JSON/CBOR->Unstructured->CBOR->final == original | ||||
| 				buf.Reset() | ||||
| 				if err := cborSerializer.Encode(uCBOR, &buf); err != nil { | ||||
| 					t.Fatalf("error encoding unstructured to cbor: %v", err) | ||||
| 				} | ||||
| 				finalCBOR, _, err := cborSerializer.Decode(buf.Bytes(), &gvk, nil) | ||||
| 				if err != nil { | ||||
| 					diag, _ := cbor.Diagnose(buf.Bytes()) | ||||
| 					t.Fatalf("error decoding cbor to native: %v, diag: %s", err, diag) | ||||
| 				} | ||||
| 				if !apiequality.Semantic.DeepEqual(item, finalCBOR) { | ||||
| 					t.Errorf("object changed during native-cbor-unstructured-cbor-native roundtrip, diff: %s", cmp.Diff(item, finalCBOR)) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Ben Luddy
					Ben Luddy