public async Task CloseFromCloseSent_Success()
        {
            var closeDescription = "Test Closed";

            using (var server = KestrelGameSocketHelpers.CreateServer(LoggerFactory, out var port, async context =>
            {
                Assert.True(context.GameSockets.IsGameSocketRequest);
                var gameSocket = await context.GameSockets.AcceptGameSocketAsync();

                var serverBuffer = new byte[1024];
                var result = await gameSocket.ReceiveAsync(new ArraySegment <byte>(serverBuffer), CancellationToken.None);
                Assert.True(result.EndOfMessage);
                Assert.Equal(0, result.Count);
                Assert.Equal(GameSocketMessageType.Close, result.MessageType);
                Assert.Equal(GameSocketCloseStatus.NormalClosure, result.CloseStatus);
                Assert.Equal(closeDescription, result.CloseStatusDescription);

                await gameSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
            }))
                using (var client = new ClientGameSocket())
                {
                    await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None);

                    await client.CloseOutputAsync(GameSocketCloseStatus.NormalClosure, closeDescription, CancellationToken.None);

                    Assert.Equal(GameSocketState.CloseSent, client.State);

                    await client.CloseAsync(GameSocketCloseStatus.NormalClosure, closeDescription, CancellationToken.None);

                    Assert.Equal(GameSocketState.Closed, client.State);
                }
        }
        public async Task ReceiveLongData()
        {
            var originalData = Encoding.UTF8.GetBytes(new string('a', 0x1FFFF));

            using (var server = KestrelGameSocketHelpers.CreateServer(LoggerFactory, out var port, async context =>
            {
                Assert.True(context.GameSockets.IsGameSocketRequest);
                var gameSocket = await context.GameSockets.AcceptGameSocketAsync();

                await gameSocket.SendAsync(new ArraySegment <byte>(originalData), GameSocketMessageType.Binary, true, CancellationToken.None);
            }))
                using (var client = new ClientGameSocket())
                {
                    await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None);

                    var clientBuffer = new byte[originalData.Length];
                    GameSocketReceiveResult result;
                    var receivedCount = 0;
                    do
                    {
                        result = await client.ReceiveAsync(new ArraySegment <byte>(clientBuffer, receivedCount, clientBuffer.Length - receivedCount), CancellationToken.None);

                        receivedCount += result.Count;
                        Assert.Equal(GameSocketMessageType.Binary, result.MessageType);
                    }while (!result.EndOfMessage);

                    Assert.Equal(originalData.Length, receivedCount);
                    Assert.Equal(GameSocketMessageType.Binary, result.MessageType);
                    Assert.Equal(originalData, clientBuffer);
                }
        }
 public async Task Connect_Success()
 {
     using (var server = KestrelGameSocketHelpers.CreateServer(LoggerFactory, out var port, async context =>
     {
         Assert.True(context.GameSockets.IsGameSocketRequest);
         var gameSocket = await context.GameSockets.AcceptGameSocketAsync();
     }))
         using (var client = new ClientGameSocket())
             await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None);
 }
        public async Task ReceiveFragmentedData_Success()
        {
            var originalData = Encoding.UTF8.GetBytes("Hello World");

            using (var server = KestrelGameSocketHelpers.CreateServer(LoggerFactory, out var port, async context =>
            {
                Assert.True(context.GameSockets.IsGameSocketRequest);
                var gameSocket = await context.GameSockets.AcceptGameSocketAsync();

                await gameSocket.SendAsync(new ArraySegment <byte>(originalData, 0, 2), GameSocketMessageType.Binary, false, CancellationToken.None);
                await gameSocket.SendAsync(new ArraySegment <byte>(originalData, 2, 2), GameSocketMessageType.Binary, false, CancellationToken.None);
                await gameSocket.SendAsync(new ArraySegment <byte>(originalData, 4, 7), GameSocketMessageType.Binary, true, CancellationToken.None);
            }))
                using (var client = new ClientGameSocket())
                {
                    await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None);

                    var clientBuffer = new byte[originalData.Length];
                    var result       = await client.ReceiveAsync(new ArraySegment <byte>(clientBuffer), CancellationToken.None);

                    Assert.False(result.EndOfMessage);
                    Assert.Equal(2, result.Count);
                    var totalReceived = result.Count;
                    Assert.Equal(GameSocketMessageType.Binary, result.MessageType);

                    result = await client.ReceiveAsync(
                        new ArraySegment <byte>(clientBuffer, totalReceived, clientBuffer.Length - totalReceived), CancellationToken.None);

                    Assert.False(result.EndOfMessage);
                    Assert.Equal(2, result.Count);
                    totalReceived += result.Count;
                    Assert.Equal(GameSocketMessageType.Binary, result.MessageType);

                    result = await client.ReceiveAsync(
                        new ArraySegment <byte>(clientBuffer, totalReceived, clientBuffer.Length - totalReceived), CancellationToken.None);

                    Assert.True(result.EndOfMessage);
                    Assert.Equal(7, result.Count);
                    totalReceived += result.Count;
                    Assert.Equal(GameSocketMessageType.Binary, result.MessageType);

                    Assert.Equal(originalData, clientBuffer);
                }
        }
        public async Task SendEmptyData_Success()
        {
            using (var server = KestrelGameSocketHelpers.CreateServer(LoggerFactory, out var port, async context =>
            {
                Assert.True(context.GameSockets.IsGameSocketRequest);
                var gameSocket = await context.GameSockets.AcceptGameSocketAsync();

                var serverBuffer = new byte[0];
                var result = await gameSocket.ReceiveAsync(new ArraySegment <byte>(serverBuffer), CancellationToken.None);
                Assert.True(result.EndOfMessage);
                Assert.Equal(0, result.Count);
                Assert.Equal(GameSocketMessageType.Binary, result.MessageType);
            }))
                using (var client = new ClientGameSocket())
                {
                    await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None);

                    var originalData = new byte[0];
                    await client.SendAsync(new ArraySegment <byte>(originalData), GameSocketMessageType.Binary, true, CancellationToken.None);
                }
        }
        public async Task NegotiateSubProtocol_Success()
        {
            using (var server = KestrelGameSocketHelpers.CreateServer(LoggerFactory, out var port, async context =>
            {
                Assert.True(context.GameSockets.IsGameSocketRequest);
                Assert.Equal("alpha, bravo, charlie", context.Request.Headers["Sec-GameSocket-Protocol"]);
                var gameSocket = await context.GameSockets.AcceptGameSocketAsync("Bravo");
            }))
                using (var client = new ClientGameSocket())
                {
                    client.Options.AddSubProtocol("alpha");
                    client.Options.AddSubProtocol("bravo");
                    client.Options.AddSubProtocol("charlie");
                    await client.ConnectAsync(new Uri($"ws://localhost:{port}/"), CancellationToken.None);

                    // The Windows version of ClientGameSocket uses the casing from the header (Bravo)
                    // However, the Managed version seems match the header against the list generated by
                    // the AddSubProtocol calls (case-insensitively) and then use the version from
                    // that list as the value for SubProtocol. This is fine, but means we need to ignore case here.
                    // We could update our AddSubProtocols above to the same case but I think it's better to
                    // ensure this behavior is codified by this test.
                    Assert.Equal("Bravo", client.SubProtocol, ignoreCase: true);
                }
        }