Exemple #1
0
 public ResultMessage <string> Logout()
 {
     _loginManager.Logout(LoginUser.TokenId);
     return(ResponseUtils.DataResult("登出成功"));
 }
Exemple #2
0
        public async Task AsyncUnaryCall_CompressMetadataSentWithRequest_RequestMessageCompressed(bool compressionDisabledOnOptions)
        {
            // Arrange
            HttpRequestMessage?httpRequestMessage = null;
            HelloRequest?      helloRequest       = null;
            bool?isRequestNotCompressed           = null;

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                httpRequestMessage = request;

                var requestData        = await request.Content !.ReadAsByteArrayAsync().DefaultTimeout();
                isRequestNotCompressed = requestData[0] == 0;

                helloRequest = await StreamSerializationHelper.ReadMessageAsync(
                    new MemoryStream(requestData),
                    ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                    "gzip",
                    maximumMessageSize: null,
                    GrpcProtocolConstants.DefaultCompressionProviders,
                    singleMessage: true,
                    CancellationToken.None);

                HelloReply reply = new HelloReply
                {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });

            var compressionProviders = GrpcProtocolConstants.DefaultCompressionProviders.Values.ToList();

            compressionProviders.Add(new TestCompressionProvider());

            var invoker = HttpClientCallInvokerFactory.Create(httpClient, configure: o => o.CompressionProviders = compressionProviders);

            var compressionMetadata = CreateClientCompressionMetadata("gzip");
            var callOptions         = new CallOptions(headers: compressionMetadata);

            if (compressionDisabledOnOptions)
            {
                callOptions = callOptions.WithWriteOptions(new WriteOptions(WriteFlags.NoCompress));
            }

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, callOptions, new HelloRequest
            {
                Name = "Hello"
            });

            // Assert
            var response = await call.ResponseAsync;

            Assert.IsNotNull(response);
            Assert.AreEqual("Hello world", response.Message);

            CompatibilityHelpers.Assert(httpRequestMessage != null);
            Assert.AreEqual("identity,gzip,test", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single());
            Assert.AreEqual("gzip", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageEncodingHeader).Single());
            Assert.AreEqual(false, httpRequestMessage.Headers.Contains(GrpcProtocolConstants.CompressionRequestAlgorithmHeader));

            CompatibilityHelpers.Assert(helloRequest != null);
            Assert.AreEqual("Hello", helloRequest.Name);

            Assert.AreEqual(compressionDisabledOnOptions, isRequestNotCompressed);
        }
Exemple #3
0
        public void DiagnosticListener_MakeCall_ActivityWritten()
        {
            // Arrange
            HttpRequestMessage? requestMessage  = null;
            HttpResponseMessage?responseMessage = null;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                requestMessage = request;

                var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout();
                responseMessage   = ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent, grpcStatusCode: StatusCode.Aborted);
                responseMessage.TrailingHeaders().Add(GrpcProtocolConstants.MessageTrailer, "value");
                return(responseMessage);
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            var result = new List <KeyValuePair <string, object?> >();

            var dataMessageMarshaller = new Marshaller <DataMessage>(m => m.ToByteArray(), data => DataMessage.Parser.ParseFrom(data));
            var dataMessageMethod     = ClientTestHelpers.GetServiceMethod <DataMessage, DataMessage>(
                MethodType.DuplexStreaming,
                dataMessageMarshaller,
                dataMessageMarshaller);

            // Act
            HttpRequestMessage? requestMessage1  = null;
            HttpResponseMessage?responseMessage1 = null;
            HttpRequestMessage? requestMessage2  = null;
            HttpResponseMessage?responseMessage2 = null;

            using (GrpcDiagnostics.DiagnosticListener.Subscribe(new ObserverToList <KeyValuePair <string, object?> >(result)))
            {
                var c1 = invoker.AsyncDuplexStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());
                c1.Dispose();

                requestMessage1  = requestMessage;
                responseMessage1 = responseMessage;

                var c2 = invoker.AsyncDuplexStreamingCall <DataMessage, DataMessage>(dataMessageMethod, string.Empty, new CallOptions());
                c2.Dispose();

                requestMessage2  = requestMessage;
                responseMessage2 = responseMessage;
            }

            // Assert
            Assert.AreEqual(4, result.Count);

            // First call
            Assert.AreEqual(GrpcDiagnostics.ActivityStartKey, result[0].Key);
            Assert.AreEqual(requestMessage1, GetValueFromAnonymousType <HttpRequestMessage>(result[0].Value !, "Request"));
            Assert.AreEqual(GrpcDiagnostics.ActivityStopKey, result[1].Key);
            Assert.AreEqual(requestMessage1, GetValueFromAnonymousType <HttpRequestMessage>(result[1].Value !, "Request"));
            Assert.AreEqual(responseMessage1, GetValueFromAnonymousType <HttpResponseMessage>(result[1].Value !, "Response"));

            // Second call
            Assert.AreEqual(GrpcDiagnostics.ActivityStartKey, result[2].Key);
            Assert.AreEqual(requestMessage2, GetValueFromAnonymousType <HttpRequestMessage>(result[2].Value !, "Request"));
            Assert.AreEqual(GrpcDiagnostics.ActivityStopKey, result[3].Key);
            Assert.AreEqual(requestMessage2, GetValueFromAnonymousType <HttpRequestMessage>(result[3].Value !, "Request"));
            Assert.AreEqual(responseMessage2, GetValueFromAnonymousType <HttpResponseMessage>(result[3].Value !, "Response"));

            // Check types are expected
            Assert.AreEqual(typeof(GrpcCall.ActivityStartData), result[0].Value !.GetType());
            Assert.AreEqual(typeof(GrpcCall.ActivityStopData), result[1].Value !.GetType());
            Assert.AreEqual(result[0].Value !.GetType(), result[2].Value !.GetType());
            Assert.AreEqual(result[1].Value !.GetType(), result[3].Value !.GetType());

            // Check values are unique for each call
            Assert.AreNotEqual(result[0].Value, result[2].Value);
            Assert.AreNotEqual(result[1].Value, result[3].Value);
        }
