diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/register.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/register.go index c64fa4f0b9a..ceb6452781d 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/register.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/register.go @@ -47,19 +47,6 @@ func addToGroupVersion(scheme *runtime.Scheme) error { if err := scheme.AddIgnoredConversionType(&metav1.TypeMeta{}, &metav1.TypeMeta{}); err != nil { return err } - err := scheme.AddConversionFuncs( - metav1.Convert_string_To_labels_Selector, - metav1.Convert_labels_Selector_To_string, - - metav1.Convert_string_To_fields_Selector, - metav1.Convert_fields_Selector_To_string, - - metav1.Convert_Map_string_To_string_To_v1_LabelSelector, - metav1.Convert_v1_LabelSelector_To_Map_string_To_string, - ) - if err != nil { - return err - } // ListOptions is the only options struct which needs conversion (it exposes labels and fields // as selectors for convenience). The other types have only a single representation today. scheme.AddKnownTypes(SchemeGroupVersion, diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/register.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/register.go index 31f3fe11425..c1a077178bf 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/register.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/register.go @@ -95,9 +95,7 @@ func AddMetaToScheme(scheme *runtime.Scheme) error { &PartialObjectMetadataList{}, ) - return scheme.AddConversionFuncs( - Convert_Slice_string_To_v1_IncludeObjectPolicy, - ) + return nil } func init() { diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/BUILD b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/BUILD index a6fe14401de..6cba6c2aa46 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/BUILD +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/BUILD @@ -21,7 +21,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/github.com/gogo/protobuf/proto:go_default_library", ], ) diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go index 5fae30ae81d..dd6f5475c80 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.pb.go @@ -81,28 +81,27 @@ func init() { } var fileDescriptor_90ec10f86b91f9a8 = []byte{ - // 321 bytes of a gzipped FileDescriptorProto + // 317 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x41, 0x4b, 0xf3, 0x30, - 0x18, 0xc7, 0x9b, 0xf7, 0x65, 0x38, 0x3a, 0x04, 0xd9, 0x69, 0xee, 0x90, 0x0d, 0x4f, 0xf3, 0xb0, - 0x84, 0x0d, 0x11, 0xc1, 0xdb, 0x6e, 0x82, 0xa2, 0xec, 0x28, 0x1e, 0x4c, 0xbb, 0xc7, 0x2e, 0xd6, - 0x34, 0x25, 0x79, 0x3a, 0xf0, 0xe6, 0x47, 0xf0, 0x63, 0xed, 0xb8, 0xe3, 0x40, 0x18, 0xae, 0x7e, - 0x11, 0x49, 0x57, 0x45, 0xa6, 0x62, 0x6f, 0x79, 0xfe, 0xe1, 0xf7, 0xcb, 0x3f, 0x89, 0x3f, 0x8e, - 0x4f, 0x2c, 0x93, 0x9a, 0xc7, 0x59, 0x00, 0x26, 0x01, 0x04, 0xcb, 0x67, 0x90, 0x4c, 0xb4, 0xe1, - 0xe5, 0x86, 0x48, 0xa5, 0x12, 0xe1, 0x54, 0x26, 0x60, 0x1e, 0x79, 0x1a, 0x47, 0x2e, 0xb0, 0x5c, - 0x01, 0x0a, 0x3e, 0x1b, 0x04, 0x80, 0x62, 0xc0, 0x23, 0x48, 0xc0, 0x08, 0x84, 0x09, 0x4b, 0x8d, - 0x46, 0xdd, 0x3c, 0xdc, 0xa0, 0xec, 0x2b, 0xca, 0xd2, 0x38, 0x72, 0x81, 0x65, 0x0e, 0x65, 0x25, - 0xda, 0xee, 0x47, 0x12, 0xa7, 0x59, 0xc0, 0x42, 0xad, 0x78, 0xa4, 0x23, 0xcd, 0x0b, 0x43, 0x90, - 0xdd, 0x15, 0x53, 0x31, 0x14, 0xab, 0x8d, 0xb9, 0x7d, 0x54, 0xa5, 0xd4, 0x76, 0x9f, 0xf6, 0xaf, - 0x57, 0x31, 0x59, 0x82, 0x52, 0xc1, 0x37, 0xe0, 0xf8, 0x2f, 0xc0, 0x86, 0x53, 0x50, 0x62, 0x9b, - 0x3b, 0x78, 0x21, 0xfe, 0xfe, 0x95, 0x30, 0x28, 0xc5, 0xc3, 0x65, 0x70, 0x0f, 0x21, 0x5e, 0x00, - 0x8a, 0x89, 0x40, 0x71, 0x2e, 0x2d, 0x36, 0x6f, 0xfc, 0xba, 0x2a, 0xe7, 0xd6, 0xbf, 0x2e, 0xe9, - 0x35, 0x86, 0x8c, 0x55, 0x79, 0x29, 0xe6, 0x68, 0x67, 0x1a, 0xed, 0xcd, 0x57, 0x1d, 0x2f, 0x5f, - 0x75, 0xea, 0x1f, 0xc9, 0xf8, 0xd3, 0xd8, 0xbc, 0xf5, 0x6b, 0x12, 0x41, 0xd9, 0x16, 0xe9, 0xfe, - 0xef, 0x35, 0x86, 0xa7, 0xd5, 0xd4, 0x3f, 0xb6, 0x1d, 0xed, 0x96, 0xe7, 0xd4, 0xce, 0x9c, 0x71, - 0xbc, 0x11, 0x8f, 0xfa, 0xf3, 0x35, 0xf5, 0x16, 0x6b, 0xea, 0x2d, 0xd7, 0xd4, 0x7b, 0xca, 0x29, - 0x99, 0xe7, 0x94, 0x2c, 0x72, 0x4a, 0x96, 0x39, 0x25, 0xaf, 0x39, 0x25, 0xcf, 0x6f, 0xd4, 0xbb, - 0xde, 0x29, 0xbf, 0xf6, 0x3d, 0x00, 0x00, 0xff, 0xff, 0xc6, 0x7e, 0x00, 0x08, 0x5a, 0x02, 0x00, - 0x00, + 0x1c, 0xc6, 0x9b, 0xf7, 0x65, 0x38, 0x3a, 0x04, 0xd9, 0x69, 0xee, 0x90, 0x0d, 0x4f, 0xf3, 0xb0, + 0x84, 0x0d, 0x11, 0xc1, 0xdb, 0x6e, 0x82, 0xa2, 0xec, 0x28, 0x1e, 0x4c, 0xbb, 0xbf, 0x5d, 0xac, + 0x69, 0x4a, 0xf2, 0xef, 0xc0, 0x9b, 0x1f, 0xc1, 0x8f, 0xb5, 0xe3, 0x8e, 0x03, 0x61, 0xb8, 0xf8, + 0x45, 0x24, 0x5d, 0x15, 0x19, 0x0a, 0xbb, 0xf5, 0x79, 0xca, 0xef, 0x97, 0x27, 0x24, 0x1c, 0xa7, + 0x67, 0x96, 0x49, 0xcd, 0xd3, 0x22, 0x02, 0x93, 0x01, 0x82, 0xe5, 0x33, 0xc8, 0x26, 0xda, 0xf0, + 0xea, 0x87, 0xc8, 0xa5, 0x12, 0xf1, 0x54, 0x66, 0x60, 0x9e, 0x79, 0x9e, 0x26, 0xbe, 0xb0, 0x5c, + 0x01, 0x0a, 0x3e, 0x1b, 0x44, 0x80, 0x62, 0xc0, 0x13, 0xc8, 0xc0, 0x08, 0x84, 0x09, 0xcb, 0x8d, + 0x46, 0xdd, 0x3c, 0xde, 0xa0, 0xec, 0x27, 0xca, 0xf2, 0x34, 0xf1, 0x85, 0x65, 0x1e, 0x65, 0x15, + 0xda, 0xee, 0x27, 0x12, 0xa7, 0x45, 0xc4, 0x62, 0xad, 0x78, 0xa2, 0x13, 0xcd, 0x4b, 0x43, 0x54, + 0x3c, 0x94, 0xa9, 0x0c, 0xe5, 0xd7, 0xc6, 0xdc, 0x3e, 0xd9, 0x65, 0xd4, 0xf6, 0x9e, 0xf6, 0xe9, + 0x5f, 0x94, 0x29, 0x32, 0x94, 0x0a, 0xb8, 0x8d, 0xa7, 0xa0, 0xc4, 0x36, 0x77, 0xf4, 0x46, 0xc2, + 0xc3, 0x1b, 0x61, 0x50, 0x8a, 0xa7, 0xeb, 0xe8, 0x11, 0x62, 0xbc, 0x02, 0x14, 0x13, 0x81, 0xe2, + 0x52, 0x5a, 0x6c, 0xde, 0x85, 0x75, 0x55, 0xe5, 0xd6, 0xbf, 0x2e, 0xe9, 0x35, 0x86, 0x8c, 0xed, + 0x72, 0x71, 0xe6, 0x69, 0x6f, 0x1a, 0x1d, 0xcc, 0x57, 0x9d, 0xc0, 0xad, 0x3a, 0xf5, 0xaf, 0x66, + 0xfc, 0x6d, 0x6c, 0xde, 0x87, 0x35, 0x89, 0xa0, 0x6c, 0x8b, 0x74, 0xff, 0xf7, 0x1a, 0xc3, 0xf3, + 0xdd, 0xd4, 0xbf, 0xae, 0x1d, 0xed, 0x57, 0xe7, 0xd4, 0x2e, 0xbc, 0x71, 0xbc, 0x11, 0x8f, 0xfa, + 0xf3, 0x35, 0x0d, 0x16, 0x6b, 0x1a, 0x2c, 0xd7, 0x34, 0x78, 0x71, 0x94, 0xcc, 0x1d, 0x25, 0x0b, + 0x47, 0xc9, 0xd2, 0x51, 0xf2, 0xee, 0x28, 0x79, 0xfd, 0xa0, 0xc1, 0xed, 0x5e, 0xf5, 0x52, 0x9f, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x82, 0x5b, 0x80, 0x29, 0x02, 0x00, 0x00, } func (m *PartialObjectMetadataList) Marshal() (dAtA []byte, err error) { diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto index 19606666f8a..59ce743766c 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto @@ -22,7 +22,6 @@ syntax = 'proto2'; package k8s.io.apimachinery.pkg.apis.meta.v1beta1; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; -import "k8s.io/apimachinery/pkg/runtime/generated.proto"; import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; // Package-wide variables from generator "generated". diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/register.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/register.go index 4b4acd72f12..8d11399fbe0 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/register.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1/register.go @@ -19,7 +19,6 @@ package v1beta1 import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" ) // GroupName is the group name for this API. @@ -33,12 +32,6 @@ func Kind(kind string) schema.GroupKind { return SchemeGroupVersion.WithKind(kind).GroupKind() } -// scheme is the registry for the common types that adhere to the meta v1beta1 API spec. -var scheme = runtime.NewScheme() - -// ParameterCodec knows about query parameters used with the meta v1beta1 API spec. -var ParameterCodec = runtime.NewParameterCodec(scheme) - // AddMetaToScheme registers base meta types into schemas. func AddMetaToScheme(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, @@ -48,14 +41,5 @@ func AddMetaToScheme(scheme *runtime.Scheme) error { &PartialObjectMetadataList{}, ) - return scheme.AddConversionFuncs( - Convert_Slice_string_To_v1beta1_IncludeObjectPolicy, - ) -} - -func init() { - utilruntime.Must(AddMetaToScheme(scheme)) - - // register manually. This usually goes through the SchemeBuilder, which we cannot use here. - utilruntime.Must(RegisterDefaults(scheme)) + return nil } diff --git a/staging/src/k8s.io/apimachinery/pkg/conversion/converter.go b/staging/src/k8s.io/apimachinery/pkg/conversion/converter.go index eaed33fc367..7ee233c7e70 100644 --- a/staging/src/k8s.io/apimachinery/pkg/conversion/converter.go +++ b/staging/src/k8s.io/apimachinery/pkg/conversion/converter.go @@ -54,7 +54,8 @@ type Converter struct { generatedConversionFuncs ConversionFuncs // Set of conversions that should be treated as a no-op - ignoredConversions map[typePair]struct{} + ignoredConversions map[typePair]struct{} + ignoredUntypedConversions map[typePair]struct{} // This is a map from a source field type and name, to a list of destination // field type and name. @@ -83,17 +84,23 @@ type Converter struct { // NewConverter creates a new Converter object. func NewConverter(nameFn NameFunc) *Converter { c := &Converter{ - conversionFuncs: NewConversionFuncs(), - generatedConversionFuncs: NewConversionFuncs(), - ignoredConversions: make(map[typePair]struct{}), - nameFunc: nameFn, - structFieldDests: make(map[typeNamePair][]typeNamePair), - structFieldSources: make(map[typeNamePair][]typeNamePair), + conversionFuncs: NewConversionFuncs(), + generatedConversionFuncs: NewConversionFuncs(), + ignoredConversions: make(map[typePair]struct{}), + ignoredUntypedConversions: make(map[typePair]struct{}), + nameFunc: nameFn, + structFieldDests: make(map[typeNamePair][]typeNamePair), + structFieldSources: make(map[typeNamePair][]typeNamePair), 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 } @@ -153,31 +160,14 @@ type FieldMappingFunc func(key string, sourceTag, destTag reflect.StructTag) (so func NewConversionFuncs() ConversionFuncs { return ConversionFuncs{ - fns: make(map[typePair]reflect.Value), untyped: make(map[typePair]ConversionFunc), } } type ConversionFuncs struct { - 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. @@ -197,12 +187,6 @@ func (c ConversionFuncs) AddUntyped(a, b interface{}, fn ConversionFunc) error { // both other and c, with other conversions taking precedence. func (c ConversionFuncs) Merge(other ConversionFuncs) ConversionFuncs { merged := NewConversionFuncs() - for k, v := range c.fns { - merged.fns[k] = v - } - for k, v := range other.fns { - merged.fns[k] = v - } for k, v := range c.untyped { merged.untyped[k] = v } @@ -360,29 +344,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. @@ -409,6 +370,7 @@ func (c *Converter) RegisterIgnoredConversion(from, to interface{}) error { return fmt.Errorf("expected pointer arg for 'to' param 1, got: %v", typeTo) } c.ignoredConversions[typePair{typeFrom.Elem(), typeTo.Elem()}] = struct{}{} + c.ignoredUntypedConversions[typePair{typeFrom, typeTo}] = struct{}{} return nil } @@ -491,6 +453,11 @@ func (c *Converter) doConversion(src, dest interface{}, flags FieldMatchingFlags flags: flags, meta: meta, } + + // ignore conversions of this type + if _, ok := c.ignoredUntypedConversions[pair]; ok { + return nil + } if fn, ok := c.conversionFuncs.untyped[pair]; ok { return fn(src, dest, scope) } @@ -517,35 +484,6 @@ func (c *Converter) doConversion(src, dest interface{}, flags FieldMatchingFlags return f(sv, dv, scope) } -// callCustom calls 'custom' with sv & dv. custom must be a conversion function. -func (c *Converter) callCustom(sv, dv, custom reflect.Value, scope *scope) error { - if !sv.CanAddr() { - sv2 := reflect.New(sv.Type()) - sv2.Elem().Set(sv) - sv = sv2 - } else { - sv = sv.Addr() - } - if !dv.CanAddr() { - if !dv.CanSet() { - return scope.errorf("can't addr or set dest.") - } - dvOrig := dv - dv := reflect.New(dvOrig.Type()) - defer func() { dvOrig.Set(dv) }() - } else { - dv = dv.Addr() - } - args := []reflect.Value{sv, dv, reflect.ValueOf(scope)} - ret := custom.Call(args)[0].Interface() - // This convolution is necessary because nil interfaces won't convert - // to errors. - if ret == nil { - return nil - } - return ret.(error) -} - // callUntyped calls predefined conversion func. func (c *Converter) callUntyped(sv, dv reflect.Value, f ConversionFunc, scope *scope) error { if !dv.CanAddr() { @@ -577,19 +515,6 @@ func (c *Converter) convert(sv, dv reflect.Value, scope *scope) error { } // Convert sv to dv. - if fv, ok := c.conversionFuncs.fns[pair]; ok { - if c.Debug != nil { - c.Debug.Logf("Calling custom conversion of '%v' to '%v'", st, dt) - } - return c.callCustom(sv, dv, fv, scope) - } - if fv, ok := c.generatedConversionFuncs.fns[pair]; ok { - if c.Debug != nil { - c.Debug.Logf("Calling generated conversion of '%v' to '%v'", st, dt) - } - return c.callCustom(sv, dv, fv, scope) - } - pair = typePair{reflect.PtrTo(sv.Type()), reflect.PtrTo(dv.Type())} if f, ok := c.conversionFuncs.untyped[pair]; ok { return c.callUntyped(sv, dv, f, scope) 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 {