public async Task WebTransportSession_AcceptNewStreamsInOrderOfArrival()
    {
        Http3Api._serviceContext.ServerOptions.EnableWebTransportAndH3Datagrams = true; // TODO add more sync code as now it is flaky

        var exitTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
        var session = await WebTransportTestUtilities.GenerateSession(Http3Api, exitTcs);

        // pretend that we received 2 new stream requests from a client
        session.AddStream(WebTransportTestUtilities.CreateStream(WebTransportStreamType.Bidirectional));
        session.AddStream(WebTransportTestUtilities.CreateStream(WebTransportStreamType.Input));

        var stream = await session.AcceptStreamAsync(CancellationToken.None);

        // verify that we accepted a bidirectional stream
        Assert.NotNull(stream);
        var streamDirectionFeature = stream.Features.GetRequiredFeature <IStreamDirectionFeature>();

        Assert.True(streamDirectionFeature.CanWrite);
        Assert.True(streamDirectionFeature.CanRead);

        var stream2 = await session.AcceptStreamAsync(CancellationToken.None);

        // verify that we accepted a unidirectional stream
        Assert.NotNull(stream2);
        var streamDirectionFeature2 = stream2.Features.GetRequiredFeature <IStreamDirectionFeature>();

        Assert.False(streamDirectionFeature2.CanWrite);
        Assert.True(streamDirectionFeature2.CanRead);

        exitTcs.SetResult();
    }
    public async Task WebTransportSession_ClosesProperly(int method)
    {
        Http3Api._serviceContext.ServerOptions.EnableWebTransportAndH3Datagrams = true;

        var exitTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
        var session = await WebTransportTestUtilities.GenerateSession(Http3Api, exitTcs);

        switch (method)
        {
        case 0:     // manual abort
            session.Abort(new(), System.Net.Http.Http3ErrorCode.InternalError);
            break;

        case 1:     // manual graceful close
            session.OnClientConnectionClosed();
            break;

        case 2:     // automatic graceful close due to application and connection ending
            exitTcs.SetResult();
            break;

        case 3:     // automatic abort due to host stream aborting
            Http3Api.Connection._streams[session.SessionId].Abort(new(), System.Net.Http.Http3ErrorCode.InternalError);
            break;
        }

        // check that all future method calls which are not related to closing throw
        Assert.Null(await session.AcceptStreamAsync(CancellationToken.None));
        Assert.Null(await session.OpenUnidirectionalStreamAsync(CancellationToken.None));

        // doublec check that no exceptions are thrown
        var _ = WebTransportTestUtilities.CreateStream(WebTransportStreamType.Bidirectional);

        exitTcs.TrySetResult();
    }
    public async Task WebTransportSession_CanOpenNewStream()
    {
        Http3Api._serviceContext.ServerOptions.EnableWebTransportAndH3Datagrams = true;

        var exitTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);

        var session = await WebTransportTestUtilities.GenerateSession(Http3Api, exitTcs);

        var stream = await session.OpenUnidirectionalStreamAsync(CancellationToken.None);

        //verify that we opened an output stream
        Assert.NotNull(stream);
        var streamDirectionFeature = stream.Features.GetRequiredFeature <IStreamDirectionFeature>();

        Assert.True(streamDirectionFeature.CanWrite);
        Assert.False(streamDirectionFeature.CanRead);

        // end the application
        exitTcs.SetResult();
    }