Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

fix for registering nested message types #23

Merged
merged 2 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 16 additions & 1 deletion grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,17 +282,32 @@ func (c *Client) convertToMethodInfo(fdset *descriptorpb.FileDescriptorSet) ([]M
appendMethodInfo(fd, sd, md)
}
}

messages := fd.Messages()

stack := make([]protoreflect.MessageDescriptor, 0, messages.Len())
for i := 0; i < messages.Len(); i++ {
message := messages.Get(i)
stack = append(stack, messages.Get(i))
}

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) {
err = protoregistry.GlobalTypes.RegisterMessage(dynamicpb.NewMessageType(message))
if err != nil {
return false
}
}

nested := message.Messages()
for i := 0; i < nested.Len(); i++ {
stack = append(stack, nested.Get(i))
}
}

return true
})
if err != nil {
Expand Down
40 changes: 40 additions & 0 deletions grpc/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
}
36 changes: 36 additions & 0 deletions grpc/testdata/nested_types/nested_types.proto
Original file line number Diff line number Diff line change
@@ -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;
}