diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 5f832e9..0a2fa76 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -56,3 +56,7 @@ jobs: HTTP_PORT: 6000 with: entrypoint: example/ms/entrypoint.sh + - name: Run strict mode example + uses: ./ + with: + entrypoint: example/strictmode/entrypoint.sh diff --git a/deployments/docker-compose/docker-compose.infra.yml b/deployments/docker-compose/docker-compose.infra.yml deleted file mode 100644 index 09c6ecb..0000000 --- a/deployments/docker-compose/docker-compose.infra.yml +++ /dev/null @@ -1,11 +0,0 @@ -version: '3.8' - -services: - jaeger: - image: jaegertracing/all-in-one:1.52 - ports: - - "16686:16686" - - "4317:4317" # grpc - environment: - - COLLECTOR_OTLP_ENABLED=true - - LOG_LEVEL=debug diff --git a/deployments/docker-compose/docker-compose.yml b/deployments/docker-compose/docker-compose.yml index e617f03..d4f14d6 100644 --- a/deployments/docker-compose/docker-compose.yml +++ b/deployments/docker-compose/docker-compose.yml @@ -40,3 +40,9 @@ services: entrypoint: example/well_known_types/entrypoint.sh volumes: - ./../../protogen/example/well_known_types:/go/src/github.com/bavix/gripmock/protogen/example/well_known_types + strict-mode: + image: bavix/gripmock:latest + entrypoint: example/strictmode/entrypoint.sh + volumes: + - ./../../protogen/example/strictmode:/go/src/github.com/bavix/gripmock/protogen/example/strictmode + \ No newline at end of file diff --git a/example/strictmode/client/main.go b/example/strictmode/client/main.go new file mode 100644 index 0000000..97bfcf3 --- /dev/null +++ b/example/strictmode/client/main.go @@ -0,0 +1,52 @@ +package main + +import ( + "context" + "log" + "os" + "time" + + grpcinterceptors "github.com/gripmock/grpc-interceptors" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + + strictmode "github.com/bavix/gripmock/protogen/example/strictmode" +) + +//nolint:mnd +func main() { + // Set up a connection to the server. + conn, err := grpc.NewClient("localhost:4770", + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithChainUnaryInterceptor(grpcinterceptors.UnaryTimeoutInterceptor(5*time.Second)), + grpc.WithChainStreamInterceptor(grpcinterceptors.StreamTimeoutInterceptor(5*time.Second))) + if err != nil { + log.Fatalf("did not connect: %v", err) + } + defer conn.Close() + + c := strictmode.NewGripMockClient(conn) + + // Contact the server and print out its response. + name := "GripMock Request" + if len(os.Args) > 1 { + name = os.Args[1] + } + r1, err := c.SayLowerHello(context.Background(), &strictmode.SayLowerHelloRequest{Name: name}, grpc.WaitForReady(true)) + if err != nil { + log.Fatalf("error from grpc: %v", err) + } + + if r1.GetMessage() != "ok" { + log.Fatalf("message is not ok: %s", r1.GetMessage()) + } + + r2, err := c.SayTitleHello(context.Background(), &strictmode.SayTitleHelloRequest{Name: name}, grpc.WaitForReady(true)) + if err != nil { + log.Fatalf("error from grpc: %v", err) + } + + if r2.GetMessage() != "OK" { + log.Fatalf("message is not ok: %s", r2.GetMessage()) + } +} diff --git a/example/strictmode/entrypoint.sh b/example/strictmode/entrypoint.sh new file mode 100755 index 0000000..2312966 --- /dev/null +++ b/example/strictmode/entrypoint.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env sh + +# this file is used by .github/workflows/integration-test.yml + +STRICT_METHOD_TITLE=false gripmock \ + --stub=example/strictmode/stub \ + example/strictmode/method.proto & + +# wait for generated files to be available and gripmock is up +gripmock check --silent --timeout=30s + +go run example/strictmode/client/*.go \ No newline at end of file diff --git a/example/strictmode/method.proto b/example/strictmode/method.proto new file mode 100644 index 0000000..093bb5c --- /dev/null +++ b/example/strictmode/method.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; + +package strictmode; + +service GripMock { + rpc SayTitleHello (SayTitleHelloRequest) returns (SayTitleHelloReply); + rpc sayLowerHello (sayLowerHelloRequest) returns (sayLowerHelloReply); +} + +message sayLowerHelloRequest { + string name = 1; +} + +message sayLowerHelloReply { + string message = 1; +} + +message SayTitleHelloRequest { + string name = 1; +} + +message SayTitleHelloReply { + string message = 1; +} diff --git a/example/strictmode/stub/lower.yaml b/example/strictmode/stub/lower.yaml new file mode 100644 index 0000000..e745e82 --- /dev/null +++ b/example/strictmode/stub/lower.yaml @@ -0,0 +1,9 @@ +service: GripMock +method: sayLowerHello +input: + ignoreArrayOrder: true + equals: + name: "GripMock Request" +output: + data: + message: "ok" diff --git a/example/strictmode/stub/title.yaml b/example/strictmode/stub/title.yaml new file mode 100644 index 0000000..1bd2c81 --- /dev/null +++ b/example/strictmode/stub/title.yaml @@ -0,0 +1,9 @@ +service: GripMock +method: SayTitleHello +input: + ignoreArrayOrder: true + equals: + name: "GripMock Request" +output: + data: + message: "OK" diff --git a/protoc-gen-gripmock/generator.go b/protoc-gen-gripmock/generator.go index 66df471..050d245 100644 --- a/protoc-gen-gripmock/generator.go +++ b/protoc-gen-gripmock/generator.go @@ -105,19 +105,28 @@ type Service struct { Methods []methodTemplate `json:"methods"` } +// methodTemplate represents a method in a gRPC service. // methodTemplate represents a method in a gRPC service. type methodTemplate struct { // SvcPackage is the package name of the service. + // For example, if the service name is "Greeter", SvcPackage would be "github.com/bavix/gripmock/protogen/example/Greeter". SvcPackage string `json:"svc_package"` - // Name is the name of the method. - Name string `json:"name"` + // RpcName is the name of the RPC method, without the "Greeter/" prefix. + // For example, if the RPC method is "Greeter.SayHello", RpcName would be "SayHello". + RpcName string `json:"rpc_name"` + // TitleName is the name of the method, without the "Say" prefix. + // For example, if the method is "SayHello", TitleName would be "Hello". + TitleName string `json:"title_name"` // ServiceName is the name of the service. + // For example, if the service name is "Greeter", ServiceName would be "Greeter". ServiceName string `json:"service_name"` // MethodType is the type of the method, which can be "standard", "server-stream", "client-stream", or "bidirectional". MethodType string `json:"method_type"` // Input is the name of the input message for the method. + // For example, if the input message is "HelloRequest", Input would be "HelloRequest". Input string `json:"input"` // Output is the name of the output message for the method. + // For example, if the output message is "HelloResponse", Output would be "HelloResponse". Output string `json:"output"` } @@ -237,7 +246,7 @@ func resolveDependencies(protos []*descriptorpb.FileDescriptorProto) map[string] var ( // aliases is a map that keeps track of package aliases. The key is the alias and the value // is a boolean indicating whether the alias is used or not. - aliases = map[string]bool{} + aliases = make(map[string]struct{}, 128) // aliasNum is an integer that keeps track of the number of used aliases. It is used to // generate new unique aliases. @@ -246,7 +255,7 @@ var ( // packages is a map that stores the package names as keys and their corresponding aliases // as values. The package names are the full go package names and the aliases are the // generated or specified aliases for the packages. - packages = map[string]string{} + packages = make(map[string]string, 32) ) // getGoPackage returns the go package alias and the go package name @@ -262,6 +271,7 @@ var ( // // The go_package option format is: package_name;alias. func getGoPackage(proto *descriptorpb.FileDescriptorProto) (alias string, goPackage string) { + // Get the go_package option from the file descriptor. goPackage = proto.GetOptions().GetGoPackage() if goPackage == "" { return @@ -292,13 +302,16 @@ func getGoPackage(proto *descriptorpb.FileDescriptorProto) (alias string, goPack } // If the alias already exists, append a number to it. - if ok := aliases[alias]; ok { + if _, ok := aliases[alias]; ok { alias = fmt.Sprintf("%s%d", alias, aliasNum) aliasNum++ } + // Add the alias to the aliases map. + aliases[alias] = struct{}{} + + // Add the package to the packages map with its alias. packages[goPackage] = alias - aliases[alias] = true return } @@ -307,10 +320,11 @@ func getGoPackage(proto *descriptorpb.FileDescriptorProto) (alias string, goPack // a slice of Service structs, each representing a gRPC service. // // The function iterates over each file descriptor and extracts the services -// defined in each file. It then populates the Services struct with relevant -// information like the service name, package name, and methods. The methods -// include information such as the method name, input and output types, and the -// type of method (standard, server-stream, client-stream, or bidirectional). +// defined in each file. It populates the Service struct with relevant +// information like the service name, package name, and methods. Each method +// represents a gRPC method and includes information such as the method name, +// input and output types, and the type of method (standard, server-stream, +// client-stream, or bidirectional). // // Parameters: // - protos: A slice of FileDescriptorProto structs representing the file @@ -319,6 +333,7 @@ func getGoPackage(proto *descriptorpb.FileDescriptorProto) (alias string, goPack // Returns: // - svcTmp: A slice of Service structs representing the extracted services. func extractServices(protos []*descriptorpb.FileDescriptorProto) []Service { + // svcTmp will hold the extracted services var svcTmp []Service title := cases.Title(language.English, cases.NoLower) @@ -350,7 +365,8 @@ func extractServices(protos []*descriptorpb.FileDescriptorProto) []Service { // Populate the methodTemplate struct methods[j] = methodTemplate{ - Name: title.String(*method.Name), + RpcName: method.GetName(), + TitleName: title.String(method.GetName()), SvcPackage: s.Package, ServiceName: svc.GetName(), Input: getMessageType(protos, method.GetInputType()), @@ -367,7 +383,16 @@ func extractServices(protos []*descriptorpb.FileDescriptorProto) []Service { return svcTmp } +// getMessageType takes a slice of file descriptors and a type string, +// and returns a fully qualified message type. +// +// The message type is split into package and type parts, and the +// function iterates over the protos to find the target message. +// If the target message is found, the function returns the fully +// qualified message type, otherwise it returns the target type. func getMessageType(protos []*descriptorpb.FileDescriptorProto, tipe string) string { + title := cases.Title(language.English, cases.NoLower) + // Split the message type into package and type parts split := strings.Split(tipe, ".")[1:] targetPackage := strings.Join(split[:len(split)-1], ".") @@ -391,13 +416,13 @@ func getMessageType(protos []*descriptorpb.FileDescriptorProto, tipe string) str } // Return the fully qualified message type - return fmt.Sprintf("%s%s", alias, msg.GetName()) + return fmt.Sprintf("%s%s", alias, title.String(msg.GetName())) } } } // Return the target type if no match was found - return targetType + return targetPackage + "." + title.String(targetType) } // keywords is a map that contains all the reserved keywords in Go. diff --git a/protoc-gen-gripmock/server.tmpl b/protoc-gen-gripmock/server.tmpl index babb376..054969e 100644 --- a/protoc-gen-gripmock/server.tmpl +++ b/protoc-gen-gripmock/server.tmpl @@ -149,7 +149,7 @@ type {{.Name}} struct{ {{end}} {{ define "standard_method" }} -func (s *{{.ServiceName}}) {{.Name}}(ctx context.Context, in *{{.Input}}) (*{{.Output}},error){ +func (s *{{.ServiceName}}) {{.TitleName}}(ctx context.Context, in *{{.Input}}) (*{{.Output}},error){ out := &{{.Output}}{} // Retrieve metadata from the incoming context. // The metadata is used to find the stub for the method being called. @@ -159,7 +159,7 @@ func (s *{{.ServiceName}}) {{.Name}}(ctx context.Context, in *{{.Input}}) (*{{.O // The stub defines the input and output messages for the method. // If the stub is found, its output message is returned. // If the stub is not found, an error is returned. - err := findStub(ctx, s.__builder__.Config().HTTPAddr, "{{.ServiceName}}", "{{.Name}}", md, in, out) + err := findStub(ctx, s.__builder__.Config().HTTPAddr, "{{.ServiceName}}", "{{.RpcName}}", md, in, out) // Return the output message and any error encountered while finding the stub. return out, err @@ -167,7 +167,7 @@ func (s *{{.ServiceName}}) {{.Name}}(ctx context.Context, in *{{.Input}}) (*{{.O {{ end }} {{ define "server_stream_method" }} -func (s *{{.ServiceName}}) {{.Name}}(in *{{.Input}},srv {{.SvcPackage}}{{.ServiceName}}_{{.Name}}Server) error { +func (s *{{.ServiceName}}) {{.TitleName}}(in *{{.Input}},srv {{.SvcPackage}}{{.ServiceName}}_{{.TitleName}}Server) error { out := &{{.Output}}{} // Retrieve metadata from the incoming context. // The metadata is used to find the stub for the method being called. @@ -178,7 +178,7 @@ func (s *{{.ServiceName}}) {{.Name}}(in *{{.Input}},srv {{.SvcPackage}}{{.Servic // The stub defines the input and output messages for the method. // If the stub is found, its output message is returned. // If the stub is not found, an error is returned. - err := findStub(ctx, s.__builder__.Config().HTTPAddr, "{{.ServiceName}}", "{{.Name}}", md, in, out) + err := findStub(ctx, s.__builder__.Config().HTTPAddr, "{{.ServiceName}}", "{{.RpcName}}", md, in, out) if err != nil { // Return the error encountered while finding the stub. return err @@ -192,7 +192,7 @@ func (s *{{.ServiceName}}) {{.Name}}(in *{{.Input}},srv {{.SvcPackage}}{{.Servic {{ end }} {{ define "client_stream_method"}} -func (s *{{.ServiceName}}) {{.Name}}(srv {{.SvcPackage}}{{.ServiceName}}_{{.Name}}Server) error { +func (s *{{.ServiceName}}) {{.TitleName}}(srv {{.SvcPackage}}{{.ServiceName}}_{{.TitleName}}Server) error { out := &{{.Output}}{} // Handle the client-streaming RPC. // This loop will continue until the client closes the RPC. @@ -214,7 +214,7 @@ func (s *{{.ServiceName}}) {{.Name}}(srv {{.SvcPackage}}{{.ServiceName}}_{{.Name // The stub defines the input and output messages for the method. // If the stub is found, its output message is returned. // If the stub is not found, an error is returned. - err = findStub(ctx, s.__builder__.Config().HTTPAddr, "{{.ServiceName}}","{{.Name}}", md, input, out) + err = findStub(ctx, s.__builder__.Config().HTTPAddr, "{{.ServiceName}}","{{.RpcName}}", md, input, out) if err != nil { // If there is an error finding the stub, return the error. return err @@ -224,7 +224,7 @@ func (s *{{.ServiceName}}) {{.Name}}(srv {{.SvcPackage}}{{.ServiceName}}_{{.Name {{ end }} {{ define "bidirectional_method"}} -func (s *{{.ServiceName}}) {{.Name}}(srv {{.SvcPackage}}{{.ServiceName}}_{{.Name}}Server) error { +func (s *{{.ServiceName}}) {{.TitleName}}(srv {{.SvcPackage}}{{.ServiceName}}_{{.TitleName}}Server) error { // Handle the bidirectional RPC. // This loop will continue until the client closes the RPC. // For each input message received from the client, it will find the stub @@ -252,7 +252,7 @@ func (s *{{.ServiceName}}) {{.Name}}(srv {{.SvcPackage}}{{.ServiceName}}_{{.Name // The stub defines the input and output messages for the method. // If the stub is found, its output message is returned. // If the stub is not found, an error is returned. - err = findStub(ctx, s.__builder__.Config().HTTPAddr, "{{.ServiceName}}","{{.Name}}", md, input, out) + err = findStub(ctx, s.__builder__.Config().HTTPAddr, "{{.ServiceName}}","{{.RpcName}}", md, input, out) if err != nil { return err } diff --git a/protogen/example/strictmode/method.pb.go b/protogen/example/strictmode/method.pb.go new file mode 100644 index 0000000..be1f8a6 --- /dev/null +++ b/protogen/example/strictmode/method.pb.go @@ -0,0 +1,349 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc v5.27.2 +// source: method.proto + +package strictmode + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +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) +) + +type SayLowerHelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *SayLowerHelloRequest) Reset() { + *x = SayLowerHelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_method_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SayLowerHelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SayLowerHelloRequest) ProtoMessage() {} + +func (x *SayLowerHelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_method_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SayLowerHelloRequest.ProtoReflect.Descriptor instead. +func (*SayLowerHelloRequest) Descriptor() ([]byte, []int) { + return file_method_proto_rawDescGZIP(), []int{0} +} + +func (x *SayLowerHelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type SayLowerHelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *SayLowerHelloReply) Reset() { + *x = SayLowerHelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_method_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SayLowerHelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SayLowerHelloReply) ProtoMessage() {} + +func (x *SayLowerHelloReply) ProtoReflect() protoreflect.Message { + mi := &file_method_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SayLowerHelloReply.ProtoReflect.Descriptor instead. +func (*SayLowerHelloReply) Descriptor() ([]byte, []int) { + return file_method_proto_rawDescGZIP(), []int{1} +} + +func (x *SayLowerHelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type SayTitleHelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *SayTitleHelloRequest) Reset() { + *x = SayTitleHelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_method_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SayTitleHelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SayTitleHelloRequest) ProtoMessage() {} + +func (x *SayTitleHelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_method_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SayTitleHelloRequest.ProtoReflect.Descriptor instead. +func (*SayTitleHelloRequest) Descriptor() ([]byte, []int) { + return file_method_proto_rawDescGZIP(), []int{2} +} + +func (x *SayTitleHelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type SayTitleHelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *SayTitleHelloReply) Reset() { + *x = SayTitleHelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_method_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SayTitleHelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SayTitleHelloReply) ProtoMessage() {} + +func (x *SayTitleHelloReply) ProtoReflect() protoreflect.Message { + mi := &file_method_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SayTitleHelloReply.ProtoReflect.Descriptor instead. +func (*SayTitleHelloReply) Descriptor() ([]byte, []int) { + return file_method_proto_rawDescGZIP(), []int{3} +} + +func (x *SayTitleHelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_method_proto protoreflect.FileDescriptor + +var file_method_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, + 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x2a, 0x0a, 0x14, 0x73, 0x61, + 0x79, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2e, 0x0a, 0x12, 0x73, 0x61, 0x79, 0x4c, 0x6f, 0x77, + 0x65, 0x72, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2a, 0x0a, 0x14, 0x53, 0x61, 0x79, 0x54, 0x69, 0x74, + 0x6c, 0x65, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x22, 0x2e, 0x0a, 0x12, 0x53, 0x61, 0x79, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x48, 0x65, + 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x32, 0xb0, 0x01, 0x0a, 0x08, 0x47, 0x72, 0x69, 0x70, 0x4d, 0x6f, 0x63, 0x6b, 0x12, + 0x51, 0x0a, 0x0d, 0x53, 0x61, 0x79, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x12, 0x20, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x53, 0x61, + 0x79, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x6d, 0x6f, 0x64, 0x65, 0x2e, + 0x53, 0x61, 0x79, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x12, 0x51, 0x0a, 0x0d, 0x73, 0x61, 0x79, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x48, 0x65, + 0x6c, 0x6c, 0x6f, 0x12, 0x20, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x6d, 0x6f, 0x64, 0x65, + 0x2e, 0x73, 0x61, 0x79, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x6d, 0x6f, + 0x64, 0x65, 0x2e, 0x73, 0x61, 0x79, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x61, 0x76, 0x69, 0x78, 0x2f, 0x67, 0x72, 0x69, 0x70, 0x6d, 0x6f, + 0x63, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2f, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x6d, 0x6f, 0x64, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_method_proto_rawDescOnce sync.Once + file_method_proto_rawDescData = file_method_proto_rawDesc +) + +func file_method_proto_rawDescGZIP() []byte { + file_method_proto_rawDescOnce.Do(func() { + file_method_proto_rawDescData = protoimpl.X.CompressGZIP(file_method_proto_rawDescData) + }) + return file_method_proto_rawDescData +} + +var file_method_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_method_proto_goTypes = []any{ + (*SayLowerHelloRequest)(nil), // 0: strictmode.sayLowerHelloRequest + (*SayLowerHelloReply)(nil), // 1: strictmode.sayLowerHelloReply + (*SayTitleHelloRequest)(nil), // 2: strictmode.SayTitleHelloRequest + (*SayTitleHelloReply)(nil), // 3: strictmode.SayTitleHelloReply +} +var file_method_proto_depIdxs = []int32{ + 2, // 0: strictmode.GripMock.SayTitleHello:input_type -> strictmode.SayTitleHelloRequest + 0, // 1: strictmode.GripMock.sayLowerHello:input_type -> strictmode.sayLowerHelloRequest + 3, // 2: strictmode.GripMock.SayTitleHello:output_type -> strictmode.SayTitleHelloReply + 1, // 3: strictmode.GripMock.sayLowerHello:output_type -> strictmode.sayLowerHelloReply + 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 init() { file_method_proto_init() } +func file_method_proto_init() { + if File_method_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_method_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*SayLowerHelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_method_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*SayLowerHelloReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_method_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*SayTitleHelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_method_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*SayTitleHelloReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_method_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_method_proto_goTypes, + DependencyIndexes: file_method_proto_depIdxs, + MessageInfos: file_method_proto_msgTypes, + }.Build() + File_method_proto = out.File + file_method_proto_rawDesc = nil + file_method_proto_goTypes = nil + file_method_proto_depIdxs = nil +} diff --git a/protogen/example/strictmode/method.proto b/protogen/example/strictmode/method.proto new file mode 100644 index 0000000..a617dcd --- /dev/null +++ b/protogen/example/strictmode/method.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; +option go_package = "github.com/bavix/gripmock/protogen/example/strictmode"; + +package strictmode; + +service GripMock { + rpc SayTitleHello (SayTitleHelloRequest) returns (SayTitleHelloReply); + rpc sayLowerHello (sayLowerHelloRequest) returns (sayLowerHelloReply); +} + +message sayLowerHelloRequest { + string name = 1; +} + +message sayLowerHelloReply { + string message = 1; +} + +message SayTitleHelloRequest { + string name = 1; +} + +message SayTitleHelloReply { + string message = 1; +} diff --git a/protogen/example/strictmode/method_grpc.pb.go b/protogen/example/strictmode/method_grpc.pb.go new file mode 100644 index 0000000..3b470b1 --- /dev/null +++ b/protogen/example/strictmode/method_grpc.pb.go @@ -0,0 +1,148 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.4.0 +// - protoc v5.27.2 +// source: method.proto + +package strictmode + +import ( + context "context" + 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.62.0 or later. +const _ = grpc.SupportPackageIsVersion8 + +const ( + GripMock_SayTitleHello_FullMethodName = "/strictmode.GripMock/SayTitleHello" + GripMock_SayLowerHello_FullMethodName = "/strictmode.GripMock/sayLowerHello" +) + +// GripMockClient is the client API for GripMock 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 GripMockClient interface { + SayTitleHello(ctx context.Context, in *SayTitleHelloRequest, opts ...grpc.CallOption) (*SayTitleHelloReply, error) + SayLowerHello(ctx context.Context, in *SayLowerHelloRequest, opts ...grpc.CallOption) (*SayLowerHelloReply, error) +} + +type gripMockClient struct { + cc grpc.ClientConnInterface +} + +func NewGripMockClient(cc grpc.ClientConnInterface) GripMockClient { + return &gripMockClient{cc} +} + +func (c *gripMockClient) SayTitleHello(ctx context.Context, in *SayTitleHelloRequest, opts ...grpc.CallOption) (*SayTitleHelloReply, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SayTitleHelloReply) + err := c.cc.Invoke(ctx, GripMock_SayTitleHello_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gripMockClient) SayLowerHello(ctx context.Context, in *SayLowerHelloRequest, opts ...grpc.CallOption) (*SayLowerHelloReply, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SayLowerHelloReply) + err := c.cc.Invoke(ctx, GripMock_SayLowerHello_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GripMockServer is the server API for GripMock service. +// All implementations must embed UnimplementedGripMockServer +// for forward compatibility +type GripMockServer interface { + SayTitleHello(context.Context, *SayTitleHelloRequest) (*SayTitleHelloReply, error) + SayLowerHello(context.Context, *SayLowerHelloRequest) (*SayLowerHelloReply, error) + mustEmbedUnimplementedGripMockServer() +} + +// UnimplementedGripMockServer must be embedded to have forward compatible implementations. +type UnimplementedGripMockServer struct { +} + +func (UnimplementedGripMockServer) SayTitleHello(context.Context, *SayTitleHelloRequest) (*SayTitleHelloReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayTitleHello not implemented") +} +func (UnimplementedGripMockServer) SayLowerHello(context.Context, *SayLowerHelloRequest) (*SayLowerHelloReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayLowerHello not implemented") +} +func (UnimplementedGripMockServer) mustEmbedUnimplementedGripMockServer() {} + +// UnsafeGripMockServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GripMockServer will +// result in compilation errors. +type UnsafeGripMockServer interface { + mustEmbedUnimplementedGripMockServer() +} + +func RegisterGripMockServer(s grpc.ServiceRegistrar, srv GripMockServer) { + s.RegisterService(&GripMock_ServiceDesc, srv) +} + +func _GripMock_SayTitleHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SayTitleHelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GripMockServer).SayTitleHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: GripMock_SayTitleHello_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GripMockServer).SayTitleHello(ctx, req.(*SayTitleHelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GripMock_SayLowerHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SayLowerHelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GripMockServer).SayLowerHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: GripMock_SayLowerHello_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GripMockServer).SayLowerHello(ctx, req.(*SayLowerHelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// GripMock_ServiceDesc is the grpc.ServiceDesc for GripMock service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var GripMock_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "strictmode.GripMock", + HandlerType: (*GripMockServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayTitleHello", + Handler: _GripMock_SayTitleHello_Handler, + }, + { + MethodName: "sayLowerHello", + Handler: _GripMock_SayLowerHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "method.proto", +}