github.com/RomiChan/protobuf@v0.1.1-0.20230204044148-2ed269a2e54d/proto/proto_test.go (about) 1 package proto_test 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "math" 7 "reflect" 8 "strconv" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 13 . "github.com/RomiChan/protobuf/proto" 14 "github.com/RomiChan/protobuf/proto/internal/testproto" 15 ) 16 17 type key struct { 18 Hi uint64 `protobuf:"varint,1,opt"` 19 Lo uint64 `protobuf:"varint,2,opt"` 20 } 21 22 type message struct { 23 A int32 `protobuf:"varint,1,opt"` 24 B int32 `protobuf:"varint,2,opt"` 25 C int32 `protobuf:"varint,3,opt"` 26 S *submessage `protobuf:"bytes,4,opt"` 27 } 28 29 type submessage struct { 30 X string `protobuf:"bytes,1,opt"` 31 Y string `protobuf:"bytes,2,opt"` 32 } 33 34 func TestMarshalUnmarshal(t *testing.T) { 35 values := []interface{}{ 36 &message{ 37 A: 1, 38 B: 2, 39 C: 3, 40 S: &submessage{ 41 X: "hello", 42 Y: "world", 43 }, 44 }, 45 46 &struct { 47 Min int64 `protobuf:"zigzag64,1,opt"` 48 Max int64 `protobuf:"zigzag64,2,opt"` 49 }{Min: math.MinInt64, Max: math.MaxInt64}, 50 51 // pointers 52 &struct { 53 M *message `protobuf:"bytes,1,opt"` 54 }{M: nil}, 55 &struct { 56 M1 *message `protobuf:"bytes,1,opt"` 57 M2 *message `protobuf:"bytes,2,opt"` 58 }{ 59 M1: &message{A: 10, B: 100, C: 1000}, 60 M2: &message{S: &submessage{X: "42"}}, 61 }, 62 63 // slices (repeated) 64 &struct { 65 S []int32 `protobuf:"varint,1,rep"` 66 }{S: nil}, 67 &struct { 68 S []int32 `protobuf:"varint,1,rep"` 69 }{S: []int32{0}}, 70 &struct { 71 S []int32 `protobuf:"varint,1,rep"` 72 }{S: []int32{0, 0, 0}}, 73 &struct { 74 S []int32 `protobuf:"varint,1,rep"` 75 }{S: []int32{1, 2, 3}}, 76 &struct { 77 S []string `protobuf:"bytes,1,rep"` 78 }{S: nil}, 79 &struct { 80 S []string `protobuf:"bytes,1,rep"` 81 }{S: []string{""}}, 82 &struct { 83 S []string `protobuf:"bytes,1,rep"` 84 }{S: []string{"A", "B", "C"}}, 85 &struct { 86 K []*key `protobuf:"bytes,1,opt"` 87 }{ 88 K: []*key{ 89 {Hi: 0, Lo: 0}, 90 {Hi: 0, Lo: 1}, 91 {Hi: 0, Lo: 2}, 92 {Hi: 0, Lo: 3}, 93 {Hi: 0, Lo: 4}, 94 }, 95 }, 96 } 97 98 for _, v := range values { 99 t.Run(fmt.Sprintf("%T/%+v", v, v), func(t *testing.T) { 100 n := Size(v) 101 102 b, err := Marshal(v) 103 if err != nil { 104 t.Fatal(err) 105 } 106 if n != len(b) { 107 t.Fatalf("value size and buffer length mismatch (%d != %d) %v to %s", n, len(b), v, hex.EncodeToString(b)) 108 } 109 110 p := reflect.New(reflect.TypeOf(v).Elem()) 111 if err := Unmarshal(b, p.Interface()); err != nil { 112 t.Fatal(err) 113 } 114 115 x := p.Interface() 116 assert.Equal(t, v, x) 117 }) 118 } 119 } 120 121 func TestProto2(t *testing.T) { 122 values := []*testproto.Proto2{ 123 {}, // nil 124 { // none-nil but default value 125 BoolValue: Bool(false), 126 Int32Val: Int32(0), 127 Uint32Val: Uint32(0), 128 Int64Val: Int64(0), 129 Uint64Val: Uint64(0), 130 FloatVal: Float32(0), 131 DoubleVal: Float64(0), 132 StringVal: String(""), 133 BytesVal: []byte{}, 134 Fixed32Val: Uint32(0), 135 Fixed64Val: Uint64(0), 136 Sint32Val: Int32(0), 137 Sint64Val: Int64(0), 138 }, 139 { 140 BoolValue: Bool(true), 141 Int32Val: Int32(1), 142 Uint32Val: Uint32(2), 143 Int64Val: Int64(3), 144 Uint64Val: Uint64(4), 145 FloatVal: Float32(114.514), 146 DoubleVal: Float64(1919.810), 147 StringVal: String("Hello World"), 148 BytesVal: make([]byte, 16), 149 Fixed32Val: Uint32(5), 150 Fixed64Val: Uint64(6), 151 Sint32Val: Int32(7), 152 Sint64Val: Int64(8), 153 }, 154 { 155 Nested: &testproto.Proto2_NestedMessage{}, 156 }, 157 { 158 Nested: &testproto.Proto2_NestedMessage{ 159 Int32Val: Int32(0), 160 Int64Val: Int64(0), 161 StringVal: String(""), 162 }, 163 }, 164 { 165 Nested: &testproto.Proto2_NestedMessage{ 166 Int32Val: Int32(114514), 167 Int64Val: Int64(1919810), 168 StringVal: String("Hello World!"), 169 }, 170 }, 171 } 172 173 for i, v := range values { 174 t.Run(strconv.Itoa(i+1), func(t *testing.T) { 175 n := Size(v) 176 b, err := Marshal(v) 177 assert.NoError(t, err) 178 assert.Len(t, b, n) 179 180 p := new(testproto.Proto2) 181 assert.NoError(t, Unmarshal(b, p)) 182 assert.Equal(t, v, p) 183 }) 184 } 185 } 186 187 func TestIssue106(t *testing.T) { 188 m1 := struct { 189 I uint32 `protobuf:"varint,1,opt"` 190 }{I: ^uint32(0)} 191 192 m2 := struct { 193 I int32 `protobuf:"varint,1,opt"` 194 }{} 195 196 b, err := Marshal(&m1) 197 assert.NoError(t, err) 198 assert.NoError(t, Unmarshal(b, &m2)) 199 assert.Equal(t, m2.I, int32(-1)) 200 } 201 202 func TestBoolPointer(t *testing.T) { 203 type message struct { 204 A *bool `protobuf:"varint,1,opt"` 205 } 206 var m message 207 data, err := Marshal(&m) 208 assert.NoError(t, err) 209 210 var b message 211 assert.NoError(t, Unmarshal(data, &b)) 212 assert.Equal(t, m, b) 213 } 214 215 func TestPrivateField(t *testing.T) { 216 type private struct { 217 a uint64 `protobuf:"varint,1,opt"` 218 b uint64 `protobuf:"varint,2,opt"` 219 } 220 type public struct { 221 A uint64 `protobuf:"varint,1,opt"` 222 B uint64 `protobuf:"varint,2,opt"` 223 } 224 s := &private{1, 2} 225 if Size(s) != 0 { 226 t.Errorf("Size of private field should be zero.") 227 } 228 data, err := Marshal(s) 229 if err != nil { 230 t.Errorf("Marshal failed: %v", err) 231 } 232 if len(data) != 0 { 233 t.Errorf("Marshal of private field should be empty.") 234 } 235 236 data, err = Marshal(&public{2, 1}) 237 if err != nil { 238 t.Errorf("Marshal failed: %v", err) 239 } 240 if len(data) == 0 { 241 t.Errorf("Marshal of public field should not be empty.") 242 } 243 err = Unmarshal(data, s) 244 if err != nil { 245 t.Errorf("Unmarshal failed: %v", err) 246 } 247 if s.a == 2 || s.b == 1 { 248 t.Errorf("Unmarshal of private field: %v", s) 249 } 250 } 251 252 func TestFixed(t *testing.T) { 253 type message struct { 254 Fixed32 uint32 `protobuf:"fixed32,1,opt"` 255 Fixed64 uint64 `protobuf:"fixed64,2,opt"` 256 } 257 m := &message{ 258 Fixed32: 0x01020304, 259 Fixed64: 0x0102030405060708, 260 } 261 if Size(m) != 14 { // 1+4+1+8 262 t.Fatalf("Size of struct with fixed32 and fixed64 fields is not 14.") 263 } 264 b, err := Marshal(m) 265 if err != nil { 266 t.Fatalf("proto.Marshal failed: %v", err) 267 } 268 var m2 message 269 if err := Unmarshal(b, &m2); err != nil { 270 t.Fatalf("proto.Unmarshal failed: %v", err) 271 } 272 if m2.Fixed32 != 0x01020304 { 273 t.Errorf("m2.Fixed32 = %x, want 0x01020304", m2.Fixed32) 274 } 275 if m2.Fixed64 != 0x0102030405060708 { 276 t.Errorf("m2.Fixed64 = %x, want 0x0102030405060708", m2.Fixed64) 277 } 278 } 279 280 func TestFixedOption(t *testing.T) { 281 type message struct { 282 Fixed32 Option[uint32] `protobuf:"fixed32,1,opt"` 283 Fixed64 Option[uint64] `protobuf:"fixed64,2,opt"` 284 } 285 var fixed32 uint32 = 0x01020304 286 var fixed64 uint64 = 0x0102030405060708 287 m := &message{ 288 Fixed32: Some(fixed32), 289 Fixed64: Some(fixed64), 290 } 291 if Size(m) != 14 { // 1+4+1+8 292 t.Fatalf("Size of struct with fixed32 and fixed64 fields is not 14.") 293 } 294 b, err := Marshal(m) 295 if err != nil { 296 t.Fatalf("proto.Marshal failed: %v", err) 297 } 298 var m2 message 299 if err := Unmarshal(b, &m2); err != nil { 300 t.Fatalf("proto.Unmarshal failed: %v", err) 301 } 302 if m2.Fixed32.Unwrap() != 0x01020304 { 303 t.Errorf("m2.Fixed32 = %v, want 0x01020304", m2.Fixed32) 304 } 305 if m2.Fixed64.Unwrap() != 0x0102030405060708 { 306 t.Errorf("m2.Fixed64 = %v, want 0x0102030405060708", m2.Fixed64) 307 } 308 } 309 310 func TestMap(t *testing.T) { 311 type message struct { 312 StrMap map[string]string `protobuf:"bytes,1,opt" protobuf_key:"bytes,1,opt" protobuf_val:"bytes,2,opt"` 313 IntMap map[int64]int64 `protobuf:"bytes,2,opt" protobuf_key:"varint,1,opt" protobuf_val:"varint,2,opt"` 314 } 315 316 var mi = &message{ 317 StrMap: map[string]string{ 318 "": "", 319 "a": "b", 320 "hello": "world", 321 }, 322 IntMap: map[int64]int64{ 323 0: 0, 324 1: 1, 325 114: 514, 326 1919: 810, 327 }, 328 } 329 330 size := Size(mi) 331 out, err := Marshal(mi) 332 assert.NoError(t, err) 333 assert.Equal(t, size, len(out)) 334 335 var mo message 336 assert.NoError(t, Unmarshal(out, &mo)) 337 assert.Equal(t, mi, &mo) 338 } 339 340 func TestIssue3(t *testing.T) { 341 type ST3 struct { 342 Str []byte `protobuf:"bytes,1,opt"` 343 } 344 type ST2 struct { 345 ST *ST3 `protobuf:"bytes,1,opt"` 346 } 347 type ST1 struct { 348 ST *ST2 `protobuf:"bytes,1,opt"` 349 } 350 st1 := &ST1{&ST2{&ST3{ 351 Str: make([]byte, 0x7D), 352 }}} 353 b, _ := Marshal(st1) 354 st2 := new(ST1) 355 assert.NoError(t, Unmarshal(b, st2)) 356 assert.Equal(t, st1, st2) 357 }