github.com/segmentio/encoding@v0.4.0/proto/reflect_test.go (about) 1 package proto 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 ) 8 9 type RecursiveMessage struct { 10 Next *RecursiveMessage `protobuf:"bytes,1,opt,name=next,proto3"` 11 } 12 13 func TestTypeOf(t *testing.T) { 14 tests := []struct { 15 value interface{} 16 proto string 17 }{ 18 // primitive types 19 {value: true, proto: "bool"}, 20 {value: int(1), proto: "int64"}, 21 {value: int32(1), proto: "int32"}, 22 {value: int64(1), proto: "int64"}, 23 {value: uint(1), proto: "uint64"}, 24 {value: uint32(1), proto: "uint32"}, 25 {value: uint64(1), proto: "uint64"}, 26 {value: float32(1), proto: "float"}, 27 {value: float64(1), proto: "double"}, 28 {value: "hello", proto: "string"}, 29 {value: []byte("A"), proto: "bytes"}, 30 31 // map types 32 {value: map[int]string{}, proto: "map<int64, string>"}, 33 34 // struct types 35 { 36 value: struct{}{}, 37 proto: `message {}`, 38 }, 39 40 { 41 value: struct{ A int }{}, 42 proto: `message { 43 int64 A = 1; 44 }`, 45 }, 46 47 { 48 value: struct { 49 A int `protobuf:"varint,1,opt,name=hello,proto3"` 50 B string `protobuf:"bytes,3,rep,name=world,proto3"` 51 }{}, 52 proto: `message { 53 int64 hello = 1; 54 repeated string world = 3; 55 }`, 56 }, 57 58 { 59 value: RecursiveMessage{}, 60 proto: `message RecursiveMessage { 61 RecursiveMessage next = 1; 62 }`, 63 }, 64 65 { 66 value: struct { 67 M RawMessage 68 }{}, 69 proto: `message { 70 bytes M = 1; 71 }`, 72 }, 73 } 74 75 for _, test := range tests { 76 t.Run(fmt.Sprintf("%T", test.value), func(t *testing.T) { 77 typ := TypeOf(reflect.TypeOf(test.value)) 78 str := typ.String() 79 80 if str != test.proto { 81 t.Error("protobuf representation mismatch") 82 t.Log("want:", test.proto) 83 t.Log("got: ", str) 84 } 85 }) 86 } 87 } 88 89 func TestTypesAreEqual(t *testing.T) { 90 if TypeOf(reflect.TypeOf(true)) != TypeOf(reflect.TypeOf(false)) { 91 t.Error("type of true is not equal to type of false") 92 } 93 } 94 95 func TestTypesAreNotEqual(t *testing.T) { 96 if TypeOf(reflect.TypeOf(false)) == TypeOf(reflect.TypeOf(0)) { 97 t.Error("type of bool equal type of int") 98 } 99 } 100 101 func TestParseStructTag(t *testing.T) { 102 tests := []struct { 103 str string 104 tag structTag 105 }{ 106 { 107 str: `bytes,1,rep,name=next,proto3`, 108 tag: structTag{ 109 name: "next", 110 version: 3, 111 wireType: Varlen, 112 fieldNumber: 1, 113 extensions: map[string]string{}, 114 repeated: true, 115 }, 116 }, 117 118 { 119 str: `bytes,5,opt,name=key,proto3`, 120 tag: structTag{ 121 name: "key", 122 version: 3, 123 wireType: Varlen, 124 fieldNumber: 5, 125 extensions: map[string]string{}, 126 }, 127 }, 128 129 { 130 str: `fixed64,6,opt,name=seed,proto3`, 131 tag: structTag{ 132 name: "seed", 133 version: 3, 134 wireType: Fixed64, 135 fieldNumber: 6, 136 extensions: map[string]string{}, 137 }, 138 }, 139 140 { 141 str: `varint,8,opt,name=expire_after,json=expireAfter,proto3`, 142 tag: structTag{ 143 name: "expire_after", 144 json: "expireAfter", 145 version: 3, 146 wireType: Varint, 147 fieldNumber: 8, 148 extensions: map[string]string{}, 149 }, 150 }, 151 152 { 153 str: `bytes,17,opt,name=batch_key,json=batchKey,proto3,customtype=U128`, 154 tag: structTag{ 155 name: "batch_key", 156 json: "batchKey", 157 version: 3, 158 wireType: Varlen, 159 fieldNumber: 17, 160 extensions: map[string]string{ 161 "customtype": "U128", 162 }, 163 }, 164 }, 165 } 166 167 for _, test := range tests { 168 t.Run(test.str, func(t *testing.T) { 169 tag, err := parseStructTag(test.str) 170 if err != nil { 171 t.Fatal(err) 172 } 173 if !reflect.DeepEqual(tag, test.tag) { 174 t.Errorf("struct tag mismatch\nwant: %+v\ngot: %+v", test.tag, tag) 175 } 176 }) 177 } 178 }