From 9ea55ad816a2d8fd5001c45d90bd34422f442b6e Mon Sep 17 00:00:00 2001 From: Bojan Date: Thu, 5 Aug 2021 20:58:37 -0300 Subject: [PATCH] do not attempt template actions with binary data. fixes #284 --- internal/wrapped/server.go | 6 + internal/wrapped/wrapped.pb.go | 171 +++++++++++----------------- internal/wrapped/wrapped_grpc.pb.go | 138 ++++++++++++++++++++++ runner/data.go | 9 +- runner/options.go | 4 + runner/options_test.go | 11 ++ runner/run_test.go | 25 ++++ testdata/wrapped.proto | 1 + 8 files changed, 259 insertions(+), 106 deletions(-) create mode 100644 internal/wrapped/wrapped_grpc.pb.go diff --git a/internal/wrapped/server.go b/internal/wrapped/server.go index 3ca4527a..3bb1941c 100644 --- a/internal/wrapped/server.go +++ b/internal/wrapped/server.go @@ -11,3 +11,9 @@ type WrappedService struct{} func (s *WrappedService) GetMessage(ctx context.Context, req *wrappers.StringValue) (*wrappers.StringValue, error) { return &wrappers.StringValue{Value: "Hello: " + req.GetValue()}, nil } + +func (s *WrappedService) GetBytesMessage(ctx context.Context, req *wrappers.BytesValue) (*wrappers.BytesValue, error) { + return &wrappers.BytesValue{Value: req.GetValue()}, nil +} + +func (s *WrappedService) mustEmbedUnimplementedWrappedServiceServer() {} diff --git a/internal/wrapped/wrapped.pb.go b/internal/wrapped/wrapped.pb.go index 13702b9c..1bb1ee00 100644 --- a/internal/wrapped/wrapped.pb.go +++ b/internal/wrapped/wrapped.pb.go @@ -1,122 +1,87 @@ // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.11.4 // source: wrapped.proto package wrapped import ( - context "context" - fmt "fmt" - math "math" - proto "github.com/golang/protobuf/proto" wrappers "github.com/golang/protobuf/ptypes/wrappers" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -func init() { proto.RegisterFile("wrapped.proto", fileDescriptor_a9aa7f80a2b4490d) } - -var fileDescriptor_a9aa7f80a2b4490d = []byte{ - // 135 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2d, 0x2f, 0x4a, 0x2c, - 0x28, 0x48, 0x4d, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0xa5, 0xe4, 0xd2, - 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0xc1, 0xc2, 0x49, 0xa5, 0x69, 0xfa, 0x10, 0x89, 0xa2, 0x62, - 0x88, 0x42, 0xa3, 0x28, 0x2e, 0xbe, 0x70, 0x88, 0xd2, 0xe0, 0xd4, 0xa2, 0xb2, 0xcc, 0xe4, 0x54, - 0x21, 0x0f, 0x2e, 0x2e, 0xf7, 0xd4, 0x12, 0xdf, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x21, 0x19, - 0x3d, 0x88, 0x01, 0x7a, 0x30, 0x03, 0xf4, 0x82, 0x4b, 0x8a, 0x32, 0xf3, 0xd2, 0xc3, 0x12, 0x73, - 0x4a, 0x53, 0xa5, 0xf0, 0xca, 0x3a, 0x09, 0x45, 0x09, 0x64, 0xe6, 0x95, 0xa4, 0x16, 0xe5, 0x25, - 0xe6, 0x40, 0xad, 0x4d, 0x49, 0x62, 0x03, 0xab, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xfd, - 0xf7, 0x3c, 0x4d, 0xb0, 0x00, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// WrappedServiceClient is the client API for WrappedService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type WrappedServiceClient interface { - GetMessage(ctx context.Context, in *wrappers.StringValue, opts ...grpc.CallOption) (*wrappers.StringValue, error) -} - -type wrappedServiceClient struct { - cc *grpc.ClientConn -} - -func NewWrappedServiceClient(cc *grpc.ClientConn) WrappedServiceClient { - return &wrappedServiceClient{cc} -} - -func (c *wrappedServiceClient) GetMessage(ctx context.Context, in *wrappers.StringValue, opts ...grpc.CallOption) (*wrappers.StringValue, error) { - out := new(wrappers.StringValue) - err := c.cc.Invoke(ctx, "/wrapped.WrappedService/GetMessage", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// WrappedServiceServer is the server API for WrappedService service. -type WrappedServiceServer interface { - GetMessage(context.Context, *wrappers.StringValue) (*wrappers.StringValue, error) -} +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) -// UnimplementedWrappedServiceServer can be embedded to have forward compatible implementations. -type UnimplementedWrappedServiceServer struct { +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +var File_wrapped_proto protoreflect.FileDescriptor + +var file_wrapped_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x07, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, + 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xa7, 0x01, 0x0a, 0x0e, 0x57, 0x72, 0x61, + 0x70, 0x70, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0a, 0x47, + 0x65, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x79, 0x74, 0x65, + 0x73, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x42, 0x12, 0x5a, 0x10, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x77, + 0x72, 0x61, 0x70, 0x70, 0x65, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } -func (*UnimplementedWrappedServiceServer) GetMessage(ctx context.Context, req *wrappers.StringValue) (*wrappers.StringValue, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetMessage not implemented") +var file_wrapped_proto_goTypes = []interface{}{ + (*wrappers.StringValue)(nil), // 0: google.protobuf.StringValue + (*wrappers.BytesValue)(nil), // 1: google.protobuf.BytesValue } - -func RegisterWrappedServiceServer(s *grpc.Server, srv WrappedServiceServer) { - s.RegisterService(&_WrappedService_serviceDesc, srv) +var file_wrapped_proto_depIdxs = []int32{ + 0, // 0: wrapped.WrappedService.GetMessage:input_type -> google.protobuf.StringValue + 1, // 1: wrapped.WrappedService.GetBytesMessage:input_type -> google.protobuf.BytesValue + 0, // 2: wrapped.WrappedService.GetMessage:output_type -> google.protobuf.StringValue + 1, // 3: wrapped.WrappedService.GetBytesMessage:output_type -> google.protobuf.BytesValue + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name } -func _WrappedService_GetMessage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(wrappers.StringValue) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WrappedServiceServer).GetMessage(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/wrapped.WrappedService/GetMessage", +func init() { file_wrapped_proto_init() } +func file_wrapped_proto_init() { + if File_wrapped_proto != nil { + return } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WrappedServiceServer).GetMessage(ctx, req.(*wrappers.StringValue)) - } - return interceptor(ctx, in, info, handler) -} - -var _WrappedService_serviceDesc = grpc.ServiceDesc{ - ServiceName: "wrapped.WrappedService", - HandlerType: (*WrappedServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetMessage", - Handler: _WrappedService_GetMessage_Handler, + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_wrapped_proto_rawDesc, + NumEnums: 0, + NumMessages: 0, + NumExtensions: 0, + NumServices: 1, }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "wrapped.proto", + GoTypes: file_wrapped_proto_goTypes, + DependencyIndexes: file_wrapped_proto_depIdxs, + }.Build() + File_wrapped_proto = out.File + file_wrapped_proto_rawDesc = nil + file_wrapped_proto_goTypes = nil + file_wrapped_proto_depIdxs = nil } diff --git a/internal/wrapped/wrapped_grpc.pb.go b/internal/wrapped/wrapped_grpc.pb.go new file mode 100644 index 00000000..18607ce9 --- /dev/null +++ b/internal/wrapped/wrapped_grpc.pb.go @@ -0,0 +1,138 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package wrapped + +import ( + context "context" + wrappers "github.com/golang/protobuf/ptypes/wrappers" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// WrappedServiceClient is the client API for WrappedService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type WrappedServiceClient interface { + GetMessage(ctx context.Context, in *wrappers.StringValue, opts ...grpc.CallOption) (*wrappers.StringValue, error) + GetBytesMessage(ctx context.Context, in *wrappers.BytesValue, opts ...grpc.CallOption) (*wrappers.BytesValue, error) +} + +type wrappedServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewWrappedServiceClient(cc grpc.ClientConnInterface) WrappedServiceClient { + return &wrappedServiceClient{cc} +} + +func (c *wrappedServiceClient) GetMessage(ctx context.Context, in *wrappers.StringValue, opts ...grpc.CallOption) (*wrappers.StringValue, error) { + out := new(wrappers.StringValue) + err := c.cc.Invoke(ctx, "/wrapped.WrappedService/GetMessage", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *wrappedServiceClient) GetBytesMessage(ctx context.Context, in *wrappers.BytesValue, opts ...grpc.CallOption) (*wrappers.BytesValue, error) { + out := new(wrappers.BytesValue) + err := c.cc.Invoke(ctx, "/wrapped.WrappedService/GetBytesMessage", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// WrappedServiceServer is the server API for WrappedService service. +// All implementations must embed UnimplementedWrappedServiceServer +// for forward compatibility +type WrappedServiceServer interface { + GetMessage(context.Context, *wrappers.StringValue) (*wrappers.StringValue, error) + GetBytesMessage(context.Context, *wrappers.BytesValue) (*wrappers.BytesValue, error) + mustEmbedUnimplementedWrappedServiceServer() +} + +// UnimplementedWrappedServiceServer must be embedded to have forward compatible implementations. +type UnimplementedWrappedServiceServer struct { +} + +func (UnimplementedWrappedServiceServer) GetMessage(context.Context, *wrappers.StringValue) (*wrappers.StringValue, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetMessage not implemented") +} +func (UnimplementedWrappedServiceServer) GetBytesMessage(context.Context, *wrappers.BytesValue) (*wrappers.BytesValue, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetBytesMessage not implemented") +} +func (UnimplementedWrappedServiceServer) mustEmbedUnimplementedWrappedServiceServer() {} + +// UnsafeWrappedServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to WrappedServiceServer will +// result in compilation errors. +type UnsafeWrappedServiceServer interface { + mustEmbedUnimplementedWrappedServiceServer() +} + +func RegisterWrappedServiceServer(s grpc.ServiceRegistrar, srv WrappedServiceServer) { + s.RegisterService(&WrappedService_ServiceDesc, srv) +} + +func _WrappedService_GetMessage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(wrappers.StringValue) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WrappedServiceServer).GetMessage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/wrapped.WrappedService/GetMessage", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WrappedServiceServer).GetMessage(ctx, req.(*wrappers.StringValue)) + } + return interceptor(ctx, in, info, handler) +} + +func _WrappedService_GetBytesMessage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(wrappers.BytesValue) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WrappedServiceServer).GetBytesMessage(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/wrapped.WrappedService/GetBytesMessage", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WrappedServiceServer).GetBytesMessage(ctx, req.(*wrappers.BytesValue)) + } + return interceptor(ctx, in, info, handler) +} + +// WrappedService_ServiceDesc is the grpc.ServiceDesc for WrappedService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var WrappedService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "wrapped.WrappedService", + HandlerType: (*WrappedServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetMessage", + Handler: _WrappedService_GetMessage_Handler, + }, + { + MethodName: "GetBytesMessage", + Handler: _WrappedService_GetBytesMessage_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "wrapped.proto", +} diff --git a/runner/data.go b/runner/data.go index 660b390e..e777a026 100644 --- a/runner/data.go +++ b/runner/data.go @@ -99,9 +99,12 @@ func newDataProvider(mtd *desc.MethodDescriptor, // Test if we can preseed data ctd := newCallData(mtd, funcs, "", 0) - ha, err := ctd.hasAction(string(dp.data)) - if err != nil { - return nil, err + ha := false + if !dp.binary { + ha, err = ctd.hasAction(string(dp.data)) + if err != nil { + return nil, err + } } dp.hasActions = ha diff --git a/runner/options.go b/runner/options.go index 1629e0ab..9fb08ebd 100644 --- a/runner/options.go +++ b/runner/options.go @@ -185,6 +185,10 @@ func NewConfig(call, host string, options ...Option) (*RunConfig, error) { return nil, errors.New("host required") } + if c.binary && c.streamDynamicMessages { + return nil, errors.New("cannot use dynamic messages with binary data") + } + if c.loadSchedule != ScheduleConst && c.loadSchedule != ScheduleStep && c.loadSchedule != ScheduleLine { diff --git a/runner/options_test.go b/runner/options_test.go index e23a945b..a9b21b88 100644 --- a/runner/options_test.go +++ b/runner/options_test.go @@ -275,6 +275,17 @@ func TestRunConfig_newRunConfig(t *testing.T) { assert.Equal(t, c.enableCompression, false) }) + t.Run("with binary data from file and dynamic message", func(t *testing.T) { + c, err := NewConfig("call", "localhost:50050", + WithProtoFile("testdata/data.proto", []string{}), + WithBinaryDataFromFile("../testdata/hello_request_data.bin"), + WithStreamDynamicMessages(true), + ) + + assert.Error(t, err) + assert.Nil(t, c) + }) + t.Run("with data from file", func(t *testing.T) { c, err := NewConfig("call", "localhost:50050", WithProtoFile("testdata/data.proto", []string{}), diff --git a/runner/run_test.go b/runner/run_test.go index d70fd2c3..fedef909 100644 --- a/runner/run_test.go +++ b/runner/run_test.go @@ -10,6 +10,7 @@ import ( "github.com/bojand/ghz/internal" "github.com/bojand/ghz/internal/helloworld" "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/ptypes/wrappers" "github.com/google/uuid" "github.com/jhump/protoreflect/desc" "github.com/jhump/protoreflect/dynamic" @@ -3112,6 +3113,30 @@ func TestRunWrappedUnary(t *testing.T) { assert.Equal(t, report.Average, report.Fastest) }) + t.Run("wrapped bin data with template chars", func(t *testing.T) { + protoMsg := wrappers.BytesValue{Value: []byte{'\x7b', '\x7b', '\xc2', '\x7d', '\x7d'}} + msg, err := proto.Marshal(&protoMsg) + assert.NoError(t, err) + + report, err := Run( + "wrapped.WrappedService.GetBytesMessage", + internal.TestLocalhost, + WithProtoFile("../testdata/wrapped.proto", []string{"../testdata"}), + WithTotalRequests(1), + WithConcurrency(1), + WithTimeout(time.Duration(20*time.Second)), + WithDialTimeout(time.Duration(20*time.Second)), + WithBinaryData(msg), + WithInsecure(true), + ) + + assert.NoError(t, err) + + assert.NotNil(t, report) + + assert.Equal(t, 1, int(report.Count)) + }) + t.Run("json string data from file", func(t *testing.T) { report, err := Run( "wrapped.WrappedService.GetMessage", diff --git a/testdata/wrapped.proto b/testdata/wrapped.proto index 42ffbbb2..bf422e4f 100644 --- a/testdata/wrapped.proto +++ b/testdata/wrapped.proto @@ -8,4 +8,5 @@ import "google/protobuf/wrappers.proto"; service WrappedService { rpc GetMessage (google.protobuf.StringValue) returns (google.protobuf.StringValue); + rpc GetBytesMessage (google.protobuf.BytesValue) returns (google.protobuf.BytesValue); } \ No newline at end of file