예제 #1
0
        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());
        }
예제 #2
0
        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);
        }
예제 #3
0
        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.");
            }
        }