Cleanup old-style conversions

This commit is contained in:
wojtekt 2019-12-04 10:34:40 +01:00
parent ab6cbd2e8d
commit 7ab3e436f7
4 changed files with 257 additions and 291 deletions

View File

@ -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.

View File

@ -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 {

View File

@ -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.

View File

@ -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 {