Skip to content

Commit

Permalink
fix for registering nested message types (#3178)
Browse files Browse the repository at this point in the history
* fix for registering nested message types

---------

Co-authored-by: Mihail Stoykov <312246+mstoykov@users.noreply.github.com>
  • Loading branch information
thiagodpf and mstoykov committed Jul 10, 2023
1 parent 199bf4e commit 9c019a4
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 1 deletion.
16 changes: 15 additions & 1 deletion js/modules/k6/grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,16 +295,30 @@ func (c *Client) convertToMethodInfo(fdset *descriptorpb.FileDescriptorSet) ([]M
}
}
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
63 changes: 63 additions & 0 deletions js/modules/k6/grpc/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,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 @@ -977,3 +979,64 @@ func TestClientInvokeHeadersDeprecated(t *testing.T) {
require.Len(t, entries, 1)
require.Contains(t, entries[0].Message, "headers property is deprecated")
}

func TestClientLoadProto(t *testing.T) {
t.Parallel()

type testState struct {
*modulestest.Runtime
httpBin *httpmultibin.HTTPMultiBin
samples chan metrics.SampleContainer
}
setup := func(t *testing.T) testState {
t.Helper()

tb := httpmultibin.NewHTTPMultiBin(t)
samples := make(chan metrics.SampleContainer, 1000)
testRuntime := modulestest.NewRuntime(t)

cwd, err := os.Getwd() //nolint:forbidigo
require.NoError(t, err)
fs := fsext.NewOsFs()
if isWindows {
fs = fsext.NewTrimFilePathSeparatorFs(fs)
}
testRuntime.VU.InitEnvField.CWD = &url.URL{Path: cwd}
testRuntime.VU.InitEnvField.FileSystems = map[string]fsext.Fs{"file": fs}

return testState{
Runtime: testRuntime,
httpBin: tb,
samples: samples,
}
}

ts := setup(t)

m, ok := New().NewModuleInstance(ts.VU).(*ModuleInstance)
require.True(t, ok)
require.NoError(t, ts.VU.Runtime().Set("grpc", m.Exports().Named))

code := `
var client = new grpc.Client();
client.load([], "../../../../lib/testutils/httpmultibin/grpc_testing/nested_types.proto");`

_, err := ts.VU.Runtime().RunString(ts.httpBin.Replacer.Replace(code))
assert.Nil(t, err, "It was not expected that there would be an error, but it got: %v", err)

expectedTypes := []string{
"grpc.testing.Outer",
"grpc.testing.Outer.MiddleAA",
"grpc.testing.Outer.MiddleAA.Inner",
"grpc.testing.Outer.MiddleBB",
"grpc.testing.Outer.MiddleBB.Inner",
"grpc.testing.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 lib/testutils/httpmultibin/grpc_testing/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.testing;

// 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;
}

0 comments on commit 9c019a4

Please sign in to comment.