Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix for registering nested message types #3178

Merged
merged 2 commits into from
Jul 10, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}