Exemple #4
0
    public TestHttpMessageHandler(ILoggerFactory loggerFactory, bool autoNegotiate = true, bool handleFirstPoll = true)
    {
        _logger = loggerFactory?.CreateLogger <TestHttpMessageHandler>() ?? NullLoggerFactory.Instance.CreateLogger <TestHttpMessageHandler>();

        if (autoNegotiate)
        {
            OnNegotiate((_, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent()));
        }

        if (handleFirstPoll)
        {
            var firstPoll = true;
            OnRequest(async(request, next, cancellationToken) =>
            {
                cancellationToken.ThrowIfCancellationRequested();
                if (ResponseUtils.IsLongPollRequest(request) && firstPoll)
                {
                    firstPoll = false;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
                }
                else
                {
                    return(await next());
                }
            });
        }
    }
Exemple #5
0
        public async Task CanReceiveDataEvenIfExceptionThrownSynchronouslyFromPreviousReceivedEvent()
        {
            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();

                var content = string.Empty;

                if (request.Method == HttpMethod.Get)
                {
                    content = "42";
                }

                return(IsNegotiateRequest(request)
                        ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse())
                        : ResponseUtils.CreateResponse(HttpStatusCode.OK, content));
            });

            var connection = new HttpConnection(new Uri("http://fakeuri.org/"), TransportType.LongPolling, loggerFactory: null, httpMessageHandler: mockHttpHandler.Object);

            try
            {
                var receiveTcs = new TaskCompletionSource <string>();

                var receivedRaised = false;
                connection.OnReceived((data) =>
                {
                    if (!receivedRaised)
                    {
                        receivedRaised = true;
                        throw new InvalidOperationException();
                    }

                    receiveTcs.TrySetResult(Encoding.UTF8.GetString(data));
                    return(Task.CompletedTask);
                });

                _ = connection.Closed.ContinueWith(task =>
                {
                    if (task.Exception != null)
                    {
                        receiveTcs.TrySetException(task.Exception);
                    }
                    else
                    {
                        receiveTcs.TrySetCanceled();
                    }
                    return(Task.CompletedTask);
                });

                await connection.StartAsync();

                Assert.Equal("42", await receiveTcs.Task.OrTimeout());
            }
            finally
            {
                await connection.DisposeAsync();
            }
        }
 public Task ConnectionCannotBeStartedIfNoTransportProvidedByServer()
 {
     return(RunInvalidNegotiateResponseTest <NoTransportSupportedException>(ResponseUtils.CreateNegotiationContent(transportTypes: HttpTransportType.None), "None of the transports supported by the client are supported by the server."));
 }
