async Task ClientShutdown_ConnectionReuse(TestContext ctx, CancellationToken cancellationToken)
        {
            var me = "ClientShutdown_ConnectionReuse()";

            LogDebug(ctx, 4, me);

            if (EffectiveType == StreamInstrumentationType.ConnectionReuseWithShutdown)
            {
                await Client.Shutdown(ctx, cancellationToken);

                LogDebug(ctx, 4, "{0} - client shutdown done", me);
            }

            Client.Close();

            clientInstrumentation = null;

            await serverTcs.Task.ConfigureAwait(false);

            LogDebug(ctx, 4, "{0} - server ready", me);

            try {
                LogDebug(ctx, 4, "{0} - restarting client", me);
                await((DotNetConnection)Client).Restart(ctx, cancellationToken).ConfigureAwait(false);
                LogDebug(ctx, 4, "{0} - done restarting client", me);
            } catch (Exception ex) {
                LogDebug(ctx, 4, "{0} - restarting client failed: {1}", me, ex);
                throw;
            }

            Client.Close();

            clientTcs.TrySetResult(true);
        }
        internal override Stream CreateNetworkStream(TestContext ctx, Socket socket, bool ownsSocket)
        {
            instrumentation = new StreamInstrumentation(ctx, ME, socket, ownsSocket);

            ConfigureNetworkStream(ctx, instrumentation);

            return(instrumentation);
        }
        protected override Task PostRun(TestContext ctx, CancellationToken cancellationToken)
        {
            if (clientInstrumentation != null)
            {
                clientInstrumentation.Dispose();
                clientInstrumentation = null;
            }
            if (serverInstrumentation != null)
            {
                serverInstrumentation.Dispose();
                serverInstrumentation = null;
            }

            return(base.PostRun(ctx, cancellationToken));
        }
        async Task ServerShutdown_ConnectionReuse(TestContext ctx, CancellationToken cancellationToken)
        {
            var me = $"ServerShutdown_ConnectionReuse({EffectiveType})";

            LogDebug(ctx, 4, me);

            Task <int> serverRead;

            if (EffectiveType == StreamInstrumentationType.ConnectionReuseWithShutdown)
            {
                var buffer = new byte[256];
                serverRead = Server.Stream.ReadAsync(buffer, 0, buffer.Length);
            }
            else
            {
                serverRead = Task.FromResult(0);
            }

            await ctx.Assert(() => serverRead, Is.EqualTo(0), "read shutdown notify").ConfigureAwait(false);

            Server.Close();

            LogDebug(ctx, 4, "{0} - restarting: {1}", me, serverInstrumentation.Socket.LocalEndPoint);

            serverInstrumentation = null;

            serverTcs.TrySetResult(true);

            try {
                await((DotNetConnection)Server).Restart(ctx, cancellationToken).ConfigureAwait(false);
                LogDebug(ctx, 4, "{0} - done restarting", me);
            } catch (Exception ex) {
                LogDebug(ctx, 4, "{0} - failed to restart: {1}", me, ex);
                throw;
            }

            await clientTcs.Task;

            Server.Close();

            LogDebug(ctx, 4, "{0} done", me);
        }
        public Stream CreateServerStream(TestContext ctx, Connection connection, Socket socket)
        {
            if ((EffectiveFlags & InstrumentationFlags.NeedServerInstrumentation) == 0)
            {
                throw ctx.AssertFail("CreateServerStream()");
            }

            var name            = string.Format("Server:{0}", EffectiveType);
            var ownsSocket      = !HasFlag(InstrumentationFlags.ReuseServerSocket);
            var instrumentation = new StreamInstrumentation(ctx, name, socket, ownsSocket);

            if (Interlocked.CompareExchange(ref serverInstrumentation, instrumentation, null) != null)
            {
                throw new InternalErrorException();
            }

            LogDebug(ctx, 4, "CreateServerStream()");

            return(instrumentation);
        }
        public Stream CreateClientStream(TestContext ctx, Connection connection, Socket socket)
        {
            if ((EffectiveFlags & InstrumentationFlags.NeedClientInstrumentation) == 0)
            {
                throw ctx.AssertFail("CreateClientStream()");
            }

            var name            = string.Format("Client:{0}", EffectiveType);
            var ownsSocket      = !HasFlag(InstrumentationFlags.ReuseClientSocket);
            var instrumentation = new StreamInstrumentation(ctx, name, socket, ownsSocket);

            var setup = DependencyInjector.Get <IConnectionFrameworkSetup> ();

            switch (EffectiveType)
            {
            case StreamInstrumentationType.VerifyAsyncStreamCalls:
                instrumentation.RequireAsync = true;
                if (setup.UsingDotNet)
                {
                    instrumentation.AllowBeginEndAsync = true;
                    instrumentation.AllowSyncFlush     = true;
                }
                break;
            }

            if (Interlocked.CompareExchange(ref clientInstrumentation, instrumentation, null) != null)
            {
                throw new InternalErrorException();
            }

            LogDebug(ctx, 4, "CreateClientStream()");

            if (!HasFlag(InstrumentationFlags.ClientStream))
            {
                return(instrumentation);
            }

            instrumentation.OnNextRead(ReadHandler);

            return(instrumentation);

            async Task <int> ReadHandler(byte[] buffer, int offset, int size,
                                         StreamInstrumentation.AsyncReadFunc func,
                                         CancellationToken cancellationToken)
            {
                ctx.Assert(Client.Stream, Is.Not.Null);
                ctx.Assert(Client.SslStream, Is.Not.Null);
                ctx.Assert(Client.SslStream.IsAuthenticated, Is.False);

                switch (EffectiveType)
                {
                case StreamInstrumentationType.ClientHandshake:
                    LogDebug(ctx, 4, "CreateClientStream(): client handshake");
                    break;

                case StreamInstrumentationType.ReadDuringClientAuth:
                    await ctx.AssertException <InvalidOperationException> (ReadClient).ConfigureAwait(false);

                    break;

                case StreamInstrumentationType.ShortReadDuringClientAuth:
                    if (size <= 5)
                    {
                        instrumentation.OnNextRead(ReadHandler);
                    }
                    size = 1;
                    break;

                case StreamInstrumentationType.VerifyAsyncStreamCalls:
                    break;

                default:
                    throw ctx.AssertFail(EffectiveType);
                }

                return(await func(buffer, offset, size, cancellationToken));
            }

            Task <int> ReadClient()
            {
                const int bufferSize = 100;

                return(Client.Stream.ReadAsync(new byte[bufferSize], 0, bufferSize));
            }
        }
 protected abstract void ConfigureNetworkStream(TestContext ctx, StreamInstrumentation instrumentation);
 protected override void Destroy()
 {
     instrumentation?.Dispose();
     instrumentation = null;
 }