mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 15:25:57 +00:00
Fix multiple conversion tests
This commit is contained in:
parent
8c1f9616cf
commit
f624314f91
@ -60,7 +60,6 @@ go_test(
|
|||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
|
||||||
"//pkg/api/v1/pod:go_default_library",
|
"//pkg/api/v1/pod:go_default_library",
|
||||||
"//pkg/apis/core:go_default_library",
|
"//pkg/apis/core:go_default_library",
|
||||||
"//pkg/apis/scheduling:go_default_library",
|
"//pkg/apis/scheduling:go_default_library",
|
||||||
|
@ -41,7 +41,6 @@ import (
|
|||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
"k8s.io/client-go/util/flowcontrol"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
|
||||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
"k8s.io/kubernetes/pkg/apis/scheduling"
|
"k8s.io/kubernetes/pkg/apis/scheduling"
|
||||||
@ -248,9 +247,7 @@ func (f *fakePodControl) CreatePodsOnNode(nodeName, namespace string, template *
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := legacyscheme.Scheme.Convert(&template.Spec, &pod.Spec, nil); err != nil {
|
template.Spec.DeepCopyInto(&pod.Spec)
|
||||||
return fmt.Errorf("unable to convert pod template: %v", err)
|
|
||||||
}
|
|
||||||
if len(nodeName) != 0 {
|
if len(nodeName) != 0 {
|
||||||
pod.Spec.NodeName = nodeName
|
pod.Spec.NodeName = nodeName
|
||||||
}
|
}
|
||||||
@ -282,9 +279,7 @@ func (f *fakePodControl) CreatePodsWithControllerRef(namespace string, template
|
|||||||
|
|
||||||
pod.Name = names.SimpleNameGenerator.GenerateName(fmt.Sprintf("%p-", pod))
|
pod.Name = names.SimpleNameGenerator.GenerateName(fmt.Sprintf("%p-", pod))
|
||||||
|
|
||||||
if err := legacyscheme.Scheme.Convert(&template.Spec, &pod.Spec, nil); err != nil {
|
template.Spec.DeepCopyInto(&pod.Spec)
|
||||||
return fmt.Errorf("unable to convert pod template: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
f.podStore.Update(pod)
|
f.podStore.Update(pod)
|
||||||
f.podIDMap[pod.Name] = pod
|
f.podIDMap[pod.Name] = pod
|
||||||
|
@ -13,11 +13,7 @@ go_test(
|
|||||||
"helper_test.go",
|
"helper_test.go",
|
||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = ["//vendor/github.com/spf13/pflag:go_default_library"],
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
|
||||||
"//vendor/github.com/google/gofuzz:go_default_library",
|
|
||||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
|
@ -20,75 +20,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/gofuzz"
|
|
||||||
flag "github.com/spf13/pflag"
|
flag "github.com/spf13/pflag"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var fuzzIters = flag.Int("fuzz-iters", 50, "How many fuzzing iterations to do.")
|
var fuzzIters = flag.Int("fuzz-iters", 50, "How many fuzzing iterations to do.")
|
||||||
|
|
||||||
// Test a weird version/kind embedding format.
|
|
||||||
type MyWeirdCustomEmbeddedVersionKindField struct {
|
|
||||||
ID string `json:"ID,omitempty"`
|
|
||||||
APIVersion string `json:"myVersionKey,omitempty"`
|
|
||||||
ObjectKind string `json:"myKindKey,omitempty"`
|
|
||||||
Z string `json:"Z,omitempty"`
|
|
||||||
Y uint64 `json:"Y,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestType1 struct {
|
|
||||||
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
|
|
||||||
A string `json:"A,omitempty"`
|
|
||||||
B int `json:"B,omitempty"`
|
|
||||||
C int8 `json:"C,omitempty"`
|
|
||||||
D int16 `json:"D,omitempty"`
|
|
||||||
E int32 `json:"E,omitempty"`
|
|
||||||
F int64 `json:"F,omitempty"`
|
|
||||||
G uint `json:"G,omitempty"`
|
|
||||||
H uint8 `json:"H,omitempty"`
|
|
||||||
I uint16 `json:"I,omitempty"`
|
|
||||||
J uint32 `json:"J,omitempty"`
|
|
||||||
K uint64 `json:"K,omitempty"`
|
|
||||||
L bool `json:"L,omitempty"`
|
|
||||||
M map[string]int `json:"M,omitempty"`
|
|
||||||
N map[string]TestType2 `json:"N,omitempty"`
|
|
||||||
O *TestType2 `json:"O,omitempty"`
|
|
||||||
P []TestType2 `json:"Q,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestType2 struct {
|
|
||||||
A string `json:"A,omitempty"`
|
|
||||||
B int `json:"B,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExternalTestType2 struct {
|
|
||||||
A string `json:"A,omitempty"`
|
|
||||||
B int `json:"B,omitempty"`
|
|
||||||
}
|
|
||||||
type ExternalTestType1 struct {
|
|
||||||
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
|
|
||||||
A string `json:"A,omitempty"`
|
|
||||||
B int `json:"B,omitempty"`
|
|
||||||
C int8 `json:"C,omitempty"`
|
|
||||||
D int16 `json:"D,omitempty"`
|
|
||||||
E int32 `json:"E,omitempty"`
|
|
||||||
F int64 `json:"F,omitempty"`
|
|
||||||
G uint `json:"G,omitempty"`
|
|
||||||
H uint8 `json:"H,omitempty"`
|
|
||||||
I uint16 `json:"I,omitempty"`
|
|
||||||
J uint32 `json:"J,omitempty"`
|
|
||||||
K uint64 `json:"K,omitempty"`
|
|
||||||
L bool `json:"L,omitempty"`
|
|
||||||
M map[string]int `json:"M,omitempty"`
|
|
||||||
N map[string]ExternalTestType2 `json:"N,omitempty"`
|
|
||||||
O *ExternalTestType2 `json:"O,omitempty"`
|
|
||||||
P []ExternalTestType2 `json:"Q,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func testLogger(t *testing.T) DebugLogger {
|
func testLogger(t *testing.T) DebugLogger {
|
||||||
// We don't set logger to eliminate rubbish logs in tests.
|
// We don't set logger to eliminate rubbish logs in tests.
|
||||||
// If you want to switch it, simply switch it to: "return t"
|
// If you want to switch it, simply switch it to: "return t"
|
||||||
@ -129,55 +67,15 @@ func TestConverter_MismatchedTypes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
src := []string{"5"}
|
src := []string{"5"}
|
||||||
var dest *int
|
var dest int
|
||||||
if err := c.Convert(&src, &dest, 0, nil); err != nil {
|
if err := c.Convert(&src, &dest, 0, nil); err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if e, a := 5, *dest; e != a {
|
if e, a := 5, dest; e != a {
|
||||||
t.Errorf("expected %#v, got %#v", e, a)
|
t.Errorf("expected %#v, got %#v", e, a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConverter_DeepCopy(t *testing.T) {
|
|
||||||
type A struct {
|
|
||||||
Foo *string
|
|
||||||
Bar []string
|
|
||||||
Baz interface{}
|
|
||||||
Qux map[string]string
|
|
||||||
}
|
|
||||||
c := NewConverter(DefaultNameFunc)
|
|
||||||
c.Debug = testLogger(t)
|
|
||||||
|
|
||||||
foo, baz := "foo", "baz"
|
|
||||||
x := A{
|
|
||||||
Foo: &foo,
|
|
||||||
Bar: []string{"bar"},
|
|
||||||
Baz: &baz,
|
|
||||||
Qux: map[string]string{"qux": "qux"},
|
|
||||||
}
|
|
||||||
y := A{}
|
|
||||||
|
|
||||||
if err := c.Convert(&x, &y, 0, nil); err != nil {
|
|
||||||
t.Fatalf("unexpected error %v", err)
|
|
||||||
}
|
|
||||||
*x.Foo = "foo2"
|
|
||||||
x.Bar[0] = "bar2"
|
|
||||||
*x.Baz.(*string) = "baz2"
|
|
||||||
x.Qux["qux"] = "qux2"
|
|
||||||
if e, a := *x.Foo, *y.Foo; e == a {
|
|
||||||
t.Errorf("expected difference between %v and %v", e, a)
|
|
||||||
}
|
|
||||||
if e, a := x.Bar, y.Bar; reflect.DeepEqual(e, a) {
|
|
||||||
t.Errorf("expected difference between %v and %v", e, a)
|
|
||||||
}
|
|
||||||
if e, a := *x.Baz.(*string), *y.Baz.(*string); e == a {
|
|
||||||
t.Errorf("expected difference between %v and %v", e, a)
|
|
||||||
}
|
|
||||||
if e, a := x.Qux, y.Qux; reflect.DeepEqual(e, a) {
|
|
||||||
t.Errorf("expected difference between %v and %v", e, a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
||||||
type A struct {
|
type A struct {
|
||||||
Foo string
|
Foo string
|
||||||
@ -192,7 +90,8 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
|||||||
c.Debug = testLogger(t)
|
c.Debug = testLogger(t)
|
||||||
convertFn1 := func(in *A, out *B, s Scope) error {
|
convertFn1 := func(in *A, out *B, s Scope) error {
|
||||||
out.Bar = in.Foo
|
out.Bar = in.Foo
|
||||||
return s.Convert(&in.Baz, &out.Baz, 0)
|
out.Baz = in.Baz
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
if err := c.RegisterUntypedConversionFunc(
|
if err := c.RegisterUntypedConversionFunc(
|
||||||
(*A)(nil), (*B)(nil),
|
(*A)(nil), (*B)(nil),
|
||||||
@ -204,7 +103,8 @@ func TestConverter_CallsRegisteredFunctions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
convertFn2 := func(in *B, out *A, s Scope) error {
|
convertFn2 := func(in *B, out *A, s Scope) error {
|
||||||
out.Foo = in.Bar
|
out.Foo = in.Bar
|
||||||
return s.Convert(&in.Baz, &out.Baz, 0)
|
out.Baz = in.Baz
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
if err := c.RegisterUntypedConversionFunc(
|
if err := c.RegisterUntypedConversionFunc(
|
||||||
(*B)(nil), (*A)(nil),
|
(*B)(nil), (*A)(nil),
|
||||||
@ -288,30 +188,6 @@ func TestConverter_IgnoredConversion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConverter_IgnoredConversionNested(t *testing.T) {
|
|
||||||
type C string
|
|
||||||
type A struct {
|
|
||||||
C C
|
|
||||||
}
|
|
||||||
type B struct {
|
|
||||||
C C
|
|
||||||
}
|
|
||||||
|
|
||||||
c := NewConverter(DefaultNameFunc)
|
|
||||||
typed := C("")
|
|
||||||
if err := c.RegisterIgnoredConversion(&typed, &typed); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
a := A{C: C("test")}
|
|
||||||
b := B{C: C("other")}
|
|
||||||
if err := c.Convert(&a, &b, AllowDifferentFieldTypeNames, nil); err != nil {
|
|
||||||
t.Errorf("%v", err)
|
|
||||||
}
|
|
||||||
if b.C != C("other") {
|
|
||||||
t.Errorf("expected no conversion of field C: %#v", b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConverter_GeneratedConversionOverridden(t *testing.T) {
|
func TestConverter_GeneratedConversionOverridden(t *testing.T) {
|
||||||
type A struct{}
|
type A struct{}
|
||||||
type B struct{}
|
type B struct{}
|
||||||
@ -392,249 +268,6 @@ func TestConverter_WithConversionOverridden(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConverter_MapsStringArrays(t *testing.T) {
|
|
||||||
type A struct {
|
|
||||||
Foo string
|
|
||||||
Baz int
|
|
||||||
Other string
|
|
||||||
}
|
|
||||||
c := NewConverter(DefaultNameFunc)
|
|
||||||
c.Debug = testLogger(t)
|
|
||||||
convertFn1 := func(input *[]string, out *string, s Scope) error {
|
|
||||||
if len(*input) == 0 {
|
|
||||||
*out = ""
|
|
||||||
}
|
|
||||||
*out = (*input)[0]
|
|
||||||
return 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
x := map[string][]string{
|
|
||||||
"Foo": {"bar"},
|
|
||||||
"Baz": {"1"},
|
|
||||||
"Other": {"", "test"},
|
|
||||||
"other": {"wrong"},
|
|
||||||
}
|
|
||||||
y := A{"test", 2, "something"}
|
|
||||||
|
|
||||||
if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames, nil); err == nil {
|
|
||||||
t.Error("unexpected non-error")
|
|
||||||
}
|
|
||||||
|
|
||||||
convertFn2 := func(input *[]string, out *int, s Scope) error {
|
|
||||||
if len(*input) == 0 {
|
|
||||||
*out = 0
|
|
||||||
}
|
|
||||||
str := (*input)[0]
|
|
||||||
i, err := strconv.Atoi(str)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*out = i
|
|
||||||
return 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames, nil); err != nil {
|
|
||||||
t.Fatalf("unexpected error %v", err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(y, A{"bar", 1, ""}) {
|
|
||||||
t.Errorf("unexpected result: %#v", y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConverter_MapsStringArraysWithMappingKey(t *testing.T) {
|
|
||||||
type A struct {
|
|
||||||
Foo string `json:"test"`
|
|
||||||
Baz int
|
|
||||||
Other string
|
|
||||||
}
|
|
||||||
c := NewConverter(DefaultNameFunc)
|
|
||||||
c.Debug = testLogger(t)
|
|
||||||
convertFn := func(input *[]string, out *string, s Scope) error {
|
|
||||||
if len(*input) == 0 {
|
|
||||||
*out = ""
|
|
||||||
}
|
|
||||||
*out = (*input)[0]
|
|
||||||
return 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
x := map[string][]string{
|
|
||||||
"Foo": {"bar"},
|
|
||||||
"test": {"baz"},
|
|
||||||
}
|
|
||||||
y := A{"", 0, ""}
|
|
||||||
|
|
||||||
if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames|IgnoreMissingFields, &Meta{}); err != nil {
|
|
||||||
t.Fatalf("unexpected error %v", err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(y, A{"bar", 0, ""}) {
|
|
||||||
t.Errorf("unexpected result: %#v", y)
|
|
||||||
}
|
|
||||||
|
|
||||||
mapping := func(key string, sourceTag, destTag reflect.StructTag) (source string, dest string) {
|
|
||||||
if s := destTag.Get("json"); len(s) > 0 {
|
|
||||||
return strings.SplitN(s, ",", 2)[0], key
|
|
||||||
}
|
|
||||||
return key, key
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.Convert(&x, &y, AllowDifferentFieldTypeNames|IgnoreMissingFields, &Meta{KeyNameMapping: mapping}); err != nil {
|
|
||||||
t.Fatalf("unexpected error %v", err)
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(y, A{"baz", 0, ""}) {
|
|
||||||
t.Errorf("unexpected result: %#v", y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConverter_fuzz(t *testing.T) {
|
|
||||||
// Use the same types from the scheme test.
|
|
||||||
table := []struct {
|
|
||||||
from, to, check interface{}
|
|
||||||
}{
|
|
||||||
{&TestType1{}, &ExternalTestType1{}, &TestType1{}},
|
|
||||||
{&ExternalTestType1{}, &TestType1{}, &ExternalTestType1{}},
|
|
||||||
}
|
|
||||||
|
|
||||||
f := fuzz.New().NilChance(.5).NumElements(0, 100)
|
|
||||||
c := NewConverter(DefaultNameFunc)
|
|
||||||
c.nameFunc = func(t reflect.Type) string {
|
|
||||||
// Hide the fact that we don't have separate packages for these things.
|
|
||||||
return map[reflect.Type]string{
|
|
||||||
reflect.TypeOf(TestType1{}): "TestType1",
|
|
||||||
reflect.TypeOf(ExternalTestType1{}): "TestType1",
|
|
||||||
reflect.TypeOf(TestType2{}): "TestType2",
|
|
||||||
reflect.TypeOf(ExternalTestType2{}): "TestType2",
|
|
||||||
}[t]
|
|
||||||
}
|
|
||||||
c.Debug = testLogger(t)
|
|
||||||
|
|
||||||
for i, item := range table {
|
|
||||||
for j := 0; j < *fuzzIters; j++ {
|
|
||||||
f.Fuzz(item.from)
|
|
||||||
err := c.Convert(item.from, item.to, 0, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("(%v, %v): unexpected error: %v", i, j, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err = c.Convert(item.to, item.check, 0, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("(%v, %v): unexpected error: %v", i, j, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if e, a := item.from, item.check; !reflect.DeepEqual(e, a) {
|
|
||||||
t.Errorf("(%v, %v): unexpected diff: %v", i, j, diff.ObjectDiff(e, a))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConverter_MapElemAddr(t *testing.T) {
|
|
||||||
type Foo struct {
|
|
||||||
A map[int]int
|
|
||||||
}
|
|
||||||
type Bar struct {
|
|
||||||
A map[string]string
|
|
||||||
}
|
|
||||||
c := NewConverter(DefaultNameFunc)
|
|
||||||
c.Debug = testLogger(t)
|
|
||||||
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)
|
|
||||||
},
|
|
||||||
); err != nil {
|
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
},
|
|
||||||
); err != nil {
|
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
f := fuzz.New().NilChance(0).NumElements(3, 3)
|
|
||||||
first := Foo{}
|
|
||||||
second := Bar{}
|
|
||||||
f.Fuzz(&first)
|
|
||||||
if err := c.Convert(&first, &second, AllowDifferentFieldTypeNames, nil); err != nil {
|
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
third := Foo{}
|
|
||||||
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) {
|
|
||||||
t.Errorf("Unexpected diff: %v", diff.ObjectDiff(e, a))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConverter_tags(t *testing.T) {
|
|
||||||
type Foo struct {
|
|
||||||
A string `test:"foo"`
|
|
||||||
}
|
|
||||||
type Bar struct {
|
|
||||||
A string `test:"bar"`
|
|
||||||
}
|
|
||||||
c := NewConverter(DefaultNameFunc)
|
|
||||||
c.Debug = testLogger(t)
|
|
||||||
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)
|
|
||||||
},
|
|
||||||
); err != nil {
|
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if err := c.Convert(&Foo{}, &Bar{}, AllowDifferentFieldTypeNames, nil); err != nil {
|
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConverter_meta(t *testing.T) {
|
func TestConverter_meta(t *testing.T) {
|
||||||
type Foo struct{ A string }
|
type Foo struct{ A string }
|
||||||
type Bar struct{ A string }
|
type Bar struct{ A string }
|
||||||
@ -646,7 +279,7 @@ func TestConverter_meta(t *testing.T) {
|
|||||||
t.Errorf("Meta did not get passed!")
|
t.Errorf("Meta did not get passed!")
|
||||||
}
|
}
|
||||||
checks++
|
checks++
|
||||||
s.Convert(&in.A, &out.A, 0)
|
out.A = in.A
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := c.RegisterUntypedConversionFunc(
|
if err := c.RegisterUntypedConversionFunc(
|
||||||
@ -657,116 +290,10 @@ func TestConverter_meta(t *testing.T) {
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
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)
|
|
||||||
},
|
|
||||||
); err != nil {
|
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if err := c.Convert(&Foo{}, &Bar{}, 0, &Meta{}); err != nil {
|
if err := c.Convert(&Foo{}, &Bar{}, 0, &Meta{}); err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if checks != 2 {
|
if checks != 1 {
|
||||||
t.Errorf("Registered functions did not get called.")
|
t.Errorf("Registered functions did not get called.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConverter_flags(t *testing.T) {
|
|
||||||
type Foo struct{ A string }
|
|
||||||
type Bar struct{ A string }
|
|
||||||
table := []struct {
|
|
||||||
from, to interface{}
|
|
||||||
flags FieldMatchingFlags
|
|
||||||
shouldSucceed bool
|
|
||||||
}{
|
|
||||||
// Check that DestFromSource allows extra fields only in source.
|
|
||||||
{
|
|
||||||
from: &struct{ A string }{},
|
|
||||||
to: &struct{ A, B string }{},
|
|
||||||
flags: DestFromSource,
|
|
||||||
shouldSucceed: false,
|
|
||||||
}, {
|
|
||||||
from: &struct{ A, B string }{},
|
|
||||||
to: &struct{ A string }{},
|
|
||||||
flags: DestFromSource,
|
|
||||||
shouldSucceed: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Check that SourceToDest allows for extra fields only in dest.
|
|
||||||
{
|
|
||||||
from: &struct{ A string }{},
|
|
||||||
to: &struct{ A, B string }{},
|
|
||||||
flags: SourceToDest,
|
|
||||||
shouldSucceed: true,
|
|
||||||
}, {
|
|
||||||
from: &struct{ A, B string }{},
|
|
||||||
to: &struct{ A string }{},
|
|
||||||
flags: SourceToDest,
|
|
||||||
shouldSucceed: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Check that IgnoreMissingFields makes the above failure cases pass.
|
|
||||||
{
|
|
||||||
from: &struct{ A string }{},
|
|
||||||
to: &struct{ A, B string }{},
|
|
||||||
flags: DestFromSource | IgnoreMissingFields,
|
|
||||||
shouldSucceed: true,
|
|
||||||
}, {
|
|
||||||
from: &struct{ A, B string }{},
|
|
||||||
to: &struct{ A string }{},
|
|
||||||
flags: SourceToDest | IgnoreMissingFields,
|
|
||||||
shouldSucceed: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Check that the field type name must match unless
|
|
||||||
// AllowDifferentFieldTypeNames is specified.
|
|
||||||
{
|
|
||||||
from: &struct{ A, B Foo }{},
|
|
||||||
to: &struct{ A Bar }{},
|
|
||||||
flags: DestFromSource,
|
|
||||||
shouldSucceed: false,
|
|
||||||
}, {
|
|
||||||
from: &struct{ A Foo }{},
|
|
||||||
to: &struct{ A, B Bar }{},
|
|
||||||
flags: SourceToDest,
|
|
||||||
shouldSucceed: false,
|
|
||||||
}, {
|
|
||||||
from: &struct{ A, B Foo }{},
|
|
||||||
to: &struct{ A Bar }{},
|
|
||||||
flags: DestFromSource | AllowDifferentFieldTypeNames,
|
|
||||||
shouldSucceed: true,
|
|
||||||
}, {
|
|
||||||
from: &struct{ A Foo }{},
|
|
||||||
to: &struct{ A, B Bar }{},
|
|
||||||
flags: SourceToDest | AllowDifferentFieldTypeNames,
|
|
||||||
shouldSucceed: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
f := fuzz.New().NilChance(.5).NumElements(0, 100)
|
|
||||||
c := NewConverter(DefaultNameFunc)
|
|
||||||
c.Debug = testLogger(t)
|
|
||||||
|
|
||||||
for i, item := range table {
|
|
||||||
for j := 0; j < *fuzzIters; j++ {
|
|
||||||
f.Fuzz(item.from)
|
|
||||||
err := c.Convert(item.from, item.to, item.flags, nil)
|
|
||||||
if item.shouldSucceed && err != nil {
|
|
||||||
t.Errorf("(%v, %v): unexpected error: %v", i, j, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !item.shouldSucceed && err == nil {
|
|
||||||
t.Errorf("(%v, %v): unexpected non-error", i, j)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -10,7 +10,6 @@ go_test(
|
|||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
srcs = [
|
srcs = [
|
||||||
"codec_test.go",
|
"codec_test.go",
|
||||||
"conversion_test.go",
|
|
||||||
"converter_test.go",
|
"converter_test.go",
|
||||||
"embedded_test.go",
|
"embedded_test.go",
|
||||||
"extension_test.go",
|
"extension_test.go",
|
||||||
|
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2014 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package runtime_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
runtimetesting "k8s.io/apimachinery/pkg/runtime/testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestStringMapConversion(t *testing.T) {
|
|
||||||
internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal}
|
|
||||||
externalGV := schema.GroupVersion{Group: "test.group", Version: "external"}
|
|
||||||
|
|
||||||
scheme := runtime.NewScheme()
|
|
||||||
scheme.Log(t)
|
|
||||||
scheme.AddKnownTypeWithName(internalGV.WithKind("Complex"), &runtimetesting.InternalComplex{})
|
|
||||||
scheme.AddKnownTypeWithName(externalGV.WithKind("Complex"), &runtimetesting.ExternalComplex{})
|
|
||||||
|
|
||||||
testCases := map[string]struct {
|
|
||||||
input map[string][]string
|
|
||||||
errFn func(error) bool
|
|
||||||
expected runtime.Object
|
|
||||||
}{
|
|
||||||
"ignores omitempty": {
|
|
||||||
input: map[string][]string{
|
|
||||||
"String": {"not_used"},
|
|
||||||
"string": {"value"},
|
|
||||||
"int": {"1"},
|
|
||||||
"Integer64": {"2"},
|
|
||||||
},
|
|
||||||
expected: &runtimetesting.ExternalComplex{String: "value", Integer: 1},
|
|
||||||
},
|
|
||||||
"returns error on bad int": {
|
|
||||||
input: map[string][]string{
|
|
||||||
"int": {"a"},
|
|
||||||
},
|
|
||||||
errFn: func(err error) bool { return err != nil },
|
|
||||||
expected: &runtimetesting.ExternalComplex{},
|
|
||||||
},
|
|
||||||
"parses int64": {
|
|
||||||
input: map[string][]string{
|
|
||||||
"Int64": {"-1"},
|
|
||||||
},
|
|
||||||
expected: &runtimetesting.ExternalComplex{Int64: -1},
|
|
||||||
},
|
|
||||||
"returns error on bad int64": {
|
|
||||||
input: map[string][]string{
|
|
||||||
"Int64": {"a"},
|
|
||||||
},
|
|
||||||
errFn: func(err error) bool { return err != nil },
|
|
||||||
expected: &runtimetesting.ExternalComplex{},
|
|
||||||
},
|
|
||||||
"parses boolean true": {
|
|
||||||
input: map[string][]string{
|
|
||||||
"bool": {"true"},
|
|
||||||
},
|
|
||||||
expected: &runtimetesting.ExternalComplex{Bool: true},
|
|
||||||
},
|
|
||||||
"parses boolean any value": {
|
|
||||||
input: map[string][]string{
|
|
||||||
"bool": {"foo"},
|
|
||||||
},
|
|
||||||
expected: &runtimetesting.ExternalComplex{Bool: true},
|
|
||||||
},
|
|
||||||
"parses boolean false": {
|
|
||||||
input: map[string][]string{
|
|
||||||
"bool": {"false"},
|
|
||||||
},
|
|
||||||
expected: &runtimetesting.ExternalComplex{Bool: false},
|
|
||||||
},
|
|
||||||
"parses boolean empty value": {
|
|
||||||
input: map[string][]string{
|
|
||||||
"bool": {""},
|
|
||||||
},
|
|
||||||
expected: &runtimetesting.ExternalComplex{Bool: true},
|
|
||||||
},
|
|
||||||
"parses boolean no value": {
|
|
||||||
input: map[string][]string{
|
|
||||||
"bool": {},
|
|
||||||
},
|
|
||||||
expected: &runtimetesting.ExternalComplex{Bool: false},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, tc := range testCases {
|
|
||||||
out := &runtimetesting.ExternalComplex{}
|
|
||||||
if err := scheme.Convert(&tc.input, out, nil); (tc.errFn == nil && err != nil) || (tc.errFn != nil && !tc.errFn(err)) {
|
|
||||||
t.Errorf("%s: unexpected error: %v", k, err)
|
|
||||||
continue
|
|
||||||
} else if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(out, tc.expected) {
|
|
||||||
t.Errorf("%s: unexpected output: %#v", k, out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -986,7 +986,7 @@ func TestMetaValuesUnregisteredConvert(t *testing.T) {
|
|||||||
|
|
||||||
// Register functions to verify that scope.Meta() gets set correctly.
|
// Register functions to verify that scope.Meta() gets set correctly.
|
||||||
convertSimple := func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error {
|
convertSimple := func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error {
|
||||||
scope.Convert(&in.TestString, &out.TestString, 0)
|
out.TestString = in.TestString
|
||||||
internalToExternalCalls++
|
internalToExternalCalls++
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -416,7 +416,7 @@ runTests() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ -n "${WHAT-}" ]]; then
|
if [[ -n "${WHAT-}" ]]; then
|
||||||
for pkg in ${WHAT}
|
for pkg in ${WHAT}
|
||||||
do
|
do
|
||||||
# running of kubeadm is captured in hack/make-targets/test-cmd.sh
|
# running of kubeadm is captured in hack/make-targets/test-cmd.sh
|
||||||
|
Loading…
Reference in New Issue
Block a user