public ResultMessage <string> Logout() { _loginManager.Logout(LoginUser.TokenId); return(ResponseUtils.DataResult("登出成功")); }
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); }
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); }
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()); } }); } }
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.")); }
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); }
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); }
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()); }
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.)")); }
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")); }
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); }
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(); }
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(); } }
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.")); }
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); }