func TestEncode(t *testing.T) { internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} scheme := runtime.NewScheme() scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) codec := serializer.NewCodecFactory(scheme).LegacyCodec(externalGV) test := &InternalSimple{ TestString: "I'm the same", } obj := runtime.Object(test) data, err := runtime.Encode(codec, obj) obj2, gvk, err2 := codec.Decode(data, nil, nil) if err != nil || err2 != nil { t.Fatalf("Failure: '%v' '%v'", err, err2) } if _, ok := obj2.(*InternalSimple); !ok { t.Fatalf("Got wrong type") } if !reflect.DeepEqual(obj2, test) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", test, obj2) } if !reflect.DeepEqual(gvk, &unversioned.GroupVersionKind{Group: "test.group", Version: "testExternal", Kind: "Simple"}) { t.Errorf("unexpected gvk returned by decode: %#v", gvk) } }
func TestEncode_Ptr(t *testing.T) { grace := int64(30) pod := &api.Pod{ ObjectMeta: api.ObjectMeta{ Labels: map[string]string{"name": "foo"}, }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, SecurityContext: &api.PodSecurityContext{}, }, } obj := runtime.Object(pod) data, err := runtime.Encode(testapi.Default.Codec(), obj) obj2, err2 := runtime.Decode(testapi.Default.Codec(), data) if err != nil || err2 != nil { t.Fatalf("Failure: '%v' '%v'", err, err2) } if _, ok := obj2.(*api.Pod); !ok { t.Fatalf("Got wrong type") } if !api.Semantic.DeepEqual(obj2, pod) { t.Errorf("\nExpected:\n\n %#v,\n\nGot:\n\n %#vDiff: %v\n\n", pod, obj2, diff.ObjectDiff(obj2, pod)) } }
func TestUnversionedTypes(t *testing.T) { internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} otherGV := unversioned.GroupVersion{Group: "group", Version: "other"} scheme := runtime.NewScheme() scheme.AddUnversionedTypes(externalGV, &InternalSimple{}) scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) scheme.AddKnownTypeWithName(otherGV.WithKind("Simple"), &ExternalSimple{}) codec := serializer.NewCodecFactory(scheme).LegacyCodec(externalGV) if unv, ok := scheme.IsUnversioned(&InternalSimple{}); !unv || !ok { t.Fatalf("type not unversioned and in scheme: %t %t", unv, ok) } kinds, _, err := scheme.ObjectKinds(&InternalSimple{}) if err != nil { t.Fatal(err) } kind := kinds[0] if kind != externalGV.WithKind("InternalSimple") { t.Fatalf("unexpected: %#v", kind) } test := &InternalSimple{ TestString: "I'm the same", } obj := runtime.Object(test) data, err := runtime.Encode(codec, obj) if err != nil { t.Fatal(err) } obj2, gvk, err := codec.Decode(data, nil, nil) if err != nil { t.Fatal(err) } if _, ok := obj2.(*InternalSimple); !ok { t.Fatalf("Got wrong type") } if !reflect.DeepEqual(obj2, test) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", test, obj2) } // object is serialized as an unversioned object (in the group and version it was defined in) if !reflect.DeepEqual(gvk, &unversioned.GroupVersionKind{Group: "test.group", Version: "testExternal", Kind: "InternalSimple"}) { t.Errorf("unexpected gvk returned by decode: %#v", gvk) } // when serialized to a different group, the object is kept in its preferred name codec = serializer.NewCodecFactory(scheme).LegacyCodec(otherGV) data, err = runtime.Encode(codec, obj) if err != nil { t.Fatal(err) } if string(data) != `{"apiVersion":"test.group/testExternal","kind":"InternalSimple","testString":"I'm the same"}`+"\n" { t.Errorf("unexpected data: %s", data) } }
func TestHasUID(t *testing.T) { testcases := []struct { obj runtime.Object hasUID bool }{ {obj: nil, hasUID: false}, {obj: &api.Pod{}, hasUID: false}, {obj: nil, hasUID: false}, {obj: runtime.Object(nil), hasUID: false}, {obj: &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("A")}}, hasUID: true}, } for i, tc := range testcases { actual, err := hasUID(tc.obj) if err != nil { t.Errorf("%d: unexpected error %v", i, err) continue } if tc.hasUID != actual { t.Errorf("%d: expected %v, got %v", i, tc.hasUID, actual) } } }
func TestScheme(t *testing.T) { internalGV := unversioned.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} externalGV := unversioned.GroupVersion{Group: "test.group", Version: "testExternal"} scheme := runtime.NewScheme() scheme.AddKnownTypeWithName(internalGV.WithKind("Simple"), &InternalSimple{}) scheme.AddKnownTypeWithName(externalGV.WithKind("Simple"), &ExternalSimple{}) // If set, would clear TypeMeta during conversion. //scheme.AddIgnoredConversionType(&TypeMeta{}, &TypeMeta{}) // test that scheme is an ObjectTyper var _ runtime.ObjectTyper = scheme internalToExternalCalls := 0 externalToInternalCalls := 0 // Register functions to verify that scope.Meta() gets set correctly. err := scheme.AddConversionFuncs( func(in *InternalSimple, out *ExternalSimple, scope conversion.Scope) error { scope.Convert(&in.TypeMeta, &out.TypeMeta, 0) scope.Convert(&in.TestString, &out.TestString, 0) internalToExternalCalls++ return nil }, func(in *ExternalSimple, out *InternalSimple, scope conversion.Scope) error { scope.Convert(&in.TypeMeta, &out.TypeMeta, 0) scope.Convert(&in.TestString, &out.TestString, 0) externalToInternalCalls++ return nil }, ) if err != nil { t.Fatalf("unexpected error: %v", err) } codecs := serializer.NewCodecFactory(scheme) codec := codecs.LegacyCodec(externalGV) jsonserializer, _ := codecs.SerializerForFileExtension("json") simple := &InternalSimple{ TestString: "foo", } // Test Encode, Decode, DecodeInto, and DecodeToVersion obj := runtime.Object(simple) data, err := runtime.Encode(codec, obj) if err != nil { t.Fatal(err) } obj2, err := runtime.Decode(codec, data) if err != nil { t.Fatal(err) } if _, ok := obj2.(*InternalSimple); !ok { t.Fatalf("Got wrong type") } if e, a := simple, obj2; !reflect.DeepEqual(e, a) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", e, a) } obj3 := &InternalSimple{} if err := runtime.DecodeInto(codec, data, obj3); err != nil { t.Fatal(err) } // clearing TypeMeta is a function of the scheme, which we do not test here (ConvertToVersion // does not automatically clear TypeMeta anymore). simple.TypeMeta = runtime.TypeMeta{Kind: "Simple", APIVersion: externalGV.String()} if e, a := simple, obj3; !reflect.DeepEqual(e, a) { t.Errorf("Expected:\n %#v,\n Got:\n %#v", e, a) } obj4, err := runtime.Decode(jsonserializer, data) if err != nil { t.Fatal(err) } if _, ok := obj4.(*ExternalSimple); !ok { t.Fatalf("Got wrong type") } // Test Convert external := &ExternalSimple{} err = scheme.Convert(simple, external) if err != nil { t.Fatalf("Unexpected error: %v", err) } if e, a := simple.TestString, external.TestString; e != a { t.Errorf("Expected %v, got %v", e, a) } // Encode and Convert should each have caused an increment. if e, a := 2, internalToExternalCalls; e != a { t.Errorf("Expected %v, got %v", e, a) } // DecodeInto and Decode should each have caused an increment because of a conversion if e, a := 2, externalToInternalCalls; e != a { t.Errorf("Expected %v, got %v", e, a) } }
// TODO: This should be done on types that are not part of our API func TestBeforeUpdate(t *testing.T) { testCases := []struct { name string tweakSvc func(oldSvc, newSvc *api.Service) // given basic valid services, each test case can customize them expectErr bool }{ { name: "no change", tweakSvc: func(oldSvc, newSvc *api.Service) { // nothing }, expectErr: false, }, { name: "change port", tweakSvc: func(oldSvc, newSvc *api.Service) { newSvc.Spec.Ports[0].Port++ }, expectErr: false, }, { name: "bad namespace", tweakSvc: func(oldSvc, newSvc *api.Service) { newSvc.Namespace = "#$%%invalid" }, expectErr: true, }, { name: "change name", tweakSvc: func(oldSvc, newSvc *api.Service) { newSvc.Name += "2" }, expectErr: true, }, { name: "change ClusterIP", tweakSvc: func(oldSvc, newSvc *api.Service) { oldSvc.Spec.ClusterIP = "1.2.3.4" newSvc.Spec.ClusterIP = "4.3.2.1" }, expectErr: true, }, { name: "change selectpor", tweakSvc: func(oldSvc, newSvc *api.Service) { newSvc.Spec.Selector = map[string]string{"newkey": "newvalue"} }, expectErr: false, }, } for _, tc := range testCases { oldSvc := makeValidService() newSvc := makeValidService() tc.tweakSvc(&oldSvc, &newSvc) ctx := api.NewDefaultContext() err := rest.BeforeUpdate(Strategy, ctx, runtime.Object(&oldSvc), runtime.Object(&newSvc)) if tc.expectErr && err == nil { t.Errorf("unexpected non-error for %q", tc.name) } if !tc.expectErr && err != nil { t.Errorf("unexpected error for %q: %v", tc.name, err) } } }