From 87146c42553b7559af70b3ea645263de6e4b1aaf Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Mon, 4 Apr 2016 23:06:02 -0400 Subject: [PATCH] Fix compilation errors in protobuf and add decode test --- pkg/runtime/serializer/protobuf/protobuf.go | 21 +-- .../serializer/protobuf/protobuf_test.go | 154 ++++++++++++++++++ 2 files changed, 162 insertions(+), 13 deletions(-) diff --git a/pkg/runtime/serializer/protobuf/protobuf.go b/pkg/runtime/serializer/protobuf/protobuf.go index a00c1389c4f..dd89ad36ceb 100644 --- a/pkg/runtime/serializer/protobuf/protobuf.go +++ b/pkg/runtime/serializer/protobuf/protobuf.go @@ -23,7 +23,6 @@ import ( "fmt" "io" "reflect" - "sync" "github.com/gogo/protobuf/proto" @@ -41,11 +40,6 @@ var ( // // This encoding scheme is experimental, and is subject to change at any time. protoEncodingPrefix = []byte{0x6b, 0x38, 0x73, 0x00} - - bufferSize = uint64(16384) - availableBuffers = sync.Pool{New: func() interface{} { - return make([]byte, bufferSize) - }} ) type errNotMarshalable struct { @@ -76,9 +70,10 @@ func NewSerializer(creater runtime.ObjectCreater, typer runtime.Typer, defaultCo } type Serializer struct { - prefix []byte - creater runtime.ObjectCreater - typer runtime.Typer + prefix []byte + creater runtime.ObjectCreater + typer runtime.Typer + contentType string } var _ runtime.Serializer = &Serializer{} @@ -168,7 +163,7 @@ func (s *Serializer) Decode(originalData []byte, gvk *unversioned.GroupVersionKi return nil, actual, runtime.NewMissingVersionErr(fmt.Sprintf("%#v", unk.TypeMeta)) } - return unmarshalToObject(s.typer, s.creater, actual, into) + return unmarshalToObject(s.typer, s.creater, actual, into, unk.Raw) } // EncodeToStream serializes the provided object to the given writer. Overrides is ignored. @@ -374,13 +369,13 @@ func (s *RawSerializer) Decode(originalData []byte, gvk *unversioned.GroupVersio return nil, actual, runtime.NewMissingVersionErr("") } - return unmarshalToObject(s.typer, s.creater, actual, into) + return unmarshalToObject(s.typer, s.creater, actual, into, data) } // unmarshalToObject is the common code between decode in the raw and normal serializer. -func unmarshalToObject(typer runtime.Typer, creater runtime.ObjectCreater, actual *unversioned.GroupVersionKind, into runtime.Object) (runtime.Object, *unversioned.GroupVersionKind, error) { +func unmarshalToObject(typer runtime.Typer, creater runtime.ObjectCreater, actual *unversioned.GroupVersionKind, into runtime.Object, data []byte) (runtime.Object, *unversioned.GroupVersionKind, error) { // use the target if necessary - obj, err := runtime.UseOrCreateObject(s.typer, s.creater, *actual, into) + obj, err := runtime.UseOrCreateObject(typer, creater, *actual, into) if err != nil { return nil, actual, err } diff --git a/pkg/runtime/serializer/protobuf/protobuf_test.go b/pkg/runtime/serializer/protobuf/protobuf_test.go index 023fd6eb86c..a581bd4bdb8 100644 --- a/pkg/runtime/serializer/protobuf/protobuf_test.go +++ b/pkg/runtime/serializer/protobuf/protobuf_test.go @@ -22,11 +22,17 @@ import ( "bytes" "encoding/hex" "fmt" + "reflect" + "strings" "testing" + "k8s.io/kubernetes/pkg/api" + _ "k8s.io/kubernetes/pkg/api/install" "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime/serializer/protobuf" + "k8s.io/kubernetes/pkg/util/diff" ) type testObject struct { @@ -185,3 +191,151 @@ func TestEncode(t *testing.T) { } } } + +func TestDecode(t *testing.T) { + wire1 := []byte{ + 0x6b, 0x38, 0x73, 0x00, // prefix + 0x0a, 0x04, + 0x0a, 0x00, // apiversion + 0x12, 0x00, // kind + 0x12, 0x00, // data + 0x1a, 0x00, // content-type + 0x22, 0x00, // content-encoding + } + wire2 := []byte{ + 0x6b, 0x38, 0x73, 0x00, // prefix + 0x0a, 0x15, + 0x0a, 0x0d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, // apiversion + 0x12, 0x04, 0x74, 0x65, 0x73, 0x74, // kind + 0x12, 0x03, 0x01, 0x02, 0x03, // data + 0x1a, 0x00, // content-type + 0x22, 0x00, // content-encoding + } + + //err1 := fmt.Errorf("a test error") + + testCases := []struct { + obj runtime.Object + data []byte + errFn func(error) bool + }{ + { + obj: &runtime.Unknown{}, + errFn: func(err error) bool { return err.Error() == "empty data" }, + }, + { + data: []byte{0x6b}, + errFn: func(err error) bool { return strings.Contains(err.Error(), "does not appear to be a protobuf message") }, + }, + { + obj: &runtime.Unknown{ + ContentType: "application/protobuf", + Raw: []byte{}, + }, + data: wire1, + }, + { + obj: &runtime.Unknown{ + TypeMeta: runtime.TypeMeta{ + APIVersion: "other/version", + Kind: "test", + }, + ContentType: "application/protobuf", + Raw: []byte{0x01, 0x02, 0x03}, + }, + data: wire2, + }, + } + + for i, test := range testCases { + s := protobuf.NewSerializer(nil, nil, "application/protobuf") + unk := &runtime.Unknown{} + err := runtime.DecodeInto(s, test.data, unk) + + 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) + } + continue + } + + if !reflect.DeepEqual(unk, test.obj) { + t.Errorf("%d: unexpected object:\n%#v", i, unk) + continue + } + } +} + +func TestDecodeObjects(t *testing.T) { + obj1 := &v1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: "cool", + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "test", + }, + }, + }, + } + obj1wire, err := obj1.Marshal() + if err != nil { + t.Fatal(err) + } + + wire1, err := (&runtime.Unknown{ + TypeMeta: runtime.TypeMeta{Kind: "Pod", APIVersion: "v1"}, + Raw: obj1wire, + }).Marshal() + if err != nil { + t.Fatal(err) + } + + wire1 = append([]byte{0x6b, 0x38, 0x73, 0x00}, wire1...) + + testCases := []struct { + obj runtime.Object + data []byte + errFn func(error) bool + }{ + { + obj: obj1, + data: wire1, + }, + } + + for i, test := range testCases { + s := protobuf.NewSerializer(api.Scheme, runtime.ObjectTyperToTyper(api.Scheme), "application/protobuf") + obj, err := runtime.Decode(s, test.data) + + 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 not have returned an object", i) + } + continue + } + + if !api.Semantic.DeepEqual(obj, test.obj) { + t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintDiff(test.obj, obj)) + continue + } + } +}