namespace ProtoTest.Demo; using global::Grpc.Core; using global::NUnit.Framework; using Google.Protobuf; using Northstar.ProtoTest; using ProtoTest.Core; using ProtoTest.Data; using ProtoTest.Grpc; using ProtoTest.Http; using ProtoTest.NUnit; using ProtoTest.SampleApp.Contracts; using ProtoTest.SampleApp.Domain; using ProtoTest.SampleApp.Grpc; /// /// The same application over gRPC: the shared [Auth] bearer token travels as metadata, the call /// is traced as a grpc.call span, and the reply is asserted like any other value. /// [Application(NorthstarTargets.Api)] [NorthstarTenant(PlanIds.Growth)] [Auth] public sealed class GrpcJourney { private static readonly Marshaller GetRequestMarshaller = Marshallers.Create( (request, context) => context.Complete(request.ToByteArray()), context => GetProjectRequest.Parser.ParseFrom(context.PayloadAsNewBuffer())); private static readonly Marshaller ListRequestMarshaller = Marshallers.Create( (request, context) => context.Complete(request.ToByteArray()), context => ListProjectsRequest.Parser.ParseFrom(context.PayloadAsNewBuffer())); private static readonly Marshaller ReplyMarshaller = Marshallers.Create( (reply, context) => context.Complete(reply.ToByteArray()), context => ProjectReply.Parser.ParseFrom(context.PayloadAsNewBuffer())); private static readonly Method GetProjectMethod = new( MethodType.Unary, "northstar.v1.Projects", "GetProject", GetRequestMarshaller, ReplyMarshaller); private static readonly Method ListProjectsMethod = new( MethodType.ServerStreaming, "northstar.v1.Projects", "ListProjects", ListRequestMarshaller, ReplyMarshaller); [ProtoTest] [SignedInAs] public async Task AProjectIsReadableOverGrpc() { // Arrange over the API, read back over gRPC. var project = await Proto.Context.Data() .For() .With(request => request.Name, "grpc-atlas") .CreateAsync(); // Act: unary, then the server stream. var client = Proto.Context.Grpc(); var reply = await client.UnaryAsync(GetProjectMethod, new GetProjectRequest { ProjectId = project.Id }); var listed = await client.ServerStreamingAsync( ListProjectsMethod, new ListProjectsRequest { Limit = 10 }); // Assert: same identity, same state, from the other protocol. Assert.Multiple(() => { reply.ShouldMatchShape(new { id = project.Id, name = "grpc-atlas", status = ProjectStatuses.Active }); Assert.That(listed.Any(item => item.Id == project.Id), Is.True, "The project created over REST is visible on the gRPC stream."); }); } }