From 002fe1b36487293fab196bea8a37499a6340dddf Mon Sep 17 00:00:00 2001 From: Thiago de Paula Ferreira Date: Wed, 5 Jul 2023 23:59:03 -0300 Subject: [PATCH 1/2] fix for registering nested message types --- go.mod | 1 + go.sum | 2 + grpc/client.go | 17 +++++++- grpc/client_test.go | 40 +++++++++++++++++++ grpc/testdata/nested_types/nested_types.proto | 36 +++++++++++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 grpc/testdata/nested_types/nested_types.proto diff --git a/go.mod b/go.mod index ee36360..dd91d1b 100644 --- a/go.mod +++ b/go.mod @@ -34,6 +34,7 @@ require ( github.com/fatih/color v1.15.0 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompatible // indirect + github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/google/uuid v1.3.0 // indirect diff --git a/go.sum b/go.sum index abe4a1c..357be7a 100644 --- a/go.sum +++ b/go.sum @@ -114,6 +114,8 @@ github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompati github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4= +github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= diff --git a/grpc/client.go b/grpc/client.go index 06d4e61..1d1e914 100644 --- a/grpc/client.go +++ b/grpc/client.go @@ -25,6 +25,8 @@ import ( "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/dynamicpb" + + "github.com/golang-collections/collections/stack" ) // Client represents a gRPC client that can be used to make RPC requests @@ -282,9 +284,16 @@ func (c *Client) convertToMethodInfo(fdset *descriptorpb.FileDescriptorSet) ([]M appendMethodInfo(fd, sd, md) } } + + s := stack.New() messages := fd.Messages() for i := 0; i < messages.Len(); i++ { - message := messages.Get(i) + s.Push(messages.Get(i)) + } + + for s.Len() > 0 { + message, _ := s.Pop().(protoreflect.MessageDescriptor) + _, errFind := protoregistry.GlobalTypes.FindMessageByName(message.FullName()) if errors.Is(errFind, protoregistry.NotFound) { err = protoregistry.GlobalTypes.RegisterMessage(dynamicpb.NewMessageType(message)) @@ -292,7 +301,13 @@ func (c *Client) convertToMethodInfo(fdset *descriptorpb.FileDescriptorSet) ([]M return false } } + + nested := message.Messages() + for i := 0; i < nested.Len(); i++ { + s.Push(nested.Get(i)) + } } + return true }) if err != nil { diff --git a/grpc/client_test.go b/grpc/client_test.go index 1536b5d..efb81b2 100644 --- a/grpc/client_test.go +++ b/grpc/client_test.go @@ -7,6 +7,8 @@ import ( "testing" "google.golang.org/grpc/reflection" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" "github.com/dop251/goja" "github.com/golang/protobuf/ptypes/any" @@ -750,3 +752,41 @@ func TestDebugStat(t *testing.T) { }) } } + +func TestClientLoadProto(t *testing.T) { + t.Parallel() + + ts := newTestState(t) + + tt := testcase{ + name: "LoadNestedTypesProto", + initString: codeBlock{ + code: ` + var client = new grpc.Client(); + client.load([], "testdata/nested_types/nested_types.proto");`, + }, + } + + replace := func(code string) (goja.Value, error) { + return ts.VU.Runtime().RunString(ts.httpBin.Replacer.Replace(code)) + } + + val, err := replace(tt.initString.code) + assertResponse(t, tt.initString, err, val, ts) + + expectedTypes := []string{ + "grpc.testdata.nested.types.Outer", + "grpc.testdata.nested.types.Outer.MiddleAA", + "grpc.testdata.nested.types.Outer.MiddleAA.Inner", + "grpc.testdata.nested.types.Outer.MiddleBB", + "grpc.testdata.nested.types.Outer.MiddleBB.Inner", + "grpc.testdata.nested.types.MeldOuter", + } + + for _, expected := range expectedTypes { + found, err := protoregistry.GlobalTypes.FindMessageByName(protoreflect.FullName(expected)) + + assert.NotNil(t, found, "Expected to find the message type %s, but an error occurred", expected) + assert.Nil(t, err, "It was not expected that there would be an error, but it got: %v", err) + } +} diff --git a/grpc/testdata/nested_types/nested_types.proto b/grpc/testdata/nested_types/nested_types.proto new file mode 100644 index 0000000..66dd353 --- /dev/null +++ b/grpc/testdata/nested_types/nested_types.proto @@ -0,0 +1,36 @@ +// The purpose of this proto file is to demonstrate that we can have +// nested types and that we should be able to load them correctly. + +syntax = "proto3"; + +package grpc.testdata.nested.types; + +// Example to demonstrate that it is possible to define +// and use message types within other message types +message Outer { // Level 0 + message MiddleAA { // Level 1 + message Inner { // Level 2 + int64 ival = 1; + bool booly = 2; + } + Inner inner = 1; + } + + message MiddleBB { // Level 1 + message Inner { // Level 2 + int32 ival = 1; + bool booly = 2; + } + Inner inner = 1; + } + + MiddleAA middleAA = 1; + MiddleBB middleBB = 2; +} + +// Example to demonstrate that it is possible to reuse +// a message type outside its parent message type +message MeldOuter { + Outer.MiddleAA.Inner innerAA = 1; + Outer.MiddleBB.Inner innerBB = 2; +} From 758b623bb009e4a3fe55af501a60e2e0cad0647b Mon Sep 17 00:00:00 2001 From: Thiago de Paula Ferreira Date: Thu, 6 Jul 2023 12:22:54 -0300 Subject: [PATCH 2/2] improving the code to not need an external dependency --- go.mod | 1 - go.sum | 2 -- grpc/client.go | 14 +++++++------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index dd91d1b..ee36360 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,6 @@ require ( github.com/fatih/color v1.15.0 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompatible // indirect - github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect github.com/google/uuid v1.3.0 // indirect diff --git a/go.sum b/go.sum index 357be7a..abe4a1c 100644 --- a/go.sum +++ b/go.sum @@ -114,8 +114,6 @@ github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompati github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4= -github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= diff --git a/grpc/client.go b/grpc/client.go index 1d1e914..6872d6d 100644 --- a/grpc/client.go +++ b/grpc/client.go @@ -25,8 +25,6 @@ import ( "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/dynamicpb" - - "github.com/golang-collections/collections/stack" ) // Client represents a gRPC client that can be used to make RPC requests @@ -285,14 +283,16 @@ func (c *Client) convertToMethodInfo(fdset *descriptorpb.FileDescriptorSet) ([]M } } - s := stack.New() messages := fd.Messages() + + stack := make([]protoreflect.MessageDescriptor, 0, messages.Len()) for i := 0; i < messages.Len(); i++ { - s.Push(messages.Get(i)) + stack = append(stack, messages.Get(i)) } - for s.Len() > 0 { - message, _ := s.Pop().(protoreflect.MessageDescriptor) + for len(stack) > 0 { + message := stack[len(stack)-1] + stack = stack[:len(stack)-1] _, errFind := protoregistry.GlobalTypes.FindMessageByName(message.FullName()) if errors.Is(errFind, protoregistry.NotFound) { @@ -304,7 +304,7 @@ func (c *Client) convertToMethodInfo(fdset *descriptorpb.FileDescriptorSet) ([]M nested := message.Messages() for i := 0; i < nested.Len(); i++ { - s.Push(nested.Get(i)) + stack = append(stack, nested.Get(i)) } }