func TestUnionFromWireInconsistencies(t *testing.T) { tests := []struct { desc string input wire.Value success *tu.Document failure string }{ { desc: "multiple recognized fields", input: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBinary([]byte{1, 2, 3})}, {ID: 2, Value: wire.NewValueString("hello")}, }}), failure: "should have exactly one field: got 2 fields", }, { desc: "recognized and unrecognized fields", input: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBinary([]byte{1, 2, 3})}, {ID: 3, Value: wire.NewValueString("hello")}, }}), success: &tu.Document{Pdf: []byte{1, 2, 3}}, }, { desc: "recognized field duplicates", input: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBinary([]byte{1, 2, 3})}, {ID: 1, Value: wire.NewValueBinary([]byte{4, 5, 6})}, }}), success: &tu.Document{Pdf: []byte{4, 5, 6}}, }, { desc: "only unrecognized fields", input: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueI32(42)}, // also a type mismatch {ID: 3, Value: wire.NewValueString("hello")}, }}), failure: "should have exactly one field: got 0 fields", }, { desc: "no fields", input: wire.NewValueStruct(wire.Struct{}), failure: "should have exactly one field: got 0 fields", }, } for _, tt := range tests { var o tu.Document err := o.FromWire(tt.input) if tt.success != nil { if assert.NoError(t, err, tt.desc) { assert.Equal(t, tt.success, &o, tt.desc) } } else { if assert.Error(t, err, tt.desc) { assert.Contains(t, err.Error(), tt.failure, tt.desc) } } } }
func TestBinarySet(t *testing.T) { tests := []struct { x td.BinarySet v wire.Value }{ { td.BinarySet{}, wire.NewValueSet( wire.ValueListFromSlice(wire.TBinary, []wire.Value{}), ), }, { td.BinarySet{ {1, 2, 3}, {4, 5, 6}, }, wire.NewValueSet( wire.ValueListFromSlice(wire.TBinary, []wire.Value{ wire.NewValueBinary([]byte{1, 2, 3}), wire.NewValueBinary([]byte{4, 5, 6}), }), ), }, } for _, tt := range tests { assertRoundTrip(t, &tt.x, tt.v, "BinarySet") } }
func (v *PrimitiveRequiredStruct) ToWire() (wire.Value, error) { var ( fields [8]wire.Field i int = 0 w wire.Value err error ) w, err = wire.NewValueBool(v.BoolField), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 1, Value: w} i++ w, err = wire.NewValueI8(v.ByteField), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 2, Value: w} i++ w, err = wire.NewValueI16(v.Int16Field), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 3, Value: w} i++ w, err = wire.NewValueI32(v.Int32Field), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 4, Value: w} i++ w, err = wire.NewValueI64(v.Int64Field), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 5, Value: w} i++ w, err = wire.NewValueDouble(v.DoubleField), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 6, Value: w} i++ w, err = wire.NewValueString(v.StringField), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 7, Value: w} i++ if v.BinaryField == nil { return w, errors.New("field BinaryField of PrimitiveRequiredStruct is required") } w, err = wire.NewValueBinary(v.BinaryField), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 8, Value: w} i++ return wire.NewValueStruct(wire.Struct{Fields: fields[:i]}), nil }
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 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 TestTypedefBinary(t *testing.T) { tests := []struct { x td.PDF v wire.Value }{ { td.PDF{1, 2, 3}, wire.NewValueBinary([]byte{1, 2, 3}), }, } for _, tt := range tests { assertRoundTrip(t, &tt.x, tt.v, "PDF") } }
func (v _Set_Binary_ValueList) ForEach(f func(wire.Value) error) error { for _, x := range v { if x == nil { return fmt.Errorf("invalid set item: value is nil") } w, err := wire.NewValueBinary(x), error(nil) if err != nil { return err } err = f(w) if err != nil { return err } } return nil }
func (v *ThriftTest_TestBinary_Args) ToWire() (wire.Value, error) { var ( fields [1]wire.Field i int = 0 w wire.Value err error ) if v.Thing != nil { w, err = wire.NewValueBinary(v.Thing), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 1, Value: w} i++ } return wire.NewValueStruct(wire.Struct{Fields: fields[:i]}), nil }
func (v *ThriftTest_TestBinary_Result) ToWire() (wire.Value, error) { var ( fields [1]wire.Field i int = 0 w wire.Value err error ) if v.Success != nil { w, err = wire.NewValueBinary(v.Success), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 0, Value: w} i++ } if i != 1 { return wire.Value{}, fmt.Errorf("ThriftTest_TestBinary_Result should have exactly one field: got %v fields", i) } return wire.NewValueStruct(wire.Struct{Fields: fields[:i]}), nil }
func (m _Map_String_Binary_MapItemList) ForEach(f func(wire.MapItem) error) error { for k, v := range m { if v == nil { return fmt.Errorf("invalid [%v]: value is nil", k) } kw, err := wire.NewValueString(k), error(nil) if err != nil { return err } vw, err := wire.NewValueBinary(v), error(nil) if err != nil { return err } err = f(wire.MapItem{Key: kw, Value: vw}) if err != nil { return err } } return nil }
func (m _Map_Binary_String_MapItemList) ForEach(f func(wire.MapItem) error) error { for _, i := range m { k := i.Key v := i.Value if k == nil { return fmt.Errorf("invalid map key: value is nil") } kw, err := wire.NewValueBinary(k), error(nil) if err != nil { return err } vw, err := wire.NewValueString(v), error(nil) if err != nil { return err } err = f(wire.MapItem{Key: kw, Value: vw}) if err != nil { return err } } return nil }
func (v *ConflictingNamesSetValueArgs) ToWire() (wire.Value, error) { var ( fields [2]wire.Field i int = 0 w wire.Value err error ) w, err = wire.NewValueString(v.Key), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 1, Value: w} i++ if v.Value == nil { return w, errors.New("field Value of ConflictingNamesSetValueArgs is required") } w, err = wire.NewValueBinary(v.Value), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 2, Value: w} i++ return wire.NewValueStruct(wire.Struct{Fields: fields[:i]}), nil }
func (v PDF) ToWire() (wire.Value, error) { x := ([]byte)(v) return wire.NewValueBinary(x), error(nil) }
func TestPrimitiveRequiredMissingFields(t *testing.T) { tests := []struct { desc string v wire.Value wantError string }{ { "bool", wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueI8(1)}, {ID: 3, Value: wire.NewValueI16(2)}, {ID: 4, Value: wire.NewValueI32(3)}, {ID: 5, Value: wire.NewValueI64(4)}, {ID: 6, Value: wire.NewValueDouble(5.0)}, {ID: 7, Value: wire.NewValueString("foo")}, {ID: 8, Value: wire.NewValueBinary([]byte("bar"))}, }}), "field BoolField of PrimitiveRequiredStruct is required", }, { "byte", wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 3, Value: wire.NewValueI16(2)}, {ID: 4, Value: wire.NewValueI32(3)}, {ID: 5, Value: wire.NewValueI64(4)}, {ID: 6, Value: wire.NewValueDouble(5.0)}, {ID: 7, Value: wire.NewValueString("foo")}, {ID: 8, Value: wire.NewValueBinary([]byte("bar"))}, }}), "field ByteField of PrimitiveRequiredStruct is required", }, { "int16", wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI8(1)}, {ID: 4, Value: wire.NewValueI32(3)}, {ID: 5, Value: wire.NewValueI64(4)}, {ID: 6, Value: wire.NewValueDouble(5.0)}, {ID: 7, Value: wire.NewValueString("foo")}, {ID: 8, Value: wire.NewValueBinary([]byte("bar"))}, }}), "field Int16Field of PrimitiveRequiredStruct is required", }, { "int32", wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI8(1)}, {ID: 3, Value: wire.NewValueI16(2)}, {ID: 5, Value: wire.NewValueI64(4)}, {ID: 6, Value: wire.NewValueDouble(5.0)}, {ID: 7, Value: wire.NewValueString("foo")}, {ID: 8, Value: wire.NewValueBinary([]byte("bar"))}, }}), "field Int32Field of PrimitiveRequiredStruct is required", }, { "int64", wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI8(1)}, {ID: 3, Value: wire.NewValueI16(2)}, {ID: 4, Value: wire.NewValueI32(3)}, {ID: 6, Value: wire.NewValueDouble(5.0)}, {ID: 7, Value: wire.NewValueString("foo")}, {ID: 8, Value: wire.NewValueBinary([]byte("bar"))}, }}), "field Int64Field of PrimitiveRequiredStruct is required", }, { "double", wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI8(1)}, {ID: 3, Value: wire.NewValueI16(2)}, {ID: 4, Value: wire.NewValueI32(3)}, {ID: 5, Value: wire.NewValueI64(4)}, {ID: 7, Value: wire.NewValueString("foo")}, {ID: 8, Value: wire.NewValueBinary([]byte("bar"))}, }}), "field DoubleField of PrimitiveRequiredStruct is required", }, { "string", wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI8(1)}, {ID: 3, Value: wire.NewValueI16(2)}, {ID: 4, Value: wire.NewValueI32(3)}, {ID: 5, Value: wire.NewValueI64(4)}, {ID: 6, Value: wire.NewValueDouble(5.0)}, {ID: 8, Value: wire.NewValueBinary([]byte("bar"))}, }}), "field StringField of PrimitiveRequiredStruct is required", }, { "binary", wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI8(1)}, {ID: 3, Value: wire.NewValueI16(2)}, {ID: 4, Value: wire.NewValueI32(3)}, {ID: 5, Value: wire.NewValueI64(4)}, {ID: 6, Value: wire.NewValueDouble(5.0)}, {ID: 7, Value: wire.NewValueString("foo")}, }}), "field BinaryField of PrimitiveRequiredStruct is required", }, } for _, tt := range tests { var s ts.PrimitiveRequiredStruct err := s.FromWire(tt.v) if assert.Error(t, err, tt.desc) { assert.Contains(t, err.Error(), tt.wantError, tt.desc) } } }
func vbinary(s string) wire.Value { return wire.NewValueBinary([]byte(s)) }
func TestStructRoundTripAndString(t *testing.T) { tests := []struct { desc string x interface { thriftType String() string } v wire.Value s string }{ { "PrimitiveRequiredStruct", &ts.PrimitiveRequiredStruct{ BoolField: true, ByteField: 1, Int16Field: 2, Int32Field: 3, Int64Field: 4, DoubleField: 5.0, StringField: "foo", BinaryField: []byte("bar"), }, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI8(1)}, {ID: 3, Value: wire.NewValueI16(2)}, {ID: 4, Value: wire.NewValueI32(3)}, {ID: 5, Value: wire.NewValueI64(4)}, {ID: 6, Value: wire.NewValueDouble(5.0)}, {ID: 7, Value: wire.NewValueString("foo")}, {ID: 8, Value: wire.NewValueBinary([]byte("bar"))}, }}), "", }, { "PrimitiveOptionalStruct: all fields", &ts.PrimitiveOptionalStruct{ BoolField: boolp(true), ByteField: bytep(1), Int16Field: int16p(2), Int32Field: int32p(3), Int64Field: int64p(4), DoubleField: doublep(5.0), StringField: stringp("foo"), BinaryField: []byte("bar"), }, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI8(1)}, {ID: 3, Value: wire.NewValueI16(2)}, {ID: 4, Value: wire.NewValueI32(3)}, {ID: 5, Value: wire.NewValueI64(4)}, {ID: 6, Value: wire.NewValueDouble(5.0)}, {ID: 7, Value: wire.NewValueString("foo")}, {ID: 8, Value: wire.NewValueBinary([]byte("bar"))}, }}), "", }, { "PrimitiveOptionalStruct: bool", &ts.PrimitiveOptionalStruct{BoolField: boolp(true)}, singleFieldStruct(1, wire.NewValueBool(true)), "", }, { "PrimitiveOptionalStruct: byte", &ts.PrimitiveOptionalStruct{ByteField: bytep(1)}, singleFieldStruct(2, wire.NewValueI8(1)), "", }, { "PrimitiveOptionalStruct: int16", &ts.PrimitiveOptionalStruct{Int16Field: int16p(2)}, singleFieldStruct(3, wire.NewValueI16(2)), "", }, { "PrimitiveOptionalStruct: int32", &ts.PrimitiveOptionalStruct{Int32Field: int32p(3)}, singleFieldStruct(4, wire.NewValueI32(3)), "", }, { "PrimitiveOptionalStruct: int64", &ts.PrimitiveOptionalStruct{Int64Field: int64p(4)}, singleFieldStruct(5, wire.NewValueI64(4)), "", }, { "PrimitiveOptionalStruct: double", &ts.PrimitiveOptionalStruct{DoubleField: doublep(5.0)}, singleFieldStruct(6, wire.NewValueDouble(5.0)), "", }, { "PrimitiveOptionalStruct: string", &ts.PrimitiveOptionalStruct{StringField: stringp("foo")}, singleFieldStruct(7, wire.NewValueString("foo")), "", }, { "PrimitiveOptionalStruct: binary", &ts.PrimitiveOptionalStruct{BinaryField: []byte("bar")}, singleFieldStruct(8, wire.NewValueBinary([]byte("bar"))), "", }, { "PrimitiveContainersRequired", &tc.PrimitiveContainersRequired{ ListOfStrings: []string{"foo", "bar", "baz"}, SetOfInts: map[int32]struct{}{1: {}, 2: {}}, MapOfIntsToDoubles: map[int64]float64{1: 2.0, 3: 4.0}, }, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TBinary, []wire.Value([]wire.Value{ wire.NewValueString("foo"), wire.NewValueString("bar"), wire.NewValueString("baz"), })), ), }, { ID: 2, Value: wire.NewValueSet( wire.ValueListFromSlice(wire.TI32, []wire.Value{ wire.NewValueI32(1), wire.NewValueI32(2), }), ), }, { ID: 3, Value: wire.NewValueMap( wire.MapItemListFromSlice(wire.TI64, wire.TDouble, []wire.MapItem{ { Key: wire.NewValueI64(1), Value: wire.NewValueDouble(2.0), }, { Key: wire.NewValueI64(3), Value: wire.NewValueDouble(4.0), }, }), ), }, }}), "", }, { "Frame", &ts.Frame{ TopLeft: &ts.Point{X: 1, Y: 2}, Size: &ts.Size{Width: 100, Height: 200}, }, 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)}, }}), }, }}), "Frame{TopLeft: Point{X: 1, Y: 2}, Size: Size{Width: 100, Height: 200}}", }, { "User: optional field missing", &ts.User{Name: "Foo Bar"}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueString("Foo Bar")}, }}), "User{Name: Foo Bar}", }, { "User: optional field present", &ts.User{ Name: "Foo Bar", Contact: &ts.ContactInfo{EmailAddress: "*****@*****.**"}, }, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueString("Foo Bar")}, {ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueString("*****@*****.**")}, }})}, }}), "User{Name: Foo Bar, Contact: ContactInfo{EmailAddress: [email protected]}}", }, { "List: self-referential struct", &ts.List{Value: 1, Tail: &ts.List{Value: 2}}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueI32(1)}, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueI32(2)}, }}), }, }}), "Node{Value: 1, Tail: Node{Value: 2}}", }, { "Document: PDF", &tu.Document{Pdf: []byte{1, 2, 3}}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBinary([]byte{1, 2, 3})}, }}), "Document{Pdf: [1 2 3]}", }, { "Document: PlainText", &tu.Document{PlainText: stringp("hello")}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueString("hello")}, }}), "Document{PlainText: hello}", }, { "ArbitraryValue: bool", &tu.ArbitraryValue{BoolValue: boolp(true)}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, }}), "ArbitraryValue{BoolValue: true}", }, { "ArbitraryValue: i64", &tu.ArbitraryValue{Int64Value: int64p(42)}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueI64(42)}, }}), "ArbitraryValue{Int64Value: 42}", }, { "ArbitraryValue: string", &tu.ArbitraryValue{StringValue: stringp("hello")}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 3, Value: wire.NewValueString("hello")}, }}), "ArbitraryValue{StringValue: hello}", }, { "ArbitraryValue: list", &tu.ArbitraryValue{ListValue: []*tu.ArbitraryValue{ {BoolValue: boolp(true)}, {Int64Value: int64p(42)}, {StringValue: stringp("hello")}, }}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 4, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TStruct, []wire.Value{ wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, }}), wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueI64(42)}, }}), wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 3, Value: wire.NewValueString("hello")}, }}), }), )}, }}), "ArbitraryValue{ListValue: [ArbitraryValue{BoolValue: true} ArbitraryValue{Int64Value: 42} ArbitraryValue{StringValue: hello}]}", }, { "ArbitraryValue: map", &tu.ArbitraryValue{MapValue: map[string]*tu.ArbitraryValue{ "bool": {BoolValue: boolp(true)}, "int64": {Int64Value: int64p(42)}, "string": {StringValue: stringp("hello")}, }}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 5, Value: wire.NewValueMap( wire.MapItemListFromSlice(wire.TBinary, wire.TStruct, []wire.MapItem{ { Key: wire.NewValueString("bool"), Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, }}), }, { Key: wire.NewValueString("int64"), Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueI64(42)}, }}), }, { Key: wire.NewValueString("string"), Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 3, Value: wire.NewValueString("hello")}, }}), }, }), )}, }}), "", }, { "EmptyStruct", &ts.EmptyStruct{}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), "", }, { "EmptyUnion", &tu.EmptyUnion{}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), "", }, { "EmptyException", &tx.EmptyException{}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), "", }, } for _, tt := range tests { assertRoundTrip(t, tt.x, tt.v, tt.desc) if tt.s != "" { assert.Equal(t, tt.s, tt.x.String(), "ToString: %v", tt.desc) } else { assert.NotPanics(t, func() { _ = tt.x.String() }, "ToString: %v", tt.desc) } } }
func TestCollectionsOfPrimitives(t *testing.T) { tests := []struct { desc string p tc.PrimitiveContainers v wire.Value }{ // Lists ///////////////////////////////////////////////////////////// { "empty list", tc.PrimitiveContainers{ListOfInts: []int64{}}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 2, Value: wire.NewValueList(wire.ValueListFromSlice(wire.TI64, []wire.Value{})), }}}), }, { "list of ints", tc.PrimitiveContainers{ListOfInts: []int64{1, 2, 3}}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 2, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TI64, []wire.Value{ wire.NewValueI64(1), wire.NewValueI64(2), wire.NewValueI64(3), }), ), }}}), }, { "list of binary", tc.PrimitiveContainers{ ListOfBinary: [][]byte{ []byte("foo"), {}, []byte("bar"), []byte("baz"), }, }, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 1, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TBinary, []wire.Value{ wire.NewValueBinary([]byte("foo")), wire.NewValueBinary([]byte{}), wire.NewValueBinary([]byte("bar")), wire.NewValueBinary([]byte("baz")), }), ), }}}), }, // Sets ////////////////////////////////////////////////////////////// { "empty set", tc.PrimitiveContainers{SetOfStrings: map[string]struct{}{}}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 3, Value: wire.NewValueSet( wire.ValueListFromSlice(wire.TBinary, []wire.Value{}), ), }}}), }, { "set of strings", tc.PrimitiveContainers{SetOfStrings: map[string]struct{}{ "foo": {}, "bar": {}, "baz": {}, }}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 3, Value: wire.NewValueSet( wire.ValueListFromSlice(wire.TBinary, []wire.Value{ wire.NewValueString("foo"), wire.NewValueString("bar"), wire.NewValueString("baz"), }), ), }}}), }, { "set of bytes", tc.PrimitiveContainers{SetOfBytes: map[int8]struct{}{ -1: {}, 1: {}, 125: {}, }}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 4, Value: wire.NewValueSet( wire.ValueListFromSlice(wire.TI8, []wire.Value{ wire.NewValueI8(-1), wire.NewValueI8(1), wire.NewValueI8(125), }), ), }}}), }, // Maps ////////////////////////////////////////////////////////////// { "empty map", tc.PrimitiveContainers{MapOfStringToBool: map[string]bool{}}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 6, Value: wire.NewValueMap( wire.MapItemListFromSlice(wire.TBinary, wire.TBool, []wire.MapItem{}), ), }}}), }, { "map of int to string", tc.PrimitiveContainers{MapOfIntToString: map[int32]string{ -1: "foo", 1234: "bar", -9876: "baz", }}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 5, Value: wire.NewValueMap( wire.MapItemListFromSlice(wire.TI32, wire.TBinary, []wire.MapItem{ {Key: wire.NewValueI32(-1), Value: wire.NewValueString("foo")}, {Key: wire.NewValueI32(1234), Value: wire.NewValueString("bar")}, {Key: wire.NewValueI32(-9876), Value: wire.NewValueString("baz")}, }), ), }}}), }, { "map of string to bool", tc.PrimitiveContainers{MapOfStringToBool: map[string]bool{ "foo": true, "bar": false, "baz": true, }}, wire.NewValueStruct(wire.Struct{Fields: []wire.Field{{ ID: 6, Value: wire.NewValueMap( wire.MapItemListFromSlice(wire.TBinary, wire.TBool, []wire.MapItem{ {Key: wire.NewValueString("foo"), Value: wire.NewValueBool(true)}, {Key: wire.NewValueString("bar"), Value: wire.NewValueBool(false)}, {Key: wire.NewValueString("baz"), Value: wire.NewValueBool(true)}, }), ), }}}), }, } for _, tt := range tests { assertRoundTrip(t, &tt.p, tt.v, tt.desc) } }
func TestStructValidation(t *testing.T) { tests := []struct { desc string serialize thriftType deserialize wire.Value typ reflect.Type // must be set if serialize is not wantError string }{ { desc: "Point: missing X", deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(42)}, }}), typ: reflect.TypeOf(ts.Point{}), wantError: "field Y of Point is required", }, { desc: "Point: missing Y", deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueDouble(42)}, }}), typ: reflect.TypeOf(ts.Point{}), wantError: "field X of Point is required", }, { desc: "Size: missing width", deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(42)}, }}), typ: reflect.TypeOf(ts.Size{}), wantError: "field Height of Size is required", }, { desc: "Size: missing height", deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueDouble(42)}, }}), typ: reflect.TypeOf(ts.Size{}), wantError: "field Width of Size is required", }, { desc: "Frame: missing topLeft", serialize: &ts.Frame{Size: &ts.Size{Width: 1, Height: 2}}, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1)}, {ID: 2, Value: wire.NewValueDouble(2)}, }}), }, }}), wantError: "field TopLeft of Frame is required", }, { desc: "Frame: missing Size", serialize: &ts.Frame{TopLeft: &ts.Point{X: 1, Y: 2}}, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1)}, {ID: 2, Value: wire.NewValueDouble(2)}, }}), }, }}), wantError: "field Size of Frame is required", }, { desc: "Frame: topLeft: missing y", deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1)}, }}), }, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1)}, {ID: 2, Value: wire.NewValueDouble(2)}, }}), }, }}), typ: reflect.TypeOf(ts.Frame{}), wantError: "field Y of Point is required", }, { desc: "Graph: missing edges", serialize: &ts.Graph{Edges: nil}, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), wantError: "field Edges of Graph is required", }, { desc: "Graph: edges: misssing end", serialize: &ts.Graph{ Edges: []*ts.Edge{ {StartPoint: &ts.Point{X: 1, Y: 2}, EndPoint: &ts.Point{X: 3, Y: 4}}, {StartPoint: &ts.Point{X: 5, Y: 6}}, }, }, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TStruct, []wire.Value{ wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1)}, {ID: 2, Value: wire.NewValueDouble(2)}, }}), }, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(3)}, {ID: 2, Value: wire.NewValueDouble(4)}, }}), }, }}), wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1)}, {ID: 2, Value: wire.NewValueDouble(2)}, }}), }, }}), }), ), }, }}), wantError: "field EndPoint of Edge is required", }, { desc: "User: contact: missing emailAddress", deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueString("hello")}, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), }, }}), typ: reflect.TypeOf(ts.User{}), wantError: "field EmailAddress of ContactInfo is required", }, { desc: "PrimitiveContainersRequired: missing list", serialize: &tc.PrimitiveContainersRequired{ SetOfInts: map[int32]struct{}{ 1: {}, 2: {}, 3: {}, }, MapOfIntsToDoubles: map[int64]float64{1: 2.3, 4: 5.6}, }, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 2, Value: wire.NewValueSet( wire.ValueListFromSlice(wire.TI32, []wire.Value{ wire.NewValueI32(1), wire.NewValueI32(2), wire.NewValueI32(3), }), ), }, { ID: 3, Value: wire.NewValueMap( wire.MapItemListFromSlice(wire.TI64, wire.TDouble, []wire.MapItem{ { Key: wire.NewValueI64(1), Value: wire.NewValueDouble(2.3), }, { Key: wire.NewValueI64(4), Value: wire.NewValueDouble(5.6), }, }), ), }, }}), wantError: "field ListOfStrings of PrimitiveContainersRequired is required", }, { desc: "PrimitiveContainersRequired: missing set", serialize: &tc.PrimitiveContainersRequired{ ListOfStrings: []string{"hello", "world"}, MapOfIntsToDoubles: map[int64]float64{1: 2.3, 4: 5.6}, }, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TBinary, []wire.Value{ wire.NewValueString("hello"), wire.NewValueString("world"), }), ), }, { ID: 3, Value: wire.NewValueMap( wire.MapItemListFromSlice(wire.TI64, wire.TDouble, []wire.MapItem{ { Key: wire.NewValueI64(1), Value: wire.NewValueDouble(2.3), }, { Key: wire.NewValueI64(4), Value: wire.NewValueDouble(5.6), }, }), ), }, }}), wantError: "field SetOfInts of PrimitiveContainersRequired is required", }, { desc: "PrimitiveContainersRequired: missing map", serialize: &tc.PrimitiveContainersRequired{ ListOfStrings: []string{"hello", "world"}, SetOfInts: map[int32]struct{}{ 1: {}, 2: {}, 3: {}, }, }, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TBinary, []wire.Value{ wire.NewValueString("hello"), wire.NewValueString("world"), }), ), }, { ID: 2, Value: wire.NewValueSet( wire.ValueListFromSlice(wire.TI32, []wire.Value{ wire.NewValueI32(1), wire.NewValueI32(2), wire.NewValueI32(3), }), ), }, }}), wantError: "field MapOfIntsToDoubles of PrimitiveContainersRequired is required", }, { desc: "Document: empty", serialize: &tu.Document{}, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), wantError: "Document should have exactly one field: got 0 fields", }, { desc: "Document: multiple", serialize: &tu.Document{ Pdf: td.PDF{}, PlainText: stringp("hello"), }, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueBinary([]byte{}), }, { ID: 2, Value: wire.NewValueString("hello"), }, }}), wantError: "Document should have exactly one field: got 2 fields", }, { desc: "ArbitraryValue: empty", serialize: &tu.ArbitraryValue{}, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), wantError: "ArbitraryValue should have exactly one field: got 0 fields", }, { desc: "ArbitraryValue: primitives", serialize: &tu.ArbitraryValue{ BoolValue: boolp(true), Int64Value: int64p(42), StringValue: stringp(""), }, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI64(42)}, {ID: 3, Value: wire.NewValueString("")}, }}), wantError: "ArbitraryValue should have exactly one field: got 3 fields", }, { desc: "ArbitraryValue: full", serialize: &tu.ArbitraryValue{ BoolValue: boolp(true), Int64Value: int64p(42), StringValue: stringp(""), ListValue: []*tu.ArbitraryValue{ {BoolValue: boolp(true)}, {Int64Value: int64p(42)}, {StringValue: stringp("")}, }, MapValue: map[string]*tu.ArbitraryValue{ "bool": {BoolValue: boolp(true)}, "int": {Int64Value: int64p(42)}, "string": {StringValue: stringp("")}, }, }, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, {ID: 2, Value: wire.NewValueI64(42)}, {ID: 3, Value: wire.NewValueString("")}, { ID: 4, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TStruct, []wire.Value{ wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, }}), wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueI64(42)}, }}), wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 3, Value: wire.NewValueString("")}, }}), }), ), }, { ID: 5, Value: wire.NewValueMap( wire.MapItemListFromSlice(wire.TBinary, wire.TStruct, []wire.MapItem{ { Key: wire.NewValueString("bool"), Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, }}), }, { Key: wire.NewValueString("int"), Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 2, Value: wire.NewValueI64(42)}, }}), }, { Key: wire.NewValueString("string"), Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 3, Value: wire.NewValueString("")}, }}), }, }), ), }, }}), wantError: "ArbitraryValue should have exactly one field: got 5 fields", }, { desc: "ArbitraryValue: error inside a list", serialize: &tu.ArbitraryValue{ ListValue: []*tu.ArbitraryValue{ {BoolValue: boolp(true)}, {}, }, }, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 4, Value: wire.NewValueList( wire.ValueListFromSlice(wire.TStruct, []wire.Value{ wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, }}), wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), })), }, }}), wantError: "ArbitraryValue should have exactly one field: got 0 fields", }, { desc: "ArbitraryValue: error inside a map value", serialize: &tu.ArbitraryValue{ MapValue: map[string]*tu.ArbitraryValue{ "bool": {BoolValue: boolp(true)}, "empty": {}, }, }, deserialize: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 5, Value: wire.NewValueMap( wire.MapItemListFromSlice(wire.TBinary, wire.TStruct, []wire.MapItem{ { Key: wire.NewValueString("bool"), Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueBool(true)}, }}), }, { Key: wire.NewValueString("empty"), Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{}}), }, }), ), }, }}), wantError: "ArbitraryValue should have exactly one field: got 0 fields", }, { desc: "FrameGroup: error inside a set", serialize: &td.FrameGroup{ &ts.Frame{ TopLeft: &ts.Point{X: 1, Y: 2}, Size: &ts.Size{Width: 3, Height: 4}, }, &ts.Frame{TopLeft: &ts.Point{X: 5, Y: 6}}, }, deserialize: wire.NewValueSet( wire.ValueListFromSlice(wire.TStruct, []wire.Value{ wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueDouble(1), }, { ID: 2, Value: wire.NewValueDouble(2), }, }}), }, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueDouble(3), }, { ID: 2, Value: wire.NewValueDouble(4), }, }}), }, }}), wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueDouble(5), }, { ID: 2, Value: wire.NewValueDouble(6), }, }}), }, }}), }), ), wantError: "field Size of Frame is required", }, { desc: "EdgeMap: error inside a map key", serialize: &td.EdgeMap{ { Key: &ts.Edge{StartPoint: &ts.Point{X: 1, Y: 2}}, Value: &ts.Edge{StartPoint: &ts.Point{X: 3, Y: 4}, EndPoint: &ts.Point{X: 5, Y: 6}}, }, }, deserialize: wire.NewValueMap( wire.MapItemListFromSlice(wire.TStruct, wire.TStruct, []wire.MapItem{ { Key: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(1)}, {ID: 2, Value: wire.NewValueDouble(2)}, }}), }, }}), Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ { ID: 1, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(3)}, {ID: 2, Value: wire.NewValueDouble(4)}, }}), }, { ID: 2, Value: wire.NewValueStruct(wire.Struct{Fields: []wire.Field{ {ID: 1, Value: wire.NewValueDouble(5)}, {ID: 2, Value: wire.NewValueDouble(6)}, }}), }, }}), }, }), ), wantError: "field EndPoint of Edge is required", }, } for _, tt := range tests { var typ reflect.Type if tt.serialize != nil { typ = reflect.TypeOf(tt.serialize).Elem() v, err := tt.serialize.ToWire() if err == nil { err = wire.EvaluateValue(v) } if assert.Error(t, err, "%v: expected failure but got %v", tt.desc, v) { assert.Contains(t, err.Error(), tt.wantError, tt.desc) } } else { typ = tt.typ } if typ == nil { t.Fatalf("invalid test %q: either typ or serialize must be set", tt.desc) } x := reflect.New(typ) args := []reflect.Value{reflect.ValueOf(tt.deserialize)} e := x.MethodByName("FromWire").Call(args)[0].Interface() if assert.NotNil(t, e, "%v: expected failure but got %v", tt.desc, x) { assert.Contains(t, e.(error).Error(), tt.wantError, tt.desc) } } }
func (v *PrimitiveOptionalStruct) ToWire() (wire.Value, error) { var ( fields [8]wire.Field i int = 0 w wire.Value err error ) if v.BoolField != nil { w, err = wire.NewValueBool(*(v.BoolField)), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 1, Value: w} i++ } if v.ByteField != nil { w, err = wire.NewValueI8(*(v.ByteField)), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 2, Value: w} i++ } if v.Int16Field != nil { w, err = wire.NewValueI16(*(v.Int16Field)), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 3, Value: w} i++ } if v.Int32Field != nil { w, err = wire.NewValueI32(*(v.Int32Field)), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 4, Value: w} i++ } if v.Int64Field != nil { w, err = wire.NewValueI64(*(v.Int64Field)), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 5, Value: w} i++ } if v.DoubleField != nil { w, err = wire.NewValueDouble(*(v.DoubleField)), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 6, Value: w} i++ } if v.StringField != nil { w, err = wire.NewValueString(*(v.StringField)), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 7, Value: w} i++ } if v.BinaryField != nil { w, err = wire.NewValueBinary(v.BinaryField), error(nil) if err != nil { return w, err } fields[i] = wire.Field{ID: 8, Value: w} i++ } return wire.NewValueStruct(wire.Struct{Fields: fields[:i]}), nil }
// ReadValue reads a value off the given type off the wire starting at the // given offset. // // Returns the Value, the new offset, and an error if there was a decode error. func (br *Reader) ReadValue(t wire.Type, off int64) (wire.Value, int64, error) { switch t { case wire.TBool: b, off, err := br.readByte(off) if err != nil { return wire.Value{}, off, err } if b != 0 && b != 1 { return wire.Value{}, off, decodeErrorf( "invalid value %q for bool field", b, ) } return wire.NewValueBool(b == 1), off, nil case wire.TI8: b, off, err := br.readByte(off) return wire.NewValueI8(int8(b)), off, err case wire.TDouble: value, off, err := br.readInt64(off) d := math.Float64frombits(uint64(value)) return wire.NewValueDouble(d), off, err case wire.TI16: n, off, err := br.readInt16(off) return wire.NewValueI16(n), off, err case wire.TI32: n, off, err := br.readInt32(off) return wire.NewValueI32(n), off, err case wire.TI64: n, off, err := br.readInt64(off) return wire.NewValueI64(n), off, err case wire.TBinary: v, off, err := br.readBytes(off) return wire.NewValueBinary(v), off, err case wire.TStruct: s, off, err := br.readStruct(off) return wire.NewValueStruct(s), off, err case wire.TMap: m, off, err := br.readMap(off) return wire.NewValueMap(m), off, err case wire.TSet: s, off, err := br.readSet(off) return wire.NewValueSet(s), off, err case wire.TList: l, off, err := br.readList(off) return wire.NewValueList(l), off, err default: return wire.Value{}, off, decodeErrorf("unknown ttype %v", t) } }