func TestRecognizer(t *testing.T) { s := runtime.NewScheme() s.AddKnownTypes(unversioned.GroupVersion{Version: "v1"}, &A{}) d := NewDecoder( json.NewSerializer(json.DefaultMetaFactory, s, runtime.ObjectTyperToTyper(s), false), json.NewYAMLSerializer(json.DefaultMetaFactory, s, runtime.ObjectTyperToTyper(s)), ) out, _, err := d.Decode([]byte(` kind: A apiVersion: v1 `), nil, nil) if err != nil { t.Fatal(err) } t.Logf("%#v", out) out, _, err = d.Decode([]byte(` { "kind":"A", "apiVersion":"v1" } `), nil, nil) if err != nil { t.Fatal(err) } t.Logf("%#v", out) }
// newCodecFactory is a helper for testing that allows a different metafactory to be specified. func newCodecFactory(scheme *runtime.Scheme, mf json.MetaFactory) CodecFactory { jsonSerializer := json.NewSerializer(mf, scheme, runtime.ObjectTyperToTyper(scheme), false) jsonPrettySerializer := json.NewSerializer(mf, scheme, runtime.ObjectTyperToTyper(scheme), true) yamlSerializer := json.NewYAMLSerializer(mf, scheme, runtime.ObjectTyperToTyper(scheme)) serializers := []serializerType{ { AcceptContentTypes: []string{"application/json"}, ContentType: "application/json", FileExtensions: []string{"json"}, Serializer: jsonSerializer, PrettySerializer: jsonPrettySerializer, }, { AcceptContentTypes: []string{"application/yaml"}, ContentType: "application/yaml", FileExtensions: []string{"yaml"}, Serializer: yamlSerializer, }, } decoders := make([]runtime.Decoder, 0, len(serializers)) accepts := []string{} alreadyAccepted := make(map[string]struct{}) for _, d := range serializers { decoders = append(decoders, d.Serializer) for _, mediaType := range d.AcceptContentTypes { if _, ok := alreadyAccepted[mediaType]; ok { continue } alreadyAccepted[mediaType] = struct{}{} accepts = append(accepts, mediaType) } } return CodecFactory{ scheme: scheme, serializers: serializers, universal: recognizer.NewDecoder(decoders...), accepts: accepts, legacySerializer: jsonSerializer, } }
func TestDecode(t *testing.T) { testCases := []struct { creater runtime.ObjectCreater typer runtime.Typer yaml bool pretty bool data []byte defaultGVK *unversioned.GroupVersionKind into runtime.Object errFn func(error) bool expectedObject runtime.Object expectedGVK *unversioned.GroupVersionKind }{ { data: []byte("{}"), expectedGVK: &unversioned.GroupVersionKind{}, errFn: func(err error) bool { return strings.Contains(err.Error(), "Object 'Kind' is missing in") }, }, { data: []byte("{}"), defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, creater: &mockCreater{err: fmt.Errorf("fake error")}, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, errFn: func(err error) bool { return err.Error() == "fake error" }, }, { data: []byte("{}"), defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, creater: &mockCreater{err: fmt.Errorf("fake error")}, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, errFn: func(err error) bool { return err.Error() == "fake error" }, }, { data: []byte("{}"), defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, creater: &mockCreater{obj: &testDecodable{}}, expectedObject: &testDecodable{ gvk: nil, // json serializer does NOT set GVK }, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, }, // version without group is not defaulted { data: []byte(`{"apiVersion":"blah"}`), defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, creater: &mockCreater{obj: &testDecodable{}}, expectedObject: &testDecodable{ gvk: nil, // json serializer does NOT set GVK }, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "", Version: "blah"}, }, // group without version is defaulted { data: []byte(`{"apiVersion":"other/"}`), defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, creater: &mockCreater{obj: &testDecodable{}}, expectedObject: &testDecodable{ gvk: nil, // json serializer does NOT set GVK }, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, }, // accept runtime.Unknown as into and bypass creator { data: []byte(`{}`), into: &runtime.Unknown{}, expectedGVK: &unversioned.GroupVersionKind{}, expectedObject: &runtime.Unknown{ RawJSON: []byte(`{}`), }, }, { data: []byte(`{"test":"object"}`), into: &runtime.Unknown{}, expectedGVK: &unversioned.GroupVersionKind{}, expectedObject: &runtime.Unknown{ RawJSON: []byte(`{"test":"object"}`), }, }, { data: []byte(`{"test":"object"}`), into: &runtime.Unknown{}, defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, expectedObject: &runtime.Unknown{ TypeMeta: runtime.TypeMeta{APIVersion: "other/blah", Kind: "Test"}, RawJSON: []byte(`{"test":"object"}`), }, }, // unregistered objects can be decoded into directly { data: []byte(`{"kind":"Test","apiVersion":"other/blah","value":1,"Other":"test"}`), into: &testDecodable{}, typer: &mockTyper{err: runtime.NewNotRegisteredErr(unversioned.GroupVersionKind{}, nil)}, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, expectedObject: &testDecodable{ Other: "test", Value: 1, }, }, // registered types get defaulted by the into object kind { data: []byte(`{"value":1,"Other":"test"}`), into: &testDecodable{}, typer: &mockTyper{gvk: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}}, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, expectedObject: &testDecodable{ Other: "test", Value: 1, }, }, // registered types get defaulted by the into object kind even without version, but return an error { data: []byte(`{"value":1,"Other":"test"}`), into: &testDecodable{}, typer: &mockTyper{gvk: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: ""}}, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: ""}, errFn: func(err error) bool { return strings.Contains(err.Error(), "Object 'apiVersion' is missing in") }, expectedObject: &testDecodable{ Other: "test", Value: 1, }, }, // runtime.VersionedObjects are decoded { data: []byte(`{"value":1,"Other":"test"}`), into: &runtime.VersionedObjects{Objects: []runtime.Object{}}, creater: &mockCreater{obj: &testDecodable{}}, typer: &mockTyper{gvk: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}}, defaultGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, expectedObject: &runtime.VersionedObjects{ Objects: []runtime.Object{ &testDecodable{ Other: "test", Value: 1, }, }, }, }, // runtime.VersionedObjects with an object are decoded into { data: []byte(`{"Other":"test"}`), into: &runtime.VersionedObjects{Objects: []runtime.Object{&testDecodable{Value: 2}}}, typer: &mockTyper{gvk: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}}, expectedGVK: &unversioned.GroupVersionKind{Kind: "Test", Group: "other", Version: "blah"}, expectedObject: &runtime.VersionedObjects{ Objects: []runtime.Object{ &testDecodable{ Other: "test", Value: 2, }, }, }, }, } for i, test := range testCases { var s runtime.Serializer if test.yaml { s = json.NewYAMLSerializer(json.DefaultMetaFactory, test.creater, test.typer) } else { s = json.NewSerializer(json.DefaultMetaFactory, test.creater, test.typer, test.pretty) } obj, gvk, err := s.Decode([]byte(test.data), test.defaultGVK, test.into) if !reflect.DeepEqual(test.expectedGVK, gvk) { t.Errorf("%d: unexpected GVK: %v", i, gvk) } switch { case err == nil && test.errFn != nil: t.Errorf("%d: failed: %v", i, err) continue case err != nil && test.errFn == nil: t.Errorf("%d: failed: %v", i, err) continue case err != nil: if !test.errFn(err) { t.Errorf("%d: failed: %v", i, err) } if obj != nil { t.Errorf("%d: should have returned nil object", i) } continue } if test.into != nil && test.into != obj { t.Errorf("%d: expected into to be returned: %v", i, obj) continue } if !reflect.DeepEqual(test.expectedObject, obj) { t.Errorf("%d: unexpected object:\n%s", i, util.ObjectGoPrintSideBySide(test.expectedObject, obj)) } } }