// roundTrip applies a single round-trip test to the given runtime object // using the given codec. The round-trip test ensures that an object can be // deep-copied and converted from internal -> versioned -> internal without // loss of data. func roundTrip(t *testing.T, codec runtime.Codec, item runtime.Object) { printer := spew.ConfigState{DisableMethods: true} original := item // deep copy the original object copied, err := api.Scheme.DeepCopy(item) if err != nil { panic(fmt.Sprintf("unable to copy: %v", err)) } item = copied.(runtime.Object) name := reflect.TypeOf(item).Elem().Name() // encode (serialize) the deep copy using the provided codec data, err := runtime.Encode(codec, item) if err != nil { if runtime.IsNotRegisteredError(err) { t.Logf("%v: not registered: %v (%s)", name, err, printer.Sprintf("%#v", item)) } else { t.Errorf("%v: %v (%s)", name, err, printer.Sprintf("%#v", item)) } return } // ensure that the deep copy is equal to the original; neither the deep // copy or conversion should alter the object if !api.Semantic.DeepEqual(original, item) { t.Errorf("0: %v: encode altered the object, diff: %v", name, diff.ObjectReflectDiff(original, item)) return } // decode (deserialize) the encoded data back into an object obj2, err := runtime.Decode(codec, data) if err != nil { t.Errorf("0: %v: %v\nCodec: %#v\nData: %s\nSource: %#v", name, err, codec, dataAsString(data), printer.Sprintf("%#v", item)) panic("failed") } // ensure that the object produced from decoding the encoded data is equal // to the original object if !api.Semantic.DeepEqual(original, obj2) { t.Errorf("\n1: %v: diff: %v\nCodec: %#v\nSource:\n\n%#v\n\nEncoded:\n\n%s\n\nFinal:\n\n%#v", name, diff.ObjectReflectDiff(item, obj2), codec, printer.Sprintf("%#v", item), dataAsString(data), printer.Sprintf("%#v", obj2)) return } // decode the encoded data into a new object (instead of letting the codec // create a new object) obj3 := reflect.New(reflect.TypeOf(item).Elem()).Interface().(runtime.Object) if err := runtime.DecodeInto(codec, data, obj3); err != nil { t.Errorf("2: %v: %v", name, err) return } // ensure that the new runtime object is equal to the original after being // decoded into if !api.Semantic.DeepEqual(item, obj3) { t.Errorf("3: %v: diff: %v\nCodec: %#v", name, diff.ObjectReflectDiff(item, obj3), codec) return } }
func annotateRuntimeObject(t *testing.T, originalObj, currentObj runtime.Object, kind string) (string, []byte) { originalAccessor, err := meta.Accessor(originalObj) if err != nil { t.Fatal(err) } originalLabels := originalAccessor.GetLabels() originalLabels["DELETE_ME"] = "DELETE_ME" originalAccessor.SetLabels(originalLabels) original, err := runtime.Encode(testapi.Default.Codec(), originalObj) if err != nil { t.Fatal(err) } currentAccessor, err := meta.Accessor(currentObj) if err != nil { t.Fatal(err) } currentAnnotations := currentAccessor.GetAnnotations() if currentAnnotations == nil { currentAnnotations = make(map[string]string) } currentAnnotations[annotations.LastAppliedConfigAnnotation] = string(original) currentAccessor.SetAnnotations(currentAnnotations) current, err := runtime.Encode(testapi.Default.Codec(), currentObj) if err != nil { t.Fatal(err) } return currentAccessor.GetName(), current }
func TestVersionedEncoding(t *testing.T) { s, _ := GetTestScheme() cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})) info, _ := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON) encoder := info.Serializer codec := cf.CodecForVersions(encoder, nil, schema.GroupVersion{Version: "v2"}, nil) out, err := runtime.Encode(codec, &TestType1{}) if err != nil { t.Fatal(err) } if string(out) != `{"myVersionKey":"v2","myKindKey":"TestType1"}`+"\n" { t.Fatal(string(out)) } codec = cf.CodecForVersions(encoder, nil, schema.GroupVersion{Version: "v3"}, nil) _, err = runtime.Encode(codec, &TestType1{}) if err == nil { t.Fatal(err) } // unversioned encode with no versions is written directly to wire codec = cf.CodecForVersions(encoder, nil, runtime.InternalGroupVersioner, nil) out, err = runtime.Encode(codec, &TestType1{}) if err != nil { t.Fatal(err) } if string(out) != `{}`+"\n" { t.Fatal(string(out)) } }
func TestDecodeSinglePod(t *testing.T) { grace := int64(30) pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ APIVersion: "", }, ObjectMeta: metav1.ObjectMeta{ Name: "test", UID: "12345", Namespace: "mynamespace", }, Spec: v1.PodSpec{ RestartPolicy: v1.RestartPolicyAlways, DNSPolicy: v1.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, Containers: []v1.Container{{ Name: "image", Image: "test/image", ImagePullPolicy: "IfNotPresent", TerminationMessagePath: "/dev/termination-log", SecurityContext: securitycontext.ValidSecurityContextWithContainerDefaults(), }}, SecurityContext: &v1.PodSecurityContext{}, SchedulerName: api.DefaultSchedulerName, }, } json, err := runtime.Encode(testapi.Default.Codec(), pod) if err != nil { t.Errorf("unexpected error: %v", err) } parsed, podOut, err := tryDecodeSinglePod(json, noDefault) if !parsed { t.Errorf("expected to have parsed file: (%s)", string(json)) } if err != nil { t.Errorf("unexpected error: %v (%s)", err, string(json)) } if !reflect.DeepEqual(pod, podOut) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, podOut, string(json)) } for _, gv := range api.Registry.EnabledVersionsForGroup(v1.GroupName) { info, _ := runtime.SerializerInfoForMediaType(api.Codecs.SupportedMediaTypes(), "application/yaml") encoder := api.Codecs.EncoderForVersion(info.Serializer, gv) yaml, err := runtime.Encode(encoder, pod) if err != nil { t.Errorf("unexpected error: %v", err) } parsed, podOut, err = tryDecodeSinglePod(yaml, noDefault) if !parsed { t.Errorf("expected to have parsed file: (%s)", string(yaml)) } if err != nil { t.Errorf("unexpected error: %v (%s)", err, string(yaml)) } if !reflect.DeepEqual(pod, podOut) { t.Errorf("expected:\n%#v\ngot:\n%#v\n%s", pod, podOut, string(yaml)) } } }
func TestCreate(t *testing.T) { obj := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} server := etcdtesting.NewEtcdTestClientServer(t) defer server.Terminate(t) helper := newEtcdHelper(server.Client, testapi.Default.Codec(), etcdtest.PathPrefix()) returnedObj := &api.Pod{} err := helper.Create(context.TODO(), "/some/key", obj, returnedObj, 5) if err != nil { t.Errorf("Unexpected error %#v", err) } _, err = runtime.Encode(testapi.Default.Codec(), obj) if err != nil { t.Errorf("Unexpected error %#v", err) } err = helper.Get(context.TODO(), "/some/key", "", returnedObj, false) if err != nil { t.Errorf("Unexpected error %#v", err) } _, err = runtime.Encode(testapi.Default.Codec(), returnedObj) if err != nil { t.Errorf("Unexpected error %#v", err) } if obj.Name != returnedObj.Name { t.Errorf("Wanted %v, got %v", obj.Name, returnedObj.Name) } }
func TestUnversionedTypes(t *testing.T) { internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} externalGV := schema.GroupVersion{Group: "test.group", Version: "testExternal"} otherGV := schema.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, &schema.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 TestDoRequestNewWayFile(t *testing.T) { reqObj := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} reqBodyExpected, err := runtime.Encode(testapi.Default.Codec(), reqObj) if err != nil { t.Errorf("unexpected error: %v", err) } file, err := ioutil.TempFile("", "foo") if err != nil { t.Errorf("unexpected error: %v", err) } defer file.Close() defer os.Remove(file.Name()) _, err = file.Write(reqBodyExpected) if err != nil { t.Errorf("unexpected error: %v", err) } expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() c := testRESTClient(t, testServer) wasCreated := true obj, err := c.Verb("POST"). Prefix("foo/bar", "baz"). Timeout(time.Second). Body(file.Name()). Do().WasCreated(&wasCreated).Get() if err != nil { t.Errorf("Unexpected error: %v %#v", err, err) return } if obj == nil { t.Error("nil obj") } else if !api.Semantic.DeepDerivative(expectedObj, obj) { t.Errorf("Expected: %#v, got %#v", expectedObj, obj) } if wasCreated { t.Errorf("expected object was created") } tmpStr := string(reqBodyExpected) requestURL := testapi.Default.ResourcePathWithPrefix("foo/bar/baz", "", "", "") requestURL += "?timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) }
func TestV1EncodeDecodeStatus(t *testing.T) { status := &metav1.Status{ Status: metav1.StatusFailure, Code: 200, Reason: metav1.StatusReasonUnknown, Message: "", } v1Codec := testapi.Default.Codec() encoded, err := runtime.Encode(v1Codec, status) if err != nil { t.Errorf("unexpected error: %v", err) } typeMeta := metav1.TypeMeta{} if err := json.Unmarshal(encoded, &typeMeta); err != nil { t.Errorf("unexpected error: %v", err) } if typeMeta.Kind != "Status" { t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded)) } if typeMeta.APIVersion != "v1" { t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded)) } decoded, err := runtime.Decode(v1Codec, encoded) if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(status, decoded) { t.Errorf("expected: %v, got: %v", status, decoded) } }
func (s *store) getStateFromObject(obj runtime.Object) (*objState, error) { state := &objState{ obj: obj, meta: &storage.ResponseMeta{}, } rv, err := s.versioner.ObjectResourceVersion(obj) if err != nil { return nil, fmt.Errorf("couldn't get resource version: %v", err) } state.rev = int64(rv) state.meta.ResourceVersion = uint64(state.rev) // Compute the serialized form - for that we need to temporarily clean // its resource version field (those are not stored in etcd). if err := s.versioner.UpdateObject(obj, 0); err != nil { return nil, errors.New("resourceVersion cannot be set on objects store in etcd") } state.data, err = runtime.Encode(s.codec, obj) if err != nil { return nil, err } s.versioner.UpdateObject(state.obj, uint64(rv)) return state, nil }
// strategicPatchObject applies a strategic merge patch of <patchJS> to // <originalObject> and stores the result in <objToUpdate>. // It additionally returns the map[string]interface{} representation of the // <originalObject> and <patchJS>. func strategicPatchObject( codec runtime.Codec, originalObject runtime.Object, patchJS []byte, objToUpdate runtime.Object, versionedObj runtime.Object, ) (originalObjMap map[string]interface{}, patchMap map[string]interface{}, retErr error) { // TODO: This should be one-step conversion that doesn't require // json marshaling and unmarshaling once #39017 is fixed. data, err := runtime.Encode(codec, originalObject) if err != nil { return nil, nil, err } originalObjMap = make(map[string]interface{}) if err := json.Unmarshal(data, &originalObjMap); err != nil { return nil, nil, err } patchMap = make(map[string]interface{}) if err := json.Unmarshal(patchJS, &patchMap); err != nil { return nil, nil, err } if err := applyPatchToObject(codec, originalObjMap, patchMap, objToUpdate, versionedObj); err != nil { return nil, nil, err } return }
// Create implements storage.Interface.Create. func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object, ttl uint64) error { if version, err := s.versioner.ObjectResourceVersion(obj); err == nil && version != 0 { return errors.New("resourceVersion should not be set on objects to be created") } data, err := runtime.Encode(s.codec, obj) if err != nil { return err } key = path.Join(s.pathPrefix, key) opts, err := s.ttlOpts(ctx, int64(ttl)) if err != nil { return err } txnResp, err := s.client.KV.Txn(ctx).If( notFound(key), ).Then( clientv3.OpPut(key, string(data), opts...), ).Commit() if err != nil { return err } if !txnResp.Succeeded { return storage.NewKeyExistsError(key, 0) } if out != nil { putResp := txnResp.Responses[0].GetResponsePut() return decode(s.codec, s.versioner, data, out, putResp.Header.Revision) } return nil }
func TestV1EncodeDecodeStatus(t *testing.T) { v1Codec := Default.Codec() encoded, err := runtime.Encode(v1Codec, status) if err != nil { t.Errorf("unexpected error: %v", err) } typeMeta := metav1.TypeMeta{} if err := json.Unmarshal(encoded, &typeMeta); err != nil { t.Errorf("unexpected error: %v", err) } if typeMeta.Kind != "Status" { t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded)) } if typeMeta.APIVersion != "v1" { t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded)) } decoded, err := runtime.Decode(v1Codec, encoded) if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(status, decoded) { t.Errorf("expected: %#v, got: %#v", status, decoded) } }
func runTest(t *testing.T, source interface{}) { name := reflect.TypeOf(source).Elem().Name() TestObjectFuzzer.Fuzz(source) _, codec := GetTestScheme() data, err := runtime.Encode(codec, source.(runtime.Object)) if err != nil { t.Errorf("%v: %v (%#v)", name, err, source) return } obj2, err := runtime.Decode(codec, data) if err != nil { t.Errorf("%v: %v (%v)", name, err, string(data)) return } if !semantic.DeepEqual(source, obj2) { t.Errorf("1: %v: diff: %v", name, diff.ObjectGoPrintSideBySide(source, obj2)) return } obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface() if err := runtime.DecodeInto(codec, data, obj3.(runtime.Object)); err != nil { t.Errorf("2: %v: %v", name, err) return } if !semantic.DeepEqual(source, obj3) { t.Errorf("3: %v: diff: %v", name, diff.ObjectDiff(source, obj3)) return } }
func TestDoRequestFailed(t *testing.T) { status := &metav1.Status{ Code: http.StatusNotFound, Status: metav1.StatusFailure, Reason: metav1.StatusReasonNotFound, Message: " \"\" not found", Details: &metav1.StatusDetails{}, } expectedBody, _ := runtime.Encode(testapi.Default.Codec(), status) fakeHandler := utiltesting.FakeHandler{ StatusCode: 404, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() c, err := restClient(testServer) if err != nil { t.Fatalf("unexpected error: %v", err) } err = c.Get().Do().Error() if err == nil { t.Errorf("unexpected non-error") } ss, ok := err.(errors.APIStatus) if !ok { t.Errorf("unexpected error type %v", err) } actual := ss.Status() if !reflect.DeepEqual(status, &actual) { t.Errorf("Unexpected mis-match: %s", diff.ObjectReflectDiff(status, &actual)) } }
func TestExperimentalEncodeDecodeStatus(t *testing.T) { status := &metav1.Status{ Status: metav1.StatusFailure, Code: 200, Reason: metav1.StatusReasonUnknown, Message: "", } // TODO: caesarxuchao: use the testapi.Extensions.Codec() once the PR that // moves experimental from v1 to v1beta1 got merged. expCodec := api.Codecs.LegacyCodec(extensions.SchemeGroupVersion) encoded, err := runtime.Encode(expCodec, status) if err != nil { t.Errorf("unexpected error: %v", err) } typeMeta := metav1.TypeMeta{} if err := json.Unmarshal(encoded, &typeMeta); err != nil { t.Errorf("unexpected error: %v", err) } if typeMeta.Kind != "Status" { t.Errorf("Kind is not set to \"Status\". Got %s", encoded) } if typeMeta.APIVersion != "v1" { t.Errorf("APIVersion is not set to \"\". Got %s", encoded) } decoded, err := runtime.Decode(expCodec, encoded) if err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(status, decoded) { t.Errorf("expected: %v, got: %v", status, decoded) } }
func (p *patcher) patchSimple(obj runtime.Object, modified []byte, source, namespace, name string) ([]byte, error) { // Serialize the current configuration of the object from the server. current, err := runtime.Encode(p.encoder, obj) if err != nil { return nil, cmdutil.AddSourceToErr(fmt.Sprintf("serializing current configuration from:\n%v\nfor:", obj), source, err) } // Retrieve the original configuration of the object from the annotation. original, err := kubectl.GetOriginalConfiguration(p.mapping, obj) if err != nil { return nil, cmdutil.AddSourceToErr(fmt.Sprintf("retrieving original configuration from:\n%v\nfor:", obj), source, err) } // Create the versioned struct from the type defined in the restmapping // (which is the API version we'll be submitting the patch to) versionedObject, err := api.Scheme.New(p.mapping.GroupVersionKind) if err != nil { return nil, cmdutil.AddSourceToErr(fmt.Sprintf("getting instance of versioned object for %v:", p.mapping.GroupVersionKind), source, err) } // Compute a three way strategic merge patch to send to server. patch, err := strategicpatch.CreateThreeWayMergePatch(original, modified, current, versionedObject, p.overwrite) if err != nil { format := "creating patch with:\noriginal:\n%s\nmodified:\n%s\ncurrent:\n%s\nfor:" return nil, cmdutil.AddSourceToErr(fmt.Sprintf(format, original, modified, current), source, err) } _, err = p.helper.Patch(namespace, name, types.StrategicMergePatchType, patch) return patch, err }
// This is to emulate the case where another party updates the object when // etcdHelper.Delete has verified the preconditions, but hasn't carried out the // deletion yet. Etcd will fail the deletion and report the conflict. etcdHelper // should retry until there is no conflict. func TestDeleteWithRetry(t *testing.T) { server := etcdtesting.NewEtcdTestClientServer(t) defer server.Terminate(t) prefix := path.Join("/", etcdtest.PathPrefix()) obj := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", UID: "A"}} // fakeGet returns a large ModifiedIndex to emulate the case that another // party has updated the object. fakeGet := func(ctx context.Context, key string, opts *etcd.GetOptions) (*etcd.Response, error) { data, _ := runtime.Encode(testapi.Default.Codec(), obj) return &etcd.Response{Node: &etcd.Node{Value: string(data), ModifiedIndex: 99}}, nil } expectedRetries := 3 helper := newEtcdHelper(server.Client, testapi.Default.Codec(), prefix) fake := &fakeDeleteKeysAPI{KeysAPI: helper.etcdKeysAPI, fakeGetCap: expectedRetries, fakeGetFunc: fakeGet} helper.etcdKeysAPI = fake returnedObj := &api.Pod{} err := helper.Create(context.TODO(), "/some/key", obj, returnedObj, 0) if err != nil { t.Errorf("Unexpected error %#v", err) } err = helper.Delete(context.TODO(), "/some/key", obj, storage.NewUIDPreconditions("A")) if err != nil { t.Errorf("Unexpected error %#v", err) } if fake.getCount != expectedRetries { t.Errorf("Expect %d retries, got %d", expectedRetries, fake.getCount) } err = helper.Get(context.TODO(), "/some/key", "", obj, false) if !storage.IsNotFound(err) { t.Errorf("Expect an NotFound error, got %v", err) } }
func TestEncode(t *testing.T) { internalGV := schema.GroupVersion{Group: "test.group", Version: runtime.APIVersionInternal} externalGV := schema.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, &schema.GroupVersionKind{Group: "test.group", Version: "testExternal", Kind: "Simple"}) { t.Errorf("unexpected gvk returned by decode: %#v", gvk) } }
func TestDoRequestNewWay(t *testing.T) { reqBody := "request body" expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() c := testRESTClient(t, testServer) obj, err := c.Verb("POST"). Prefix("foo", "bar"). Suffix("baz"). Timeout(time.Second). Body([]byte(reqBody)). Do().Get() if err != nil { t.Errorf("Unexpected error: %v %#v", err, err) return } if obj == nil { t.Error("nil obj") } else if !api.Semantic.DeepDerivative(expectedObj, obj) { t.Errorf("Expected: %#v, got %#v", expectedObj, obj) } requestURL := testapi.Default.ResourcePathWithPrefix("foo/bar", "", "", "baz") requestURL += "?timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &reqBody) }
func encodeOrDie(obj runtime.Object) []byte { data, err := runtime.Encode(internal.Codecs.LegacyCodec(api.SchemeGroupVersion), obj) if err != nil { panic(err.Error()) } return data }
func TestDirectCodec(t *testing.T) { s := GetDirectCodecTestScheme() cf := newCodecFactory(s, newSerializersForScheme(s, testMetaFactory{})) info, _ := runtime.SerializerInfoForMediaType(cf.SupportedMediaTypes(), runtime.ContentTypeJSON) serializer := info.Serializer df := DirectCodecFactory{cf} ignoredGV, err := schema.ParseGroupVersion("ignored group/ignored version") if err != nil { t.Fatal(err) } directEncoder := df.EncoderForVersion(serializer, ignoredGV) directDecoder := df.DecoderToVersion(serializer, ignoredGV) out, err := runtime.Encode(directEncoder, &ExternalTestType1{}) if err != nil { t.Fatal(err) } if string(out) != `{"myVersionKey":"v1","myKindKey":"ExternalTestType1"}`+"\n" { t.Fatal(string(out)) } a, _, err := directDecoder.Decode(out, nil, nil) e := &ExternalTestType1{ MyWeirdCustomEmbeddedVersionKindField: MyWeirdCustomEmbeddedVersionKindField{ APIVersion: "v1", ObjectKind: "ExternalTestType1", }, } if !semantic.DeepEqual(e, a) { t.Fatalf("expect %v, got %v", e, a) } }
func TestValidateOk(t *testing.T) { schema, err := loadSchemaForTest() if err != nil { t.Fatalf("Failed to load: %v", err) } tests := []struct { obj runtime.Object typeName string }{ {obj: &api.Pod{}}, {obj: &api.Service{}}, {obj: &api.ReplicationController{}}, } seed := rand.Int63() apiObjectFuzzer := apitesting.FuzzerFor(nil, testapi.Default.InternalGroupVersion(), rand.NewSource(seed)) for i := 0; i < 5; i++ { for _, test := range tests { testObj := test.obj apiObjectFuzzer.Fuzz(testObj) data, err := runtime.Encode(testapi.Default.Codec(), testObj) if err != nil { t.Errorf("unexpected error: %v", err) } err = schema.ValidateBytes(data) if err != nil { t.Errorf("unexpected error: %v", err) } } } }
// TestEncodePtr tests that a pointer to a golang type can be encoded and // decoded without information loss or mutation. func TestEncodePtr(t *testing.T) { grace := int64(30) pod := &api.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{"name": "foo"}, }, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, TerminationGracePeriodSeconds: &grace, SecurityContext: &api.PodSecurityContext{}, SchedulerName: api.DefaultSchedulerName, }, } 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)) } }
// TestUnversionedTypes establishes that the default codec can encode and // decode unversioned objects. func TestUnversionedTypes(t *testing.T) { testcases := []runtime.Object{ &metav1.Status{Status: "Failure", Message: "something went wrong"}, &metav1.APIVersions{Versions: []string{"A", "B", "C"}}, &metav1.APIGroupList{Groups: []metav1.APIGroup{{Name: "mygroup"}}}, &metav1.APIGroup{Name: "mygroup"}, &metav1.APIResourceList{GroupVersion: "mygroup/myversion"}, } for _, obj := range testcases { // Make sure the unversioned codec can encode unversionedJSON, err := runtime.Encode(testapi.Default.Codec(), obj) if err != nil { t.Errorf("%v: unexpected error: %v", obj, err) continue } // Make sure the versioned codec under test can decode versionDecodedObject, err := runtime.Decode(testapi.Default.Codec(), unversionedJSON) if err != nil { t.Errorf("%v: unexpected error: %v", obj, err) continue } // Make sure it decodes correctly if !reflect.DeepEqual(obj, versionDecodedObject) { t.Errorf("%v: expected %#v, got %#v", obj, obj, versionDecodedObject) continue } } }
// TestCommonKindsRegistered verifies that all group/versions registered with // the testapi package have the common kinds. func TestCommonKindsRegistered(t *testing.T) { for _, kind := range commonKinds { for _, group := range testapi.Groups { gv := group.GroupVersion() gvk := gv.WithKind(kind) obj, err := api.Scheme.New(gvk) if err != nil { t.Error(err) } defaults := gv.WithKind("") if _, got, err := api.Codecs.LegacyCodec().Decode([]byte(`{"kind":"`+kind+`"}`), &defaults, nil); err != nil || gvk != *got { t.Errorf("expected %v: %v %v", gvk, got, err) } data, err := runtime.Encode(api.Codecs.LegacyCodec(*gv), obj) if err != nil { t.Errorf("expected %v: %v\n%s", gvk, err, string(data)) continue } if !bytes.Contains(data, []byte(`"kind":"`+kind+`","apiVersion":"`+gv.String()+`"`)) { if kind != "Status" { t.Errorf("expected %v: %v\n%s", gvk, err, string(data)) continue } // TODO: this is wrong, but legacy clients expect it if !bytes.Contains(data, []byte(`"kind":"`+kind+`","apiVersion":"v1"`)) { t.Errorf("expected %v: %v\n%s", gvk, err, string(data)) continue } } } } }
func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) { data, err := runtime.Encode(codec, obj) if err != nil { return "", err } return fmt.Sprintf("%x", md5.Sum(data)), nil }
func TestSetControllerConversion(t *testing.T) { if err := api.Scheme.AddConversionFuncs(Convert_v1beta1_ReplicaSet_to_api_ReplicationController); err != nil { t.Fatal(err) } rs := &extensions.ReplicaSet{} rc := &api.ReplicationController{} extGroup := testapi.Extensions defaultGroup := testapi.Default fuzzInternalObject(t, extGroup.InternalGroupVersion(), rs, rand.Int63()) t.Logf("rs._internal.extensions -> rs.v1beta1.extensions") data, err := runtime.Encode(extGroup.Codec(), rs) if err != nil { t.Fatalf("unexpected encoding error: %v", err) } decoder := api.Codecs.DecoderToVersion( api.Codecs.UniversalDeserializer(), runtime.NewMultiGroupVersioner( *defaultGroup.GroupVersion(), schema.GroupKind{Group: defaultGroup.GroupVersion().Group}, schema.GroupKind{Group: extGroup.GroupVersion().Group}, ), ) t.Logf("rs.v1beta1.extensions -> rc._internal") if err := runtime.DecodeInto(decoder, data, rc); err != nil { t.Fatalf("unexpected decoding error: %v", err) } t.Logf("rc._internal -> rc.v1") data, err = runtime.Encode(defaultGroup.Codec(), rc) if err != nil { t.Fatalf("unexpected encoding error: %v", err) } t.Logf("rc.v1 -> rs._internal.extensions") if err := runtime.DecodeInto(decoder, data, rs); err != nil { t.Fatalf("unexpected decoding error: %v", err) } }
func TestRefetchSchemaWhenValidationFails(t *testing.T) { schema, err := loadSchemaForTest() if err != nil { t.Errorf("Error loading schema: %v", err) t.FailNow() } output, err := json.Marshal(schema) if err != nil { t.Errorf("Error serializing schema: %v", err) t.FailNow() } requests := map[string]int{} c := &manualfake.RESTClient{ NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), Client: manualfake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case strings.HasPrefix(p, "/swaggerapi") && m == "GET": requests[p] = requests[p] + 1 return &http.Response{StatusCode: 200, Header: header(), Body: ioutil.NopCloser(bytes.NewBuffer(output))}, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } }), } dir := os.TempDir() + "/schemaCache" os.RemoveAll(dir) fullDir, err := substituteUserHome(dir) if err != nil { t.Errorf("Error getting fullDir: %v", err) t.FailNow() } cacheFile := path.Join(fullDir, "foo", "bar", schemaFileName) err = writeSchemaFile(output, fullDir, cacheFile, "foo", "bar") if err != nil { t.Errorf("Error building old cache schema: %v", err) t.FailNow() } obj := &extensions.Deployment{} data, err := runtime.Encode(testapi.Extensions.Codec(), obj) if err != nil { t.Errorf("unexpected error: %v", err) t.FailNow() } // Re-get request, should use HTTP and write if getSchemaAndValidate(c, data, "foo", "bar", dir, nil); err != nil { t.Errorf("unexpected error validating: %v", err) } if requests["/swaggerapi/foo/bar"] != 1 { t.Errorf("expected 1 schema request, saw: %d", requests["/swaggerapi/foo/bar"]) } }
func TestDecoder(t *testing.T) { table := []watch.EventType{watch.Added, watch.Deleted, watch.Modified, watch.Error} for _, eventType := range table { out, in := io.Pipe() codec := testapi.Default.Codec() decoder := restclientwatch.NewDecoder(streaming.NewDecoder(out, codec), codec) expect := &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} encoder := json.NewEncoder(in) go func() { data, err := runtime.Encode(testapi.Default.Codec(), expect) if err != nil { t.Fatalf("Unexpected error %v", err) } event := metav1.WatchEvent{ Type: string(eventType), Object: runtime.RawExtension{Raw: json.RawMessage(data)}, } if err := encoder.Encode(&event); err != nil { t.Errorf("Unexpected error %v", err) } in.Close() }() done := make(chan struct{}) go func() { action, got, err := decoder.Decode() if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := eventType, action; e != a { t.Errorf("Expected %v, got %v", e, a) } if e, a := expect, got; !api.Semantic.DeepDerivative(e, a) { t.Errorf("Expected %v, got %v", e, a) } t.Logf("Exited read") close(done) }() <-done done = make(chan struct{}) go func() { _, _, err := decoder.Decode() if err == nil { t.Errorf("Unexpected nil error") } close(done) }() <-done decoder.Close() } }
// BenchmarkEncodeCodec measures the cost of performing a codec encode, which includes // reflection (to clear APIVersion and Kind) func BenchmarkEncodeCodec(b *testing.B) { items := benchmarkItems() width := len(items) b.ResetTimer() for i := 0; i < b.N; i++ { if _, err := runtime.Encode(testapi.Default.Codec(), &items[i%width]); err != nil { b.Fatal(err) } } b.StopTimer() }