Exemple #7
0
        public async Task AsyncClientStreamingCall_ManyParallelCalls_ReadDirectlyToRequestStream()
        {
            // Arrange
            var requestStreams = new List <WriterTestStream>();
            var attempts       = 100;

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                WriterTestStream writerTestStream;
                lock (requestStreams)
                {
                    Interlocked.Increment(ref callCount);
                    writerTestStream = new WriterTestStream();
                    requestStreams.Add(writerTestStream);
                }
                await request.Content !.CopyToAsync(writerTestStream);

                var reply = new HelloReply {
                    Message = "Hello world"
                };
                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig(maxAttempts: attempts);
            var invoker       = HttpClientCallInvokerFactory.Create(
                httpClient,
                serviceConfig: serviceConfig,
                configure: o => o.MaxRetryAttempts = attempts);

            // Act
            var call           = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());
            var writeAsyncTask = call.RequestStream.WriteAsync(new HelloRequest {
                Name = "World"
            });

            // Assert
            await TestHelpers.AssertIsTrueRetryAsync(() => callCount == attempts, "All calls made at once.");

            var firstMessages = await Task.WhenAll(requestStreams.Select(s => s.WaitForDataAsync())).DefaultTimeout();

            await writeAsyncTask.DefaultTimeout();

            foreach (var message in firstMessages)
            {
                Assert.IsTrue(firstMessages[0].Span.SequenceEqual(message.Span));
            }

            writeAsyncTask = call.RequestStream.WriteAsync(new HelloRequest {
                Name = "World 2"
            });
            var secondMessages = await Task.WhenAll(requestStreams.Select(s => s.WaitForDataAsync())).DefaultTimeout();

            await writeAsyncTask.DefaultTimeout();

            foreach (var message in secondMessages)
            {
                Assert.IsTrue(secondMessages[0].Span.SequenceEqual(message.Span));
            }

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

            var rs = await call.ResponseAsync.DefaultTimeout();

            Assert.AreEqual("Hello world", rs.Message);
            Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode);
        }
        public async Task HttpConnectionRetriesAccessTokenProviderWhenAuthFailsLongPolling()
        {
            var testHttpHandler      = new TestHttpMessageHandler(autoNegotiate: false);
            var requestsExecuted     = false;
            var accessTokenCallCount = 0;
            var pollCount            = 0;

            testHttpHandler.OnNegotiate((_, cancellationToken) =>
            {
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent()));
            });

            var startSendTcs     = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var longPollTcs      = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var messageFragments = new[] { "This ", "is ", "a ", "test" };

            testHttpHandler.OnLongPoll(async _ =>
            {
                // fail every other request
                if (pollCount % 2 == 0)
                {
                    pollCount++;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized));
                }
                if (pollCount / 2 >= messageFragments.Length)
                {
                    startSendTcs.SetResult();
                    await longPollTcs.Task;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
                }

                var resp = ResponseUtils.CreateResponse(HttpStatusCode.OK, messageFragments[pollCount / 2]);
                pollCount++;
                return(resp);
            });

            var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);

            testHttpHandler.OnRequest((request, next, token) =>
            {
                if (!requestsExecuted)
                {
                    requestsExecuted = true;
                    return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized)));
                }

                Assert.Equal("Bearer", request.Headers.Authorization.Scheme);

                Assert.Equal(accessTokenCallCount.ToString(CultureInfo.InvariantCulture), request.Headers.Authorization.Parameter);

                tcs.SetResult();

                return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK)));
            });

            Task <string> AccessTokenProvider()
            {
                accessTokenCallCount++;
                return(Task.FromResult(accessTokenCallCount.ToString(CultureInfo.InvariantCulture)));
            }

            await WithConnectionAsync(
                CreateConnection(testHttpHandler, transportType : HttpTransportType.LongPolling, accessTokenProvider : AccessTokenProvider),
                async (connection) =>
            {
                await connection.StartAsync().DefaultTimeout();
                var message = await connection.Transport.Input.ReadAtLeastAsync(14);
                Assert.Equal("This is a test", Encoding.UTF8.GetString(message.Buffer));
                await startSendTcs.Task;
                await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello world 1"));
                await tcs.Task;
                longPollTcs.SetResult();
            });

            // 1 negotiate + 4 (number of polls) + 1 for last poll + 1 for send
            Assert.Equal(7, accessTokenCallCount);
        }
        public async Task HttpConnectionRetriesAccessTokenProviderWhenAuthFailsServerSentEvents()
        {
            var testHttpHandler      = new TestHttpMessageHandler(autoNegotiate: false);
            var requestsExecuted     = false;
            var accessTokenCallCount = 0;

            testHttpHandler.OnNegotiate((_, cancellationToken) =>
            {
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent()));
            });

            var sendRequestExecuted = false;
            var sendFinishedTcs     = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);

            testHttpHandler.OnSocketSend((_, _) =>
            {
                if (!sendRequestExecuted)
                {
                    sendRequestExecuted = true;
                    return(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized));
                }
                sendFinishedTcs.SetResult();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });

            var tcs    = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
            var stream = new BlockingStream(tcs);

            testHttpHandler.OnRequest((request, next, token) =>
            {
                if (!requestsExecuted)
                {
                    requestsExecuted = true;
                    return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized)));
                }

                Assert.Equal("Bearer", request.Headers.Authorization.Scheme);

                Assert.Equal(accessTokenCallCount.ToString(CultureInfo.InvariantCulture), request.Headers.Authorization.Parameter);

                return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK, new StreamContent(stream))));
            });

            Task <string> AccessTokenProvider()
            {
                accessTokenCallCount++;
                return(Task.FromResult(accessTokenCallCount.ToString(CultureInfo.InvariantCulture)));
            }

            await WithConnectionAsync(
                CreateConnection(testHttpHandler, transportType : HttpTransportType.ServerSentEvents, accessTokenProvider : AccessTokenProvider),
                async (connection) =>
            {
                await connection.StartAsync().DefaultTimeout();
                await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello world 1"));
                await sendFinishedTcs.Task;
                tcs.TrySetResult();
                await connection.Transport.Input.ReadAllAsync();
            });

            // 1 negotiate + 1 retry stream request + 1 retry send
            Assert.Equal(3, accessTokenCallCount);
        }
        public async Task AsyncClientStreamingCall_Success_RequestContentSent()
        {
            // Arrange
            var requestContentTcs = new TaskCompletionSource <Task <Stream> >(TaskCreationOptions.RunContinuationsAsynchronously);

            PushStreamContent <HelloRequest, HelloReply>?content = null;

            var handler = TestHttpMessageHandler.Create(async request =>
            {
                content        = (PushStreamContent <HelloRequest, HelloReply>)request.Content !;
                var streamTask = content.ReadAsStreamAsync();
                requestContentTcs.SetResult(streamTask);

                // Wait for RequestStream.CompleteAsync()
                await streamTask;

                HelloReply reply = new HelloReply
                {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var invoker = HttpClientCallInvokerFactory.Create(handler, "http://localhost");

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());
            var requestContentTask = await requestContentTcs.Task.DefaultTimeout();

            // Assert
            Assert.IsNotNull(call);
            Assert.IsNotNull(content);

            var responseTask = call.ResponseAsync;

            Assert.IsFalse(responseTask.IsCompleted, "Response not returned until client stream is complete.");


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

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

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

            var requestContent = await requestContentTask.DefaultTimeout();

            var requestMessage = await StreamSerializationHelper.ReadMessageAsync(
                requestContent,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).DefaultTimeout();

            Assert.AreEqual("1", requestMessage !.Name);
            requestMessage = await StreamSerializationHelper.ReadMessageAsync(
                requestContent,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).DefaultTimeout();

            Assert.AreEqual("2", requestMessage !.Name);

            var responseMessage = await responseTask.DefaultTimeout();

            Assert.AreEqual("Hello world", responseMessage.Message);
        }
Exemple #11
0
        public async Task AsyncClientStreamingCall_CompressMetadataSentWithRequest_RequestMessageCompressed()
        {
            // Arrange
            HttpRequestMessage?httpRequestMessage = null;
            HelloRequest?      helloRequest1      = null;
            HelloRequest?      helloRequest2      = null;
            bool?isRequestNotCompressed1          = null;
            bool?isRequestNotCompressed2          = null;

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                httpRequestMessage = request;

                var requestData   = await request.Content.ReadAsByteArrayAsync();
                var requestStream = new MemoryStream(requestData);

                isRequestNotCompressed1 = requestData[0] == 0;
                helloRequest1           = await StreamExtensions.ReadMessageAsync(
                    requestStream,
                    NullLogger.Instance,
                    ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                    "gzip",
                    maximumMessageSize: null,
                    GrpcProtocolConstants.DefaultCompressionProviders,
                    singleMessage: false,
                    CancellationToken.None);

                isRequestNotCompressed2 = requestData[requestStream.Position] == 0;
                helloRequest2           = await StreamExtensions.ReadMessageAsync(
                    requestStream,
                    NullLogger.Instance,
                    ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                    "gzip",
                    maximumMessageSize: null,
                    GrpcProtocolConstants.DefaultCompressionProviders,
                    singleMessage: false,
                    CancellationToken.None);

                var reply = new HelloReply
                {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });

            var compressionProviders = GrpcProtocolConstants.DefaultCompressionProviders.Values.ToList();

            compressionProviders.Add(new TestCompressionProvider());

            var invoker = HttpClientCallInvokerFactory.Create(httpClient, configure: o => o.CompressionProviders = compressionProviders);

            var compressionMetadata = CreateClientCompressionMetadata("gzip");
            var callOptions         = new CallOptions(headers: compressionMetadata);

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, callOptions);

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

            call.RequestStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress);
            await call.RequestStream.WriteAsync(new HelloRequest
            {
                Name = "Hello Two"
            }).DefaultTimeout();

            await call.RequestStream.CompleteAsync();

            // Assert
            var response = await call.ResponseAsync.DefaultTimeout();

            Assert.IsNotNull(response);
            Assert.AreEqual("Hello world", response.Message);

            Debug.Assert(httpRequestMessage != null);
            Assert.AreEqual("identity,gzip,test", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageAcceptEncodingHeader).Single());
            Assert.AreEqual("gzip", httpRequestMessage.Headers.GetValues(GrpcProtocolConstants.MessageEncodingHeader).Single());
            Assert.AreEqual(false, httpRequestMessage.Headers.Contains(GrpcProtocolConstants.CompressionRequestAlgorithmHeader));

            Debug.Assert(helloRequest1 != null);
            Assert.AreEqual("Hello One", helloRequest1.Name);
            Debug.Assert(helloRequest2 != null);
            Assert.AreEqual("Hello Two", helloRequest2.Name);

            Assert.IsFalse(isRequestNotCompressed1);
            Assert.IsTrue(isRequestNotCompressed2);
        }
