github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/proto/binary/binary_test.go (about)

     1  package binary
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/cloudwego/dynamicgo/proto"
    10  	"github.com/cloudwego/dynamicgo/testdata/kitex_gen/pb/example"
    11  	goproto "google.golang.org/protobuf/proto"
    12  	"google.golang.org/protobuf/reflect/protoreflect"
    13  )
    14  
    15  type TestMode int8
    16  
    17  const (
    18  	PartialTest TestMode = iota
    19  	ScalarsTest
    20  	MessageTest
    21  	NestedTest
    22  	ListTest
    23  	MapTest
    24  	OneofTest
    25  )
    26  
    27  type testCase struct {
    28  	file        string
    29  	service     string
    30  	isInput     bool
    31  	fieldNumber int
    32  	mode        TestMode
    33  }
    34  
    35  var testGroup = map[string]testCase{
    36  	"Partial test": testCase{
    37  		file:        "../../testdata/idl/example.proto",
    38  		service:     "PartialMethodTest",
    39  		isInput:     false,
    40  		fieldNumber: 3,
    41  		mode:        PartialTest,
    42  	},
    43  	"Scalars test": testCase{
    44  		file:        "../../testdata/idl/example.proto",
    45  		service:     "ScalarsMethodTest",
    46  		isInput:     false,
    47  		fieldNumber: 7,
    48  		mode:        ScalarsTest,
    49  	},
    50  	"Message test": testCase{
    51  		file:        "../../testdata/idl/example.proto",
    52  		service:     "MessageMethodTest",
    53  		isInput:     false,
    54  		fieldNumber: 1,
    55  		mode:        MessageTest,
    56  	},
    57  	"NestedMessage test": testCase{
    58  		file:        "../../testdata/idl/example.proto",
    59  		service:     "NestedMethodTest",
    60  		isInput:     false,
    61  		fieldNumber: 1,
    62  		mode:        NestedTest,
    63  	},
    64  	"List test": testCase{
    65  		file:        "../../testdata/idl/example.proto",
    66  		service:     "ListMethodTest",
    67  		isInput:     false,
    68  		fieldNumber: 1,
    69  		mode:        ListTest,
    70  	},
    71  	"Map test": testCase{
    72  		file:        "../../testdata/idl/example.proto",
    73  		service:     "MapMethodTest",
    74  		isInput:     false,
    75  		fieldNumber: 1,
    76  		mode:        MapTest,
    77  	},
    78  	"Oneof test": testCase{
    79  		file:        "../../testdata/idl/example.proto",
    80  		service:     "OneofMethodTest",
    81  		isInput:     false,
    82  		fieldNumber: 1,
    83  		mode:        OneofTest,
    84  	},
    85  }
    86  
    87  func binaryDataBuild(mode TestMode) []byte {
    88  	var req protoreflect.ProtoMessage
    89  	switch mode {
    90  	case PartialTest:
    91  		data := &example.ExamplePartialResp{}
    92  		// data.ShortEnglishMsg = "first"
    93  		// data.ChineseMsg = "哈哈哈哈但是"
    94  		data.LongEnglishMsg = "noboiubibipbpsdakonobnuondfap123141adfasdf"
    95  		req = data
    96  	case MessageTest:
    97  		data := &example.ExampleMessageResp{}
    98  		data.Base = &example.InnerBase{}
    99  		data.Base.SBool = true
   100  		data.Base.SInt32 = 12
   101  		data.Base.SInt64 = 52
   102  		data.Base.SUint32 = uint32(22)
   103  		data.Base.SUint64 = uint64(62)
   104  		data.Base.SFixed32 = uint32(120)
   105  		data.Base.SFixed64 = uint64(240)
   106  		data.Base.SSfixed32 = int32(120)
   107  		data.Base.SSfixed64 = int64(240)
   108  		data.Base.SFloat = 26.4
   109  		data.Base.SDouble = 55.2
   110  		data.Base.SBytes = []byte{1, 2, 7, 12, 64}
   111  		data.Base.SString = "npdabigdbas dsaf@232#~32adgna;sbf;"
   112  		req = data
   113  	case NestedTest:
   114  		data := &example.ExampleNestedResp{}
   115  		data.TestNested = &example.Nested{}
   116  		data.TestNested.SString = "aaaa"
   117  		data.TestNested.Base = &example.InnerBase{}
   118  		data.TestNested.Base.SBool = true
   119  		data.TestNested.Base.SInt32 = 12
   120  		data.TestNested.Base.SInt64 = 52
   121  		data.TestNested.Base.SUint32 = uint32(22)
   122  		data.TestNested.Base.SUint64 = uint64(62)
   123  		data.TestNested.Base.SFixed32 = uint32(120)
   124  		data.TestNested.Base.SFixed64 = uint64(240)
   125  		data.TestNested.Base.SSfixed32 = int32(120)
   126  		data.TestNested.Base.SSfixed64 = int64(240)
   127  		data.TestNested.Base.SFloat = 26.4
   128  		data.TestNested.Base.SDouble = 55.2
   129  		data.TestNested.Base.SBytes = []byte{1, 2, 7, 12, 64}
   130  		data.TestNested.Base.SString = "npdabigdbas dsaf@232#~32adgna;sbf;"
   131  		req = data
   132  	case ScalarsTest:
   133  		data := &example.ExampleScalarsResp{}
   134  		data.Scalars = &example.Scalars{}
   135  		data.Scalars.SBool = true
   136  		data.Scalars.SInt32 = 12
   137  		data.Scalars.SInt64 = 52
   138  		data.Scalars.SUint32 = uint32(22)
   139  		data.Scalars.SUint64 = uint64(62)
   140  		data.Scalars.SFixed32 = uint32(120)
   141  		data.Scalars.SFixed64 = uint64(240)
   142  		data.Scalars.SSfixed32 = int32(120)
   143  		data.Scalars.SSfixed64 = int64(240)
   144  		data.Scalars.SFloat = 26.4
   145  		data.Scalars.SDouble = 55.2
   146  		data.Scalars.SBytes = []byte{1, 2, 7, 12, 64}
   147  		data.Scalars.SString = "npdabigdbas dsaf@232#~32adgna;sbf;"
   148  		req = data
   149  	case ListTest:
   150  		data := &example.ExampleListResp{}
   151  		data.TestList = &example.Repeats{}
   152  		data.TestList.RptBool = []bool{true, false, true, true, false, true}
   153  		data.TestList.RptInt32 = []int32{int32(12), int32(52), int32(123), int32(205)}
   154  		data.TestList.RptInt64 = []int64{int64(21), int64(56), int64(210), int64(650)}
   155  		data.TestList.RptUint32 = []uint32{uint32(22), uint32(78), uint32(110), uint32(430)}
   156  		data.TestList.RptUint64 = []uint64{uint64(24), uint64(88), uint64(250), uint64(400)}
   157  		data.TestList.RptFloat = []float32{float32(33), float32(50), float32(88), float32(130)}
   158  		data.TestList.RptDouble = []float64{float64(33), float64(50), float64(88), float64(130)}
   159  		data.TestList.RptString = []string{string("aaaa"), string("12sdfa"), string("2165cxvznpnbhpbnda"), string("bpibpbpi2b3541341")}
   160  		data.TestList.RptBytes = [][]byte{[]byte{97, 98, 99, 100, 101, 102, 103}, []byte{104, 105, 106, 107, 108, 109, 110}, []byte{111, 112, 113, 114, 115, 116, 117}, []byte{118, 119, 120, 121, 122, 123, 124}}
   161  		req = data
   162  	case MapTest:
   163  		data := &example.ExampleMapResp{}
   164  		data.TestMap = &example.Maps{}
   165  		data.TestMap.Int32ToStr = make(map[int32]string)
   166  		data.TestMap.Int32ToStr[1] = "aaa"
   167  		data.TestMap.Int32ToStr[2] = "bbb"
   168  		data.TestMap.Int32ToStr[3] = "ccc"
   169  
   170  		data.TestMap.BoolToUint32 = make(map[bool]uint32)
   171  		data.TestMap.BoolToUint32[true] = uint32(10)
   172  		data.TestMap.BoolToUint32[false] = uint32(12)
   173  		data.TestMap.BoolToUint32[true] = uint32(14)
   174  
   175  		data.TestMap.Uint64ToEnum = make(map[uint64]example.Enum)
   176  		data.TestMap.Uint64ToEnum[uint64(1)] = example.Enum_ONE
   177  		data.TestMap.Uint64ToEnum[uint64(2)] = example.Enum_TWO
   178  		data.TestMap.Uint64ToEnum[uint64(3)] = example.Enum_TEN
   179  
   180  		data.TestMap.StrToNested = make(map[string]*example.Nested)
   181  		nestedObj1 := example.Nested{}
   182  		nestedObj1.SString = "111"
   183  		nestedObj1.Base = &example.InnerBase{}
   184  		nestedObj1.Base.SBool = true
   185  		nestedObj1.Base.SString = "nested111"
   186  		nestedObj2 := example.Nested{}
   187  		nestedObj2.SString = "222"
   188  		nestedObj2.Base = &example.InnerBase{}
   189  		nestedObj2.Base.SBool = false
   190  		nestedObj2.Base.SString = "nested222"
   191  		nestedObj3 := example.Nested{}
   192  		nestedObj3.SString = "333"
   193  		nestedObj3.Base = &example.InnerBase{}
   194  		nestedObj3.Base.SBool = true
   195  		nestedObj3.Base.SString = "nested333"
   196  		data.TestMap.StrToNested["aaa"] = &nestedObj1
   197  		data.TestMap.StrToNested["bbb"] = &nestedObj2
   198  		data.TestMap.StrToNested["ccc"] = &nestedObj3
   199  
   200  		data.TestMap.StrToOneofs = make(map[string]*example.Oneofs)
   201  		oneofObj1 := example.Oneofs{}
   202  		enumUnion := &example.Oneofs_OneofEnum{}
   203  		enumUnion.OneofEnum = example.Enum_ONE
   204  		oneofObj1.Union = enumUnion
   205  		data.TestMap.StrToOneofs["aaa"] = &oneofObj1
   206  
   207  		oneofObj2 := example.Oneofs{}
   208  		stringUnion := &example.Oneofs_OneofString{}
   209  		stringUnion.OneofString = "stringUnion"
   210  		oneofObj2.Union = stringUnion
   211  		data.TestMap.StrToOneofs["bbb"] = &oneofObj2
   212  
   213  		oneofObj3 := example.Oneofs{}
   214  		nestedUnion := &example.Oneofs_OneofNested{}
   215  		nestedUnion.OneofNested = &example.Nested{}
   216  		nestedUnion.OneofNested.SString = "nestedStringUnion"
   217  		nestedUnion.OneofNested.Base = &example.InnerBase{}
   218  		nestedUnion.OneofNested.Base.SBool = true
   219  		nestedUnion.OneofNested.Base.SString = "bbb"
   220  		oneofObj3.Union = nestedUnion
   221  		data.TestMap.StrToOneofs["ccc"] = &oneofObj3
   222  		req = data
   223  	case OneofTest:
   224  		data := &example.ExampleOneofResp{}
   225  		data.TestOneof = &example.Oneofs{}
   226  		// enum inner of union
   227  		// enumUnion := &example.Oneofs_OneofEnum{}
   228  		// enumUnion.OneofEnum = example.Enum_ONE
   229  		// data.TestOneof.Union = enumUnion
   230  		// string inner of union
   231  		// stringUnion := &example.Oneofs_OneofString{}
   232  		// stringUnion.OneofString = "aaaa"
   233  		// data.TestOneof.Union = stringUnion
   234  		// Nested inner of union
   235  		nestedUnion := example.Oneofs_OneofNested{}
   236  		nestedUnion.OneofNested = &example.Nested{}
   237  		nestedUnion.OneofNested.SString = "aaa"
   238  		nestedUnion.OneofNested.Base = &example.InnerBase{}
   239  		nestedUnion.OneofNested.Base.SBool = true
   240  		nestedUnion.OneofNested.Base.SString = "bbb"
   241  		data.TestOneof.Union = &nestedUnion
   242  		req = data
   243  	}
   244  	res, err := goproto.Marshal(req)
   245  	if err != nil {
   246  		panic("proto Marshal failed: PartialTest")
   247  	}
   248  	return res
   249  }
   250  
   251  func TestBinaryProtocol_ReadAnyWithDesc(t *testing.T) {
   252  	for name, test := range testGroup {
   253  		t.Run(name, func(t *testing.T) {
   254  			p1, err := proto.NewDescritorFromPath(context.Background(), test.file)
   255  			if err != nil {
   256  				panic(err)
   257  			}
   258  			// get Target FieldDescriptor
   259  			var fieldDescriptor *proto.FieldDescriptor
   260  			if test.isInput {
   261  				fieldDescriptor = p1.LookupMethodByName(test.service).Input().Message().ByNumber(proto.FieldNumber(test.fieldNumber))
   262  			} else {
   263  				fieldDescriptor = p1.LookupMethodByName(test.service).Output().Message().ByNumber(proto.FieldNumber(test.fieldNumber))
   264  			}
   265  			// protoc build pbData
   266  			pbData := binaryDataBuild(test.mode)
   267  			p := NewBinaryProtol(pbData)
   268  			// WriteAnyWithDesc write the data into BinaryProtocol
   269  			hasmessageLen := true
   270  			if !fieldDescriptor.IsMap() && !fieldDescriptor.IsList() {
   271  				if _, _, _, err := p.ConsumeTag(); err != nil {
   272  					panic(err)
   273  				}
   274  			}
   275  			v1, err := p.ReadAnyWithDesc(fieldDescriptor.Type(), hasmessageLen, true, false, true)
   276  			fmt.Printf("%#v\n", v1)
   277  
   278  			// wirte
   279  			p = NewBinaryProtocolBuffer()
   280  			if !fieldDescriptor.IsMap() && !fieldDescriptor.IsList() {
   281  				p.AppendTagByKind(fieldDescriptor.Number(), fieldDescriptor.Kind())
   282  			}
   283  			needMessageLen := true
   284  			err = p.WriteAnyWithDesc(fieldDescriptor.Type(), v1, needMessageLen, true, false, true)
   285  			if err != nil {
   286  				panic(err)
   287  			}
   288  			fmt.Printf("%x\n", p.RawBuf())
   289  
   290  			// Read again by ReadAnyWithDesc
   291  			p = NewBinaryProtol(p.RawBuf())
   292  			hasmessageLen = true
   293  			if !fieldDescriptor.IsMap() && !fieldDescriptor.IsList() {
   294  				if _, _, _, err := p.ConsumeTag(); err != nil {
   295  					panic(err)
   296  				}
   297  			}
   298  			v2, err := p.ReadAnyWithDesc(fieldDescriptor.Type(), hasmessageLen, true, false, true)
   299  			if err != nil {
   300  				panic(err)
   301  			}
   302  			fmt.Printf("%#v\n", v2)
   303  			if !reflect.DeepEqual(v1, v2) {
   304  				panic("test ReadAnyWithDesc error")
   305  			}
   306  		})
   307  	}
   308  }
   309  
   310  func TestTag(t *testing.T) {
   311  	src := make([]byte, 0, 1024)
   312  	p := NewBinaryProtol(src)
   313  	// using a for loop to check each case of appendtag and consumeTag
   314  	// the case is in the TestTag2
   315  
   316  	testCase := []struct {
   317  		number proto.FieldNumber
   318  		wtyp   proto.WireType
   319  		err    error
   320  	}{
   321  		{0, proto.Fixed32Type, errInvalidTag},
   322  		{1, proto.Fixed32Type, nil},
   323  		{proto.FirstReservedNumber, proto.BytesType, nil},
   324  		{proto.LastReservedNumber, proto.StartGroupType, nil},
   325  		{proto.MaxValidNumber, proto.VarintType, nil},
   326  	}
   327  
   328  	for _, c := range testCase {
   329  		p.AppendTag(c.number, c.wtyp)
   330  		num, _, _, err := p.ConsumeTag()
   331  		if err != nil && err != errInvalidTag {
   332  			t.Fatal(err)
   333  		}
   334  		if num != c.number {
   335  			t.Fatal("test failed")
   336  		}
   337  	}
   338  
   339  	_, _, _, err := p.ConsumeTag()
   340  	if err != errInvalidTag {
   341  		t.Fatal("test failed")
   342  	}
   343  }