diff --git a/.gitignore b/.gitignore index f63396501..dddbec92a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/vendor/ # Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a diff --git a/Makefile b/Makefile index 28c348596..f604fc0be 100755 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ deps: download_plugins download_plugins: @echo "--- 🐿 Installing plugins"; \ ./scripts/install-cli.sh - ~/.pact/bin/pact-plugin-cli -y install https://github.com/pactflow/pact-protobuf-plugin/releases/tag/v-0.3.8 + ~/.pact/bin/pact-plugin-cli -y install https://github.com/pactflow/pact-protobuf-plugin/releases/tag/v-0.3.13 ~/.pact/bin/pact-plugin-cli -y install https://github.com/pact-foundation/pact-plugins/releases/tag/csv-plugin-0.0.1 ~/.pact/bin/pact-plugin-cli -y install https://github.com/mefellows/pact-matt-plugin/releases/tag/v0.0.9 ~/.pact/bin/pact-plugin-cli -y install https://github.com/austek/pact-avro-plugin/releases/tag/v0.0.3 @@ -97,3 +97,17 @@ updatedeps: go get -d -v -p 2 ./... .PHONY: install bin default dev test pact updatedeps clean release + +PROTOC ?= $(shell which protoc) + +.PHONY: protos +protos: + @echo "--- 🛠 Compiling Protobufs" + cd ./examples/grpc/routeguide && $(PROTOC) --go_out=paths=source_relative:. \ + --go-grpc_out=paths=source_relative:. ./route_guide.proto + +.PHONY: grpc-test +grpc-test: + rm -rf ./examples/pacts + go test -v -tags=consumer -count=1 github.com/pact-foundation/pact-go/v2/examples/grpc + go test -v -timeout=30s -tags=provider -count=1 github.com/pact-foundation/pact-go/v2/examples/grpc diff --git a/consumer/http_v4_test.go b/consumer/http_v4_test.go index 154a8b227..b2505bbeb 100644 --- a/consumer/http_v4_test.go +++ b/consumer/http_v4_test.go @@ -58,7 +58,7 @@ func TestHttpV4TypeSystem(t *testing.T) { UponReceiving("some scenario"). UsingPlugin(PluginConfig{ Plugin: "protobuf", - Version: "0.3.8", + Version: "0.3.13", }). WithRequest("GET", "/"). // WithRequest("GET", "/", func(b *V4InteractionWithPluginRequestBuilder) { diff --git a/examples/grpc/common.go b/examples/grpc/common.go new file mode 100644 index 000000000..5ffba450f --- /dev/null +++ b/examples/grpc/common.go @@ -0,0 +1,7 @@ +//go:build consumer || provider + +package grpc + +import "os" + +var dir, _ = os.Getwd() diff --git a/examples/grpc/grpc_consumer_test.go b/examples/grpc/grpc_consumer_test.go index 962ad08b5..44fdd8640 100644 --- a/examples/grpc/grpc_consumer_test.go +++ b/examples/grpc/grpc_consumer_test.go @@ -15,19 +15,18 @@ import ( "github.com/pact-foundation/pact-go/v2/log" message "github.com/pact-foundation/pact-go/v2/message/v4" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) -var dir, _ = os.Getwd() - -func TestGrpcInteraction(t *testing.T) { +func TestGetFeatureSuccess(t *testing.T) { p, _ := message.NewSynchronousPact(message.Config{ Consumer: "grpcconsumer", Provider: "grpcprovider", PactDir: filepath.ToSlash(fmt.Sprintf("%s/../pacts", dir)), }) - log.SetLogLevel("INFO") + log.SetLogLevel("DEBUG") dir, _ := os.Getwd() path := fmt.Sprintf("%s/routeguide/route_guide.proto", dir) @@ -53,7 +52,7 @@ func TestGrpcInteraction(t *testing.T) { Given("feature 'Big Tree' exists"). UsingPlugin(message.PluginConfig{ Plugin: "protobuf", - Version: "0.3.8", + Version: "0.3.13", }). WithContents(grpcInteraction, "application/protobuf"). StartTransport("grpc", "127.0.0.1", nil). // For plugin tests, we can't assume if a transport is needed, so this is optional @@ -93,3 +92,145 @@ func TestGrpcInteraction(t *testing.T) { assert.NoError(t, err) } + +func TestGetFeatureError(t *testing.T) { + log.SetLogLevel("DEBUG") + p, _ := message.NewSynchronousPact(message.Config{ + Consumer: "grpcconsumer", + Provider: "grpcprovider", + PactDir: filepath.ToSlash(fmt.Sprintf("%s/../pacts", dir)), + }) + + dir, _ := os.Getwd() + path := fmt.Sprintf("%s/routeguide/route_guide.proto", dir) + + grpcInteraction := `{ + "pact:proto": "` + path + `", + "pact:proto-service": "RouteGuide/GetFeature", + "pact:content-type": "application/protobuf", + "request": { + "latitude": "matching(number, -1)", + "longitude": "matching(number, -1)" + }, + "responseMetadata": { + "grpc-status": "NOT_FOUND", + "grpc-message": "matching(type, 'no feature was found at latitude:-1 longitude:-1')" + } + }` + + err := p.AddSynchronousMessage("Route guide - GetFeature - error response"). + Given("feature does not exist at -1, -1"). + UsingPlugin(message.PluginConfig{ + Plugin: "protobuf", + Version: "0.3.13", + }). + WithContents(grpcInteraction, "application/protobuf"). + StartTransport("grpc", "127.0.0.1", nil). // For plugin tests, we can't assume if a transport is needed, so this is optional + ExecuteTest(t, func(transport message.TransportConfig, m message.SynchronousMessage) error { + fmt.Println("gRPC transport running on", transport) + + // Establish the gRPC connection + conn, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", transport.Port), grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + defer conn.Close() + + // Create the gRPC client + c := routeguide.NewRouteGuideClient(conn) + + point := &routeguide.Point{ + Latitude: -1, + Longitude: -1, + } + + // Now we can make a normal gRPC request + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + _, err = c.GetFeature(ctx, point) + + require.Error(t, err) + // TODO: uncomment once new FFI and new pact-protobuf plugin are released with a fix + // https://github.com/pact-foundation/pact-reference/commit/29b326e59b48a6a78a019b37e378b7742c728da5 + // require.ErrorContains(t, err, "no feature was found at latitude:-1 longitude:-1") + + return nil + }) + + assert.NoError(t, err) +} + +func TestSaveFeature(t *testing.T) { + p, _ := message.NewSynchronousPact(message.Config{ + Consumer: "grpcconsumer", + Provider: "grpcprovider", + PactDir: filepath.ToSlash(fmt.Sprintf("%s/../pacts", dir)), + }) + log.SetLogLevel("INFO") + + dir, _ := os.Getwd() + path := fmt.Sprintf("%s/routeguide/route_guide.proto", dir) + + grpcInteraction := `{ + "pact:proto": "` + path + `", + "pact:proto-service": "RouteGuide/SaveFeature", + "pact:content-type": "application/protobuf", + "request": { + "name": "notEmpty('A shed')", + "location": { + "latitude": "matching(number, 99)", + "longitude": "matching(number, 99)" + } + }, + "response": { + "name": "notEmpty('A shed')", + "location": { + "latitude": "matching(number, 99)", + "longitude": "matching(number, 99)" + } + } + }` + + err := p.AddSynchronousMessage("Route guide - SaveFeature"). + Given("feature does not exist at -1, -1"). + UsingPlugin(message.PluginConfig{ + Plugin: "protobuf", + Version: "0.3.13", + }). + WithContents(grpcInteraction, "application/protobuf"). + StartTransport("grpc", "127.0.0.1", nil). // For plugin tests, we can't assume if a transport is needed, so this is optional + ExecuteTest(t, func(transport message.TransportConfig, m message.SynchronousMessage) error { + fmt.Println("gRPC transport running on", transport) + + // Establish the gRPC connection + conn, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", transport.Port), grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + t.Fatal("unable to communicate to grpc server", err) + } + defer conn.Close() + + // Create the gRPC client + c := routeguide.NewRouteGuideClient(conn) + feature := &routeguide.Feature{ + Name: "A shed", + Location: &routeguide.Point{ + Latitude: 99, + Longitude: 99, + }, + } + + // Now we can make a normal gRPC request + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + response, err := c.SaveFeature(ctx, feature) + + if err != nil { + t.Fatal(err.Error()) + } + + assert.Equal(t, feature.GetName(), response.GetName()) + assert.Equal(t, feature.GetLocation().GetLatitude(), feature.GetLocation().GetLatitude()) + + return nil + }) + + assert.NoError(t, err) +} diff --git a/examples/grpc/grpc_provider_test.go b/examples/grpc/grpc_provider_test.go index 8b8c87394..3ee67607a 100644 --- a/examples/grpc/grpc_provider_test.go +++ b/examples/grpc/grpc_provider_test.go @@ -8,7 +8,6 @@ import ( "log" "net" - "os" "path/filepath" "testing" @@ -20,8 +19,6 @@ import ( "google.golang.org/grpc" ) -var dir, _ = os.Getwd() - func TestGrpcProvider(t *testing.T) { go startProvider() l.SetLogLevel("TRACE") @@ -31,7 +28,7 @@ func TestGrpcProvider(t *testing.T) { err := verifier.VerifyProvider(t, provider.VerifyRequest{ ProviderBaseURL: "http://localhost:8222", Transports: []provider.Transport{ - provider.Transport{ + { Protocol: "grpc", Port: 8222, }, diff --git a/examples/grpc/routeguide/route_guide.pb.go b/examples/grpc/routeguide/route_guide.pb.go index 85c3033c7..e7c7f4442 100644 --- a/examples/grpc/routeguide/route_guide.pb.go +++ b/examples/grpc/routeguide/route_guide.pb.go @@ -14,14 +14,13 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.25.0 -// protoc v3.14.0 -// source: examples/route_guide/routeguide/route_guide.proto +// protoc-gen-go v1.32.0 +// protoc v4.25.2 +// source: route_guide.proto package routeguide import ( - proto "github.com/golang/protobuf/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -35,10 +34,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - // Points are represented as latitude-longitude pairs in the E7 representation // (degrees multiplied by 10**7 and rounded to the nearest integer). // Latitudes should be in the range +/- 90 degrees and longitude should be in @@ -55,7 +50,7 @@ type Point struct { func (x *Point) Reset() { *x = Point{} if protoimpl.UnsafeEnabled { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[0] + mi := &file_route_guide_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -68,7 +63,7 @@ func (x *Point) String() string { func (*Point) ProtoMessage() {} func (x *Point) ProtoReflect() protoreflect.Message { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[0] + mi := &file_route_guide_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -81,7 +76,7 @@ func (x *Point) ProtoReflect() protoreflect.Message { // Deprecated: Use Point.ProtoReflect.Descriptor instead. func (*Point) Descriptor() ([]byte, []int) { - return file_examples_route_guide_routeguide_route_guide_proto_rawDescGZIP(), []int{0} + return file_route_guide_proto_rawDescGZIP(), []int{0} } func (x *Point) GetLatitude() int32 { @@ -114,7 +109,7 @@ type Rectangle struct { func (x *Rectangle) Reset() { *x = Rectangle{} if protoimpl.UnsafeEnabled { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[1] + mi := &file_route_guide_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -127,7 +122,7 @@ func (x *Rectangle) String() string { func (*Rectangle) ProtoMessage() {} func (x *Rectangle) ProtoReflect() protoreflect.Message { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[1] + mi := &file_route_guide_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -140,7 +135,7 @@ func (x *Rectangle) ProtoReflect() protoreflect.Message { // Deprecated: Use Rectangle.ProtoReflect.Descriptor instead. func (*Rectangle) Descriptor() ([]byte, []int) { - return file_examples_route_guide_routeguide_route_guide_proto_rawDescGZIP(), []int{1} + return file_route_guide_proto_rawDescGZIP(), []int{1} } func (x *Rectangle) GetLo() *Point { @@ -169,12 +164,14 @@ type Feature struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The point where the feature is detected. Location *Point `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"` + // A description of the feature. + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` } func (x *Feature) Reset() { *x = Feature{} if protoimpl.UnsafeEnabled { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[2] + mi := &file_route_guide_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -187,7 +184,7 @@ func (x *Feature) String() string { func (*Feature) ProtoMessage() {} func (x *Feature) ProtoReflect() protoreflect.Message { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[2] + mi := &file_route_guide_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -200,7 +197,7 @@ func (x *Feature) ProtoReflect() protoreflect.Message { // Deprecated: Use Feature.ProtoReflect.Descriptor instead. func (*Feature) Descriptor() ([]byte, []int) { - return file_examples_route_guide_routeguide_route_guide_proto_rawDescGZIP(), []int{2} + return file_route_guide_proto_rawDescGZIP(), []int{2} } func (x *Feature) GetName() string { @@ -217,6 +214,13 @@ func (x *Feature) GetLocation() *Point { return nil } +func (x *Feature) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + // A RouteNote is a message sent while at a given point. type RouteNote struct { state protoimpl.MessageState @@ -232,7 +236,7 @@ type RouteNote struct { func (x *RouteNote) Reset() { *x = RouteNote{} if protoimpl.UnsafeEnabled { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[3] + mi := &file_route_guide_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -245,7 +249,7 @@ func (x *RouteNote) String() string { func (*RouteNote) ProtoMessage() {} func (x *RouteNote) ProtoReflect() protoreflect.Message { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[3] + mi := &file_route_guide_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -258,7 +262,7 @@ func (x *RouteNote) ProtoReflect() protoreflect.Message { // Deprecated: Use RouteNote.ProtoReflect.Descriptor instead. func (*RouteNote) Descriptor() ([]byte, []int) { - return file_examples_route_guide_routeguide_route_guide_proto_rawDescGZIP(), []int{3} + return file_route_guide_proto_rawDescGZIP(), []int{3} } func (x *RouteNote) GetLocation() *Point { @@ -298,7 +302,7 @@ type RouteSummary struct { func (x *RouteSummary) Reset() { *x = RouteSummary{} if protoimpl.UnsafeEnabled { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[4] + mi := &file_route_guide_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -311,7 +315,7 @@ func (x *RouteSummary) String() string { func (*RouteSummary) ProtoMessage() {} func (x *RouteSummary) ProtoReflect() protoreflect.Message { - mi := &file_examples_route_guide_routeguide_route_guide_proto_msgTypes[4] + mi := &file_route_guide_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -324,7 +328,7 @@ func (x *RouteSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use RouteSummary.ProtoReflect.Descriptor instead. func (*RouteSummary) Descriptor() ([]byte, []int) { - return file_examples_route_guide_routeguide_route_guide_proto_rawDescGZIP(), []int{4} + return file_route_guide_proto_rawDescGZIP(), []int{4} } func (x *RouteSummary) GetPointCount() int32 { @@ -355,12 +359,10 @@ func (x *RouteSummary) GetElapsedTime() int32 { return 0 } -var File_examples_route_guide_routeguide_route_guide_proto protoreflect.FileDescriptor +var File_route_guide_proto protoreflect.FileDescriptor -var file_examples_route_guide_routeguide_route_guide_proto_rawDesc = []byte{ - 0x0a, 0x31, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x5f, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, - 0x65, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x70, 0x72, +var file_route_guide_proto_rawDesc = []byte{ + 0x0a, 0x11, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x22, 0x41, 0x0a, 0x05, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, @@ -371,99 +373,107 @@ var file_examples_route_guide_routeguide_route_guide_proto_rawDesc = []byte{ 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x02, 0x6c, 0x6f, 0x12, 0x21, 0x0a, 0x02, 0x68, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x52, 0x02, 0x68, 0x69, 0x22, 0x4c, 0x0a, 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x74, 0x52, 0x02, 0x68, 0x69, 0x22, 0x6e, 0x0a, 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0x54, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x65, - 0x12, 0x2d, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x0c, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0a, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x66, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, - 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0b, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x32, - 0x85, 0x02, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x47, 0x75, 0x69, 0x64, 0x65, 0x12, 0x36, - 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x11, 0x2e, 0x72, - 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x1a, - 0x13, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, - 0x69, 0x64, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, 0x6c, 0x65, 0x1a, 0x13, 0x2e, - 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, - 0x64, 0x65, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x3f, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x43, - 0x68, 0x61, 0x74, 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, - 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x1a, 0x15, 0x2e, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4e, 0x6f, 0x74, - 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x68, 0x0a, 0x1b, 0x69, 0x6f, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x42, 0x0f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x47, 0x75, 0x69, - 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x72, 0x70, - 0x63, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x5f, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, - 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x54, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4e, 0x6f, + 0x74, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, + 0x65, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x0c, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x0a, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, + 0x0d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, + 0x65, 0x32, 0xc0, 0x02, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x47, 0x75, 0x69, 0x64, 0x65, + 0x12, 0x36, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x11, + 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x1a, 0x13, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x0b, 0x53, 0x61, 0x76, 0x65, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x13, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, + 0x75, 0x69, 0x64, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x13, 0x2e, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, + 0x2e, 0x52, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, 0x6c, 0x65, 0x1a, 0x13, 0x2e, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, + 0x00, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x12, 0x11, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, + 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x1a, 0x18, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, + 0x64, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, + 0x00, 0x28, 0x01, 0x12, 0x3f, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x43, 0x68, 0x61, 0x74, + 0x12, 0x15, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x2e, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x1a, 0x15, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, + 0x75, 0x69, 0x64, 0x65, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x22, 0x00, + 0x28, 0x01, 0x30, 0x01, 0x42, 0x68, 0x0a, 0x1b, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, + 0x69, 0x64, 0x65, 0x42, 0x0f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x47, 0x75, 0x69, 0x64, 0x65, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, + 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x67, 0x75, + 0x69, 0x64, 0x65, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x67, 0x75, 0x69, 0x64, 0x65, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_examples_route_guide_routeguide_route_guide_proto_rawDescOnce sync.Once - file_examples_route_guide_routeguide_route_guide_proto_rawDescData = file_examples_route_guide_routeguide_route_guide_proto_rawDesc + file_route_guide_proto_rawDescOnce sync.Once + file_route_guide_proto_rawDescData = file_route_guide_proto_rawDesc ) -func file_examples_route_guide_routeguide_route_guide_proto_rawDescGZIP() []byte { - file_examples_route_guide_routeguide_route_guide_proto_rawDescOnce.Do(func() { - file_examples_route_guide_routeguide_route_guide_proto_rawDescData = protoimpl.X.CompressGZIP(file_examples_route_guide_routeguide_route_guide_proto_rawDescData) +func file_route_guide_proto_rawDescGZIP() []byte { + file_route_guide_proto_rawDescOnce.Do(func() { + file_route_guide_proto_rawDescData = protoimpl.X.CompressGZIP(file_route_guide_proto_rawDescData) }) - return file_examples_route_guide_routeguide_route_guide_proto_rawDescData + return file_route_guide_proto_rawDescData } -var file_examples_route_guide_routeguide_route_guide_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_examples_route_guide_routeguide_route_guide_proto_goTypes = []interface{}{ +var file_route_guide_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_route_guide_proto_goTypes = []interface{}{ (*Point)(nil), // 0: routeguide.Point (*Rectangle)(nil), // 1: routeguide.Rectangle (*Feature)(nil), // 2: routeguide.Feature (*RouteNote)(nil), // 3: routeguide.RouteNote (*RouteSummary)(nil), // 4: routeguide.RouteSummary } -var file_examples_route_guide_routeguide_route_guide_proto_depIdxs = []int32{ +var file_route_guide_proto_depIdxs = []int32{ 0, // 0: routeguide.Rectangle.lo:type_name -> routeguide.Point 0, // 1: routeguide.Rectangle.hi:type_name -> routeguide.Point 0, // 2: routeguide.Feature.location:type_name -> routeguide.Point 0, // 3: routeguide.RouteNote.location:type_name -> routeguide.Point 0, // 4: routeguide.RouteGuide.GetFeature:input_type -> routeguide.Point - 1, // 5: routeguide.RouteGuide.ListFeatures:input_type -> routeguide.Rectangle - 0, // 6: routeguide.RouteGuide.RecordRoute:input_type -> routeguide.Point - 3, // 7: routeguide.RouteGuide.RouteChat:input_type -> routeguide.RouteNote - 2, // 8: routeguide.RouteGuide.GetFeature:output_type -> routeguide.Feature - 2, // 9: routeguide.RouteGuide.ListFeatures:output_type -> routeguide.Feature - 4, // 10: routeguide.RouteGuide.RecordRoute:output_type -> routeguide.RouteSummary - 3, // 11: routeguide.RouteGuide.RouteChat:output_type -> routeguide.RouteNote - 8, // [8:12] is the sub-list for method output_type - 4, // [4:8] is the sub-list for method input_type + 2, // 5: routeguide.RouteGuide.SaveFeature:input_type -> routeguide.Feature + 1, // 6: routeguide.RouteGuide.ListFeatures:input_type -> routeguide.Rectangle + 0, // 7: routeguide.RouteGuide.RecordRoute:input_type -> routeguide.Point + 3, // 8: routeguide.RouteGuide.RouteChat:input_type -> routeguide.RouteNote + 2, // 9: routeguide.RouteGuide.GetFeature:output_type -> routeguide.Feature + 2, // 10: routeguide.RouteGuide.SaveFeature:output_type -> routeguide.Feature + 2, // 11: routeguide.RouteGuide.ListFeatures:output_type -> routeguide.Feature + 4, // 12: routeguide.RouteGuide.RecordRoute:output_type -> routeguide.RouteSummary + 3, // 13: routeguide.RouteGuide.RouteChat:output_type -> routeguide.RouteNote + 9, // [9:14] is the sub-list for method output_type + 4, // [4:9] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } -func init() { file_examples_route_guide_routeguide_route_guide_proto_init() } -func file_examples_route_guide_routeguide_route_guide_proto_init() { - if File_examples_route_guide_routeguide_route_guide_proto != nil { +func init() { file_route_guide_proto_init() } +func file_route_guide_proto_init() { + if File_route_guide_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_examples_route_guide_routeguide_route_guide_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_route_guide_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Point); i { case 0: return &v.state @@ -475,7 +485,7 @@ func file_examples_route_guide_routeguide_route_guide_proto_init() { return nil } } - file_examples_route_guide_routeguide_route_guide_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_route_guide_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Rectangle); i { case 0: return &v.state @@ -487,7 +497,7 @@ func file_examples_route_guide_routeguide_route_guide_proto_init() { return nil } } - file_examples_route_guide_routeguide_route_guide_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_route_guide_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Feature); i { case 0: return &v.state @@ -499,7 +509,7 @@ func file_examples_route_guide_routeguide_route_guide_proto_init() { return nil } } - file_examples_route_guide_routeguide_route_guide_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_route_guide_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RouteNote); i { case 0: return &v.state @@ -511,7 +521,7 @@ func file_examples_route_guide_routeguide_route_guide_proto_init() { return nil } } - file_examples_route_guide_routeguide_route_guide_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_route_guide_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RouteSummary); i { case 0: return &v.state @@ -528,18 +538,18 @@ func file_examples_route_guide_routeguide_route_guide_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_examples_route_guide_routeguide_route_guide_proto_rawDesc, + RawDescriptor: file_route_guide_proto_rawDesc, NumEnums: 0, NumMessages: 5, NumExtensions: 0, NumServices: 1, }, - GoTypes: file_examples_route_guide_routeguide_route_guide_proto_goTypes, - DependencyIndexes: file_examples_route_guide_routeguide_route_guide_proto_depIdxs, - MessageInfos: file_examples_route_guide_routeguide_route_guide_proto_msgTypes, + GoTypes: file_route_guide_proto_goTypes, + DependencyIndexes: file_route_guide_proto_depIdxs, + MessageInfos: file_route_guide_proto_msgTypes, }.Build() - File_examples_route_guide_routeguide_route_guide_proto = out.File - file_examples_route_guide_routeguide_route_guide_proto_rawDesc = nil - file_examples_route_guide_routeguide_route_guide_proto_goTypes = nil - file_examples_route_guide_routeguide_route_guide_proto_depIdxs = nil + File_route_guide_proto = out.File + file_route_guide_proto_rawDesc = nil + file_route_guide_proto_goTypes = nil + file_route_guide_proto_depIdxs = nil } diff --git a/examples/grpc/routeguide/route_guide.proto b/examples/grpc/routeguide/route_guide.proto index 966c434a8..9d4e6db95 100644 --- a/examples/grpc/routeguide/route_guide.proto +++ b/examples/grpc/routeguide/route_guide.proto @@ -31,6 +31,9 @@ service RouteGuide { // position. rpc GetFeature(Point) returns (Feature) {} + // Save the feature. + rpc SaveFeature(Feature) returns (Feature) {} + // A server-to-client streaming RPC. // // Obtains the Features available within the given Rectangle. Results are @@ -80,6 +83,9 @@ message Feature { // The point where the feature is detected. Point location = 2; + + // A description of the feature. + string description = 3; } // A RouteNote is a message sent while at a given point. diff --git a/examples/grpc/routeguide/route_guide_grpc.pb.go b/examples/grpc/routeguide/route_guide_grpc.pb.go index 32f7910a3..8ab71705c 100644 --- a/examples/grpc/routeguide/route_guide_grpc.pb.go +++ b/examples/grpc/routeguide/route_guide_grpc.pb.go @@ -1,8 +1,22 @@ +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v3.14.0 -// source: examples/route_guide/routeguide/route_guide.proto +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.2 +// source: route_guide.proto package routeguide @@ -18,6 +32,14 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 +const ( + RouteGuide_GetFeature_FullMethodName = "/routeguide.RouteGuide/GetFeature" + RouteGuide_SaveFeature_FullMethodName = "/routeguide.RouteGuide/SaveFeature" + RouteGuide_ListFeatures_FullMethodName = "/routeguide.RouteGuide/ListFeatures" + RouteGuide_RecordRoute_FullMethodName = "/routeguide.RouteGuide/RecordRoute" + RouteGuide_RouteChat_FullMethodName = "/routeguide.RouteGuide/RouteChat" +) + // RouteGuideClient is the client API for RouteGuide 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. @@ -29,6 +51,8 @@ type RouteGuideClient interface { // A feature with an empty name is returned if there's no feature at the given // position. GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) + // Save the feature. + SaveFeature(ctx context.Context, in *Feature, opts ...grpc.CallOption) (*Feature, error) // A server-to-client streaming RPC. // // Obtains the Features available within the given Rectangle. Results are @@ -58,7 +82,16 @@ func NewRouteGuideClient(cc grpc.ClientConnInterface) RouteGuideClient { func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) { out := new(Feature) - err := c.cc.Invoke(ctx, "/routeguide.RouteGuide/GetFeature", in, out, opts...) + err := c.cc.Invoke(ctx, RouteGuide_GetFeature_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *routeGuideClient) SaveFeature(ctx context.Context, in *Feature, opts ...grpc.CallOption) (*Feature, error) { + out := new(Feature) + err := c.cc.Invoke(ctx, RouteGuide_SaveFeature_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -66,7 +99,7 @@ func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...gr } func (c *routeGuideClient) ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) { - stream, err := c.cc.NewStream(ctx, &RouteGuide_ServiceDesc.Streams[0], "/routeguide.RouteGuide/ListFeatures", opts...) + stream, err := c.cc.NewStream(ctx, &RouteGuide_ServiceDesc.Streams[0], RouteGuide_ListFeatures_FullMethodName, opts...) if err != nil { return nil, err } @@ -98,7 +131,7 @@ func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) { } func (c *routeGuideClient) RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) { - stream, err := c.cc.NewStream(ctx, &RouteGuide_ServiceDesc.Streams[1], "/routeguide.RouteGuide/RecordRoute", opts...) + stream, err := c.cc.NewStream(ctx, &RouteGuide_ServiceDesc.Streams[1], RouteGuide_RecordRoute_FullMethodName, opts...) if err != nil { return nil, err } @@ -132,7 +165,7 @@ func (x *routeGuideRecordRouteClient) CloseAndRecv() (*RouteSummary, error) { } func (c *routeGuideClient) RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error) { - stream, err := c.cc.NewStream(ctx, &RouteGuide_ServiceDesc.Streams[2], "/routeguide.RouteGuide/RouteChat", opts...) + stream, err := c.cc.NewStream(ctx, &RouteGuide_ServiceDesc.Streams[2], RouteGuide_RouteChat_FullMethodName, opts...) if err != nil { return nil, err } @@ -173,6 +206,8 @@ type RouteGuideServer interface { // A feature with an empty name is returned if there's no feature at the given // position. GetFeature(context.Context, *Point) (*Feature, error) + // Save the feature. + SaveFeature(context.Context, *Feature) (*Feature, error) // A server-to-client streaming RPC. // // Obtains the Features available within the given Rectangle. Results are @@ -200,6 +235,9 @@ type UnimplementedRouteGuideServer struct { func (UnimplementedRouteGuideServer) GetFeature(context.Context, *Point) (*Feature, error) { return nil, status.Errorf(codes.Unimplemented, "method GetFeature not implemented") } +func (UnimplementedRouteGuideServer) SaveFeature(context.Context, *Feature) (*Feature, error) { + return nil, status.Errorf(codes.Unimplemented, "method SaveFeature not implemented") +} func (UnimplementedRouteGuideServer) ListFeatures(*Rectangle, RouteGuide_ListFeaturesServer) error { return status.Errorf(codes.Unimplemented, "method ListFeatures not implemented") } @@ -232,7 +270,7 @@ func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/routeguide.RouteGuide/GetFeature", + FullMethod: RouteGuide_GetFeature_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(RouteGuideServer).GetFeature(ctx, req.(*Point)) @@ -240,6 +278,24 @@ func _RouteGuide_GetFeature_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _RouteGuide_SaveFeature_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Feature) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RouteGuideServer).SaveFeature(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: RouteGuide_SaveFeature_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RouteGuideServer).SaveFeature(ctx, req.(*Feature)) + } + return interceptor(ctx, in, info, handler) +} + func _RouteGuide_ListFeatures_Handler(srv interface{}, stream grpc.ServerStream) error { m := new(Rectangle) if err := stream.RecvMsg(m); err != nil { @@ -324,6 +380,10 @@ var RouteGuide_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetFeature", Handler: _RouteGuide_GetFeature_Handler, }, + { + MethodName: "SaveFeature", + Handler: _RouteGuide_SaveFeature_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -343,5 +403,5 @@ var RouteGuide_ServiceDesc = grpc.ServiceDesc{ ClientStreams: true, }, }, - Metadata: "examples/route_guide/routeguide/route_guide.proto", + Metadata: "route_guide.proto", } diff --git a/examples/grpc/routeguide/server/server.go b/examples/grpc/routeguide/server/server.go index 1c8b4c678..fa59e7ddf 100644 --- a/examples/grpc/routeguide/server/server.go +++ b/examples/grpc/routeguide/server/server.go @@ -28,17 +28,19 @@ import ( "flag" "fmt" "io" - "os" "log" "math" "net" + "os" "sync" "time" "google.golang.org/grpc" "github.com/pact-foundation/pact-go/v2/examples/grpc/routeguide/data" + "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" + "google.golang.org/grpc/status" "github.com/golang/protobuf/proto" @@ -69,7 +71,13 @@ func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb } } // No feature was found, return an unnamed feature - return &pb.Feature{Location: point}, nil + return nil, status.Errorf(codes.NotFound, "no feature was found at %v", point) +} + +// SaveFeature saves the feature +func (s *routeGuideServer) SaveFeature(ctx context.Context, feature *pb.Feature) (*pb.Feature, error) { + s.savedFeatures = append(s.savedFeatures, feature) + return feature, nil } // ListFeatures lists all features contained within the given bounding Rectangle. @@ -849,5 +857,6 @@ var exampleData = []byte(`[{ "latitude": 180, "longitude": 200 }, - "name": "Really big tree" + "name": "Really big tree", + "description": "This tree is really big" }]`) diff --git a/examples/protobuf-message/protobuf_consumer_test.go b/examples/protobuf-message/protobuf_consumer_test.go index a373653b5..a7226acfe 100644 --- a/examples/protobuf-message/protobuf_consumer_test.go +++ b/examples/protobuf-message/protobuf_consumer_test.go @@ -42,7 +42,7 @@ func TestPluginMessageConsumer(t *testing.T) { ExpectsToReceive("feature message"). UsingPlugin(message.PluginConfig{ Plugin: "protobuf", - Version: "0.3.8", + Version: "0.3.13", }). WithContents(protoMessage, "application/protobuf"). ExecuteTest(t, func(m message.AsynchronousMessage) error { diff --git a/internal/native/message_server.go b/internal/native/message_server.go index 1e6f50b6b..723ff6952 100644 --- a/internal/native/message_server.go +++ b/internal/native/message_server.go @@ -502,17 +502,15 @@ func (m *Message) GetMessageResponseContents() ([][]byte, error) { // Get Response body len := C.pactffi_sync_message_get_response_contents_length(message, C.size_t(i)) - if len == 0 { - return nil, errors.New("retrieved an empty message") - } - data := C.pactffi_sync_message_get_response_contents_bin(message, C.size_t(i)) - if data == nil { - return nil, errors.New("retrieved an empty pointer to the message contents") + if len != 0 { + data := C.pactffi_sync_message_get_response_contents_bin(message, C.size_t(i)) + if data == nil { + return nil, errors.New("retrieved an empty pointer to the message contents") + } + ptr := unsafe.Pointer(data) + bytes := C.GoBytes(ptr, C.int(len)) + responses[i] = bytes } - ptr := unsafe.Pointer(data) - bytes := C.GoBytes(ptr, C.int(len)) - - responses[i] = bytes } return responses, nil diff --git a/internal/native/message_server_test.go b/internal/native/message_server_test.go index d4cdf8619..c6ce2b972 100644 --- a/internal/native/message_server_test.go +++ b/internal/native/message_server_test.go @@ -7,8 +7,8 @@ import ( "encoding/json" "fmt" "io" + l "log" "os" - l"log" "testing" "time" @@ -187,11 +187,31 @@ func TestGetSyncMessageContentsAsBytes(t *testing.T) { assert.Equal(t, "response", v.Some) } +func TestGetSyncMessageContentsAsBytes_EmptyResponse(t *testing.T) { + s := NewMessageServer("test-message-consumer", "test-message-provider") + + m := s.NewSyncMessageInteraction(""). + Given("some state"). + GivenWithParameter("param", map[string]interface{}{ + "foo": "bar", + }). + ExpectsToReceive("some message"). + WithMetadata(map[string]string{ + "meta": "data", + }) + + bytes, err := m.GetMessageResponseContents() + assert.NoError(t, err) + assert.NotNil(t, bytes) + assert.Equal(t, 1, len(bytes)) + assert.Empty(t, bytes[0]) +} + func TestGetPluginSyncMessageContentsAsBytes(t *testing.T) { m := NewMessageServer("test-message-consumer", "test-message-provider") // Protobuf plugin test - err := m.UsingPlugin("protobuf", "0.3.8") + err := m.UsingPlugin("protobuf", "0.3.11") assert.NoError(t, err) i := m.NewSyncMessageInteraction("grpc interaction") @@ -244,11 +264,57 @@ func TestGetPluginSyncMessageContentsAsBytes(t *testing.T) { } +func TestGetPluginSyncMessageContentsAsBytes_EmptyResponse(t *testing.T) { + m := NewMessageServer("test-message-consumer", "test-message-provider") + + // Protobuf plugin test + err := m.UsingPlugin("protobuf", "0.3.11") + assert.NoError(t, err) + + i := m.NewSyncMessageInteraction("grpc interaction") + + dir, _ := os.Getwd() + path := fmt.Sprintf("%s/pact_plugin.proto", dir) + + grpcInteraction := `{ + "pact:proto": "` + path + `", + "pact:proto-service": "PactPlugin/InitPlugin", + "pact:content-type": "application/protobuf", + "request": { + "implementation": "notEmpty('pact-go-driver')", + "version": "matching(semver, '0.0.0')" + } + }` + + err = i. + Given("plugin state"). + // For gRPC interactions we prpvide the config once for both the request and response parts + WithPluginInteractionContents(INTERACTION_PART_REQUEST, "application/protobuf", grpcInteraction) + assert.NoError(t, err) + + bytes, err := i.GetMessageRequestContents() + assert.NoError(t, err) + assert.NotNil(t, bytes) + + // Should be able to convert request body back into a protobuf + p := &InitPluginRequest{} + err = proto.Unmarshal(bytes, p) + assert.NoError(t, err) + assert.Equal(t, "0.0.0", p.Version) + + // Should be able to convert response into a protobuf + response_bytes, err := i.GetMessageResponseContents() + assert.NoError(t, err) + assert.NotNil(t, response_bytes) + assert.Equal(t, 1, len(response_bytes)) + assert.Empty(t, response_bytes[0]) +} + func TestGetPluginAsyncMessageContentsAsBytes(t *testing.T) { m := NewMessageServer("test-message-consumer", "test-message-provider") // Protobuf plugin test - _ = m.UsingPlugin("protobuf", "0.3.8") + _ = m.UsingPlugin("protobuf", "0.3.11") i := m.NewAsyncMessageInteraction("grpc interaction") @@ -288,7 +354,7 @@ func TestGrpcPluginInteraction(t *testing.T) { m := NewMessageServer("test-message-consumer", "test-message-provider") // Protobuf plugin test - _ = m.UsingPlugin("protobuf", "0.3.8") + _ = m.UsingPlugin("protobuf", "0.3.13") i := m.NewSyncMessageInteraction("grpc interaction") @@ -356,3 +422,74 @@ func TestGrpcPluginInteraction(t *testing.T) { err = m.WritePactFileForServer(port, tmpPactFolder, true) assert.NoError(t, err) } + +func TestGrpcPluginInteraction_ErrorResponse(t *testing.T) { + tmpPactFolder, err := os.MkdirTemp("", "pact-go") + assert.NoError(t, err) + _ = log.SetLogLevel("TRACE") + + m := NewMessageServer("test-message-consumer", "test-message-provider") + + // Protobuf plugin test + _ = m.UsingPlugin("protobuf", "0.3.11") + + i := m.NewSyncMessageInteraction("grpc interaction") + + dir, _ := os.Getwd() + path := fmt.Sprintf("%s/pact_plugin.proto", dir) + + grpcInteraction := `{ + "pact:proto": "` + path + `", + "pact:proto-service": "PactPlugin/InitPlugin", + "pact:content-type": "application/protobuf", + "request": { + "implementation": "notEmpty('pact-go-driver')", + "version": "matching(semver, '0.0.0')" + }, + "responseMetadata": { + "grpc-status": "NOT_FOUND", + "grpc-message": "matching(type, 'not found')" + } + }` + + err = i. + Given("plugin state"). + // For gRPC interactions we prpvide the config once for both the request and response parts + WithPluginInteractionContents(INTERACTION_PART_REQUEST, "application/protobuf", grpcInteraction) + assert.NoError(t, err) + + // Start the gRPC mock server + port, err := m.StartTransport("grpc", "127.0.0.1", 0, make(map[string][]interface{})) + assert.NoError(t, err) + defer m.CleanupMockServer(port) + + // Now we can make a normal gRPC request + initPluginRequest := &InitPluginRequest{ + Implementation: "pact-go-test", + Version: "1.0.0", + } + + // Need to make a gRPC call here + conn, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", port), grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + l.Fatalf("did not connect: %v", err) + } + defer conn.Close() + c := NewPactPluginClient(conn) + + // Contact the server and print out its response. + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + r, err := c.InitPlugin(ctx, initPluginRequest) + assert.Nil(t, r) + assert.ErrorContains(t, err, "not found") + + mismatches := m.MockServerMismatchedRequests(port) + if len(mismatches) != 0 { + assert.Len(t, mismatches, 0) + t.Log(mismatches) + } + + err = m.WritePactFileForServer(port, tmpPactFolder, true) + assert.NoError(t, err) +} diff --git a/message/v4/synchronous_message_test.go b/message/v4/synchronous_message_test.go index 87d87ff45..0b546f022 100644 --- a/message/v4/synchronous_message_test.go +++ b/message/v4/synchronous_message_test.go @@ -105,7 +105,7 @@ func TestSyncTypeSystem(t *testing.T) { Given("some state"). UsingPlugin(PluginConfig{ Plugin: "protobuf", - Version: "0.3.8", + Version: "0.3.13", }). WithContents(grpcInteraction, "application/protobuf"). StartTransport("grpc", "127.0.0.1", nil). // For plugin tests, we can't assume if a transport is needed, so this is optional @@ -128,7 +128,7 @@ func TestSyncTypeSystem(t *testing.T) { Given("some state"). UsingPlugin(PluginConfig{ Plugin: "protobuf", - Version: "0.3.8", + Version: "0.3.13", }). WithContents(grpcInteraction, "application/protobuf"). StartTransport("grpc", "127.0.0.1", nil). // For plugin tests, we can't assume if a transport is needed, so this is optional