Exemple #12
0
        public async Task AsyncDuplexStreamingCall_MessagesStreamed_MessagesReceived()
        {
            // Arrange
            var streamContent = new SyncPointMemoryStream();

            PushStreamContent content = null;

            var httpClient = TestHelpers.CreateTestClient(async request =>
            {
                content = (PushStreamContent)request.Content;
                await content.PushComplete.DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, new StreamContent(streamContent)));
            });
            var invoker = new HttpClientCallInvoker(httpClient);

            // Act
            var call = invoker.AsyncDuplexStreamingCall <HelloRequest, HelloReply>(TestHelpers.ServiceMethod, null, new CallOptions());

            var requestStream  = call.RequestStream;
            var responseStream = call.ResponseStream;

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

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

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

            var requestContent = await content.ReadAsStreamAsync().DefaultTimeout();

            var requestMessage = await requestContent.ReadStreamedMessageAsync(TestHelpers.ServiceMethod.RequestMarshaller.Deserializer, CancellationToken.None).DefaultTimeout();

            Assert.AreEqual("1", requestMessage.Name);
            requestMessage = await requestContent.ReadStreamedMessageAsync(TestHelpers.ServiceMethod.RequestMarshaller.Deserializer, CancellationToken.None).DefaultTimeout();

            Assert.AreEqual("2", requestMessage.Name);

            Assert.IsNull(responseStream.Current);

            var moveNextTask1 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsFalse(moveNextTask1.IsCompleted);

            await streamContent.AddDataAndWait(await TestHelpers.GetResponseDataAsync(new HelloReply
            {
                Message = "Hello world 1"
            }).DefaultTimeout()).DefaultTimeout();

            Assert.IsTrue(await moveNextTask1.DefaultTimeout());
            Assert.IsNotNull(responseStream.Current);
            Assert.AreEqual("Hello world 1", responseStream.Current.Message);

            var moveNextTask2 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsFalse(moveNextTask2.IsCompleted);

            await streamContent.AddDataAndWait(await TestHelpers.GetResponseDataAsync(new HelloReply
            {
                Message = "Hello world 2"
            }).DefaultTimeout()).DefaultTimeout();

            Assert.IsTrue(await moveNextTask2.DefaultTimeout());
            Assert.IsNotNull(responseStream.Current);
            Assert.AreEqual("Hello world 2", responseStream.Current.Message);

            var moveNextTask3 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsFalse(moveNextTask3.IsCompleted);

            await streamContent.AddDataAndWait(Array.Empty <byte>()).DefaultTimeout();

            Assert.IsFalse(await moveNextTask3.DefaultTimeout());

            var moveNextTask4 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsTrue(moveNextTask4.IsCompleted);
            Assert.IsFalse(await moveNextTask3.DefaultTimeout());
        }
