protected internal override async Task <HttpResponse> HandleRequest(
            TestContext ctx, HttpOperation operation, HttpConnection connection, HttpRequest request,
            RequestFlags effectiveFlags, CancellationToken cancellationToken)
        {
            if (RemoteEndPoint == null)
            {
                RemoteEndPoint = connection.RemoteEndPoint;
            }

            switch (TestRunner.EffectiveType)
            {
            case HttpInstrumentationTestType.CloseIdleConnection:
            case HttpInstrumentationTestType.CloseCustomConnectionGroup:
            case HttpInstrumentationTestType.AbortResponse:
                ctx.Assert(request.Method, Is.EqualTo("GET"), "method");
                break;

            case HttpInstrumentationTestType.ReuseConnection2:
                ctx.Assert(request.Method, Is.EqualTo("POST"), "method");
                break;

            case HttpInstrumentationTestType.NtlmInstrumentation:
            case HttpInstrumentationTestType.NtlmClosesConnection:
            case HttpInstrumentationTestType.NtlmReusesConnection:
            case HttpInstrumentationTestType.ParallelNtlm:
            case HttpInstrumentationTestType.NtlmWhileQueued:
            case HttpInstrumentationTestType.NtlmWhileQueued2:
                return(await HandleNtlmRequest(
                           ctx, operation, connection, request, effectiveFlags, cancellationToken).ConfigureAwait(false));

            case HttpInstrumentationTestType.ReuseConnection:
            case HttpInstrumentationTestType.ReuseCustomConnectionGroup:
            case HttpInstrumentationTestType.RedirectOnSameConnection:
                ctx.Assert(request.Method, Is.EqualTo("GET"), "method");
                AssertReusingConnection(ctx, connection);
                break;

            case HttpInstrumentationTestType.ReuseAfterPartialRead:
                // We can't reuse the connection because we did not read the entire response.
                ctx.Assert(request.Method, Is.EqualTo("GET"), "method");
                AssertNotReusingConnection(ctx, connection);
                break;

            case HttpInstrumentationTestType.CustomConnectionGroup:
                // We can't reuse the connection because we're in a different connection group.
                ctx.Assert(request.Method, Is.EqualTo("GET"), "method");
                AssertNotReusingConnection(ctx, connection);
                break;

            default:
                throw ctx.AssertFail(TestRunner.EffectiveType);
            }

            HttpResponse response;
            HttpInstrumentationContent content;
            ListenerOperation          redirect;

            switch (TestRunner.EffectiveType)
            {
            case HttpInstrumentationTestType.ReuseAfterPartialRead:
                return(new HttpResponse(HttpStatusCode.OK, Content)
                {
                    WriteAsBlob = true
                });

            case HttpInstrumentationTestType.AbortResponse:
                content = new HttpInstrumentationContent(TestRunner, currentRequest);
                return(new HttpResponse(HttpStatusCode.OK, content));

            case HttpInstrumentationTestType.ReuseConnection2:
                return(new HttpResponse(HttpStatusCode.OK, Content));

            case HttpInstrumentationTestType.RedirectOnSameConnection:
                redirect = operation.RegisterRedirect(ctx, Target);
                response = HttpResponse.CreateRedirect(HttpStatusCode.Redirect, redirect);
                response.SetBody(new StringContent($"{ME} Redirecting"));
                response.WriteAsBlob = true;
                return(response);

            default:
                return(HttpResponse.CreateSuccess(ME));
            }
        }
        async Task <HttpResponse> HandleNtlmRequest(
            TestContext ctx, HttpOperation operation, HttpConnection connection, HttpRequest request,
            RequestFlags effectiveFlags, CancellationToken cancellationToken)
        {
            var me = $"{ME}.{nameof (HandleNtlmRequest)}";

            ctx.LogDebug(3, $"{me}: {connection.RemoteEndPoint}");

            AuthenticationState state;
            var response = AuthManager.HandleAuthentication(ctx, connection, request, out state);

            ctx.LogDebug(3, $"{me}: {connection.RemoteEndPoint} - {state} {response}");

            if (state == AuthenticationState.Unauthenticated)
            {
                ctx.Assert(currentAuthState, Is.EqualTo(AuthenticationState.None), "first request");
                currentAuthState = AuthenticationState.Unauthenticated;
            }
            else if (TestRunner.EffectiveType == HttpInstrumentationTestType.NtlmInstrumentation)
            {
                if (state == AuthenticationState.Challenge)
                {
                    ctx.LogDebug(3, $"{me}: {connection.RemoteEndPoint} {RemoteEndPoint}");
                    challengeEndPoint = connection.RemoteEndPoint;
                }
                else
                {
                    ctx.Assert(connection.RemoteEndPoint, Is.EqualTo(challengeEndPoint), "must reuse connection");
                }
            }

            if (TestRunner.EffectiveType == HttpInstrumentationTestType.ParallelNtlm)
            {
                var parallelOperation = TestRunner.StartParallelNtlm(
                    ctx, this, state, cancellationToken);
                if (parallelOperation != null)
                {
                    await parallelOperation.WaitForCompletion().ConfigureAwait(false);
                }
            }

            var keepAlive = !CloseConnection && (effectiveFlags & (RequestFlags.KeepAlive | RequestFlags.CloseConnection)) == RequestFlags.KeepAlive;

            if (response != null)
            {
                response.Redirect = operation.RegisterRedirect(ctx, this, request.Path);
                return(response);
            }

            cancellationToken.ThrowIfCancellationRequested();

            HttpInstrumentationContent content;

            switch (TestRunner.EffectiveType)
            {
            case HttpInstrumentationTestType.NtlmWhileQueued:
                content = new HttpInstrumentationContent(TestRunner, currentRequest);
                return(new HttpResponse(HttpStatusCode.OK, content));

            case HttpInstrumentationTestType.NtlmWhileQueued2:
                content = new HttpInstrumentationContent(TestRunner, currentRequest);
                return(new HttpResponse(HttpStatusCode.OK, content)
                {
                    CloseConnection = true
                });
            }

            var ret = await Target.HandleRequest(ctx, operation, connection, request, effectiveFlags, cancellationToken);

            ctx.LogDebug(3, $"{me} target done: {Target} {ret}");
            ret.KeepAlive = false;
            return(ret);
        }