diff options
Diffstat (limited to 'mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs')
-rw-r--r-- | mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs b/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs new file mode 100644 index 0000000000..3666003a3f --- /dev/null +++ b/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs @@ -0,0 +1,242 @@ +#if NET_4_5 && !MOBILE +using System; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Net.WebSockets; +using System.Reflection; +using System.Text; + +using NUnit.Framework; + + +namespace MonoTests.System.Net.WebSockets +{ + [TestFixture] + public class ClientWebSocketTest + { + const string EchoServerUrl = "ws://echo.websocket.org"; + const int Port = 42123; + HttpListener listener; + ClientWebSocket socket; + MethodInfo headerSetMethod; + + [SetUp] + public void Setup () + { + listener = new HttpListener (); + listener.Prefixes.Add ("http://localhost:" + Port + "/"); + listener.Start (); + socket = new ClientWebSocket (); + } + + [TearDown] + public void Teardown () + { + if (listener != null) { + listener.Stop (); + listener = null; + } + if (socket != null) { + if (socket.State == WebSocketState.Open) + socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (); + socket.Dispose (); + socket = null; + } + } + + [Test] + public void ServerHandshakeReturnCrapStatusCodeTest () + { + HandleHttpRequestAsync ((req, resp) => resp.StatusCode = 418); + try { + socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait (); + } catch (AggregateException e) { + AssertWebSocketException (e, WebSocketError.Success, typeof (WebException)); + return; + } + Assert.Fail ("Should have thrown"); + } + + [Test] + public void ServerHandshakeReturnWrongUpgradeHeader () + { + HandleHttpRequestAsync ((req, resp) => { + resp.StatusCode = 101; + resp.Headers["Upgrade"] = "gtfo"; + }); + try { + socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait (); + } catch (AggregateException e) { + AssertWebSocketException (e, WebSocketError.Success); + return; + } + Assert.Fail ("Should have thrown"); + } + + [Test] + public void ServerHandshakeReturnWrongConnectionHeader () + { + HandleHttpRequestAsync ((req, resp) => { + resp.StatusCode = 101; + resp.Headers["Upgrade"] = "websocket"; + // Mono http request doesn't like the forcing, test still valid since the default connection header value is empty + //ForceSetHeader (resp.Headers, "Connection", "Foo"); + }); + try { + socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait (); + } catch (AggregateException e) { + AssertWebSocketException (e, WebSocketError.Success); + return; + } + Assert.Fail ("Should have thrown"); + } + + [Test] + public void EchoTest () + { + const string Payload = "This is a websocket test"; + + Assert.AreEqual (WebSocketState.None, socket.State); + socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (); + Assert.AreEqual (WebSocketState.Open, socket.State); + + var sendBuffer = Encoding.ASCII.GetBytes (Payload); + socket.SendAsync (new ArraySegment<byte> (sendBuffer), WebSocketMessageType.Text, true, CancellationToken.None).Wait (); + + var receiveBuffer = new byte[Payload.Length]; + var resp = socket.ReceiveAsync (new ArraySegment<byte> (receiveBuffer), CancellationToken.None).Result; + + Assert.AreEqual (Payload.Length, resp.Count); + Assert.IsTrue (resp.EndOfMessage); + Assert.AreEqual (WebSocketMessageType.Text, resp.MessageType); + Assert.AreEqual (Payload, Encoding.ASCII.GetString (receiveBuffer, 0, resp.Count)); + + socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (); + Assert.AreEqual (WebSocketState.Closed, socket.State); + } + + [Test] + public void CloseOutputAsyncTest () + { + socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (); + Assert.AreEqual (WebSocketState.Open, socket.State); + + socket.CloseOutputAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (); + Assert.AreEqual (WebSocketState.CloseSent, socket.State); + + var resp = socket.ReceiveAsync (new ArraySegment<byte> (new byte[0]), CancellationToken.None).Result; + Assert.AreEqual (WebSocketState.Closed, socket.State); + Assert.AreEqual (WebSocketMessageType.Close, resp.MessageType); + Assert.AreEqual (WebSocketCloseStatus.NormalClosure, resp.CloseStatus); + Assert.AreEqual (string.Empty, resp.CloseStatusDescription); + } + + [Test] + public void CloseAsyncTest () + { + socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (); + Assert.AreEqual (WebSocketState.Open, socket.State); + + socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (); + Assert.AreEqual (WebSocketState.Closed, socket.State); + } + + [Test, ExpectedException (typeof (InvalidOperationException))] + public void SendAsyncArgTest_NotConnected () + { + socket.SendAsync (new ArraySegment<byte> (new byte[0]), WebSocketMessageType.Text, true, CancellationToken.None); + } + + [Test, ExpectedException (typeof (ArgumentNullException))] + public void SendAsyncArgTest_NoArray () + { + socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (); + socket.SendAsync (new ArraySegment<byte> (), WebSocketMessageType.Text, true, CancellationToken.None); + } + + [Test, ExpectedException (typeof (InvalidOperationException))] + public void ReceiveAsyncArgTest_NotConnected () + { + socket.ReceiveAsync (new ArraySegment<byte> (new byte[0]), CancellationToken.None); + } + + [Test, ExpectedException (typeof (ArgumentNullException))] + public void ReceiveAsyncArgTest_NoArray () + { + socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (); + socket.ReceiveAsync (new ArraySegment<byte> (), CancellationToken.None); + } + + [Test] + public void ReceiveAsyncWrongState_Closed () + { + try { + socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (); + socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (); + socket.ReceiveAsync (new ArraySegment<byte> (new byte[0]), CancellationToken.None).Wait (); + } catch (AggregateException e) { + AssertWebSocketException (e, WebSocketError.Success); + return; + } + Assert.Fail ("Should have thrown"); + } + + [Test] + public void SendAsyncWrongState_Closed () + { + try { + socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (); + socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (); + socket.SendAsync (new ArraySegment<byte> (new byte[0]), WebSocketMessageType.Text, true, CancellationToken.None).Wait (); + } catch (AggregateException e) { + AssertWebSocketException (e, WebSocketError.Success); + return; + } + Assert.Fail ("Should have thrown"); + } + + [Test] + public void SendAsyncWrongState_CloseSent () + { + try { + socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (); + socket.CloseOutputAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (); + socket.SendAsync (new ArraySegment<byte> (new byte[0]), WebSocketMessageType.Text, true, CancellationToken.None).Wait (); + } catch (AggregateException e) { + AssertWebSocketException (e, WebSocketError.Success); + return; + } + Assert.Fail ("Should have thrown"); + } + + async Task HandleHttpRequestAsync (Action<HttpListenerRequest, HttpListenerResponse> handler) + { + var ctx = await listener.GetContextAsync (); + handler (ctx.Request, ctx.Response); + ctx.Response.Close (); + } + + void AssertWebSocketException (AggregateException e, WebSocketError error, Type inner = null) + { + var wsEx = e.InnerException as WebSocketException; + Console.WriteLine (e.InnerException.ToString ()); + Assert.IsNotNull (wsEx, "Not a websocketexception"); + Assert.AreEqual (error, wsEx.WebSocketErrorCode); + if (inner != null) { + Assert.IsNotNull (wsEx.InnerException); + Assert.IsInstanceOfType (inner, wsEx.InnerException); + } + } + + void ForceSetHeader (WebHeaderCollection headers, string name, string value) + { + if (headerSetMethod == null) + headerSetMethod = typeof (WebHeaderCollection).GetMethod ("AddValue", BindingFlags.NonPublic); + headerSetMethod.Invoke (headers, new[] { name, value }); + } + } +} + +#endif |