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 | package testing | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"bytes" |  | ||||||
| 	"fmt" |  | ||||||
| 	"math/rand" | 	"math/rand" | ||||||
| 	"os" |  | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"strconv" |  | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" |  | ||||||
|  |  | ||||||
| 	"github.com/google/go-cmp/cmp" | 	"github.com/google/go-cmp/cmp" | ||||||
| 	fuzz "github.com/google/gofuzz" | 	fuzz "github.com/google/gofuzz" | ||||||
|  |  | ||||||
| 	v1 "k8s.io/api/core/v1" | 	v1 "k8s.io/api/core/v1" | ||||||
| 	"k8s.io/apimachinery/pkg/api/apitesting/fuzzer" | 	"k8s.io/apimachinery/pkg/api/apitesting/fuzzer" | ||||||
|  | 	"k8s.io/apimachinery/pkg/api/apitesting/roundtrip" | ||||||
| 	apiequality "k8s.io/apimachinery/pkg/api/equality" | 	apiequality "k8s.io/apimachinery/pkg/api/equality" | ||||||
| 	"k8s.io/apimachinery/pkg/api/meta" | 	"k8s.io/apimachinery/pkg/api/meta" | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
| 	metaunstruct "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | 	metaunstruct "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||||||
| 	"k8s.io/apimachinery/pkg/runtime" | 	"k8s.io/apimachinery/pkg/runtime" | ||||||
| 	"k8s.io/apimachinery/pkg/runtime/schema" | 	"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/json" | ||||||
|  | 	"k8s.io/apimachinery/pkg/util/sets" | ||||||
| 	"k8s.io/kubernetes/pkg/api/legacyscheme" | 	"k8s.io/kubernetes/pkg/api/legacyscheme" | ||||||
| 	api "k8s.io/kubernetes/pkg/apis/core" | 	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) { | func TestRoundtripToUnstructured(t *testing.T) { | ||||||
| 	// These are GVKs that whose CBOR roundtrippability is blocked by a known issue that must be | 	skipped := sets.New( | ||||||
| 	// resolved as a prerequisite for alpha. | 		// TODO: Support cross-protocol RawExtension roundtrips. | ||||||
| 	knownFailureReasons := map[string][]schema.GroupVersionKind{ | 		schema.GroupVersionKind{Version: "v1", Kind: "List"}, | ||||||
| 		// If a RawExtension's bytes are invalid JSON, its containing object can't be encoded to JSON. | 		schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "ControllerRevision"}, | ||||||
| 		"rawextension needs to work in programs that assume json": { | 		schema.GroupVersionKind{Group: "apps", Version: "v1beta1", Kind: "ControllerRevisionList"}, | ||||||
| 			{Version: "v1", Kind: "List"}, | 		schema.GroupVersionKind{Group: "apps", Version: "v1beta2", Kind: "ControllerRevision"}, | ||||||
| 			{Group: "apps", Version: "v1beta1", Kind: "ControllerRevision"}, | 		schema.GroupVersionKind{Group: "apps", Version: "v1beta2", Kind: "ControllerRevisionList"}, | ||||||
| 			{Group: "apps", Version: "v1beta1", Kind: "ControllerRevisionList"}, | 		schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ControllerRevision"}, | ||||||
| 			{Group: "apps", Version: "v1beta2", Kind: "ControllerRevision"}, | 		schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "ControllerRevisionList"}, | ||||||
| 			{Group: "apps", Version: "v1beta2", Kind: "ControllerRevisionList"}, | 		schema.GroupVersionKind{Group: "admission.k8s.io", Version: "v1beta1", Kind: "AdmissionReview"}, | ||||||
| 			{Group: "apps", Version: "v1", Kind: "ControllerRevision"}, | 		schema.GroupVersionKind{Group: "admission.k8s.io", Version: "v1", Kind: "AdmissionReview"}, | ||||||
| 			{Group: "apps", Version: "v1", Kind: "ControllerRevisionList"}, | 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaim"}, | ||||||
| 			{Group: "admission.k8s.io", Version: "v1beta1", Kind: "AdmissionReview"}, | 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimList"}, | ||||||
| 			{Group: "admission.k8s.io", Version: "v1", Kind: "AdmissionReview"}, | 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimParameters"}, | ||||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaim"}, | 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimParametersList"}, | ||||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimList"}, | 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClassParameters"}, | ||||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimParameters"}, | 		schema.GroupVersionKind{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClassParametersList"}, | ||||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClaimParametersList"}, | 	) | ||||||
| 			{Group: "resource.k8s.io", Version: "v1alpha2", Kind: "ResourceClassParameters"}, |  | ||||||
| 			{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() { | 	for gvk := range legacyscheme.Scheme.AllKnownTypes() { | ||||||
| 		if nonRoundTrippableTypes.Has(gvk.Kind) { | 		if nonRoundTrippableTypes.Has(gvk.Kind) { | ||||||
| 			continue | 			skipped.Insert(gvk) | ||||||
| 		} |  | ||||||
| 		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) |  | ||||||
| 					} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			fuzzer := fuzzer.FuzzerFor(FuzzerFuncs, rand.NewSource(seed), legacyscheme.Codecs) | 	roundtrip.RoundtripToUnstructured(t, legacyscheme.Scheme, FuzzerFuncs, skipped) | ||||||
|  |  | ||||||
| 			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)) |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		}) |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestRoundTripWithEmptyCreationTimestamp(t *testing.T) { | 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