Exemple #13
0
        public async Task CreateClient_ServerCallContextAndUserCancellationToken_PropogatedDeadlineAndCancellation(Canceller canceller)
        {
            // Arrange
            var baseAddress = new Uri("http://localhost");
            var deadline    = DateTime.UtcNow.AddDays(1);
            var contextCts  = new CancellationTokenSource();
            var userCts     = new CancellationTokenSource();
            var tcs         = new TaskCompletionSource <object?>(TaskCreationOptions.RunContinuationsAsynchronously);

            CallOptions options = default;

            var handler = TestHttpMessageHandler.Create(async(r, token) =>
            {
                token.Register(() => tcs.SetCanceled());

                await tcs.Task;

                var streamContent = await ClientTestHelpers.CreateResponseContent(new HelloReply()).DefaultTimeout();
                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });

            var services = new ServiceCollection();

            services.AddOptions();
            services.AddSingleton(CreateHttpContextAccessorWithServerCallContext(deadline, contextCts.Token));
            services
            .AddGrpcClient <Greeter.GreeterClient>(o =>
            {
                o.Address = baseAddress;
            })
            .EnableCallContextPropagation()
            .AddInterceptor(() => new CallbackInterceptor(o => options = o))
            .ConfigurePrimaryHttpMessageHandler(() => handler);

            var serviceProvider = services.BuildServiceProvider(validateScopes: true);

            var clientFactory = CreateGrpcClientFactory(serviceProvider);
            var client        = clientFactory.CreateClient <Greeter.GreeterClient>(nameof(Greeter.GreeterClient));

            // Act
            using var call = client.SayHelloAsync(new HelloRequest(), cancellationToken: userCts.Token);
            var responseTask = call.ResponseAsync;

            // Assert
            Assert.AreEqual(deadline, options.Deadline);

            // CancellationToken passed to call is a linked cancellation token.
            // It's created from the context and user tokens.
            Assert.AreNotEqual(contextCts.Token, options.CancellationToken);
            Assert.AreNotEqual(userCts.Token, options.CancellationToken);
            Assert.AreNotEqual(CancellationToken.None, options.CancellationToken);

            Assert.IsFalse(responseTask.IsCompleted);

            // Either CTS should cancel call.
            switch (canceller)
            {
            case Canceller.Context:
                contextCts.Cancel();
                break;

            case Canceller.User:
                userCts.Cancel();
                break;
            }

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

            Assert.AreEqual(StatusCode.Cancelled, ex.StatusCode);
            ex = await ExceptionAssert.ThrowsAsync <RpcException>(() => call.ResponseHeadersAsync).DefaultTimeout();

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

            Assert.AreEqual(StatusCode.Cancelled, call.GetStatus().StatusCode);
            Assert.Throws <InvalidOperationException>(() => call.GetTrailers());
        }
        public async Task EventsAreNotRunningOnMainLoop()
        {
            var mockHttpHandler = new Mock <HttpMessageHandler>();

            mockHttpHandler.Protected()
            .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
            .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
            {
                await Task.Yield();
                return(IsNegotiateRequest(request)
                        ? ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationResponse())
                        : ResponseUtils.CreateResponse(HttpStatusCode.OK));
            });

            var mockTransport = new Mock <ITransport>();
            Channel <byte[], SendMessage> channel = null;

            mockTransport.Setup(t => t.StartAsync(It.IsAny <Uri>(), It.IsAny <Channel <byte[], SendMessage> >(), It.IsAny <TransferMode>(), It.IsAny <string>(), It.IsAny <IConnection>()))
            .Returns <Uri, Channel <byte[], SendMessage>, TransferMode, string, IConnection>((url, c, transferMode, connectionId, _) =>
            {
                channel = c;
                return(Task.CompletedTask);
            });
            mockTransport.Setup(t => t.StopAsync())
            .Returns(() =>
            {
                channel.Writer.TryComplete();
                return(Task.CompletedTask);
            });
            mockTransport.SetupGet(t => t.Mode).Returns(TransferMode.Text);

            var callbackInvokedTcs = new TaskCompletionSource <object>();
            var closedTcs          = new TaskCompletionSource <object>();

            var connection = new HttpConnection(new Uri("http://fakeuri.org/"), new TestTransportFactory(mockTransport.Object), loggerFactory: null,
                                                httpOptions: new HttpOptions {
                HttpMessageHandler = mockHttpHandler.Object
            });

            connection.OnReceived(_ =>
            {
                callbackInvokedTcs.SetResult(null);
                return(closedTcs.Task);
            });

            await connection.StartAsync();

            channel.Writer.TryWrite(Array.Empty <byte>());

            // Ensure that the Received callback has been called before attempting the second write
            await callbackInvokedTcs.Task.OrTimeout();

            channel.Writer.TryWrite(Array.Empty <byte>());

            // Ensure that SignalR isn't blocked by the receive callback
            Assert.False(channel.Reader.TryRead(out var message));

            closedTcs.SetResult(null);

            await connection.DisposeAsync();
        }
        public async Task NegotiateThatReturnsRedirectUrlDoesNotAddAnotherNegotiateVersionQueryString()
        {
            var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false);
            var negotiateCount  = 0;

            testHttpHandler.OnNegotiate((request, cancellationToken) =>
            {
                negotiateCount++;
                if (negotiateCount == 1)
                {
                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                        JsonConvert.SerializeObject(new
                    {
                        url = "https://another.domain.url/chat?negotiateVersion=1"
                    })));
                }
                else
                {
                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                        JsonConvert.SerializeObject(new
                    {
                        connectionId = "0rge0d00-0040-0030-0r00-000q00r00e00",
                        availableTransports = new object[]
                        {
                            new
                            {
                                transport = "LongPolling",
                                transferFormats = new[] { "Text" }
                            },
                        }
                    })));
                }
            });

            testHttpHandler.OnLongPoll((token) =>
            {
                var tcs = new TaskCompletionSource <HttpResponseMessage>(TaskCreationOptions.RunContinuationsAsynchronously);

                token.Register(() => tcs.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)));

                return(tcs.Task);
            });

            testHttpHandler.OnLongPollDelete((token) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted));

            using (var noErrorScope = new VerifyNoErrorsScope())
            {
                await WithConnectionAsync(
                    CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory),
                    async (connection) =>
                {
                    await connection.StartAsync().DefaultTimeout();
                });
            }

            Assert.Equal("http://fakeuri.org/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[0].RequestUri.ToString());
            Assert.Equal("https://another.domain.url/chat/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[1].RequestUri.ToString());
            Assert.Equal("https://another.domain.url/chat?negotiateVersion=1&id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[2].RequestUri.ToString());
            Assert.Equal("https://another.domain.url/chat?negotiateVersion=1&id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[3].RequestUri.ToString());
            Assert.Equal(5, testHttpHandler.ReceivedRequests.Count);
        }
        public async Task HttpConnectionSetsInherentKeepAliveFeature(HttpTransportType transportType, bool expectedValue)
        {
            using (StartVerifiableLog())
            {
                var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false);

                testHttpHandler.OnNegotiate((_, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent()));

                testHttpHandler.OnRequest((request, next, token) => Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)));

                await WithConnectionAsync(
                    CreateConnection(testHttpHandler, transportType : transportType, loggerFactory : LoggerFactory),
                    async (connection) =>
                {
                    await connection.StartAsync().DefaultTimeout();

                    var feature = connection.Features.Get <IConnectionInherentKeepAliveFeature>();
                    Assert.NotNull(feature);
                    Assert.Equal(expectedValue, feature.HasInherentKeepAlive);
                });
            }
        }
 public Task ConnectionCannotBeStartedIfNoCommonTransportsBetweenClientAndServer()
 {
     return(RunInvalidNegotiateResponseTest <AggregateException>(ResponseUtils.CreateNegotiationContent(transportTypes: HttpTransportType.ServerSentEvents),
                                                                 "Unable to connect to the server with any of the available transports. (ServerSentEvents failed: The transport is disabled by the client.)"));
 }
