summaryrefslogtreecommitdiff
path: root/mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs')
-rw-r--r--mcs/class/System/Test/System.Net.WebSockets/ClientWebSocketTest.cs242
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