public void SendMessageSendsAndReceivesAMessage()
 {
     var action = "DoSomething";
     var request = new ServerRequest
     {
         ServerName = "TestServer"
     };
     var url = "http://somewhere/";
     var factory = new TestClientFactory((u, a, d) =>
     {
         Assert.AreEqual(url + "server/TestServer/RawXmlMessage.aspx", u.AbsoluteUri);
         Assert.AreEqual("POST", a);
         Assert.AreEqual(action, d["action"]);
         Assert.AreEqual(request.ToString(), d["message"]);
         var theResponse = new Response
         {
             RequestIdentifier = request.Identifier
         };
         return Encoding.UTF8.GetBytes(theResponse.ToString());
     });
     var connection = new HttpConnection(new Uri(url), factory);
     var response = connection.SendMessage(action, request);
     Assert.IsInstanceOf<Response>(response);
     Assert.AreEqual(request.Identifier, response.RequestIdentifier);
 }
 public void SendMessageAsyncSendsMessage()
 {
     var action = "DoSomething";
     var request = new ServerRequest
     {
         ServerName = "TestServer"
     };
     var url = "http://somewhere/";
     var factory = new TestClientFactory((u, a, d) =>
     {
         Assert.AreEqual(url + "server/TestServer/RawXmlMessage.aspx", u.AbsoluteUri);
         Assert.AreEqual("POST", a);
         Assert.AreEqual(action, d["action"]);
         Assert.AreEqual(request.ToString(), d["message"]);
         var theResponse = new Response
         {
             RequestIdentifier = request.Identifier
         };
         return Encoding.UTF8.GetBytes(theResponse.ToString());
     });
     var connection = new HttpConnection(new Uri(url), factory);
     var completed = false;
     connection.SendMessageCompleted += (o, e) =>
     {
         completed = true;
         Assert.IsFalse(e.Cancelled);
         Assert.IsNull(e.Error);
     };
     connection.SendMessageAsync(action, request);
     Assert.IsTrue(completed);
 }
Esempio n. 3
0
        public async void Should_Be_Able_To_Publish_Dynamic_Objects()
        {
            using (var client = TestClientFactory.CreateNormal())
            {
                /* Setup */
                var tcs = new TaskCompletionSource <DynamicMessage>();
                client.SubscribeAsync <DynamicMessage>((message, context) =>
                {
                    tcs.TrySetResult(message);
                    return(Task.FromResult(true));
                });

                /* Test */
                client.PublishAsync(new DynamicMessage {
                    Body = new { IsDynamic = true }
                });
                await tcs.Task;

                /* Assert */
                Assert.True(tcs.Task.Result.Body.IsDynamic);
            }
        }
Esempio n. 4
0
        public async Task Should_Not_Throw_If_Credentials_Are_Correct()
        {
            /* Setup */
            var config = new RawRabbitConfiguration
            {
                Username  = "******",
                Password  = "******",
                Hostnames = new List <string> {
                    "localhost"
                },
                VirtualHost = "/",
                Port        = 5672
            };

            /* Test */
            var b = TestClientFactory.CreateNormal(ioc => ioc.AddSingleton(p => config));

            b.Dispose();

            /* Assert */
            Assert.True(true, "Does not throw.");
        }
Esempio n. 5
0
        public async Task Unary_CanceledBeforeServerCall_Failure()
        {
            var callCount = 0;
            var tcs       = new TaskCompletionSource <DataMessage>(TaskCreationOptions.RunContinuationsAsynchronously);

            Task <DataMessage> UnaryFailure(DataMessage request, ServerCallContext context)
            {
                callCount++;
                return(tcs.Task);
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddUnaryMethod <DataMessage, DataMessage>(UnaryFailure);

            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig(nonFatalStatusCodes: new List <StatusCode> {
                StatusCode.DeadlineExceeded
            });
            var channel = CreateChannel(serviceConfig: serviceConfig);

            var client = TestClientFactory.Create(channel, method);
            var cts    = new CancellationTokenSource();

            cts.Cancel();

            // Act
            var call = client.UnaryCall(new DataMessage(), new CallOptions(cancellationToken: cts.Token));

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode);
            Assert.AreEqual(StatusCode.Cancelled, call.GetStatus().StatusCode);
            Assert.AreEqual(0, callCount);

            AssertHasLog(LogLevel.Debug, "CallCommited", "Call commited. Reason: Canceled");

            tcs.SetResult(new DataMessage());
        }
Esempio n. 6
0
        public async Task Unary_DeadlineExceedAfterServerCall_Failure(int exceptedServerCallCount)
        {
            var callCount = 0;
            var tcs       = new TaskCompletionSource <DataMessage>(TaskCreationOptions.RunContinuationsAsynchronously);

            Task <DataMessage> UnaryFailure(DataMessage request, ServerCallContext context)
            {
                callCount++;

                if (callCount < exceptedServerCallCount)
                {
                    return(Task.FromException <DataMessage>(new RpcException(new Status(StatusCode.DeadlineExceeded, ""))));
                }

                return(tcs.Task);
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddUnaryMethod <DataMessage, DataMessage>(UnaryFailure);

            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig(nonFatalStatusCodes: new List <StatusCode> {
                StatusCode.DeadlineExceeded
            });
            var channel = CreateChannel(serviceConfig: serviceConfig);

            var client = TestClientFactory.Create(channel, method);

            // Act
            var call = client.UnaryCall(new DataMessage(), new CallOptions(deadline: DateTime.UtcNow.AddMilliseconds(200)));

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual(StatusCode.DeadlineExceeded, ex.StatusCode);
            Assert.AreEqual(StatusCode.DeadlineExceeded, call.GetStatus().StatusCode);

            Assert.IsFalse(Logs.Any(l => l.EventId.Name == "DeadlineTimerRescheduled"));
        }
        public async Task ReceivedMessageExceedsDefaultSize_ThrowError()
        {
            Task <HelloReply> UnaryDeadlineExceeded(HelloRequest request, ServerCallContext context)
            {
                // Return message is 4 MB + 1 B. Default receive size is 4 MB
                return(Task.FromResult(new HelloReply {
                    Message = new string('!', (1024 * 1024 * 4) + 1)
                }));
            }

            // Arrange
            SetExpectedErrorsFilter(writeContext =>
            {
                if (writeContext.LoggerName == "Grpc.Net.Client.Internal.GrpcCall" &&
                    writeContext.EventId.Name == "ErrorReadingMessage" &&
                    writeContext.State.ToString() == "Error reading message.")
                {
                    return(true);
                }

                return(false);
            });

            var method = Fixture.DynamicGrpc.AddUnaryMethod <HelloRequest, HelloReply>(UnaryDeadlineExceeded);

            var channel = CreateChannel();

            channel.DisableClientDeadlineTimer = true;

            var client = TestClientFactory.Create(channel, method);

            // Act
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => client.UnaryCall(new HelloRequest()).ResponseAsync).DefaultTimeout();

            // Assert
            Assert.AreEqual(StatusCode.ResourceExhausted, ex.StatusCode);
            Assert.AreEqual("Received message exceeds the maximum configured message size.", ex.Status.Detail);
        }
Esempio n. 8
0
        public async Task Should_Honor_Last_Configuration()
        {
            /* Setup */
            using (var client = TestClientFactory.CreateExtendable())
            {
                const string exchangeName = "topology";
                TestChannel.ExchangeDelete(exchangeName);

                /* Test */
                var result = await client.UpdateTopologyAsync(c => c
                                                              .ForExchange(exchangeName)
                                                              .UseConfiguration(e => e.WithType(ExchangeType.Headers))
                                                              .ForExchange(exchangeName)
                                                              .UseConfiguration(e => e.WithType(ExchangeType.Topic))
                                                              .ForExchange(exchangeName)
                                                              .UseConfiguration(e => e.WithType(ExchangeType.Direct))
                                                              .ForExchange(exchangeName)
                                                              .UseConfiguration(e => e.WithType(ExchangeType.Fanout)));

                /* Assert */
                Assert.Equal(result.Exchanges[0].Exchange.ExchangeType, ExchangeType.Fanout.ToString().ToLower());
            }
        }
Esempio n. 9
0
        public async Task Should_Work_For_Pub_Sub()
        {
            /* Setup */
            using (var client = TestClientFactory.CreateNormal(ioc => ioc
                                                               .AddSingleton <IConfigurationEvaluator, AttributeConfigEvaluator>()
                                                               ))
            {
                var tcs = new TaskCompletionSource <AttributedMessage>();
                client.SubscribeAsync <AttributedMessage>((message, context) =>
                {
                    tcs.TrySetResult(message);
                    return(Task.FromResult(true));
                });

                /* Test */
                await client.PublishAsync(new AttributedMessage());

                await tcs.Task;

                /* Assert */
                Assert.True(true, "Routing successful.");
            }
        }
Esempio n. 10
0
        public async Task Should_Support_The_Hello_World_Tutorial()
        {
            /* Setup */
            using (var sender = TestClientFactory.CreateNormal())
                using (var reciever = TestClientFactory.CreateNormal())
                {
                    var sent = new BasicMessage {
                        Prop = "Hello, world!"
                    };
                    var recieved = new TaskCompletionSource <BasicMessage>();

                    reciever.SubscribeAsync <BasicMessage>((message, info) =>
                    {
                        recieved.SetResult(message);
                        return(Task.FromResult(true));
                    }, configuration => configuration
                                                           .WithQueue(queue =>
                                                                      queue
                                                                      .WithName("hello")
                                                                      .WithExclusivity(false)
                                                                      .WithAutoDelete(false)
                                                                      )
                                                           .WithRoutingKey("hello")
                                                           );

                    /* Test */
                    await sender.PublishAsync(sent,
                                              configuration : builder => builder
                                              .WithRoutingKey("hello")
                                              );

                    await recieved.Task;

                    /* Assert */
                    Assert.Equal(expected: sent.Prop, actual: recieved.Task.Result.Prop);
                }
        }
Esempio n. 11
0
        public async Task Should_Perform_Rpc_Without_Direct_Reply_To()
        {
            /* Setup */
            using (var requester = TestClientFactory.CreateNormal())
                using (var responder = TestClientFactory.CreateNormal())
                {
                    var response = new BasicResponse {
                        Prop = "This is the response."
                    };
                    responder.RespondAsync <BasicRequest, BasicResponse>((req, i) =>
                    {
                        return(Task.FromResult(response));
                    });

                    /* Test */
                    var firstRecieved = await requester.RequestAsync <BasicRequest, BasicResponse>(new BasicRequest(),
                                                                                                   configuration : cfg => cfg
                                                                                                   .WithReplyQueue(
                                                                                                       q => q
                                                                                                       .WithName("special_reply_queue")
                                                                                                       .WithAutoDelete())
                                                                                                   .WithNoAck(false));

                    var secondRecieved = await requester.RequestAsync <BasicRequest, BasicResponse>(new BasicRequest(),
                                                                                                    configuration : cfg => cfg
                                                                                                    .WithReplyQueue(
                                                                                                        q => q
                                                                                                        .WithName("another_special_reply_queue")
                                                                                                        .WithAutoDelete())
                                                                                                    .WithNoAck(false)
                                                                                                    );

                    /* Assert */
                    Assert.Equal(expected: response.Prop, actual: firstRecieved.Prop);
                    Assert.Equal(expected: response.Prop, actual: secondRecieved.Prop);
                }
        }
