mirror of https://github.com/k3s-io/k3s
Merge pull request #45543 from sttts/sttts-external-roundtrip
Automatic merge from submit-queue (batch tested with PRs 45382, 45384, 44781, 45333, 45543) Do roundtrip testing with external kinds in client-go TPR example This tests that our serialization machinery works for TPR types, i.e. without internal counterpart and without generated code. /cc @nileboxpull/6/head
commit
aba95a169b
|
@ -38,6 +38,7 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
|
|
|
@ -36,6 +36,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
@ -125,24 +126,28 @@ func roundTripTypes(t *testing.T, scheme *runtime.Scheme, codecFactory runtimese
|
|||
}
|
||||
}
|
||||
|
||||
func RoundTripSpecificKindWithoutProtobuf(t *testing.T, internalGVK schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
|
||||
roundTripSpecificKind(t, internalGVK, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true)
|
||||
func RoundTripSpecificKindWithoutProtobuf(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
|
||||
roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true)
|
||||
}
|
||||
|
||||
func RoundTripSpecificKind(t *testing.T, internalGVK schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
|
||||
roundTripSpecificKind(t, internalGVK, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, false)
|
||||
func RoundTripSpecificKind(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
|
||||
roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, false)
|
||||
}
|
||||
|
||||
func roundTripSpecificKind(t *testing.T, internalGVK schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool, skipProtobuf bool) {
|
||||
if nonRoundTrippableTypes[internalGVK] {
|
||||
t.Logf("skipping %v", internalGVK)
|
||||
func roundTripSpecificKind(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool, skipProtobuf bool) {
|
||||
if nonRoundTrippableTypes[gvk] {
|
||||
t.Logf("skipping %v", gvk)
|
||||
return
|
||||
}
|
||||
t.Logf("round tripping %v", internalGVK)
|
||||
t.Logf("round tripping %v", gvk)
|
||||
|
||||
// Try a few times, since runTest uses random values.
|
||||
for i := 0; i < *FuzzIters; i++ {
|
||||
roundTripToAllExternalVersions(t, scheme, codecFactory, fuzzer, internalGVK, nonRoundTrippableTypes, skipProtobuf)
|
||||
if gvk.Version == runtime.APIVersionInternal {
|
||||
roundTripToAllExternalVersions(t, scheme, codecFactory, fuzzer, gvk, nonRoundTrippableTypes, skipProtobuf)
|
||||
} else {
|
||||
roundTripOfExternalType(t, scheme, codecFactory, fuzzer, gvk, skipProtobuf)
|
||||
}
|
||||
if t.Failed() {
|
||||
break
|
||||
}
|
||||
|
@ -209,10 +214,43 @@ func roundTripToAllExternalVersions(t *testing.T, scheme *runtime.Scheme, codecF
|
|||
}
|
||||
}
|
||||
|
||||
func roundTripOfExternalType(t *testing.T, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, externalGVK schema.GroupVersionKind, skipProtobuf bool) {
|
||||
object, err := scheme.New(externalGVK)
|
||||
if err != nil {
|
||||
t.Fatalf("Couldn't make a %v? %v", externalGVK, err)
|
||||
}
|
||||
typeAcc, err := meta.TypeAccessor(object)
|
||||
if err != nil {
|
||||
t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableInternalTypes: %v", externalGVK, err)
|
||||
}
|
||||
|
||||
fuzzInternalObject(t, fuzzer, object)
|
||||
|
||||
externalGoType := reflect.TypeOf(object).PkgPath()
|
||||
t.Logf("\tround tripping external type %v %v", externalGVK, externalGoType)
|
||||
|
||||
typeAcc.SetKind(externalGVK.Kind)
|
||||
typeAcc.SetAPIVersion(externalGVK.GroupVersion().String())
|
||||
|
||||
roundTrip(t, scheme, json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false), object)
|
||||
|
||||
// TODO remove this hack after we're past the intermediate steps
|
||||
if !skipProtobuf {
|
||||
roundTrip(t, scheme, protobuf.NewSerializer(scheme, scheme, "application/protobuf"), object)
|
||||
}
|
||||
}
|
||||
|
||||
// roundTrip applies a single round-trip test to the given runtime object
|
||||
// using the given codec. The round-trip test ensures that an object can be
|
||||
// deep-copied and converted from internal -> versioned -> internal without
|
||||
// loss of data.
|
||||
// deep-copied, converted, marshaled and back without loss of data.
|
||||
//
|
||||
// For internal types this means
|
||||
//
|
||||
// internal -> external -> json/protobuf -> external -> internal.
|
||||
//
|
||||
// For external types this means
|
||||
//
|
||||
// external -> json/protobuf -> external.
|
||||
func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object runtime.Object) {
|
||||
printer := spew.ConfigState{DisableMethods: true}
|
||||
original := object
|
||||
|
|
|
@ -122,6 +122,10 @@
|
|||
"ImportPath": "github.com/golang/groupcache/lru",
|
||||
"Rev": "02826c3e79038b59d737d3b1c0a1d937f71a4433"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/protobuf/proto",
|
||||
"Rev": "4bd1920723d7b7c925de087aa32e2187708897f7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/gofuzz",
|
||||
"Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c"
|
||||
|
@ -286,6 +290,10 @@
|
|||
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
|
||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery",
|
||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
|
|
@ -14,8 +14,11 @@ go_test(
|
|||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -17,8 +17,15 @@ limitations under the License.
|
|||
package v1
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/google/gofuzz"
|
||||
|
||||
apitesting "k8s.io/apimachinery/pkg/api/testing"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
var _ runtime.Object = &Example{}
|
||||
|
@ -26,3 +33,31 @@ var _ metav1.ObjectMetaAccessor = &Example{}
|
|||
|
||||
var _ runtime.Object = &ExampleList{}
|
||||
var _ metav1.ListMetaAccessor = &ExampleList{}
|
||||
|
||||
func exampleFuzzerFuncs(t apitesting.TestingCommon) []interface{} {
|
||||
return []interface{}{
|
||||
func(obj *ExampleList, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
obj.Items = make([]Example, c.Intn(10))
|
||||
for i := range obj.Items {
|
||||
c.Fuzz(&obj.Items[i])
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TestRoundTrip tests that the third-party kinds can be marshaled and unmarshaled correctly to/from JSON
|
||||
// without the loss of information. Moreover, deep copy is tested.
|
||||
func TestRoundTrip(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
|
||||
AddToScheme(scheme)
|
||||
|
||||
seed := rand.Int63()
|
||||
fuzzerFuncs := apitesting.MergeFuzzerFuncs(t, apitesting.GenericFuzzerFuncs(t, codecs), exampleFuzzerFuncs(t))
|
||||
fuzzer := apitesting.FuzzerFor(fuzzerFuncs, rand.NewSource(seed))
|
||||
|
||||
apitesting.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("Example"), scheme, codecs, fuzzer, nil)
|
||||
apitesting.RoundTripSpecificKindWithoutProtobuf(t, SchemeGroupVersion.WithKind("ExampleList"), scheme, codecs, fuzzer, nil)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue