public async Task CloseAsync_CloseDescriptionIsMaxLengthPlusOne_ThrowsArgumentException(Uri server) { string closeDescription = new string('C', CloseDescriptionMaxLength + 1); using (ClientWebSocket cws = await WebSocketHelper.GetConnectedWebSocket(server, TimeOutMilliseconds, _output)) { var cts = new CancellationTokenSource(TimeOutMilliseconds); string expectedInnerMessage = ResourceHelper.GetExceptionMessage( "net_WebSockets_InvalidCloseStatusDescription", closeDescription, CloseDescriptionMaxLength); var expectedException = new ArgumentException(expectedInnerMessage, "statusDescription"); string expectedMessage = expectedException.Message; AssertExtensions.Throws <ArgumentException>("statusDescription", () => { Task t = cws.CloseAsync(WebSocketCloseStatus.NormalClosure, closeDescription, cts.Token); }); Assert.Equal(WebSocketState.Open, cws.State); } }
public async Task Abort_ConnectAndAbort_ThrowsWebSocketExceptionWithmessage(Uri server) { using (var cws = new ClientWebSocket()) { var cts = new CancellationTokenSource(TimeOutMilliseconds); var ub = new UriBuilder(server); ub.Query = "delay10sec"; Task t = cws.ConnectAsync(ub.Uri, cts.Token); cws.Abort(); WebSocketException ex = await Assert.ThrowsAsync <WebSocketException>(() => t); Assert.Equal(ResourceHelper.GetExceptionMessage("net_webstatus_ConnectFailure"), ex.Message); if (PlatformDetection.IsNetCore) // bug fix in netcoreapp: https://github.com/dotnet/corefx/pull/35960 { Assert.Equal(WebSocketError.Faulted, ex.WebSocketErrorCode); } Assert.Equal(WebSocketState.Closed, cws.State); } }
public async Task SendAsync_SendCloseMessageType_ThrowsArgumentExceptionWithMessage(Uri server) { using (ClientWebSocket cws = await WebSocketHelper.GetConnectedWebSocket(server, TimeOutMilliseconds, _output)) { var cts = new CancellationTokenSource(TimeOutMilliseconds); string expectedInnerMessage = ResourceHelper.GetExceptionMessage( "net_WebSockets_Argument_InvalidMessageType", "Close", "SendAsync", "Binary", "Text", "CloseOutputAsync"); var expectedException = new ArgumentException(expectedInnerMessage, "messageType"); string expectedMessage = expectedException.Message; Assert.Throws <ArgumentException>(() => { Task t = cws.SendAsync(new ArraySegment <byte>(), WebSocketMessageType.Close, true, cts.Token); }); Assert.Equal(WebSocketState.Open, cws.State); } }
public async Task SendReceive_ConnectionClosedPrematurely_ReceiveAsyncFailsAndWebSocketStateUpdated() { var options = new LoopbackServer.Options { WebSocketEndpoint = true }; Func <ClientWebSocket, LoopbackServer, Uri, Task> connectToServerThatAbortsConnection = async(clientSocket, server, url) => { var pendingReceiveAsyncPosted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); // Start listening for incoming connections on the server side. Task acceptTask = server.AcceptConnectionAsync(async connection => { // Complete the WebSocket upgrade. After this is done, the client-side ConnectAsync should complete. Assert.NotNull(await LoopbackHelper.WebSocketHandshakeAsync(connection)); // Wait for client-side ConnectAsync to complete and for a pending ReceiveAsync to be posted. await pendingReceiveAsyncPosted.Task.WaitAsync(TimeSpan.FromMilliseconds(TimeOutMilliseconds)); // Close the underlying connection prematurely (without sending a WebSocket Close frame). connection.Socket.Shutdown(SocketShutdown.Both); connection.Socket.Close(); }); // Initiate a connection attempt. var cts = new CancellationTokenSource(TimeOutMilliseconds); await clientSocket.ConnectAsync(url, cts.Token); // Post a pending ReceiveAsync before the TCP connection is torn down. var recvBuffer = new byte[100]; var recvSegment = new ArraySegment <byte>(recvBuffer); Task pendingReceiveAsync = ReceiveAsync(clientSocket, recvSegment, cts.Token); pendingReceiveAsyncPosted.SetResult(); // Wait for the server to close the underlying connection. await acceptTask.WaitAsync(cts.Token); WebSocketException pendingReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => pendingReceiveAsync); Assert.Equal(WebSocketError.ConnectionClosedPrematurely, pendingReceiveException.WebSocketErrorCode); if (PlatformDetection.IsInAppContainer) { const uint WININET_E_CONNECTION_ABORTED = 0x80072EFE; Assert.NotNull(pendingReceiveException.InnerException); Assert.Equal(WININET_E_CONNECTION_ABORTED, (uint)pendingReceiveException.InnerException.HResult); } WebSocketException newReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => ReceiveAsync(clientSocket, recvSegment, cts.Token)); Assert.Equal( ResourceHelper.GetExceptionMessage("net_WebSockets_InvalidState", "Aborted", "Open, CloseSent"), newReceiveException.Message); Assert.Equal(WebSocketState.Aborted, clientSocket.State); Assert.Null(clientSocket.CloseStatus); }; await LoopbackServer.CreateServerAsync(async (server, url) => { using (ClientWebSocket clientSocket = new ClientWebSocket()) { await connectToServerThatAbortsConnection(clientSocket, server, url); } }, options); }
// This will also pass when no exception is thrown. Current implementation doesn't throw. public async Task ReceiveAsync_MultipleOutstandingReceiveOperations_Throws(Uri server) { using (ClientWebSocket cws = await WebSocketHelper.GetConnectedWebSocket(server, TimeOutMilliseconds, _output)) { var cts = new CancellationTokenSource(TimeOutMilliseconds); Task[] tasks = new Task[2]; await SendAsync( cws, WebSocketData.GetBufferFromText(".delay5sec"), WebSocketMessageType.Text, true, cts.Token); var recvBuffer = new byte[100]; var recvSegment = new ArraySegment <byte>(recvBuffer); try { for (int i = 0; i < tasks.Length; i++) { tasks[i] = ReceiveAsync(cws, recvSegment, cts.Token); } await Task.WhenAll(tasks); Assert.Equal(WebSocketState.Open, cws.State); } catch (Exception ex) { if (ex is InvalidOperationException) { Assert.Equal( ResourceHelper.GetExceptionMessage( "net_Websockets_AlreadyOneOutstandingOperation", "ReceiveAsync"), ex.Message); Assert.True(WebSocketState.Aborted == cws.State, cws.State + " state when InvalidOperationException"); } else if (ex is WebSocketException) { // Multiple cases. Assert.True(WebSocketState.Aborted == cws.State, cws.State + " state when WebSocketException"); WebSocketError errCode = (ex as WebSocketException).WebSocketErrorCode; Assert.True( (errCode == WebSocketError.InvalidState) || (errCode == WebSocketError.Success), "WebSocketErrorCode"); } else if (ex is OperationCanceledException) { Assert.True(WebSocketState.Aborted == cws.State, cws.State + " state when OperationCanceledException"); } else { Assert.True(false, "Unexpected exception: " + ex.Message); } } } }
public async Task SendReceive_ConnectionClosedPrematurely_ReceiveAsyncFailsAndWebSocketStateUpdated() { var options = new LoopbackServer.Options { WebSocketEndpoint = true }; Func <ClientWebSocket, Socket, Uri, Task> connectToServerThatAbortsConnection = async(clientSocket, server, url) => { AutoResetEvent pendingReceiveAsyncPosted = new AutoResetEvent(false); // Start listening for incoming connections on the server side. Task <List <string> > acceptTask = LoopbackServer.AcceptSocketAsync(server, async(socket, stream, reader, writer) => { // Complete the WebSocket upgrade. After this is done, the client-side ConnectAsync should complete. Assert.True(await LoopbackServer.WebSocketHandshakeAsync(socket, reader, writer)); // Wait for client-side ConnectAsync to complete and for a pending ReceiveAsync to be posted. pendingReceiveAsyncPosted.WaitOne(TimeOutMilliseconds); // Close the underlying connection prematurely (without sending a WebSocket Close frame). socket.Shutdown(SocketShutdown.Both); socket.Close(); return(null); }, options); // Initiate a connection attempt. var cts = new CancellationTokenSource(TimeOutMilliseconds); await clientSocket.ConnectAsync(url, cts.Token); // Post a pending ReceiveAsync before the TCP connection is torn down. var recvBuffer = new byte[100]; var recvSegment = new ArraySegment <byte>(recvBuffer); Task pendingReceiveAsync = ReceiveAsync(clientSocket, recvSegment, cts.Token); pendingReceiveAsyncPosted.Set(); // Wait for the server to close the underlying connection. acceptTask.Wait(cts.Token); // Validate I/O errors and socket state. if (PlatformDetection.IsFullFramework) { _output.WriteLine("[Windows] ManagedWebSocket-based implementation."); WebSocketException pendingReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => pendingReceiveAsync); Assert.Equal(WebSocketError.ConnectionClosedPrematurely, pendingReceiveException.WebSocketErrorCode); WebSocketException newReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => ReceiveAsync(clientSocket, recvSegment, cts.Token)); Assert.Equal(WebSocketError.Success, newReceiveException.WebSocketErrorCode); Assert.Equal( ResourceHelper.GetExceptionMessage("net_WebSockets_InvalidState", "Aborted", "Open, CloseSent"), newReceiveException.Message); Assert.Equal(WebSocketState.Aborted, clientSocket.State); Assert.Null(clientSocket.CloseStatus); } else if (PlatformDetection.IsUap) { _output.WriteLine("WinRTWebSocket-based implementation."); const uint WININET_E_CONNECTION_ABORTED = 0x80072EFE; WebSocketException pendingReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => pendingReceiveAsync); Assert.Equal(WebSocketError.ConnectionClosedPrematurely, pendingReceiveException.WebSocketErrorCode); Assert.NotNull(pendingReceiveException.InnerException); Assert.Equal(WININET_E_CONNECTION_ABORTED, (uint)pendingReceiveException.InnerException.HResult); WebSocketException newReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => ReceiveAsync(clientSocket, recvSegment, cts.Token)); Assert.Equal(WebSocketError.Success, newReceiveException.WebSocketErrorCode); Assert.Equal( ResourceHelper.GetExceptionMessage("net_WebSockets_InvalidState", "Aborted", "Open, CloseSent"), newReceiveException.Message); Assert.Equal(WebSocketState.Aborted, clientSocket.State); Assert.Null(clientSocket.CloseStatus); } else { _output.WriteLine("[Non-Windows] ManagedWebSocket-based implementation."); WebSocketException pendingReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => pendingReceiveAsync); Assert.Equal(WebSocketError.ConnectionClosedPrematurely, pendingReceiveException.WebSocketErrorCode); WebSocketException newReceiveException = await Assert.ThrowsAsync <WebSocketException>(() => ReceiveAsync(clientSocket, recvSegment, cts.Token)); Assert.Equal(WebSocketError.ConnectionClosedPrematurely, newReceiveException.WebSocketErrorCode); Assert.Equal(WebSocketState.Open, clientSocket.State); Assert.Null(clientSocket.CloseStatus); } }; await LoopbackServer.CreateServerAsync(async (server, url) => { using (ClientWebSocket clientSocket = new ClientWebSocket()) { await connectToServerThatAbortsConnection(clientSocket, server, url); } }, options); }