public async Task ValidateHttpListenerRedirectUriAsync() { HttpListenerInterceptor listenerInterceptor = new HttpListenerInterceptor( Substitute.For <ICoreLogger>()); int port = FindFreeLocalhostPort(); listenerInterceptor.TestBeforeStart = (url) => Assert.AreEqual(@"http://*****:*****@"/TestPath/", url); // Start the listener in the background Task <Uri> listenTask = listenerInterceptor.ListenToSingleRequestAndRespondAsync( port, "/TestPath/", (u) => { return(new MessageAndHttpCode(HttpStatusCode.OK, "ok")); }, CancellationToken.None); // Issue an http request on the main thread await SendMessageToPortAsync(port, "TestPath").ConfigureAwait(false); // Wait for the listner to do its stuff listenTask.Wait(1000 /* 1s timeout */); // Assert Assert.IsTrue(listenTask.IsCompleted); Assert.AreEqual(GetLocalhostUriWithParams(port, "TestPath"), listenTask.Result.ToString()); }
public async Task Cancellation_BeforeGetContext_Async() { HttpListenerInterceptor listenerInterceptor = new HttpListenerInterceptor( Substitute.For <ICoreLogger>()); CancellationTokenSource cts = new CancellationTokenSource(); int port = FindFreeLocalhostPort(); listenerInterceptor.TestBeforeGetContext = () => cts.Cancel(); // Start the listener in the background await AssertException.TaskThrowsAsync <OperationCanceledException>( () => listenerInterceptor.ListenToSingleRequestAndRespondAsync( port, (u) => { return(new MessageAndHttpCode(HttpStatusCode.OK, "ok")); }, cts.Token)) .ConfigureAwait(false); }
private async Task <Uri> SeleniumAcquireAuthAsync( Uri authorizationUri, Uri redirectUri, CancellationToken externalCancellationToken) { using (var driver = InitDriverAndGoToUrl(authorizationUri.OriginalString)) { var listener = new HttpListenerInterceptor(_logger); Uri authCodeUri = null; // Run the TCP listener and the selenium automation in parallel // but make sure to start the TCP listener first CancellationTokenSource innerSource = new CancellationTokenSource(); var tcpCancellationToken = CancellationTokenSource.CreateLinkedTokenSource( innerSource.Token, externalCancellationToken); Task <Uri> listenForAuthCodeTask = listener.ListenToSingleRequestAndRespondAsync( redirectUri.Port, redirectUri.AbsolutePath, (uri) => { authCodeUri = uri; _logger.Info("Auth code intercepted. Writing message back to browser"); return(GetMessageToShowInBroswerAfterAuth(uri)); }, tcpCancellationToken.Token); //_ = Task.Run(async () => await listenForAuthCodeTask.ConfigureAwait(false)); var seleniumAutomationTask = Task.Factory.StartNew(() => { _seleniumAutomationLogic(driver); _logger.Info("Selenium automation finished"); }); Trace.WriteLine($"Before WhenAny: seleniumAutomationTask {seleniumAutomationTask.Status} listenForAuthCodeTask {listenForAuthCodeTask.Status}"); // There is no guarantee over which task will finish first - TCP listener or Selenium automation // as the TCP listener has some post processing to do (extracting the url etc.) await Task.WhenAny(seleniumAutomationTask, listenForAuthCodeTask) .ConfigureAwait(false); Trace.WriteLine($"After WhenAny: seleniumAutomationTask {seleniumAutomationTask.Status} listenForAuthCodeTask {listenForAuthCodeTask.Status}"); // No need to wait to post a nice message in the browser if (authCodeUri != null) { return(authCodeUri); } if (seleniumAutomationTask.IsFaulted) { Trace.WriteLine("The selenium automation failed: " + seleniumAutomationTask.Exception.Message); RecordException(driver, seleniumAutomationTask.Exception); throw seleniumAutomationTask.Exception; } if (listenForAuthCodeTask.IsCanceled) { Trace.WriteLine("The TCP listener has timed out (or was canceled)."); if (!externalCancellationToken.IsCancellationRequested) { Assert.Fail("The TCP listener is in a canceled state, but cancellation has not been requested!"); } throw new OperationCanceledException(externalCancellationToken); } if (listenForAuthCodeTask.IsFaulted) { Trace.WriteLine("The TCP listener failed."); RecordException(driver, listenForAuthCodeTask.Exception); throw listenForAuthCodeTask.Exception; } _logger.Info($"Selenium finished, but TCP listener is still going. " + $"Selenium status: {seleniumAutomationTask.Status} " + $"TCP listener status: { listenForAuthCodeTask.Status}. "); // At this point we need to give the TcpListener some time to complete // but not too much as it should be fast await Task.WhenAny(Task.Delay(tcpTimeoutAfterSelenium), listenForAuthCodeTask).ConfigureAwait(false); if (authCodeUri != null) { return(authCodeUri); } innerSource.Cancel(); if (listenForAuthCodeTask.IsCanceled) { throw new OperationCanceledException(); } throw new InvalidOperationException( $"Unknown exception: selenium status: {seleniumAutomationTask.Status} TCP listener status: {listenForAuthCodeTask.Status}. " + $"Possible cause - the redirect Uri used is not the one configured." + $" A screen shot will be stored in the test results for you to inspect."); } }