Merge branch 'patch-1' of https://github.com/ReubenBond/mono into ReubenBond-patch-1
[mono.git] / mcs / class / System / Test / System.Net.WebSockets / ClientWebSocketTest.cs
index 212d5db9ca5f38f8948ce9cd39bfc257b33f7407..a990f67e65848183a4c9ac8d2c50060406987d95 100644 (file)
@@ -1,3 +1,4 @@
+#if NET_4_5
 using System;
 using System.Net;
 using System.Threading;
@@ -9,7 +10,6 @@ using System.Text;
 
 using NUnit.Framework;
 
-#if NET_4_5
 
 namespace MonoTests.System.Net.WebSockets
 {
@@ -40,7 +40,7 @@ namespace MonoTests.System.Net.WebSockets
                        }
                        if (socket != null) {
                                if (socket.State == WebSocketState.Open)
-                                       socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait ();
+                                       socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (2000);
                                socket.Dispose ();
                                socket = null;
                        }
@@ -49,9 +49,12 @@ namespace MonoTests.System.Net.WebSockets
                [Test]
                public void ServerHandshakeReturnCrapStatusCodeTest ()
                {
+                       // On purpose, 
+                       #pragma warning disable 4014
                        HandleHttpRequestAsync ((req, resp) => resp.StatusCode = 418);
+                       #pragma warning restore 4014
                        try {
-                               socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait ();
+                               Assert.IsTrue (socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait (5000));
                        } catch (AggregateException e) {
                                AssertWebSocketException (e, WebSocketError.Success, typeof (WebException));
                                return;
@@ -62,12 +65,14 @@ namespace MonoTests.System.Net.WebSockets
                [Test]
                public void ServerHandshakeReturnWrongUpgradeHeader ()
                {
+                       #pragma warning disable 4014
                        HandleHttpRequestAsync ((req, resp) => {
                                        resp.StatusCode = 101;
                                        resp.Headers["Upgrade"] = "gtfo";
                                });
+                       #pragma warning restore 4014
                        try {
-                               socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait ();
+                               Assert.IsTrue (socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait (5000));
                        } catch (AggregateException e) {
                                AssertWebSocketException (e, WebSocketError.Success);
                                return;
@@ -78,14 +83,16 @@ namespace MonoTests.System.Net.WebSockets
                [Test]
                public void ServerHandshakeReturnWrongConnectionHeader ()
                {
+                       #pragma warning disable 4014
                        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");
                                });
+                       #pragma warning restore 4014
                        try {
-                               socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait ();
+                               Assert.IsTrue (socket.ConnectAsync (new Uri ("ws://localhost:" + Port), CancellationToken.None).Wait (5000));
                        } catch (AggregateException e) {
                                AssertWebSocketException (e, WebSocketError.Success);
                                return;
@@ -103,7 +110,7 @@ namespace MonoTests.System.Net.WebSockets
                        Assert.AreEqual (WebSocketState.Open, socket.State);
 
                        var sendBuffer = Encoding.ASCII.GetBytes (Payload);
-                       socket.SendAsync (new ArraySegment<byte> (sendBuffer), WebSocketMessageType.Text, true, CancellationToken.None).Wait ();
+                       Assert.IsTrue (socket.SendAsync (new ArraySegment<byte> (sendBuffer), WebSocketMessageType.Text, true, CancellationToken.None).Wait (5000));
 
                        var receiveBuffer = new byte[Payload.Length];
                        var resp = socket.ReceiveAsync (new ArraySegment<byte> (receiveBuffer), CancellationToken.None).Result;
@@ -113,17 +120,17 @@ namespace MonoTests.System.Net.WebSockets
                        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.IsTrue (socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (5000));
                        Assert.AreEqual (WebSocketState.Closed, socket.State);
                }
 
                [Test]
                public void CloseOutputAsyncTest ()
                {
-                       socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait ();
+                       Assert.IsTrue (socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (5000));
                        Assert.AreEqual (WebSocketState.Open, socket.State);
 
-                       socket.CloseOutputAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait ();
+                       Assert.IsTrue (socket.CloseOutputAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (5000));
                        Assert.AreEqual (WebSocketState.CloseSent, socket.State);
 
                        var resp = socket.ReceiveAsync (new ArraySegment<byte> (new byte[0]), CancellationToken.None).Result;
@@ -136,10 +143,10 @@ namespace MonoTests.System.Net.WebSockets
                [Test]
                public void CloseAsyncTest ()
                {
-                       socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait ();
+                       Assert.IsTrue (socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (5000));
                        Assert.AreEqual (WebSocketState.Open, socket.State);
 
-                       socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait ();
+                       Assert.IsTrue (socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (5000));
                        Assert.AreEqual (WebSocketState.Closed, socket.State);
                }
 
@@ -152,7 +159,7 @@ namespace MonoTests.System.Net.WebSockets
                [Test, ExpectedException (typeof (ArgumentNullException))]
                public void SendAsyncArgTest_NoArray ()
                {
-                       socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait ();
+                       Assert.IsTrue (socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (5000));
                        socket.SendAsync (new ArraySegment<byte> (), WebSocketMessageType.Text, true, CancellationToken.None);
                }
 
@@ -165,7 +172,7 @@ namespace MonoTests.System.Net.WebSockets
                [Test, ExpectedException (typeof (ArgumentNullException))]
                public void ReceiveAsyncArgTest_NoArray ()
                {
-                       socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait ();
+                       Assert.IsTrue (socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (5000));
                        socket.ReceiveAsync (new ArraySegment<byte> (), CancellationToken.None);
                }
 
@@ -173,9 +180,9 @@ namespace MonoTests.System.Net.WebSockets
                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 ();
+                               Assert.IsTrue (socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (5000));
+                               Assert.IsTrue (socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (5000));
+                               Assert.IsTrue (socket.ReceiveAsync (new ArraySegment<byte> (new byte[0]), CancellationToken.None).Wait (5000));
                        } catch (AggregateException e) {
                                AssertWebSocketException (e, WebSocketError.Success);
                                return;
@@ -187,9 +194,9 @@ namespace MonoTests.System.Net.WebSockets
                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 ();
+                               Assert.IsTrue (socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (5000));
+                               Assert.IsTrue (socket.CloseAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (5000));
+                               Assert.IsTrue (socket.SendAsync (new ArraySegment<byte> (new byte[0]), WebSocketMessageType.Text, true, CancellationToken.None).Wait (5000));
                        } catch (AggregateException e) {
                                AssertWebSocketException (e, WebSocketError.Success);
                                return;
@@ -201,15 +208,50 @@ namespace MonoTests.System.Net.WebSockets
                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 ();
+                               Assert.IsTrue (socket.ConnectAsync (new Uri (EchoServerUrl), CancellationToken.None).Wait (5000));
+                               Assert.IsTrue (socket.CloseOutputAsync (WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None).Wait (5000));
+                               Assert.IsTrue (socket.SendAsync (new ArraySegment<byte> (new byte[0]), WebSocketMessageType.Text, true, CancellationToken.None).Wait (5000));
                        } catch (AggregateException e) {
                                AssertWebSocketException (e, WebSocketError.Success);
                                return;
                        }
                        Assert.Fail ("Should have thrown");
                }
+               
+               [Test]
+               public async Task SendAsyncEndOfMessageTest() {
+                       var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token;
+                       await SendAsyncEndOfMessageTest(false, WebSocketMessageType.Text, cancellationToken);
+                       await SendAsyncEndOfMessageTest(true, WebSocketMessageType.Text, cancellationToken);
+                       await SendAsyncEndOfMessageTest(false, WebSocketMessageType.Binary, cancellationToken);
+                       await SendAsyncEndOfMessageTest(true, WebSocketMessageType.Binary, cancellationToken);
+               }
+               
+               public async Task SendAsyncEndOfMessageTest(bool expectedEndOfMessage, WebSocketMessageType webSocketMessageType, CancellationToken cancellationToken){
+                       using (var client = new ClientWebSocket()) {    
+                               // Configure the listener.
+                               var serverReceive = HandleHttpWebSocketRequestAsync<WebSocketReceiveResult>(async socket => await socket.ReceiveAsync(new ArraySegment<byte>(new byte[32]), cancellationToken), cancellationToken);
+                               
+                               // Connect to the listener and make the request.
+                               await client.ConnectAsync (new Uri ("ws://localhost:" + Port + "/"), cancellationToken);
+                               await client.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes("test")), webSocketMessageType, expectedEndOfMessage, cancellationToken);
+                               
+                               // Wait for the listener to handle the request and return its result.
+                               var result = await serverReceive;
+                               
+                               // Cleanup and check results.
+                               await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Finished", cancellationToken);
+                               Assert.AreEqual(expectedEndOfMessage, result.EndOfMessage, "EndOfMessage should be " + expectedEndOfMessage);
+                       }
+               }
+               
+               async Task<T> HandleHttpWebSocketRequestAsync<T>(Func<WebSocket, Task<T>> action, CancellationToken cancellationToken) {
+                       var ctx = await this.listener.GetContextAsync();
+                       var wsContext = await ctx.AcceptWebSocketAsync(null);
+                       var result = await action(wsContext.WebSocket);
+                       await wsContext.WebSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Finished", cancellationToken);
+                       return result;
+               }
 
                async Task HandleHttpRequestAsync (Action<HttpListenerRequest, HttpListenerResponse> handler)
                {
@@ -226,7 +268,7 @@ namespace MonoTests.System.Net.WebSockets
                        Assert.AreEqual (error, wsEx.WebSocketErrorCode);
                        if (inner != null) {
                                Assert.IsNotNull (wsEx.InnerException);
-                               Assert.IsInstanceOfType (inner, wsEx.InnerException);
+                               Assert.IsTrue (inner.IsInstanceOfType (wsEx.InnerException));
                        }
                }