Exemple #18
0
        public async Task AsyncUnaryCall_SuccessAfterRetry_RequestContentSent()
        {
            // Arrange
            HttpContent?content = null;

            bool?  firstRequestPreviousAttemptsHeader       = null;
            string?secondRequestPreviousAttemptsHeaderValue = null;
            var    requestContent = new MemoryStream();

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callCount++;

                content = request.Content !;
                await content.CopyToAsync(requestContent);
                requestContent.Seek(0, SeekOrigin.Begin);

                if (callCount == 1)
                {
                    firstRequestPreviousAttemptsHeader = request.Headers.TryGetValues(GrpcProtocolConstants.RetryPreviousAttemptsHeader, out _);

                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
                }

                if (request.Headers.TryGetValues(GrpcProtocolConstants.RetryPreviousAttemptsHeader, out var retryAttemptCountValue))
                {
                    secondRequestPreviousAttemptsHeaderValue = retryAttemptCountValue.Single();
                }

                var reply = new HelloReply {
                    Message = "Hello world"
                };
                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent, customTrailers: new Dictionary <string, string>
                {
                    ["custom-trailer"] = "Value!"
                }));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions(), new HelloRequest {
                Name = "World"
            });

            // Assert
            Assert.AreEqual(2, callCount);
            Assert.AreEqual("Hello world", (await call.ResponseAsync.DefaultTimeout()).Message);
            Assert.AreEqual("1", (await call.ResponseHeadersAsync.DefaultTimeout()).GetValue(GrpcProtocolConstants.RetryPreviousAttemptsHeader));

            Assert.IsNotNull(content);

            var requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

            Assert.AreEqual("World", requestMessage !.Name);

            Assert.IsFalse(firstRequestPreviousAttemptsHeader);
            Assert.AreEqual("1", secondRequestPreviousAttemptsHeaderValue);

            var trailers = call.GetTrailers();

            Assert.AreEqual("Value!", trailers.GetValue("custom-trailer"));
        }
Exemple #19
0
        public async Task AsyncClientStreamingCall_SuccessAfterRetry_RequestContentSent(int hedgingDelayMS)
        {
            // Arrange
            var callLock       = new object();
            var requestContent = new MemoryStream();

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                var firstCall = false;
                lock (callLock)
                {
                    callCount++;
                    if (callCount == 1)
                    {
                        firstCall = true;
                    }
                }
                if (firstCall)
                {
                    await request.Content !.CopyToAsync(new MemoryStream());
                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
                }

                var content = (PushStreamContent <HelloRequest, HelloReply>)request.Content !;
                await content.PushComplete.DefaultTimeout();

                await request.Content !.CopyToAsync(requestContent);

                var reply = new HelloReply {
                    Message = "Hello world"
                };
                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var serviceConfig = ServiceConfigHelpers.CreateHedgingServiceConfig(maxAttempts: 2, hedgingDelay: TimeSpan.FromMilliseconds(hedgingDelayMS));
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.GetServiceMethod(MethodType.ClientStreaming), string.Empty, new CallOptions());

            // Assert
            Assert.IsNotNull(call);

            var responseTask = call.ResponseAsync;

            Assert.IsFalse(responseTask.IsCompleted, "Response not returned until client stream is complete.");


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

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

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

            var responseMessage = await responseTask.DefaultTimeout();

            Assert.AreEqual("Hello world", responseMessage.Message);

            requestContent.Seek(0, SeekOrigin.Begin);

            var requests = new List <HelloRequest>();

            while (true)
            {
                var requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

                if (requestMessage == null)
                {
                    break;
                }

                requests.Add(requestMessage);
            }

            Assert.AreEqual(2, requests.Count);
            Assert.AreEqual("1", requests[0].Name);
            Assert.AreEqual("2", requests[1].Name);
        }
Exemple #20
0
        public async Task AsyncClientStreamingCall_SuccessAfterRetry_RequestContentSent()
        {
            // Arrange
            var requestContent = new MemoryStream();

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                Interlocked.Increment(ref callCount);

                var currentContent = new MemoryStream();
                await request.Content !.CopyToAsync(currentContent);

                if (callCount == 1)
                {
                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
                }

                currentContent.Seek(0, SeekOrigin.Begin);
                await currentContent.CopyToAsync(requestContent);

                var reply = new HelloReply {
                    Message = "Hello world"
                };
                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.GetServiceMethod(MethodType.ClientStreaming), string.Empty, new CallOptions());

            // Assert
            Assert.IsNotNull(call);

            var responseTask = call.ResponseAsync;

            Assert.IsFalse(responseTask.IsCompleted, "Response not returned until client stream is complete.");

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

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

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

            var responseMessage = await responseTask.DefaultTimeout();

            Assert.AreEqual("Hello world", responseMessage.Message);

            requestContent.Seek(0, SeekOrigin.Begin);

            var requests = new List <HelloRequest>();

            while (true)
            {
                var requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

                if (requestMessage == null)
                {
                    break;
                }

                requests.Add(requestMessage);
            }

            Assert.AreEqual(2, requests.Count);
            Assert.AreEqual("1", requests[0].Name);
            Assert.AreEqual("2", requests[1].Name);

            call.Dispose();
        }
Exemple #21
0
    public async Task SSETransportStopsWithErrorIfSendingMessageFails()
    {
        bool ExpectedErrors(WriteContext writeContext)
        {
            return(writeContext.LoggerName == typeof(ServerSentEventsTransport).FullName &&
                   writeContext.EventId.Name == "ErrorSending");
        }

        var eventStreamTcs = new TaskCompletionSource();
        var readTcs        = new TaskCompletionSource <int>();

        var mockHttpHandler = new Mock <HttpMessageHandler>();

        mockHttpHandler.Protected()
        .Setup <Task <HttpResponseMessage> >("SendAsync", ItExpr.IsAny <HttpRequestMessage>(), ItExpr.IsAny <CancellationToken>())
        .Returns <HttpRequestMessage, CancellationToken>(async(request, cancellationToken) =>
        {
            await Task.Yield();

            if (request.Headers.Accept?.Contains(new MediaTypeWithQualityHeaderValue("text/event-stream")) == true)
            {
                // Receive loop started - allow stopping the transport
                eventStreamTcs.SetResult();

                // returns unfinished task to block pipelines
                var mockStream = new Mock <Stream>();
                mockStream
                .Setup(s => s.ReadAsync(It.IsAny <Memory <byte> >(), It.IsAny <CancellationToken>()))
                .Returns <Memory <byte>, CancellationToken>(async(data, ct) =>
                {
                    using (ct.Register(() => readTcs.TrySetCanceled()))
                    {
                        return(await readTcs.Task);
                    }
                });
                mockStream.Setup(s => s.CanRead).Returns(true);
                return(new HttpResponseMessage {
                    Content = new StreamContent(mockStream.Object)
                });
            }

            return(ResponseUtils.CreateResponse(System.Net.HttpStatusCode.InternalServerError));
        });

        using (var httpClient = new HttpClient(mockHttpHandler.Object))
            using (StartVerifiableLog(expectedErrorsFilter: ExpectedErrors))
            {
                var sseTransport = new ServerSentEventsTransport(httpClient, loggerFactory: LoggerFactory);

                await sseTransport.StartAsync(
                    new Uri("http://fakeuri.org"), TransferFormat.Text).DefaultTimeout();

                await eventStreamTcs.Task;

                await sseTransport.Output.WriteAsync(new byte[] { 0x42 });

                var exception = await Assert.ThrowsAsync <HttpRequestException>(() => sseTransport.Input.ReadAllAsync().DefaultTimeout());

                Assert.Contains("500", exception.Message);

                // Errors are only communicated through the pipe
                await sseTransport.Running.DefaultTimeout();
            }
    }
