From 7ab3e436f71ddfbfc372c49049eafe250992d5c5 Mon Sep 17 00:00:00 2001 From: wojtekt Date: Wed, 4 Dec 2019 10:34:40 +0100 Subject: [PATCH] Cleanup old-style conversions --- .../apimachinery/pkg/conversion/converter.go | 46 +-- .../pkg/conversion/converter_test.go | 317 ++++++++++-------- .../k8s.io/apimachinery/pkg/runtime/scheme.go | 39 --- .../apimachinery/pkg/runtime/scheme_test.go | 146 ++++---- 4 files changed, 257 insertions(+), 291 deletions(-) diff --git a/staging/src/k8s.io/apimachinery/pkg/conversion/converter.go b/staging/src/k8s.io/apimachinery/pkg/conversion/converter.go index eaed33fc367..fac22b5a6f6 100644 --- a/staging/src/k8s.io/apimachinery/pkg/conversion/converter.go +++ b/staging/src/k8s.io/apimachinery/pkg/conversion/converter.go @@ -93,7 +93,12 @@ func NewConverter(nameFn NameFunc) *Converter { inputFieldMappingFuncs: make(map[reflect.Type]FieldMappingFunc), inputDefaultFlags: make(map[reflect.Type]FieldMatchingFlags), } - c.RegisterConversionFunc(Convert_Slice_byte_To_Slice_byte) + c.RegisterUntypedConversionFunc( + (*[]byte)(nil), (*[]byte)(nil), + func(a, b interface{}, s Scope) error { + return Convert_Slice_byte_To_Slice_byte(a.(*[]byte), b.(*[]byte), s) + }, + ) return c } @@ -159,25 +164,11 @@ func NewConversionFuncs() ConversionFuncs { } type ConversionFuncs struct { + // FIXME: Remove. fns map[typePair]reflect.Value untyped map[typePair]ConversionFunc } -// Add adds the provided conversion functions to the lookup table - they must have the signature -// `func(type1, type2, Scope) error`. Functions are added in the order passed and will override -// previously registered pairs. -func (c ConversionFuncs) Add(fns ...interface{}) error { - for _, fn := range fns { - fv := reflect.ValueOf(fn) - ft := fv.Type() - if err := verifyConversionFunctionSignature(ft); err != nil { - return err - } - c.fns[typePair{ft.In(0).Elem(), ft.In(1).Elem()}] = fv - } - return nil -} - // AddUntyped adds the provided conversion function to the lookup table for the types that are // supplied as a and b. a and b must be pointers or an error is returned. This method overwrites // previously defined functions. @@ -360,29 +351,6 @@ func verifyConversionFunctionSignature(ft reflect.Type) error { return nil } -// RegisterConversionFunc registers a conversion func with the -// Converter. conversionFunc must take three parameters: a pointer to the input -// type, a pointer to the output type, and a conversion.Scope (which should be -// used if recursive conversion calls are desired). It must return an error. -// -// Example: -// c.RegisterConversionFunc( -// func(in *Pod, out *v1.Pod, s Scope) error { -// // conversion logic... -// return nil -// }) -// DEPRECATED: Will be removed in favor of RegisterUntypedConversionFunc -func (c *Converter) RegisterConversionFunc(conversionFunc interface{}) error { - return c.conversionFuncs.Add(conversionFunc) -} - -// Similar to RegisterConversionFunc, but registers conversion function that were -// automatically generated. -// DEPRECATED: Will be removed in favor of RegisterGeneratedUntypedConversionFunc -func (c *Converter) RegisterGeneratedConversionFunc(conversionFunc interface{}) error { - return c.generatedConversionFuncs.Add(conversionFunc) -} - // RegisterUntypedConversionFunc registers a function that converts between a and b by passing objects of those // types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce // any other guarantee. diff --git a/staging/src/k8s.io/apimachinery/pkg/conversion/converter_test.go b/staging/src/k8s.io/apimachinery/pkg/conversion/converter_test.go index b13ffece28d..2c1e7a5c642 100644 --- a/staging/src/k8s.io/apimachinery/pkg/conversion/converter_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/conversion/converter_test.go @@ -111,24 +111,26 @@ func TestConverter_byteSlice(t *testing.T) { func TestConverter_MismatchedTypes(t *testing.T) { c := NewConverter(DefaultNameFunc) - err := c.RegisterConversionFunc( - func(in *[]string, out *int, s Scope) error { - if str, err := strconv.Atoi((*in)[0]); err != nil { - return err - } else { - *out = str - return nil - } + convertFn := func(in *[]string, out *int, s Scope) error { + if str, err := strconv.Atoi((*in)[0]); err != nil { + return err + } else { + *out = str + return nil + } + } + if err := c.RegisterUntypedConversionFunc( + (*[]string)(nil), (*int)(nil), + func(a, b interface{}, s Scope) error { + return convertFn(a.(*[]string), b.(*int), s) }, - ) - if err != nil { + ); err != nil { t.Fatalf("Unexpected error: %v", err) } src := []string{"5"} var dest *int - err = c.Convert(&src, &dest, 0, nil) - if err != nil { + if err := c.Convert(&src, &dest, 0, nil); err != nil { t.Fatalf("unexpected error: %v", err) } if e, a := 5, *dest; e != a { @@ -136,47 +138,6 @@ func TestConverter_MismatchedTypes(t *testing.T) { } } -func TestConverter_DefaultConvert(t *testing.T) { - type A struct { - Foo string - Baz int - } - type B struct { - Bar string - Baz int - } - c := NewConverter(DefaultNameFunc) - c.Debug = testLogger(t) - c.nameFunc = func(t reflect.Type) string { return "MyType" } - - // Ensure conversion funcs can call DefaultConvert to get default behavior, - // then fixup remaining fields manually - err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { - if err := s.DefaultConvert(in, out, IgnoreMissingFields); err != nil { - return err - } - out.Bar = in.Foo - return nil - }) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - - x := A{"hello, intrepid test reader!", 3} - y := B{} - - err = c.Convert(&x, &y, 0, nil) - if err != nil { - t.Fatalf("unexpected error %v", err) - } - if e, a := x.Foo, y.Bar; e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := x.Baz, y.Baz; e != a { - t.Errorf("expected %v, got %v", e, a) - } -} - func TestConverter_DeepCopy(t *testing.T) { type A struct { Foo *string @@ -229,26 +190,35 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) { type C struct{} c := NewConverter(DefaultNameFunc) c.Debug = testLogger(t) - err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { + convertFn1 := func(in *A, out *B, s Scope) error { out.Bar = in.Foo return s.Convert(&in.Baz, &out.Baz, 0) - }) - if err != nil { + } + if err := c.RegisterUntypedConversionFunc( + (*A)(nil), (*B)(nil), + func(a, b interface{}, s Scope) error { + return convertFn1(a.(*A), b.(*B), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } - err = c.RegisterConversionFunc(func(in *B, out *A, s Scope) error { + convertFn2 := func(in *B, out *A, s Scope) error { out.Foo = in.Bar return s.Convert(&in.Baz, &out.Baz, 0) - }) - if err != nil { + } + if err := c.RegisterUntypedConversionFunc( + (*B)(nil), (*A)(nil), + func(a, b interface{}, s Scope) error { + return convertFn2(a.(*B), b.(*A), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } x := A{"hello, intrepid test reader!", 3} y := B{} - err = c.Convert(&x, &y, 0, nil) - if err != nil { + if err := c.Convert(&x, &y, 0, nil); err != nil { t.Fatalf("unexpected error %v", err) } if e, a := x.Foo, y.Bar; e != a { @@ -261,8 +231,7 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) { z := B{"all your test are belong to us", 42} w := A{} - err = c.Convert(&z, &w, 0, nil) - if err != nil { + if err := c.Convert(&z, &w, 0, nil); err != nil { t.Fatalf("unexpected error %v", err) } if e, a := z.Bar, w.Foo; e != a { @@ -272,14 +241,18 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) { t.Errorf("expected %v, got %v", e, a) } - err = c.RegisterConversionFunc(func(in *A, out *C, s Scope) error { + convertFn3 := func(in *A, out *C, s Scope) error { return fmt.Errorf("C can't store an A, silly") - }) - if err != nil { + } + if err := c.RegisterUntypedConversionFunc( + (*A)(nil), (*C)(nil), + func(a, b interface{}, s Scope) error { + return convertFn3(a.(*A), b.(*C), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } - err = c.Convert(&A{}, &C{}, 0, nil) - if err == nil { + if err := c.Convert(&A{}, &C{}, 0, nil); err == nil { t.Errorf("unexpected non-error") } } @@ -290,10 +263,16 @@ func TestConverter_IgnoredConversion(t *testing.T) { count := 0 c := NewConverter(DefaultNameFunc) - if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { + convertFn := func(in *A, out *B, s Scope) error { count++ return nil - }); err != nil { + } + if err := c.RegisterUntypedConversionFunc( + (*A)(nil), (*B)(nil), + func(a, b interface{}, s Scope) error { + return convertFn(a.(*A), b.(*B), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } if err := c.RegisterIgnoredConversion(&A{}, &B{}); err != nil { @@ -337,14 +316,26 @@ func TestConverter_GeneratedConversionOverridden(t *testing.T) { type A struct{} type B struct{} c := NewConverter(DefaultNameFunc) - if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { + convertFn1 := func(in *A, out *B, s Scope) error { return nil - }); err != nil { + } + if err := c.RegisterUntypedConversionFunc( + (*A)(nil), (*B)(nil), + func(a, b interface{}, s Scope) error { + return convertFn1(a.(*A), b.(*B), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } - if err := c.RegisterGeneratedConversionFunc(func(in *A, out *B, s Scope) error { + convertFn2 := func(in *A, out *B, s Scope) error { return fmt.Errorf("generated function should be overridden") - }); err != nil { + } + if err := c.RegisterGeneratedUntypedConversionFunc( + (*A)(nil), (*B)(nil), + func(a, b interface{}, s Scope) error { + return convertFn2(a.(*A), b.(*B), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } @@ -359,21 +350,36 @@ func TestConverter_WithConversionOverridden(t *testing.T) { type A struct{} type B struct{} c := NewConverter(DefaultNameFunc) - if err := c.RegisterConversionFunc(func(in *A, out *B, s Scope) error { + convertFn1 := func(in *A, out *B, s Scope) error { return fmt.Errorf("conversion function should be overridden") - }); err != nil { + } + if err := c.RegisterUntypedConversionFunc( + (*A)(nil), (*B)(nil), + func(a, b interface{}, s Scope) error { + return convertFn1(a.(*A), b.(*B), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } - if err := c.RegisterGeneratedConversionFunc(func(in *A, out *B, s Scope) error { + convertFn2 := func(in *A, out *B, s Scope) error { return fmt.Errorf("generated function should be overridden") - }); err != nil { + } + if err := c.RegisterGeneratedUntypedConversionFunc( + (*A)(nil), (*B)(nil), + func(a, b interface{}, s Scope) error { + return convertFn2(a.(*A), b.(*B), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } ext := NewConversionFuncs() - ext.Add(func(in *A, out *B, s Scope) error { - return nil - }) + ext.AddUntyped( + (*A)(nil), (*B)(nil), + func(a, b interface{}, s Scope) error { + return nil + }, + ) newc := c.WithConversions(ext) a := A{} @@ -394,13 +400,19 @@ func TestConverter_MapsStringArrays(t *testing.T) { } c := NewConverter(DefaultNameFunc) c.Debug = testLogger(t) - if err := c.RegisterConversionFunc(func(input *[]string, out *string, s Scope) error { + convertFn1 := func(input *[]string, out *string, s Scope) error { if len(*input) == 0 { *out = "" } *out = (*input)[0] return nil - }); err != nil { + } + if err := c.RegisterUntypedConversionFunc( + (*[]string)(nil), (*string)(nil), + func(a, b interface{}, s Scope) error { + return convertFn1(a.(*[]string), b.(*string), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } @@ -416,7 +428,7 @@ func TestConverter_MapsStringArrays(t *testing.T) { t.Error("unexpected non-error") } - if err := c.RegisterConversionFunc(func(input *[]string, out *int, s Scope) error { + convertFn2 := func(input *[]string, out *int, s Scope) error { if len(*input) == 0 { *out = 0 } @@ -427,7 +439,13 @@ func TestConverter_MapsStringArrays(t *testing.T) { } *out = i return nil - }); err != nil { + } + if err := c.RegisterUntypedConversionFunc( + (*[]string)(nil), (*int)(nil), + func(a, b interface{}, s Scope) error { + return convertFn2(a.(*[]string), b.(*int), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } @@ -447,13 +465,19 @@ func TestConverter_MapsStringArraysWithMappingKey(t *testing.T) { } c := NewConverter(DefaultNameFunc) c.Debug = testLogger(t) - if err := c.RegisterConversionFunc(func(input *[]string, out *string, s Scope) error { + convertFn := func(input *[]string, out *string, s Scope) error { if len(*input) == 0 { *out = "" } *out = (*input)[0] return nil - }); err != nil { + } + if err := c.RegisterUntypedConversionFunc( + (*[]string)(nil), (*string)(nil), + func(a, b interface{}, s Scope) error { + return convertFn(a.(*[]string), b.(*string), s) + }, + ); err != nil { t.Fatalf("unexpected error %v", err) } @@ -536,39 +560,43 @@ func TestConverter_MapElemAddr(t *testing.T) { } c := NewConverter(DefaultNameFunc) c.Debug = testLogger(t) - err := c.RegisterConversionFunc( - func(in *int, out *string, s Scope) error { - *out = fmt.Sprintf("%v", *in) - return nil + convertFn1 := func(in *int, out *string, s Scope) error { + *out = fmt.Sprintf("%v", *in) + return nil + } + if err := c.RegisterUntypedConversionFunc( + (*int)(nil), (*string)(nil), + func(a, b interface{}, s Scope) error { + return convertFn1(a.(*int), b.(*string), s) }, - ) - if err != nil { + ); err != nil { t.Fatalf("Unexpected error: %v", err) } - err = c.RegisterConversionFunc( - func(in *string, out *int, s Scope) error { - if str, err := strconv.Atoi(*in); err != nil { - return err - } else { - *out = str - return nil - } + convertFn2 := func(in *string, out *int, s Scope) error { + if str, err := strconv.Atoi(*in); err != nil { + return err + } else { + *out = str + return nil + } + } + if err := c.RegisterUntypedConversionFunc( + (*string)(nil), (*int)(nil), + func(a, b interface{}, s Scope) error { + return convertFn2(a.(*string), b.(*int), s) }, - ) - if err != nil { + ); err != nil { t.Fatalf("Unexpected error: %v", err) } f := fuzz.New().NilChance(0).NumElements(3, 3) first := Foo{} second := Bar{} f.Fuzz(&first) - err = c.Convert(&first, &second, AllowDifferentFieldTypeNames, nil) - if err != nil { + if err := c.Convert(&first, &second, AllowDifferentFieldTypeNames, nil); err != nil { t.Fatalf("Unexpected error: %v", err) } third := Foo{} - err = c.Convert(&second, &third, AllowDifferentFieldTypeNames, nil) - if err != nil { + if err := c.Convert(&second, &third, AllowDifferentFieldTypeNames, nil); err != nil { t.Fatalf("error on Convert: %v", err) } if e, a := first, third; !reflect.DeepEqual(e, a) { @@ -585,22 +613,24 @@ func TestConverter_tags(t *testing.T) { } c := NewConverter(DefaultNameFunc) c.Debug = testLogger(t) - err := c.RegisterConversionFunc( - func(in *string, out *string, s Scope) error { - if e, a := "foo", s.SrcTag().Get("test"); e != a { - t.Errorf("expected %v, got %v", e, a) - } - if e, a := "bar", s.DestTag().Get("test"); e != a { - t.Errorf("expected %v, got %v", e, a) - } - return nil + convertFn := func(in *string, out *string, s Scope) error { + if e, a := "foo", s.SrcTag().Get("test"); e != a { + t.Errorf("expected %v, got %v", e, a) + } + if e, a := "bar", s.DestTag().Get("test"); e != a { + t.Errorf("expected %v, got %v", e, a) + } + return nil + } + if err := c.RegisterUntypedConversionFunc( + (*string)(nil), (*string)(nil), + func(a, b interface{}, s Scope) error { + return convertFn(a.(*string), b.(*string), s) }, - ) - if err != nil { + ); err != nil { t.Fatalf("Unexpected error: %v", err) } - err = c.Convert(&Foo{}, &Bar{}, AllowDifferentFieldTypeNames, nil) - if err != nil { + if err := c.Convert(&Foo{}, &Bar{}, AllowDifferentFieldTypeNames, nil); err != nil { t.Fatalf("Unexpected error: %v", err) } } @@ -611,33 +641,38 @@ func TestConverter_meta(t *testing.T) { c := NewConverter(DefaultNameFunc) c.Debug = testLogger(t) checks := 0 - err := c.RegisterConversionFunc( - func(in *Foo, out *Bar, s Scope) error { - if s.Meta() == nil { - t.Errorf("Meta did not get passed!") - } - checks++ - s.Convert(&in.A, &out.A, 0) - return nil + convertFn1 := func(in *Foo, out *Bar, s Scope) error { + if s.Meta() == nil { + t.Errorf("Meta did not get passed!") + } + checks++ + s.Convert(&in.A, &out.A, 0) + return nil + } + if err := c.RegisterUntypedConversionFunc( + (*Foo)(nil), (*Bar)(nil), + func(a, b interface{}, s Scope) error { + return convertFn1(a.(*Foo), b.(*Bar), s) }, - ) - if err != nil { + ); err != nil { t.Fatalf("Unexpected error: %v", err) } - err = c.RegisterConversionFunc( - func(in *string, out *string, s Scope) error { - if s.Meta() == nil { - t.Errorf("Meta did not get passed a second time!") - } - checks++ - return nil + convertFn2 := func(in *string, out *string, s Scope) error { + if s.Meta() == nil { + t.Errorf("Meta did not get passed a second time!") + } + checks++ + return nil + } + if err := c.RegisterUntypedConversionFunc( + (*string)(nil), (*string)(nil), + func(a, b interface{}, s Scope) error { + return convertFn2(a.(*string), b.(*string), s) }, - ) - if err != nil { + ); err != nil { t.Fatalf("Unexpected error: %v", err) } - err = c.Convert(&Foo{}, &Bar{}, 0, &Meta{}) - if err != nil { + if err := c.Convert(&Foo{}, &Bar{}, 0, &Meta{}); err != nil { t.Fatalf("Unexpected error: %v", err) } if checks != 2 { diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go b/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go index c21ed0499ae..4b739ec38fe 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/scheme.go @@ -308,45 +308,6 @@ func (s *Scheme) AddIgnoredConversionType(from, to interface{}) error { return s.converter.RegisterIgnoredConversion(from, to) } -// AddConversionFuncs adds functions to the list of conversion functions. The given -// functions should know how to convert between two of your API objects, or their -// sub-objects. We deduce how to call these functions from the types of their two -// parameters; see the comment for Converter.Register. -// -// Note that, if you need to copy sub-objects that didn't change, you can use the -// conversion.Scope object that will be passed to your conversion function. -// Additionally, all conversions started by Scheme will set the SrcVersion and -// DestVersion fields on the Meta object. Example: -// -// s.AddConversionFuncs( -// func(in *InternalObject, out *ExternalObject, scope conversion.Scope) error { -// // You can depend on Meta() being non-nil, and this being set to -// // the source version, e.g., "" -// s.Meta().SrcVersion -// // You can depend on this being set to the destination version, -// // e.g., "v1". -// s.Meta().DestVersion -// // Call scope.Convert to copy sub-fields. -// s.Convert(&in.SubFieldThatMoved, &out.NewLocation.NewName, 0) -// return nil -// }, -// ) -// -// (For more detail about conversion functions, see Converter.Register's comment.) -// -// Also note that the default behavior, if you don't add a conversion function, is to -// sanely copy fields that have the same names and same type names. It's OK if the -// destination type has extra fields, but it must not remove any. So you only need to -// add conversion functions for things with changed/removed fields. -func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error { - for _, f := range conversionFuncs { - if err := s.converter.RegisterConversionFunc(f); err != nil { - return err - } - } - return nil -} - // AddConversionFunc registers a function that converts between a and b by passing objects of those // types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce // any other guarantee. diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/scheme_test.go b/staging/src/k8s.io/apimachinery/pkg/runtime/scheme_test.go index d4881fe5c86..e53765bd3e9 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/scheme_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/scheme_test.go @@ -31,6 +31,47 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" ) +type testConversions struct { + internalToExternalCalls int + externalToInternalCalls int +} + +func (c *testConversions) internalToExternalSimple(in *runtimetesting.InternalSimple, out *runtimetesting.ExternalSimple, scope conversion.Scope) error { + if err := scope.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { + return err + } + if err := scope.Convert(&in.TestString, &out.TestString, 0); err != nil { + return err + } + c.internalToExternalCalls++ + return nil +} + +func (c *testConversions) externalToInternalSimple(in *runtimetesting.ExternalSimple, out *runtimetesting.InternalSimple, scope conversion.Scope) error { + if err := scope.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { + return err + } + if err := scope.Convert(&in.TestString, &out.TestString, 0); err != nil { + return err + } + c.externalToInternalCalls++ + return nil +} + +func (c *testConversions) registerConversions(s *runtime.Scheme) error { + if err := s.AddConversionFunc((*runtimetesting.InternalSimple)(nil), (*runtimetesting.ExternalSimple)(nil), func(a, b interface{}, scope conversion.Scope) error { + return c.internalToExternalSimple(a.(*runtimetesting.InternalSimple), b.(*runtimetesting.ExternalSimple), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*runtimetesting.ExternalSimple)(nil), (*runtimetesting.InternalSimple)(nil), func(a, b interface{}, scope conversion.Scope) error { + return c.externalToInternalSimple(a.(*runtimetesting.ExternalSimple), b.(*runtimetesting.InternalSimple), scope) + }); err != nil { + return err + } + return nil +} + func TestScheme(t *testing.T) { internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} internalGVK := internalGV.WithKind("Simple") @@ -47,37 +88,13 @@ func TestScheme(t *testing.T) { // test that scheme is an ObjectTyper var _ runtime.ObjectTyper = scheme - internalToExternalCalls := 0 - externalToInternalCalls := 0 + conversions := &testConversions{ + internalToExternalCalls: 0, + externalToInternalCalls: 0, + } // Register functions to verify that scope.Meta() gets set correctly. - err := scheme.AddConversionFuncs( - func(in *runtimetesting.InternalSimple, out *runtimetesting.ExternalSimple, scope conversion.Scope) error { - err := scope.Convert(&in.TypeMeta, &out.TypeMeta, 0) - if err != nil { - return err - } - err = scope.Convert(&in.TestString, &out.TestString, 0) - if err != nil { - return err - } - internalToExternalCalls++ - return nil - }, - func(in *runtimetesting.ExternalSimple, out *runtimetesting.InternalSimple, scope conversion.Scope) error { - err := scope.Convert(&in.TypeMeta, &out.TypeMeta, 0) - if err != nil { - return err - } - err = scope.Convert(&in.TestString, &out.TestString, 0) - if err != nil { - return err - } - externalToInternalCalls++ - return nil - }, - ) - if err != nil { + if err := conversions.registerConversions(scheme); err != nil { t.Fatalf("unexpected error: %v", err) } @@ -133,8 +150,7 @@ func TestScheme(t *testing.T) { } external := &runtimetesting.ExternalSimple{} - err = scheme.Convert(simple, external, nil) - if err != nil { + if err := scheme.Convert(simple, external, nil); err != nil { t.Fatalf("Unexpected error: %v", err) } if e, a := simple.TestString, external.TestString; e != a { @@ -147,12 +163,11 @@ func TestScheme(t *testing.T) { } unstructuredObj := &runtimetesting.Unstructured{} - err = scheme.Convert(simple, unstructuredObj, nil) + err := scheme.Convert(simple, unstructuredObj, nil) if err == nil || !strings.Contains(err.Error(), "to Unstructured without providing a preferred version to convert to") { t.Fatalf("Unexpected non-error: %v", err) } - err = scheme.Convert(simple, unstructuredObj, externalGV) - if err != nil { + if err := scheme.Convert(simple, unstructuredObj, externalGV); err != nil { t.Fatalf("Unexpected error: %v", err) } if e, a := simple.TestString, unstructuredObj.Object["testString"].(string); e != a { @@ -171,8 +186,7 @@ func TestScheme(t *testing.T) { TestString: "foo", } - err = scheme.Convert(external, unstructuredObj, nil) - if err != nil { + if err := scheme.Convert(external, unstructuredObj, nil); err != nil { t.Fatalf("Unexpected error: %v", err) } if e, a := external.TestString, unstructuredObj.Object["testString"].(string); e != a { @@ -187,8 +201,7 @@ func TestScheme(t *testing.T) { "test": []interface{}{"other", "test"}, }} uOut := &runtimetesting.Unstructured{} - err = scheme.Convert(uIn, uOut, nil) - if err != nil { + if err := scheme.Convert(uIn, uOut, nil); err != nil { t.Fatalf("Unexpected error: %v", err) } if !reflect.DeepEqual(uIn.Object, uOut.Object) { @@ -203,8 +216,7 @@ func TestScheme(t *testing.T) { } unstructuredObj.SetGroupVersionKind(externalGV.WithKind("Simple")) externalOut := &runtimetesting.ExternalSimple{} - err = scheme.Convert(unstructuredObj, externalOut, nil) - if err != nil { + if err := scheme.Convert(unstructuredObj, externalOut, nil); err != nil { t.Fatalf("Unexpected error: %v", err) } if externalOut.TestString != "bla" { @@ -212,12 +224,12 @@ func TestScheme(t *testing.T) { } }) t.Run("Encode and Convert should each have caused an increment", func(t *testing.T) { - if e, a := 3, internalToExternalCalls; e != a { + if e, a := 3, conversions.internalToExternalCalls; e != a { t.Errorf("Expected %v, got %v", e, a) } }) t.Run("DecodeInto and Decode should each have caused an increment because of a conversion", func(t *testing.T) { - if e, a := 2, externalToInternalCalls; e != a { + if e, a := 2, conversions.externalToInternalCalls; e != a { t.Errorf("Expected %v, got %v", e, a) } }) @@ -481,9 +493,12 @@ func GetTestScheme() *runtime.Scheme { s.AddKnownTypeWithName(differentExternalGV.WithKind("TestType1"), &runtimetesting.ExternalTestType1{}) s.AddUnversionedTypes(externalGV, &runtimetesting.UnversionedType{}) - utilruntime.Must(s.AddConversionFuncs(func(in *runtimetesting.TestType1, out *runtimetesting.ExternalTestType1, s conversion.Scope) error { + convertTestType := func(in *runtimetesting.TestType1, out *runtimetesting.ExternalTestType1, s conversion.Scope) error { out.A = in.A return nil + } + utilruntime.Must(s.AddConversionFunc((*runtimetesting.TestType1)(nil), (*runtimetesting.ExternalTestType1)(nil), func(a, b interface{}, scope conversion.Scope) error { + return convertTestType(a.(*runtimetesting.TestType1), b.(*runtimetesting.ExternalTestType1), scope) })) return s } @@ -931,25 +946,13 @@ func TestMetaValues(t *testing.T) { s.AddKnownTypeWithName(internalGV.WithKind("Simple"), &runtimetesting.InternalSimple{}) s.AddKnownTypeWithName(externalGV.WithKind("Simple"), &runtimetesting.ExternalSimple{}) - internalToExternalCalls := 0 - externalToInternalCalls := 0 + conversions := &testConversions{ + internalToExternalCalls: 0, + externalToInternalCalls: 0, + } // Register functions to verify that scope.Meta() gets set correctly. - err := s.AddConversionFuncs( - func(in *runtimetesting.InternalSimple, out *runtimetesting.ExternalSimple, scope conversion.Scope) error { - t.Logf("internal -> external") - scope.Convert(&in.TestString, &out.TestString, 0) - internalToExternalCalls++ - return nil - }, - func(in *runtimetesting.ExternalSimple, out *runtimetesting.InternalSimple, scope conversion.Scope) error { - t.Logf("external -> internal") - scope.Convert(&in.TestString, &out.TestString, 0) - externalToInternalCalls++ - return nil - }, - ) - if err != nil { + if err := conversions.registerConversions(s); err != nil { t.Fatalf("unexpected error: %v", err) } simple := &runtimetesting.InternalSimple{ @@ -972,10 +975,10 @@ func TestMetaValues(t *testing.T) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", e, a) } - if e, a := 1, internalToExternalCalls; e != a { + if e, a := 1, conversions.internalToExternalCalls; e != a { t.Errorf("Expected %v, got %v", e, a) } - if e, a := 1, externalToInternalCalls; e != a { + if e, a := 1, conversions.externalToInternalCalls; e != a { t.Errorf("Expected %v, got %v", e, a) } } @@ -997,21 +1000,20 @@ func TestMetaValuesUnregisteredConvert(t *testing.T) { internalToExternalCalls := 0 // Register functions to verify that scope.Meta() gets set correctly. - err := s.AddConversionFuncs( - func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error { - scope.Convert(&in.TestString, &out.TestString, 0) - internalToExternalCalls++ - return nil - }, - ) - if err != nil { + convertSimple := func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error { + scope.Convert(&in.TestString, &out.TestString, 0) + internalToExternalCalls++ + return nil + } + if err := s.AddConversionFunc((*InternalSimple)(nil), (*ExternalSimple)(nil), func(a, b interface{}, scope conversion.Scope) error { + return convertSimple(a.(*InternalSimple), b.(*ExternalSimple), scope) + }); err != nil { t.Fatalf("unexpected error: %v", err) } simple := &InternalSimple{TestString: "foo"} external := &ExternalSimple{} - err = s.Convert(simple, external, nil) - if err != nil { + if err := s.Convert(simple, external, nil); err != nil { t.Fatalf("Unexpected error: %v", err) } if e, a := simple.TestString, external.TestString; e != a {