Merge pull request #2400 from esdrubal/extrahead
[mono.git] / mcs / class / System / Test / System.Net / HttpListenerTest.cs
index 05ff63ce8ea011b8bc9d3103fcfbe76e12d83aab..589ec80e924146c2654a16df2109de8a2dfc3695 100644 (file)
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-#if NET_2_0
 using System;
+using System.IO;
 using System.Net;
 using System.Net.Sockets;
 using System.Threading;
+using System.Threading.Tasks;
 using NUnit.Framework;
+using MonoTests.Helpers;
 
 namespace MonoTests.System.Net {
        [TestFixture]
        public class HttpListenerTest {
+
+               int port;
+
+               [SetUp]
+               public void SetUp () {
+                       port = NetworkHelpers.FindFreePort ();
+               }
+
                [Test]
                public void DefaultProperties ()
                {
@@ -152,10 +162,12 @@ namespace MonoTests.System.Net {
                [Test]
                public void TwoListeners_SameAddress ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener1 = new HttpListener ();
-                       listener1.Prefixes.Add ("http://127.0.0.1:7777/");
+                       listener1.Prefixes.Add ("http://127.0.0.1:" + port + "/");
                        HttpListener listener2 = new HttpListener ();
-                       listener2.Prefixes.Add ("http://127.0.0.1:7777/hola/");
+                       listener2.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/");
                        listener1.Start ();
                        listener2.Start ();
                }
@@ -164,10 +176,12 @@ namespace MonoTests.System.Net {
                [ExpectedException (typeof (HttpListenerException))]
                public void TwoListeners_SameURL ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener1 = new HttpListener ();
-                       listener1.Prefixes.Add ("http://127.0.0.1:7777/hola/");
+                       listener1.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/");
                        HttpListener listener2 = new HttpListener ();
-                       listener2.Prefixes.Add ("http://127.0.0.1:7777/hola/");
+                       listener2.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/");
                        listener1.Start ();
                        listener2.Start ();
                }
@@ -176,8 +190,10 @@ namespace MonoTests.System.Net {
                [ExpectedException (typeof (HttpListenerException))]
                public void MultipleSlashes ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola////");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola////");
                        // this one throws on Start(), not when adding it.
                        listener.Start ();
                }
@@ -186,8 +202,10 @@ namespace MonoTests.System.Net {
                [ExpectedException (typeof (HttpListenerException))]
                public void PercentSign ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola%3E/");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola%3E/");
                        // this one throws on Start(), not when adding it.
                        listener.Start ();
                }
@@ -202,8 +220,10 @@ namespace MonoTests.System.Net {
                [Test]
                public void CloseTwice ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola/");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
                        listener.Start ();
                        listener.Close ();
                        listener.Close ();
@@ -212,8 +232,10 @@ namespace MonoTests.System.Net {
                [Test]
                public void StartStopStart ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola/");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
                        listener.Start ();
                        listener.Stop ();
                        listener.Start ();
@@ -223,8 +245,10 @@ namespace MonoTests.System.Net {
                [Test]
                public void StartStopDispose ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        using (HttpListener listener = new HttpListener ()){
-                               listener.Prefixes.Add ("http://localhost:7777/hola/");
+                               listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
                                listener.Start ();
                                listener.Stop ();
                        }
@@ -240,8 +264,10 @@ namespace MonoTests.System.Net {
                [Test]
                public void AbortTwice ()
                {
+                       if (!CanOpenPort (port))
+                               Assert.Ignore ("port");
                        HttpListener listener = new HttpListener ();
-                       listener.Prefixes.Add ("http://localhost:7777/hola/");
+                       listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
                        listener.Start ();
                        listener.Abort ();
                        listener.Abort ();
@@ -450,7 +476,110 @@ namespace MonoTests.System.Net {
                                Event.Close ();
                        }
                }
+
+               [Test]
+               public void ConnectionReuse ()
+               {
+                       var uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
+
+                       HttpListener listener = new HttpListener ();
+                       listener.Prefixes.Add (uri);
+                       listener.Start ();
+
+                       IPEndPoint expectedIpEndPoint = CreateListenerRequest (listener, uri);
+
+                       Assert.AreEqual (expectedIpEndPoint, CreateListenerRequest (listener, uri), "reuse1");
+                       Assert.AreEqual (expectedIpEndPoint, CreateListenerRequest (listener, uri), "reuse2");
+               }
+
+               public IPEndPoint CreateListenerRequest (HttpListener listener, string uri)
+               {
+                       IPEndPoint ipEndPoint = null;
+                       var mre = new ManualResetEventSlim ();
+                       listener.BeginGetContext (result => {
+                               ipEndPoint = ListenerCallback (result);
+                               mre.Set ();
+                       }, listener);
+
+                       var request = (HttpWebRequest) WebRequest.Create (uri);
+                       request.Method = "POST";
+
+                       // We need to write something
+                       request.GetRequestStream ().Write (new byte [] {(byte)'a'}, 0, 1);
+                       request.GetRequestStream ().Dispose ();
+
+                       // Send request, socket is created or reused.
+                       var response = request.GetResponse ();
+
+                       // Close response so socket can be reused.
+                       response.Close ();
+
+                       mre.Wait ();
+
+                       return ipEndPoint;
+               }
+
+               public static IPEndPoint ListenerCallback (IAsyncResult result)
+               {
+                       var listener = (HttpListener) result.AsyncState;
+                       var context = listener.EndGetContext (result);
+                       var clientEndPoint = context.Request.RemoteEndPoint;
+
+                       // Disposing InputStream should not avoid socket reuse
+                       context.Request.InputStream.Dispose ();
+
+                       // Close OutputStream to send response
+                       context.Response.OutputStream.Close ();
+
+                       return clientEndPoint;
+               }
+               
+               [Test]
+               public void HttpClientIsDisconnectedCheckForWriteException()
+               {
+                       string uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
+
+                       AutoResetEvent exceptionOccuredEvent = new AutoResetEvent (false);
+                       HttpListener listener = new HttpListener {
+                               IgnoreWriteExceptions = false
+                       };
+                       listener.Prefixes.Add (uri);
+                       listener.Start ();
+                       listener.BeginGetContext (result =>
+                       {
+                               HttpListenerContext context = listener.EndGetContext (result);
+                               context.Response.SendChunked = true;
+                               context.Request.InputStream.Close ();
+                               
+                               var bytes = new byte [1024];
+                               using(Stream outputStream = context.Response.OutputStream) {
+                                       try {
+                                               while (true) 
+                                                       outputStream.Write (bytes, 0, bytes.Length);
+                                       } catch {
+                                               exceptionOccuredEvent.Set ();
+                                       }
+                               }
+                       }, null);
+
+                       Task.Factory.StartNew (() =>
+                       {
+                               var webRequest = (HttpWebRequest)WebRequest.Create (uri);
+                               webRequest.Method = "POST";
+                               webRequest.KeepAlive = false;
+                               Stream requestStream = webRequest.GetRequestStream ();
+                               requestStream.WriteByte (1);
+                               requestStream.Close ();
+                               using (WebResponse response = webRequest.GetResponse ())
+                               using (Stream stream = response.GetResponseStream ()) {
+                                       byte[] clientBytes = new byte [1024];
+                                       Assert.IsNotNull (stream, "#01");
+                                       stream.Read (clientBytes, 0, clientBytes.Length);
+                               }
+                       });
+
+                       Assert.IsTrue (exceptionOccuredEvent.WaitOne (15 * 1000), "#02");
+               }
        }
 }
-#endif