func checkEncodeDecode(t *testing.T, typ wire.Type, tests []encodeDecodeTest) { for _, tt := range tests { buffer := bytes.Buffer{} // encode and match bytes err := Binary.Encode(tt.value, &buffer) if assert.NoError(t, err, "Encode failed:\n%s", tt.value) { assert.Equal(t, tt.encoded, buffer.Bytes()) } // decode and match value value, err := Binary.Decode(bytes.NewReader(tt.encoded), typ) if assert.NoError(t, err, "Decode failed:\n%s", tt.value) { assert.True( t, wire.ValuesAreEqual(tt.value, value), fmt.Sprintf("\n\t %v (expected)\n\t!= %v (actual)", tt.value, value), ) } // encode the decoded value again buffer = bytes.Buffer{} err = Binary.Encode(value, &buffer) if assert.NoError(t, err, "Encode of decoded value failed:\n%s", tt.value) { assert.Equal(t, tt.encoded, buffer.Bytes()) } } }
// assertRoundTrip checks if x.ToWire() results in the given Value and whether // x.FromWire() with the given value results in the original x. func assertRoundTrip(t *testing.T, x thriftType, v wire.Value, msg string, args ...interface{}) bool { message := fmt.Sprintf(msg, args...) if w, err := x.ToWire(); assert.NoError(t, err, "failed to serialize: %v", x) { if !assert.True( t, wire.ValuesAreEqual(v, w), "%v: %v.ToWire() != %v", message, x, v) { return false } var buff bytes.Buffer if !assert.NoError(t, protocol.Binary.Encode(w, &buff), "%v: failed to serialize", message) { return false } // Flip v to deserialize(serialize(x.ToWire())) to ensure full round // tripping newV, err := protocol.Binary.Decode(bytes.NewReader(buff.Bytes()), v.Type()) if !assert.NoError(t, err, "%v: failed to deserialize", message) { return false } if !assert.True( t, wire.ValuesAreEqual(newV, v), "%v: deserialize(serialize(%v.ToWire())) != %v", message, x, v) { return false } v = newV } xType := reflect.TypeOf(x) if xType.Kind() == reflect.Ptr { xType = xType.Elem() } gotX := reflect.New(xType) err := gotX.MethodByName("FromWire"). Call([]reflect.Value{reflect.ValueOf(v)})[0]. Interface() if assert.Nil(t, err, "FromWire: %v", message) { return assert.Equal(t, x, gotX.Interface(), "FromWire: %v", message) } return false }
func TestBinaryLargeLength(t *testing.T) { // 5 MB + 4 bytes for length data := make([]byte, 5242880+4) data[0], data[1], data[2], data[3] = 0x0, 0x50, 0x0, 0x0 // 5 MB value, err := Binary.Decode(bytes.NewReader(data), wire.TBinary) require.NoError(t, err, "failed to decode value") want := wire.NewValueBinary(data[4:]) assert.True(t, wire.ValuesAreEqual(want, value), "values did not match") }
func TestDisableEnveloperEncode(t *testing.T) { rand := rand.New(rand.NewSource(time.Now().Unix())) tests := []struct { value wire.Value want []byte }{ { wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), []byte{0x00}, }, { wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueI32(42)}, }}), []byte{ 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, }, }, } for _, tt := range tests { e := wire.Envelope{Value: tt.value, Type: wire.Call} generate(&e.Name, rand) generate(&e.SeqID, rand) var buffer bytes.Buffer proto := disableEnvelopingProtocol{protocol.Binary, wire.Reply} if !assert.NoError(t, proto.EncodeEnveloped(e, &buffer)) { continue } assert.Equal(t, tt.want, buffer.Bytes()) gotE, err := proto.DecodeEnveloped(bytes.NewReader(tt.want)) if !assert.NoError(t, err) { continue } assert.Equal(t, wire.Reply, gotE.Type) assert.True(t, wire.ValuesAreEqual(tt.value, gotE.Value)) } }
func TestListOfBinaryReadNil(t *testing.T) { value := wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 1, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TBinary, []wire.Value{ wire.NewValueBinary([]byte("foo")), wire.NewValueBinary(nil), wire.NewValueBinary([]byte("bar")), wire.NewValueBinary([]byte("baz")), }), ), }}}) var c tc.PrimitiveContainers require.NoError(t, c.FromWire(value)) got, err := c.ToWire() require.NoError(t, err) require.NoError(t, wire.EvaluateValue(got)) assert.True(t, wire.ValuesAreEqual(value, got)) }
func roundTrip(t *testing.T, x thriftType, msg string) thriftType { v, err := x.ToWire() if !assert.NoError(t, err, "failed to serialize: %v", x) { return nil } var buff bytes.Buffer if !assert.NoError(t, protocol.Binary.Encode(v, &buff), "%v: failed to serialize", msg) { return nil } newV, err := protocol.Binary.Decode(bytes.NewReader(buff.Bytes()), v.Type()) if !assert.NoError(t, err, "%v: failed to deserialize", msg) { return nil } if !assert.True( t, wire.ValuesAreEqual(newV, v), "%v: deserialize(serialize(%v.ToWire())) != %v", msg, x, v) { return nil } xType := reflect.TypeOf(x) if xType.Kind() == reflect.Ptr { xType = xType.Elem() } gotX := reflect.New(xType) errval := gotX.MethodByName("FromWire"). Call([]reflect.Value{reflect.ValueOf(newV)})[0]. Interface() if !assert.Nil(t, errval, "FromWire: %v", msg) { return nil } assert.Equal(t, x, gotX.Interface(), "FromWire: %v", msg) return gotX.Interface().(thriftType) }
func TestStructWithDefaults(t *testing.T) { enumDefaultFoo := te.EnumDefaultFoo enumDefaultBar := te.EnumDefaultBar enumDefaultBaz := te.EnumDefaultBaz tests := []struct { give *ts.DefaultsStruct giveWire wire.Value wantToWire wire.Value wantFromWire *ts.DefaultsStruct }{ { give: &ts.DefaultsStruct{}, giveWire: wire.NewValueStruct(wire.Struct{}), wantToWire: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueI32(100)}, {ID: 2, Value: wire.NewValueI32(200)}, {ID: 3, Value: wire.NewValueI32(1)}, {ID: 4, Value: wire.NewValueI32(2)}, { ID: 5, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TBinary, []wire.Value{ wire.NewValueString("hello"), wire.NewValueString("world"), }), ), }, { ID: 6, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TDouble, []wire.Value{ wire.NewValueDouble(1.0), wire.NewValueDouble(2.0), wire.NewValueDouble(3.0), }), ), }, { ID: 7, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1.0)}, {ID: 2, Value: wire.NewValueDouble(2.0)}, }}), }, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(100.0)}, {ID: 2, Value: wire.NewValueDouble(200.0)}, }}), }, }}), }, { ID: 8, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1.0)}, {ID: 2, Value: wire.NewValueDouble(2.0)}, }}), }, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(3.0)}, {ID: 2, Value: wire.NewValueDouble(4.0)}, }}), }, }}), }, }}), wantFromWire: &ts.DefaultsStruct{ RequiredPrimitive: int32p(100), OptionalPrimitive: int32p(200), RequiredEnum: &enumDefaultBar, OptionalEnum: &enumDefaultBaz, RequiredList: []string{"hello", "world"}, OptionalList: []float64{1.0, 2.0, 3.0}, RequiredStruct: &ts.Frame{ TopLeft: &ts.Point{X: 1.0, Y: 2.0}, Size: &ts.Size{Width: 100.0, Height: 200.0}, }, OptionalStruct: &ts.Edge{ StartPoint: &ts.Point{X: 1.0, Y: 2.0}, EndPoint: &ts.Point{X: 3.0, Y: 4.0}, }, }, }, { give: &ts.DefaultsStruct{ RequiredPrimitive: int32p(0), OptionalEnum: &enumDefaultFoo, RequiredList: []string{}, }, giveWire: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueI32(0)}, {ID: 4, Value: wire.NewValueI32(0)}, { ID: 5, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TBinary, []wire.Value{}), ), }, }}), wantToWire: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueI32(0)}, {ID: 2, Value: wire.NewValueI32(200)}, {ID: 3, Value: wire.NewValueI32(1)}, {ID: 4, Value: wire.NewValueI32(0)}, { ID: 5, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TBinary, []wire.Value{}), ), }, { ID: 6, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TDouble, []wire.Value{ wire.NewValueDouble(1.0), wire.NewValueDouble(2.0), wire.NewValueDouble(3.0), }), ), }, { ID: 7, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1.0)}, {ID: 2, Value: wire.NewValueDouble(2.0)}, }}), }, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(100.0)}, {ID: 2, Value: wire.NewValueDouble(200.0)}, }}), }, }}), }, { ID: 8, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1.0)}, {ID: 2, Value: wire.NewValueDouble(2.0)}, }}), }, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(3.0)}, {ID: 2, Value: wire.NewValueDouble(4.0)}, }}), }, }}), }, }}), wantFromWire: &ts.DefaultsStruct{ RequiredPrimitive: int32p(0), OptionalPrimitive: int32p(200), RequiredEnum: &enumDefaultBar, OptionalEnum: &enumDefaultFoo, RequiredList: []string{}, OptionalList: []float64{1.0, 2.0, 3.0}, RequiredStruct: &ts.Frame{ TopLeft: &ts.Point{X: 1.0, Y: 2.0}, Size: &ts.Size{Width: 100.0, Height: 200.0}, }, OptionalStruct: &ts.Edge{ StartPoint: &ts.Point{X: 1.0, Y: 2.0}, EndPoint: &ts.Point{X: 3.0, Y: 4.0}, }, }, }, } for _, tt := range tests { if gotWire, err := tt.give.ToWire(); assert.NoError( t, err, "%v.ToWire() failed", tt.give) { assert.True( t, wire.ValuesAreEqual(tt.wantToWire, gotWire), "%v.ToWire() != %v", tt.give, tt.wantToWire) } var gotFromWire ts.DefaultsStruct if err := gotFromWire.FromWire(tt.giveWire); assert.NoError(t, err) { assert.Equal(t, tt.wantFromWire, &gotFromWire) } } }