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  }