Fix compilation errors in protobuf and add decode test

pull/6/head
Clayton Coleman 2016-04-04 23:06:02 -04:00
parent bfc991646b
commit 87146c4255
2 changed files with 162 additions and 13 deletions

View File

@ -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("<protobuf encoded body - must provide default type>")
}
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
}

View File

@ -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
}
}
}