Esempio n. 12
0
        private async Task TestTelemetryHeaderIsSet(HttpMessageHandler?handler)
        {
            string?telemetryHeader = null;

            Task <HelloReply> UnaryTelemetryHeader(HelloRequest request, ServerCallContext context)
            {
                telemetryHeader = context.RequestHeaders.GetValue(
#if NET5_0
                    "traceparent"
#else
                    "request-id"
#endif
                    );

                return(Task.FromResult(new HelloReply()));
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddUnaryMethod <HelloRequest, HelloReply>(UnaryTelemetryHeader);

            var options = new GrpcChannelOptions
            {
                LoggerFactory = LoggerFactory,
                HttpHandler   = handler
            };

            // Want to test the behavior of the default, internally created handler.
            // Only supply the URL to a manually created GrpcChannel.
            var channel = GrpcChannel.ForAddress(Fixture.GetUrl(TestServerEndpointName.Http2), options);
            var client  = TestClientFactory.Create(channel, method);

            // Act
            await client.UnaryCall(new HelloRequest());

            // Assert
            Assert.IsNotNull(telemetryHeader);
        }
        public async Task Should_Be_Able_To_Recieve_Different_Types_Of_Messages()
        {
            /* Setup */
            using (var publisher = TestClientFactory.CreateNormal())
                using (var subscriber = TestClientFactory.CreateNormal())
                {
                    var basicMsg = new BasicMessage {
                        Prop = "Hello, world!"
                    };
                    var simpleMsg = new SimpleMessage {
                        IsSimple = true
                    };

                    var basicMsgTcs  = new TaskCompletionSource <BasicMessage>();
                    var simpleMsgTcs = new TaskCompletionSource <SimpleMessage>();

                    subscriber.SubscribeAsync <BasicMessage>((msg, i) =>
                    {
                        basicMsgTcs.SetResult(msg);
                        return(basicMsgTcs.Task);
                    });
                    subscriber.SubscribeAsync <SimpleMessage>((msg, i) =>
                    {
                        simpleMsgTcs.SetResult(msg);
                        return(basicMsgTcs.Task);
                    });

                    /* Test */
                    publisher.PublishAsync(basicMsg);
                    publisher.PublishAsync(simpleMsg);
                    Task.WaitAll(basicMsgTcs.Task, simpleMsgTcs.Task);

                    /* Assert */
                    Assert.Equal(expected: basicMsg.Prop, actual: basicMsgTcs.Task.Result.Prop);
                    Assert.Equal(expected: simpleMsg.IsSimple, actual: simpleMsgTcs.Task.Result.IsSimple);
                }
        }
Esempio n. 14
0
        public async Task Should_Call_Message_Handler_In_Correct_Order()
        {
            /* Setup */
            using (var publisher = TestClientFactory.CreateExtendable())
            {
                publisher.SubscribeAsync <FirstMessage>((message, context) =>
                                                        publisher.PublishAsync(new SecondMessage(), context.GlobalRequestId));
                publisher.SubscribeAsync <SecondMessage>((message, context) =>
                                                         publisher.PublishAsync(new ThirdMessage(), context.GlobalRequestId));
                publisher.SubscribeAsync <ThirdMessage>((message, context) =>
                                                        publisher.PublishAsync(new ForthMessage(), context.GlobalRequestId));
                var recieveIndex  = 0;
                var secondMsgDate = DateTime.MinValue;
                var thirdMsgDate  = DateTime.MinValue;

                /* Test */
                var chain = _client.ExecuteSequence(c => c
                                                    .PublishAsync(new FirstMessage())
                                                    .When <SecondMessage>((message, context) =>
                {
                    secondMsgDate = DateTime.Now;
                    return(Task.FromResult(true));
                })
                                                    .When <ThirdMessage>((message, context) =>
                {
                    thirdMsgDate = DateTime.Now;
                    return(Task.FromResult(true));
                })
                                                    .Complete <ForthMessage>()
                                                    );

                await chain.Task;

                /* Assert */
                Assert.True(secondMsgDate < thirdMsgDate);
            }
        }
Esempio n. 15
0
        public async Task Unary_DeadlineExceedBeforeServerCall_Failure()
        {
            var callCount = 0;
            var tcs       = new TaskCompletionSource <DataMessage>(TaskCreationOptions.RunContinuationsAsynchronously);

            Task <DataMessage> UnaryFailure(DataMessage request, ServerCallContext context)
            {
                callCount++;
                return(tcs.Task);
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddUnaryMethod <DataMessage, DataMessage>(UnaryFailure);

            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig(retryableStatusCodes: new List <StatusCode> {
                StatusCode.DeadlineExceeded
            });
            var channel = CreateChannel(serviceConfig: serviceConfig);

            var client = TestClientFactory.Create(channel, method);

            // Act
            var call = client.UnaryCall(new DataMessage(), new CallOptions(deadline: DateTime.UtcNow));

            // Assert
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseAsync).DefaultTimeout();

            Assert.AreEqual(StatusCode.DeadlineExceeded, ex.StatusCode);
            Assert.AreEqual(StatusCode.DeadlineExceeded, call.GetStatus().StatusCode);
            Assert.AreEqual(0, callCount);

            AssertHasLog(LogLevel.Debug, "RetryEvaluated", "Evaluated retry for failed gRPC call. Status code: 'DeadlineExceeded', Attempt: 1, Retry: False");
            AssertHasLog(LogLevel.Debug, "CallCommited", "Call commited. Reason: DeadlineExceeded");

            tcs.SetResult(new DataMessage());
        }
Esempio n. 16
0
        public async Task Should_Retry_For_Publish_Subscribe_After_Given_Timespan()
        {
            /* Setup */
            using (var subscriber = TestClientFactory.CreateNormal <AdvancedMessageContext>())
                using (var publisher = TestClientFactory.CreateNormal <AdvancedMessageContext>())
                {
                    var subscribeTcs   = new TaskCompletionSource <bool>();
                    var delay          = TimeSpan.FromSeconds(1);
                    var hasBeenDelayed = false;
                    var firstRecieved  = DateTime.MinValue;
                    var secondRecieved = DateTime.MinValue;

                    subscriber.SubscribeAsync <BasicMessage>((message, context) =>
                    {
                        if (!hasBeenDelayed)
                        {
                            firstRecieved = DateTime.Now;
                            context.RetryLater(delay);
                            hasBeenDelayed = true;
                            return(Task.FromResult(true));
                        }
                        secondRecieved = DateTime.Now;
                        return(Task.Delay(10).ContinueWith(t => subscribeTcs.SetResult(true)));
                    });

                    /* Test */
                    await publisher.PublishAsync(new BasicMessage { Prop = "I'm about to be reborn!" });

                    await subscribeTcs.Task;
                    var actualDelay = secondRecieved - firstRecieved;
                    await Task.Delay(80);

                    /* Assert */
                    Assert.Equal(expected: delay.Seconds, actual: actualDelay.Seconds);
                }
        }
Esempio n. 17
0
        public async Task Should_Update_Exhange_Type()
        {
            /* Setup */
            const string exchangeName = "topology";

            TestChannel.ExchangeDelete(exchangeName);
            TestChannel.ExchangeDeclare(exchangeName, RabbitMQ.Client.ExchangeType.Direct);

            using (var client = TestClientFactory.CreateExtendable())
            {
                /* Test */
                await client.UpdateTopologyAsync(t => t
                                                 .ForExchange(exchangeName)
                                                 .UseConfiguration(e => e
                                                                   .WithType(ExchangeType.Topic)
                                                                   .WithDurability(false))
                                                 );

                /* Assert */
                TestChannel.ExchangeDeclare(exchangeName, RabbitMQ.Client.ExchangeType.Topic);
                Assert.True(true, "Did not throw");
                Assert.Throws <OperationInterruptedException>(() => TestChannel.ExchangeDeclare(exchangeName, RabbitMQ.Client.ExchangeType.Direct));
            }
        }
Esempio n. 18
0
        public async Task ShareSocketsHttpHandler()
        {
            Task <HelloReply> Unary(HelloRequest request, ServerCallContext context)
            {
                return(Task.FromResult(new HelloReply {
                    Message = request.Name
                }));
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddUnaryMethod <HelloRequest, HelloReply>(Unary);

            var http = Fixture.CreateHandler(TestServerEndpointName.Http2);

            var channel1 = GrpcChannel.ForAddress(http.address, new GrpcChannelOptions
            {
                LoggerFactory = LoggerFactory,
                HttpHandler   = http.handler
            });

            var channel2 = GrpcChannel.ForAddress(http.address, new GrpcChannelOptions
            {
                LoggerFactory = LoggerFactory,
                HttpHandler   = http.handler
            });

            var client2 = TestClientFactory.Create(channel2, method);

            // Act
            var reply = await client2.UnaryCall(new HelloRequest { Name = "World" }).ResponseAsync.DefaultTimeout();

            // Assert
            Assert.AreEqual(HttpHandlerType.SocketsHttpHandler, channel1.HttpHandlerType);
            Assert.AreEqual(HttpHandlerType.SocketsHttpHandler, channel2.HttpHandlerType);
            Assert.AreEqual("World", reply.Message);
        }
        public async Task Should_Keep_Consumer_Open_After_Publish_Exception()
        {
            /* Setup */
            using (var client = TestClientFactory.CreateNormal())
            {
                var hasThrownTcs   = new TaskCompletionSource <bool>();
                var hasRecievedTcs = new TaskCompletionSource <bool>();
                client.SubscribeAsync <BasicMessage>((message, context) =>
                {
                    if (!hasThrownTcs.Task.IsCompleted)
                    {
                        Timer timer = null;
                        timer       = new Timer(state =>
                        {
                            timer?.Dispose();
                            hasThrownTcs.SetResult(true);
                        }, null, TimeSpan.FromMilliseconds(100), new TimeSpan(-1));
                        throw new Exception("Uh uh!");
                    }
                    else
                    {
                        hasRecievedTcs.SetResult(true);
                    }
                    return(Task.FromResult(true));
                });

                /* Test */
                client.PublishAsync(new BasicMessage());
                await hasThrownTcs.Task;
                client.PublishAsync(new BasicMessage());
                await hasRecievedTcs.Task;

                /* Assert */
                Assert.True(true);
            }
        }
        public async Task Should_Throw_Publish_Confirm_Exception_If_Server_Doesnt_Respond_Within_Time_Limit()
        {
            /* Setup */
            var publisher = TestClientFactory.CreateNormal(ioc => ioc.AddSingleton(p =>
            {
                var config = RawRabbitConfiguration.Local;
                config.PublishConfirmTimeout = TimeSpan.FromTicks(1);
                return(config);
            }));

            using (publisher)
            {
                /* Test */
                /* Assert */
                try
                {
                    await publisher.PublishAsync <BasicMessage>();
                }
                catch (PublishConfirmException)
                {
                    Assert.True(true);
                }
            }
        }
Esempio n. 21
0
        public async Task Should_Forward_Context_On_Rpc()
        {
            /* Setup */
            using (var requester = TestClientFactory.CreateNormal())
                using (var firstResponder = TestClientFactory.CreateNormal())
                    using (var secondResponder = TestClientFactory.CreateNormal())
                    {
                        var            tcs           = new TaskCompletionSource <bool>();
                        MessageContext firstContext  = null;
                        MessageContext secondContext = null;

                        firstResponder.RespondAsync <FirstRequest, FirstResponse>(async(req, c) =>
                        {
                            firstContext = c;
                            var resp     = await firstResponder.RequestAsync <SecondRequest, SecondResponse>(new SecondRequest(), c.GlobalRequestId);
                            return(new FirstResponse {
                                Infered = resp.Source
                            });
                        });
                        secondResponder.RespondAsync <SecondRequest, SecondResponse>((req, c) =>
                        {
                            secondContext = c;
                            tcs.SetResult(true);
                            return(Task.FromResult(new SecondResponse {
                                Source = Guid.NewGuid()
                            }));
                        });

                        /* Test */
                        requester.RequestAsync <FirstRequest, FirstResponse>();
                        await tcs.Task;

                        /* Assert */
                        Assert.Equal(firstContext.GlobalRequestId, secondContext.GlobalRequestId);
                    }
        }
Esempio n. 22
0
        public async Task UnaryMethod_DeadlineExceededCall_PollingCountersUpdatedCorrectly()
        {
            var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously);

            // Ignore errors
            SetExpectedErrorsFilter(writeContext =>
            {
                return(true);
            });

            async Task <HelloReply> UnaryDeadlineExceeded(HelloRequest request, ServerCallContext context)
            {
                await PollAssert(() => context.Status.StatusCode == StatusCode.DeadlineExceeded).DefaultTimeout();

                tcs.TrySetResult(true);

                return(new HelloReply());
            }

            // Arrange
            var clientEventListener = CreateEnableListener(Grpc.Net.Client.Internal.GrpcEventSource.Log);
            var serverEventListener = CreateEnableListener(Grpc.AspNetCore.Server.Internal.GrpcEventSource.Log);

            // Act - Start call
            var method = Fixture.DynamicGrpc.AddUnaryMethod <HelloRequest, HelloReply>(UnaryDeadlineExceeded);

            var channel = CreateChannel();

            channel.DisableClientDeadlineTimer = true;

            var client = TestClientFactory.Create(Channel, method);

            var call = client.UnaryCall(new HelloRequest(), new CallOptions(deadline: DateTime.UtcNow.AddMilliseconds(500)));

            // Assert - Call in progress
            await AssertCounters(serverEventListener, new Dictionary <string, long>
            {
                ["current-calls"]           = 1,
                ["calls-failed"]            = 0,
                ["calls-deadline-exceeded"] = 0,
            }).DefaultTimeout();
            await AssertCounters(clientEventListener, new Dictionary <string, long>
            {
                ["current-calls"]           = 1,
                ["calls-failed"]            = 0,
                ["calls-deadline-exceeded"] = 0,
            }).DefaultTimeout();

            // Act - Wait for call to deadline on server
            await tcs.Task.DefaultTimeout();

            // Assert - Call complete
            await AssertCounters(serverEventListener, new Dictionary <string, long>
            {
                ["current-calls"]           = 0,
                ["calls-failed"]            = 1,
                ["calls-deadline-exceeded"] = 1,
            }).DefaultTimeout();
            await AssertCounters(clientEventListener, new Dictionary <string, long>
            {
                ["current-calls"]           = 0,
                ["calls-failed"]            = 1,
                ["calls-deadline-exceeded"] = 1,
            }).DefaultTimeout();
        }
Esempio n. 23
0
        public async Task DuplexStreamingMethod_Success_PollingCountersUpdatedCorrectly()
        {
            async Task DuplexStreamingMethod(IAsyncStreamReader <HelloRequest> requestStream, IServerStreamWriter <HelloReply> responseStream, ServerCallContext context)
            {
                while (await requestStream.MoveNext().DefaultTimeout())
                {
                }

                await responseStream.WriteAsync(new HelloReply { Message = "Message 1" }).DefaultTimeout();

                await responseStream.WriteAsync(new HelloReply { Message = "Message 2" }).DefaultTimeout();
            }

            // Arrange
            var clientEventListener = CreateEnableListener(Grpc.Net.Client.Internal.GrpcEventSource.Log);
            var serverEventListener = CreateEnableListener(Grpc.AspNetCore.Server.Internal.GrpcEventSource.Log);

            // Act - Start call
            var method = Fixture.DynamicGrpc.AddDuplexStreamingMethod <HelloRequest, HelloReply>(DuplexStreamingMethod);

            var client = TestClientFactory.Create(Channel, method);

            var call = client.DuplexStreamingCall();

            // Assert - Call in progress
            await AssertCounters(serverEventListener, new Dictionary <string, long>
            {
                ["current-calls"]     = 1,
                ["messages-sent"]     = 0,
                ["messages-received"] = 0,
            }).DefaultTimeout();
            await AssertCounters(clientEventListener, new Dictionary <string, long>
            {
                ["current-calls"]     = 1,
                ["messages-sent"]     = 0,
                ["messages-received"] = 0,
            }).DefaultTimeout();

            await call.RequestStream.WriteAsync(new HelloRequest { Name = "Name 1" }).DefaultTimeout();

            await call.RequestStream.WriteAsync(new HelloRequest { Name = "Name 2" }).DefaultTimeout();

            await call.RequestStream.CompleteAsync().DefaultTimeout();

            while (await call.ResponseStream.MoveNext().DefaultTimeout())
            {
            }

            // Assert - Call complete
            await AssertCounters(serverEventListener, new Dictionary <string, long>
            {
                ["current-calls"]     = 0,
                ["messages-sent"]     = 2,
                ["messages-received"] = 2,
            }).DefaultTimeout();
            await AssertCounters(clientEventListener, new Dictionary <string, long>
            {
                ["current-calls"]     = 0,
                ["messages-sent"]     = 2,
                ["messages-received"] = 2,
            }).DefaultTimeout();
        }
Esempio n. 24
0
        public async Task Duplex_ManyParallelRequests_MessageRoundTripped()
        {
            const string ImportantMessage =
                @"       _____  _____   _____ 
       |  __ \|  __ \ / ____|
   __ _| |__) | |__) | |     
  / _` |  _  /|  ___/| |     
 | (_| | | \ \| |    | |____ 
  \__, |_|  \_\_|     \_____|
   __/ |                     
  |___/                      
  _                          
 (_)                         
  _ ___                      
 | / __|                     
 | \__ \          _          
 |_|___/         | |         
   ___ ___   ___ | |         
  / __/ _ \ / _ \| |         
 | (_| (_) | (_) | |         
  \___\___/ \___/|_|         
                             
                             ";

            var attempts          = 100;
            var allUploads        = new List <string>();
            var allCompletedTasks = new List <Task>();
            var tcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);

            async Task MessageUpload(
                IAsyncStreamReader <StringValue> requestStream,
                IServerStreamWriter <StringValue> responseStream,
                ServerCallContext context)
            {
                // Receive chunks
                var chunks = new List <string>();

                await foreach (var chunk in requestStream.ReadAllAsync())
                {
                    chunks.Add(chunk.Value);
                }

                Task completeTask;

                lock (allUploads)
                {
                    allUploads.Add(string.Join(Environment.NewLine, chunks));
                    if (allUploads.Count < attempts)
                    {
                        // Check that unused calls are canceled.
                        completeTask = Task.Run(async() =>
                        {
                            await tcs.Task;

                            var cancellationTcs = new TaskCompletionSource <bool>();
                            context.CancellationToken.Register(s => ((TaskCompletionSource <bool>)s !).SetResult(true), cancellationTcs);
                            await cancellationTcs.Task;
                        });
                    }
                    else
                    {
                        // Write response in used call.
                        completeTask = Task.Run(async() =>
                        {
                            // Write chunks
                            foreach (var chunk in chunks)
                            {
                                await responseStream.WriteAsync(new StringValue
                                {
                                    Value = chunk
                                });
                            }
                        });
                    }
                }

                await completeTask;
            }

            var method = Fixture.DynamicGrpc.AddDuplexStreamingMethod <StringValue, StringValue>(MessageUpload);

            var channel = CreateChannel(serviceConfig: ServiceConfigHelpers.CreateHedgingServiceConfig(maxAttempts: 100, hedgingDelay: TimeSpan.Zero), maxRetryAttempts: 100);

            var client = TestClientFactory.Create(channel, method);

            using var call = client.DuplexStreamingCall();

            var lines = ImportantMessage.Split(Environment.NewLine);

            for (var i = 0; i < lines.Length; i++)
            {
                await call.RequestStream.WriteAsync(new StringValue { Value = lines[i] }).DefaultTimeout();

                await Task.Delay(TimeSpan.FromSeconds(0.01)).DefaultTimeout();
            }
            await call.RequestStream.CompleteAsync().DefaultTimeout();

            await TestHelpers.AssertIsTrueRetryAsync(() => allUploads.Count == 100, "Wait for all calls to reach server.").DefaultTimeout();

            tcs.SetResult(null);

            var receivedLines = new List <string>();

            await foreach (var line in call.ResponseStream.ReadAllAsync().DefaultTimeout())
            {
                receivedLines.Add(line.Value);
            }

            Assert.AreEqual(ImportantMessage, string.Join(Environment.NewLine, receivedLines));

            foreach (var upload in allUploads)
            {
                Assert.AreEqual(ImportantMessage, upload);
            }

            await Task.WhenAll(allCompletedTasks).DefaultTimeout();
        }
        public async Task UnaryCall_MultipleCalls_RoundRobin()
        {
            // Ignore errors
            SetExpectedErrorsFilter(writeContext =>
            {
                return(true);
            });

            SyncPoint?syncPoint = null;
            string?   host      = null;

            async Task <HelloReply> UnaryMethod(HelloRequest request, ServerCallContext context)
            {
                host = context.Host;
                if (syncPoint != null)
                {
                    await syncPoint.WaitToContinue();
                }

                return(new HelloReply {
                    Message = request.Name
                });
            }

            // Arrange
            using var endpoint1 = BalancerHelpers.CreateGrpcEndpoint <HelloRequest, HelloReply>(50051, UnaryMethod, nameof(UnaryMethod));
            using var endpoint2 = BalancerHelpers.CreateGrpcEndpoint <HelloRequest, HelloReply>(50052, UnaryMethod, nameof(UnaryMethod));

            var channel = await BalancerHelpers.CreateChannel(LoggerFactory, new LoadBalancingConfig("least_used"), new[] { endpoint1.Address, endpoint2.Address }, connect : true);

            await BalancerHelpers.WaitForSubchannelsToBeReadyAsync(
                Logger,
                channel,
                expectedCount : 2,
                getPickerSubchannels : picker => ((LeastUsedPicker?)picker)?._subchannels.ToArray() ?? Array.Empty <Subchannel>()).DefaultTimeout();

            var client = TestClientFactory.Create(channel, endpoint1.Method);

            // Act
            var reply = await client.UnaryCall(new HelloRequest { Name = "Balancer" }).ResponseAsync.DefaultTimeout();

            // Assert
            Assert.AreEqual("Balancer", reply.Message);
            Assert.AreEqual("127.0.0.1:50051", host);

            // Act
            reply = await client.UnaryCall(new HelloRequest { Name = "Balancer" }).ResponseAsync.DefaultTimeout();

            // Assert
            Assert.AreEqual("Balancer", reply.Message);
            Assert.AreEqual("127.0.0.1:50051", host);

            // Act
            var sp1          = syncPoint = new SyncPoint(runContinuationsAsynchronously: true);
            var pendingCall1 = client.UnaryCall(new HelloRequest {
                Name = "Balancer"
            });
            // Assert
            await syncPoint.WaitForSyncPoint().DefaultTimeout();

            Assert.AreEqual("127.0.0.1:50051", host);

            // Act
            var sp2          = syncPoint = new SyncPoint(runContinuationsAsynchronously: true);
            var pendingCall2 = client.UnaryCall(new HelloRequest {
                Name = "Balancer"
            });
            // Assert
            await syncPoint.WaitForSyncPoint().DefaultTimeout();

            Assert.AreEqual("127.0.0.1:50052", host);

            // Act
            var sp3          = syncPoint = new SyncPoint(runContinuationsAsynchronously: true);
            var pendingCall3 = client.UnaryCall(new HelloRequest {
                Name = "Balancer"
            });
            // Assert
            await syncPoint.WaitForSyncPoint().DefaultTimeout();

            Assert.AreEqual("127.0.0.1:50051", host);

            sp1.Continue();
            sp2.Continue();
            sp3.Continue();
        }
Esempio n. 26
0
        private async Task RunConcurrentStreams(bool writeResponseHeaders)
        {
            SetExpectedErrorsFilter(writeContext =>
            {
                return(true);
            });

            var streamCount   = 210;
            var count         = 0;
            var tcs           = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);
            var connectionIds = new List <string>();
            var l             = new object();

            async Task <HelloReply> UnaryThrowError(HelloRequest request, ServerCallContext context)
            {
                lock (l)
                {
                    count++;

                    var connectionId = context.GetHttpContext().Connection.Id;
                    if (!connectionIds.Contains(connectionId))
                    {
                        connectionIds.Add(connectionId);
                    }
                }

                Logger.LogInformation($"Received message '{request.Name}'");

                if (writeResponseHeaders)
                {
                    await context.WriteResponseHeadersAsync(new Metadata());
                }

                if (count == streamCount)
                {
                    tcs.SetResult(null);
                }

                await tcs.Task;

                return(new HelloReply {
                    Message = request.Name
                });
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddUnaryMethod <HelloRequest, HelloReply>(UnaryThrowError);

            var channel = GrpcChannel.ForAddress(Fixture.GetUrl(TestServerEndpointName.Http2), new GrpcChannelOptions
            {
                LoggerFactory = LoggerFactory
            });

            var client = TestClientFactory.Create(channel, method);

            var calls = new AsyncUnaryCall <HelloReply> [streamCount];

            try
            {
                // Act
                for (var i = 0; i < calls.Length; i++)
                {
                    var call = client.UnaryCall(new HelloRequest {
                        Name = (i + 1).ToString()
                    });
                    calls[i] = call;

                    if (writeResponseHeaders)
                    {
                        await call.ResponseHeadersAsync.DefaultTimeout();
                    }
                }

                await Task.WhenAll(calls.Select(c => c.ResponseHeadersAsync)).DefaultTimeout();

                // Assert
                Assert.AreEqual(3, connectionIds.Count);
            }
            catch (Exception ex)
            {
                throw new Exception($"Received {count} of {streamCount} on the server. Connection Ids: {string.Join(", ", connectionIds)}", ex);
            }
            finally
            {
                for (var i = 0; i < calls.Length; i++)
                {
                    calls[i].Dispose();
                }
            }
        }
Esempio n. 27
0
        public async Task ServerStreaming_CancellationOnClientWithoutResponseHeaders_CancellationSentToServer()
        {
            var syncPoint         = new SyncPoint();
            var serverCompleteTcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);

            async Task ServerStreamingCall(DataMessage request, IServerStreamWriter <DataMessage> streamWriter, ServerCallContext context)
            {
                await syncPoint.WaitToContinue().DefaultTimeout();

                // Wait until the client cancels
                while (!context.CancellationToken.IsCancellationRequested)
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(10));
                }

                serverCompleteTcs.TrySetResult(null);
            }

            // Arrange
            SetExpectedErrorsFilter(writeContext =>
            {
                // Kestrel cancellation error message
                if (writeContext.Exception is IOException &&
                    writeContext.Exception.Message == "The client reset the request stream.")
                {
                    return(true);
                }

                if (writeContext.LoggerName == "Grpc.Net.Client.Internal.GrpcCall" &&
                    writeContext.EventId.Name == "GrpcStatusError" &&
                    writeContext.Message == "Call failed with gRPC error status. Status code: 'Cancelled', Message: 'Call canceled by the client.'.")
                {
                    return(true);
                }

                if (writeContext.LoggerName == "Grpc.Net.Client.Internal.GrpcCall" &&
                    writeContext.EventId.Name == "ErrorStartingCall" &&
                    writeContext.Message == "Error starting gRPC call.")
                {
                    return(true);
                }

                // Ignore all logging related errors for now
                return(false);
            });

            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <DataMessage, DataMessage>(ServerStreamingCall);

            var channel = CreateChannel();
            var cts     = new CancellationTokenSource();

            var client = TestClientFactory.Create(channel, method);

            // Act
            var call = client.ServerStreamingCall(new DataMessage(), new CallOptions(cancellationToken: cts.Token));
            await syncPoint.WaitForSyncPoint();

            syncPoint.Continue();

            // Assert
            var moveNextTask = call.ResponseStream.MoveNext(CancellationToken.None);

            cts.Cancel();

            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => moveNextTask).DefaultTimeout();

            Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode);

            await serverCompleteTcs.Task.DefaultTimeout();
        }
Esempio n. 28
0
        public async Task SendValidRequest_ClientAbort_ClientThrowsCancelledException()
        {
            var serverAbortedTcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);

            async Task ServerStreamingEcho(ServerStreamingEchoRequest request, IServerStreamWriter <ServerStreamingEchoResponse> responseStream, ServerCallContext context)
            {
                Logger.LogInformation("Server call started");

                var httpContext = context.GetHttpContext();

                httpContext.RequestAborted.Register(() => serverAbortedTcs.SetResult(null));

                for (var i = 0; i < request.MessageCount; i++)
                {
                    try
                    {
                        Logger.LogInformation($"Server writing message {i}");
                        await responseStream.WriteAsync(new ServerStreamingEchoResponse
                        {
                            Message = request.Message
                        });

                        await Task.Delay(request.MessageInterval.ToTimeSpan(), context.CancellationToken);
                    }
                    catch (OperationCanceledException)
                    {
                        return;
                    }
                }
            }

            // Arrage
            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <ServerStreamingEchoRequest, ServerStreamingEchoResponse>(ServerStreamingEcho);

            var httpClient = CreateGrpcWebClient();
            var channel    = GrpcChannel.ForAddress(httpClient.BaseAddress !, new GrpcChannelOptions
            {
                HttpClient    = httpClient,
                LoggerFactory = LoggerFactory
            });

            var cts = new CancellationTokenSource();

            var client = TestClientFactory.Create(channel, method);

            // Act
            var call = client.ServerStreamingCall(new ServerStreamingEchoRequest
            {
                Message         = "test",
                MessageCount    = 2,
                MessageInterval = TimeSpan.FromMilliseconds(100).ToDuration()
            }, new CallOptions(cancellationToken: cts.Token));

            // Assert
            Assert.IsTrue(await call.ResponseStream.MoveNext(CancellationToken.None).DefaultTimeout());
            Assert.AreEqual("test", call.ResponseStream.Current.Message);

            cts.Cancel();

            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseStream.MoveNext(CancellationToken.None)).DefaultTimeout();

            Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode);
            Assert.AreEqual("Call canceled by the client.", ex.Status.Detail);

            Assert.AreEqual(StatusCode.Cancelled, call.GetStatus().StatusCode);

            // It is possible get into a situation where the response stream finishes slightly before the call.
            // Small delay to ensure call logging is complete.
            await Task.Delay(50);

            AssertHasLog(LogLevel.Information, "GrpcStatusError", "Call failed with gRPC error status. Status code: 'Cancelled', Message: 'Call canceled by the client.'.");

            // HTTP/1.1 doesn't appear to send the cancellation to the server.
            // This might be because the server has finished reading the response body
            // and doesn't have a way to get the notification.
            if (EndpointName != TestServerEndpointName.Http1)
            {
                // Verify the abort reached the server.
                await serverAbortedTcs.Task.DefaultTimeout();
            }
        }
 public void SendMessageAsyncPassesOnRemoteException()
 {
     var action = "DoSomething";
     var request = new ServerRequest
     {
         ServerName = "TestServer"
     };
     var url = "http://somewhere/";
     var errorMessage = "Oops, an error happened";
     var factory = new TestClientFactory((u, a, d) =>
     {
         throw new CruiseControlException(errorMessage);
     });
     var connection = new HttpConnection(new Uri(url), factory);
     var completed = false;
     connection.SendMessageCompleted += (o, e) =>
     {
         completed = true;
         Assert.IsFalse(e.Cancelled);
         Assert.IsNotNull(e.Error);
         Assert.AreEqual(errorMessage, e.Error.Message);
         Assert.IsNull(e.Response);
     };
     connection.SendMessageAsync(action, request);
     Assert.IsTrue(completed);
 }
 public void SendMessageAsyncCanBeCancelled()
 {
     var action = "DoSomething";
     var request = new ServerRequest
     {
         ServerName = "TestServer"
     };
     var url = "http://nowhere";
     HttpConnection connection = null;
     var factory = new TestClientFactory((u, a, d) =>
     {
         connection.CancelAsync();
         return new byte[0];
     });
     connection = new HttpConnection(new Uri(url), factory);
     var completed = false;
     connection.SendMessageCompleted += (o, e) =>
     {
         completed = true;
         Assert.IsTrue(e.Cancelled);
         Assert.IsNull(e.Error);
         Assert.IsNull(e.Response);
     };
     connection.SendMessageAsync(action, request);
     Assert.IsTrue(completed);
 }
        public void InvokeApplicationBeforeItsConnection()
        {
            RunWith10SecTimeout(async() =>
            {
                Task <GreetingResponse> HandleAsync(GreetingRequest request, MethodCallContext context)
                {
                    return(Task.FromResult(new GreetingResponse {
                        Greeting = request.Name + "1"
                    }));
                }

                var brokerInstance      = _testBrokerFixture.SharedInstance;
                var createdServersCount = 0;
                var createdServerClient = new TaskCompletionSource <IClient>();
                var echoServerFactory   = new TestClientFactory(
                    (broker, id) =>
                {
                    var optionsBuilder = new ClientOptionsBuilder()
                                         .WithBrokerWorkingDir(brokerInstance.WorkingDir)
                                         .WithAppInstanceId(id)
                                         .WithApplicationId(EchoServerClient.Id)
                                         .WithDefaultConfiguration()
                                         .WithProvidedService(
                        GreetingService.Id,
                        x => x.WithUnaryMethod <GreetingRequest, GreetingResponse>(GreetingService.HelloMethodId,
                                                                                   HandleAsync));
                    var serverClient = ClientFactory.Instance.Create(optionsBuilder.Build());
                    createdServerClient.SetResult(serverClient);
                    createdServersCount++;
                    return(Task.FromResult(serverClient));
                });

                var appLauncher = RegisterDisposable(
                    new TestAppLauncher(
                        brokerInstance,
                        new Dictionary <string, TestClientFactory>
                {
                    { EchoServerClient.Id, echoServerFactory }
                },
                        false
                        )
                    );
                await appLauncher.StartAsync();

                var client1 = CreateClient <EchoClient>();
                await client1.ConnectAsync();

                var client2 = CreateClient <EchoClient>();
                await client2.ConnectAsync();

                var helloTask = client1.GreetingService.Hello(new GreetingRequest {
                    Name = "Test1"
                }).ResponseAsync;
                var callUnconnectedServerTask = createdServerClient.Task.ContinueWith(async task =>
                {
                    var serverClient = task.Result;
                    await Task.Delay(TimeSpan.FromSeconds(1));
                    var providedMethodReference = ProvidedMethodReference.CreateWithAppInstanceId(GreetingService.Id,
                                                                                                  GreetingService.HelloMethodId, EchoServerClient.Id, serverClient.ApplicationInstanceId);
                    var methodCallDescriptor = new MethodCallDescriptor(providedMethodReference);
                    await client2.CallInvoker.CallUnary <GreetingRequest, GreetingResponse>(methodCallDescriptor,
                                                                                            new GreetingRequest()
                    {
                        Name = "Test2"
                    });
                }).Unwrap();

                var connectedServerAfterDelayTask = createdServerClient.Task.ContinueWith(async task =>
                {
                    var serverClient = task.Result;

                    await Task.Delay(TimeSpan.FromSeconds(3));

                    serverClient.ConnectionId.ShouldBe(UniqueId.Empty);
                    var onlineConnectionsResponse =
                        await client1.AppLifecycleService.GetConnections(new GetConnectionsRequest
                    {
                        AppInstanceId = serverClient.ApplicationInstanceId
                    });
                    onlineConnectionsResponse.Connections.Count.ShouldBe(0);

                    await serverClient.ConnectAsync();
                }).Unwrap();

                await Task.WhenAll(helloTask, callUnconnectedServerTask, connectedServerAfterDelayTask);

                createdServersCount.ShouldBe(1);
            });
        }
Esempio n. 32
0
        public async Task ServerStreaming_ThrowErrorWithTrailers_TrailersReturnedToClient()
        {
            async Task ServerStreamingWithTrailers(DataMessage request, IServerStreamWriter <DataMessage> responseStream, ServerCallContext context)
            {
                await context.WriteResponseHeadersAsync(new Metadata
                {
                    { "Key", "Value1" },
                    { "Key", "Value2" },
                });

                await responseStream.WriteAsync(new DataMessage());

                await responseStream.WriteAsync(new DataMessage());

                await responseStream.WriteAsync(new DataMessage());

                await responseStream.WriteAsync(new DataMessage());

                context.ResponseTrailers.Add("Key", "ResponseTrailers");
                throw new RpcException(new Status(StatusCode.Aborted, "Message"), new Metadata
                {
                    { "Key", "RpcException" }
                });
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <DataMessage, DataMessage>(ServerStreamingWithTrailers);

            var channel = CreateChannel();

            var client = TestClientFactory.Create(channel, method);

            // Act
            var call = client.ServerStreamingCall(new DataMessage());

            // Assert
            var headers = await call.ResponseHeadersAsync.DefaultTimeout();

            var keyHeaders = headers.GetAll("key").ToList();

            Assert.AreEqual("key", keyHeaders[0].Key);
            Assert.AreEqual("Value1", keyHeaders[0].Value);
            Assert.AreEqual("key", keyHeaders[1].Key);
            Assert.AreEqual("Value2", keyHeaders[1].Value);

            Assert.IsTrue(await call.ResponseStream.MoveNext().DefaultTimeout());
            Assert.IsTrue(await call.ResponseStream.MoveNext().DefaultTimeout());
            Assert.IsTrue(await call.ResponseStream.MoveNext().DefaultTimeout());
            Assert.IsTrue(await call.ResponseStream.MoveNext().DefaultTimeout());

            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseStream.MoveNext()).DefaultTimeout();

            var trailers = call.GetTrailers();

            Assert.AreEqual(2, trailers.Count);
            Assert.AreEqual("key", trailers[0].Key);
            Assert.AreEqual("ResponseTrailers", trailers[0].Value);
            Assert.AreEqual("key", trailers[1].Key);
            Assert.AreEqual("RpcException", trailers[1].Value);

            Assert.AreEqual(StatusCode.Aborted, call.GetStatus().StatusCode);
            Assert.AreEqual("Message", call.GetStatus().Detail);
        }
Esempio n. 33
0
        public async Task ServerStreaming_CancellationOnClientAfterResponseHeadersReceived_CancellationSentToServer()
        {
            var serverCompleteTcs = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);

            async Task ServerStreamingCall(DataMessage request, IServerStreamWriter <DataMessage> streamWriter, ServerCallContext context)
            {
                // Write until the client cancels
                while (!context.CancellationToken.IsCancellationRequested)
                {
                    await streamWriter.WriteAsync(new DataMessage());

                    await Task.Delay(TimeSpan.FromMilliseconds(10));
                }

                serverCompleteTcs.TrySetResult(null);
            }

            // Arrange
            SetExpectedErrorsFilter(writeContext =>
            {
                // Kestrel cancellation error message
                if (writeContext.Exception is IOException &&
                    writeContext.Exception.Message == "The client reset the request stream.")
                {
                    return(true);
                }

                // Cancellation happened after checking token but before writing message
                if (writeContext.LoggerName == "Grpc.AspNetCore.Server.ServerCallHandler" &&
                    writeContext.EventId.Name == "ErrorExecutingServiceMethod" &&
                    writeContext.Exception is InvalidOperationException &&
                    writeContext.Exception.Message == "Cannot write message after request is complete.")
                {
                    return(true);
                }

                if (writeContext.LoggerName == "Grpc.Net.Client.Internal.GrpcCall" &&
                    writeContext.EventId.Name == "GrpcStatusError" &&
                    writeContext.Message == "Call failed with gRPC error status. Status code: 'Cancelled', Message: 'Call canceled by the client.'.")
                {
                    return(true);
                }

                // Ignore all logging related errors for now
                return(false);
            });

            var method = Fixture.DynamicGrpc.AddServerStreamingMethod <DataMessage, DataMessage>(ServerStreamingCall);

            var channel = CreateChannel();
            var cts     = new CancellationTokenSource();

            var client = TestClientFactory.Create(channel, method);

            // Act
            var call = client.ServerStreamingCall(new DataMessage(), new CallOptions(cancellationToken: cts.Token));

            // Assert

            // 1. Lets read some messages
            Assert.IsTrue(await call.ResponseStream.MoveNext(CancellationToken.None).DefaultTimeout());
            Assert.IsTrue(await call.ResponseStream.MoveNext(CancellationToken.None).DefaultTimeout());

            // 2. Cancel the token that was passed to the gRPC call. This was given to HttpClient.SendAsync
            cts.Cancel();

            // 3. Read from the response stream. This will throw a cancellation exception locally
            var ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseStream.MoveNext(CancellationToken.None)).DefaultTimeout();

            Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode);

            // 4. Check that the cancellation was sent to the server. This will
            await serverCompleteTcs.Task.DefaultTimeout();
        }
Esempio n. 34
0
        private async Task RunConcurrentStreams(bool writeResponseHeaders)
        {
            var streamCount = 201;
            var count       = 0;
            var tcs         = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);

            async Task WaitForAllStreams(IAsyncStreamReader <DataMessage> requestStream, IServerStreamWriter <DataMessage> responseStream, ServerCallContext context)
            {
                Interlocked.Increment(ref count);

                if (writeResponseHeaders)
                {
                    await context.WriteResponseHeadersAsync(new Metadata());
                }

                if (count == streamCount)
                {
                    tcs.SetResult(null);
                }

                await tcs.Task;
            }

            // Arrange
            var method = Fixture.DynamicGrpc.AddDuplexStreamingMethod <DataMessage, DataMessage>(WaitForAllStreams);

            var channel = GrpcChannel.ForAddress(Fixture.GetUrl(TestServerEndpointName.Http2));

            var client = TestClientFactory.Create(channel, method);

            var calls = new AsyncDuplexStreamingCall <DataMessage, DataMessage> [streamCount];

            try
            {
                // Act
                for (var i = 0; i < calls.Length; i++)
                {
                    var call = client.DuplexStreamingCall();
                    calls[i] = call;

                    if (writeResponseHeaders)
                    {
                        await call.ResponseHeadersAsync.DefaultTimeout();
                    }
                }

                // Assert
                await Task.WhenAll(calls.Select(c => c.ResponseHeadersAsync)).DefaultTimeout();
            }
            catch (Exception ex)
            {
                throw new Exception($"Received {count} of {streamCount} on the server.", ex);
            }
            finally
            {
                for (var i = 0; i < calls.Length; i++)
                {
                    calls[i].Dispose();
                }
            }
        }