Exemple #22
0
        public async Task AsyncDuplexStreamingCall_SuccessAfterRetry_RequestContentSent()
        {
            // Arrange
            var requestContent = new MemoryStream();
            var syncPoint      = new SyncPoint(runContinuationsAsynchronously: true);

            var callCount  = 0;
            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                callCount++;
                var content = (PushStreamContent <HelloRequest, HelloReply>)request.Content !;

                if (callCount == 1)
                {
                    _ = content.CopyToAsync(new MemoryStream());

                    await syncPoint.WaitForSyncPoint();

                    return(ResponseUtils.CreateHeadersOnlyResponse(HttpStatusCode.OK, StatusCode.Unavailable));
                }

                syncPoint.Continue();

                await content.PushComplete.DefaultTimeout();
                await content.CopyToAsync(requestContent);
                requestContent.Seek(0, SeekOrigin.Begin);

                var reply = new HelloReply {
                    Message = "Hello world"
                };
                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var serviceConfig = ServiceConfigHelpers.CreateRetryServiceConfig();
            var invoker       = HttpClientCallInvokerFactory.Create(httpClient, serviceConfig: serviceConfig);

            // Act
            var call         = invoker.AsyncDuplexStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.GetServiceMethod(MethodType.DuplexStreaming), string.Empty, new CallOptions());
            var moveNextTask = call.ResponseStream.MoveNext(CancellationToken.None);

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

            // Wait until the first call has failed and the second is on the server
            await syncPoint.WaitToContinue().DefaultTimeout();

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

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

            // Assert
            Assert.IsTrue(await moveNextTask.DefaultTimeout());
            Assert.AreEqual("Hello world", call.ResponseStream.Current.Message);

            var requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

            Assert.AreEqual("1", requestMessage !.Name);
            requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

            Assert.AreEqual("2", requestMessage !.Name);
            requestMessage = await ReadRequestMessage(requestContent).DefaultTimeout();

            Assert.IsNull(requestMessage);
        }
        public async Task AsyncDuplexStreamingCall_MessagesStreamed_MessagesReceived()
        {
            // Arrange
            var streamContent = new SyncPointMemoryStream();

            PushStreamContent <HelloRequest, HelloReply>?content = null;

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                content = (PushStreamContent <HelloRequest, HelloReply>)request.Content;
                await content.PushComplete.DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, new StreamContent(streamContent)));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncDuplexStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());

            var requestStream  = call.RequestStream;
            var responseStream = call.ResponseStream;

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

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

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

            Assert.IsNotNull(content);
            var requestContent = await content !.ReadAsStreamAsync().DefaultTimeout();
            var requestMessage = await requestContent.ReadMessageAsync(
                NullLogger.Instance,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).AsTask().DefaultTimeout();

            Assert.AreEqual("1", requestMessage.Name);
            requestMessage = await requestContent.ReadMessageAsync(
                NullLogger.Instance,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).AsTask().DefaultTimeout();

            Assert.AreEqual("2", requestMessage.Name);

            Assert.IsNull(responseStream.Current);

            var moveNextTask1 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsFalse(moveNextTask1.IsCompleted);

            await streamContent.AddDataAndWait(await ClientTestHelpers.GetResponseDataAsync(new HelloReply
            {
                Message = "Hello world 1"
            }).DefaultTimeout()).DefaultTimeout();

            Assert.IsTrue(await moveNextTask1.DefaultTimeout());
            Assert.IsNotNull(responseStream.Current);
            Assert.AreEqual("Hello world 1", responseStream.Current.Message);

            var moveNextTask2 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsFalse(moveNextTask2.IsCompleted);

            await streamContent.AddDataAndWait(await ClientTestHelpers.GetResponseDataAsync(new HelloReply
            {
                Message = "Hello world 2"
            }).DefaultTimeout()).DefaultTimeout();

            Assert.IsTrue(await moveNextTask2.DefaultTimeout());
            Assert.IsNotNull(responseStream.Current);
            Assert.AreEqual("Hello world 2", responseStream.Current.Message);

            var moveNextTask3 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsFalse(moveNextTask3.IsCompleted);

            await streamContent.AddDataAndWait(Array.Empty <byte>()).DefaultTimeout();

            Assert.IsFalse(await moveNextTask3.DefaultTimeout());

            var moveNextTask4 = responseStream.MoveNext(CancellationToken.None);

            Assert.IsTrue(moveNextTask4.IsCompleted);
            Assert.IsFalse(await moveNextTask3.DefaultTimeout());
        }
        public async Task NegotiateThatReturnsUrlGetFollowedWithAccessToken()
        {
            var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false);
            var firstNegotiate  = true;

            testHttpHandler.OnNegotiate((request, cancellationToken) =>
            {
                if (firstNegotiate)
                {
                    firstNegotiate = false;

                    // The first negotiate requires an access token
                    if (request.Headers.Authorization?.Parameter != "firstSecret")
                    {
                        return(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized));
                    }

                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                        JsonConvert.SerializeObject(new
                    {
                        url = "https://another.domain.url/chat",
                        accessToken = "secondSecret"
                    })));
                }

                // All other requests require an access token
                if (request.Headers.Authorization?.Parameter != "secondSecret")
                {
                    return(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized));
                }

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                    JsonConvert.SerializeObject(new
                {
                    connectionId = "0rge0d00-0040-0030-0r00-000q00r00e00",
                    availableTransports = new object[]
                    {
                        new
                        {
                            transport = "LongPolling",
                            transferFormats = new[] { "Text" }
                        },
                    }
                })));
            });

            testHttpHandler.OnLongPoll((request, token) =>
            {
                // All other requests require an access token
                if (request.Headers.Authorization?.Parameter != "secondSecret")
                {
                    return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized)));
                }
                var tcs = new TaskCompletionSource <HttpResponseMessage>(TaskCreationOptions.RunContinuationsAsynchronously);

                token.Register(() => tcs.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)));

                return(tcs.Task);
            });

            testHttpHandler.OnLongPollDelete((token) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted));

            Task <string> AccessTokenProvider() => Task.FromResult <string>("firstSecret");

            using (var noErrorScope = new VerifyNoErrorsScope())
            {
                await WithConnectionAsync(
                    CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory, accessTokenProvider : AccessTokenProvider),
                    async (connection) =>
                {
                    await connection.StartAsync().DefaultTimeout();
                });
            }

            Assert.Equal("http://fakeuri.org/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[0].RequestUri.ToString());
            Assert.Equal("https://another.domain.url/chat/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[1].RequestUri.ToString());
            Assert.Equal("https://another.domain.url/chat?id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[2].RequestUri.ToString());
            Assert.Equal("https://another.domain.url/chat?id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[3].RequestUri.ToString());
            // Delete request
            Assert.Equal(5, testHttpHandler.ReceivedRequests.Count);
        }
        public async Task PickAsync_HedgingWithDrop_ThrowsError()
        {
            // Arrange
            string?authority          = null;
            var    testMessageHandler = TestHttpMessageHandler.Create(async request =>
            {
                authority = request.RequestUri !.Authority;
                var reply = new HelloReply {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });

            var services = new ServiceCollection();

            services.AddNUnitLogger();
            services.AddSingleton <TestResolver>();
            services.AddSingleton <ResolverFactory, TestResolverFactory>();
            DropLoadBalancer?loadBalancer = null;

            services.AddSingleton <LoadBalancerFactory>(new DropLoadBalancerFactory(c =>
            {
                loadBalancer = new DropLoadBalancer(c);
                return(loadBalancer);
            }));
            services.AddSingleton <ISubchannelTransportFactory>(new TestSubchannelTransportFactory());

            var invoker = HttpClientCallInvokerFactory.Create(testMessageHandler, "test:///localhost", configure: o =>
            {
                o.Credentials     = ChannelCredentials.Insecure;
                o.ServiceProvider = services.BuildServiceProvider();
                o.ServiceConfig   = new ServiceConfig
                {
                    MethodConfigs =
                    {
                        new MethodConfig
                        {
                            Names         = { MethodName.Default     },
                            HedgingPolicy = new HedgingPolicy
                            {
                                MaxAttempts         = 5,
                                HedgingDelay        = TimeSpan.FromMinutes(10),
                                NonFatalStatusCodes ={ StatusCode.DataLoss                    }
                            }
                        }
                    },
                    LoadBalancingConfigs = { new LoadBalancingConfig("drop") }
                };
            });

            // Act
            var call = invoker.AsyncUnaryCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions().WithWaitForReady(), new HelloRequest());

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

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

            Assert.AreEqual(1, loadBalancer !.PickCount);
        }
 public Task StartThrowsFormatExceptionIfNegotiationResponseHasNoConnectionId()
 {
     return(RunInvalidNegotiateResponseTest <FormatException>(ResponseUtils.CreateNegotiationContent(connectionId: string.Empty), "Invalid connection id."));
 }
Exemple #27
0
 public bool IsSuccess()
 {
     return(ResponseUtils.IsSuccess(this));
 }
 public Task NegotiateResponseWithNegotiateVersionRequiresConnectionToken()
 {
     return(RunInvalidNegotiateResponseTest <InvalidDataException>(ResponseUtils.CreateNegotiationContent(negotiateVersion: 1, connectionToken: null), "Invalid negotiation response received."));
 }
        public async Task AsyncClientStreamingCall_Success_RequestContentSent()
        {
            // Arrange
            PushStreamContent <HelloRequest, HelloReply>?content = null;

            var httpClient = ClientTestHelpers.CreateTestClient(async request =>
            {
                content = (PushStreamContent <HelloRequest, HelloReply>)request.Content;
                await content.PushComplete.DefaultTimeout();

                HelloReply reply = new HelloReply
                {
                    Message = "Hello world"
                };

                var streamContent = await ClientTestHelpers.CreateResponseContent(reply).DefaultTimeout();

                return(ResponseUtils.CreateResponse(HttpStatusCode.OK, streamContent));
            });
            var invoker = HttpClientCallInvokerFactory.Create(httpClient);

            // Act
            var call = invoker.AsyncClientStreamingCall <HelloRequest, HelloReply>(ClientTestHelpers.ServiceMethod, string.Empty, new CallOptions());

            // Assert
            Assert.IsNotNull(call);
            Assert.IsNotNull(content);

            var responseTask = call.ResponseAsync;

            Assert.IsFalse(responseTask.IsCompleted, "Response not returned until client stream is complete.");

            var streamTask = content !.ReadAsStreamAsync();

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

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

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

            var requestContent = await streamTask.DefaultTimeout();

            var requestMessage = await requestContent.ReadMessageAsync(
                NullLogger.Instance,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).AsTask().DefaultTimeout();

            Assert.AreEqual("1", requestMessage !.Name);
            requestMessage = await requestContent.ReadMessageAsync(
                NullLogger.Instance,
                ClientTestHelpers.ServiceMethod.RequestMarshaller.ContextualDeserializer,
                GrpcProtocolConstants.IdentityGrpcEncoding,
                maximumMessageSize : null,
                GrpcProtocolConstants.DefaultCompressionProviders,
                singleMessage : false,
                CancellationToken.None).AsTask().DefaultTimeout();

            Assert.AreEqual("2", requestMessage !.Name);

            var responseMessage = await responseTask.DefaultTimeout();

            Assert.AreEqual("Hello world", responseMessage.Message);
        }
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            var exception = actionExecutedContext.Exception;

            //全局异常捕获,记录未被捕获的异常
            LogDbHelper.LogFatal(exception,
                                 actionExecutedContext.Request.RequestUri.OriginalString + "=>" + actionExecutedContext.Request.Method,
                                 OperationType.Exception
                                 );

            actionExecutedContext.Response =
                actionExecutedContext.Request.CreateResponse(HttpStatusCode.InternalServerError, ResponseUtils.ErrorResult <object>(exception));

            base.OnException(actionExecutedContext);
        }