* HttpListener2Test.cs: Added test for multiple responses.
[mono.git] / mcs / class / System / Test / System.Net / HttpListener2Test.cs
index 7138ac39a0e9963c15de8fe21da328aa8104f29d..952546c8aa7d085530e9b3e6b76d0397c90770bb 100644 (file)
@@ -28,6 +28,8 @@
 //
 #if NET_2_0
 using System;
+using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.Net;
 using System.Net.Sockets;
@@ -41,6 +43,9 @@ using NUnit.Framework;
 // ***************************************************************************************
 namespace MonoTests.System.Net {
        [TestFixture]
+#if TARGET_JVM 
+       [Ignore ("The class HttpListener is not supported")]
+#endif
        public class HttpListener2Test {
                public class MyNetworkStream : NetworkStream {
                        public MyNetworkStream (Socket sock) : base (sock, true)
@@ -61,6 +66,15 @@ namespace MonoTests.System.Net {
                        return listener;
                }
 
+               public static HttpListener CreateAndStartListener (string prefix, AuthenticationSchemes authSchemes)
+               {
+                       HttpListener listener = new HttpListener ();
+                       listener.AuthenticationSchemes = authSchemes;
+                       listener.Prefixes.Add (prefix);
+                       listener.Start ();
+                       return listener;
+               }
+
                public static MyNetworkStream CreateNS (int port)
                {
                        Socket sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
@@ -128,13 +142,39 @@ namespace MonoTests.System.Net {
                [Test]
                public void Test3 ()
                {
-                       HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test3/");
-                       NetworkStream ns = CreateNS (9000);
-                       Send (ns, "MET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n"); // bad method
-                       string response = Receive (ns, 512);
-                       ns.Close ();
-                       listener.Close ();
-                       Assert.IsTrue (response.StartsWith ("HTTP/1.1 400"));
+                       StringBuilder bad = new StringBuilder ();
+                       for (int i = 0; i < 33; i++){
+                               if (i != 13)
+                                       bad.Append ((char) i);
+                       }
+                       bad.Append ('(');
+                       bad.Append (')');
+                       bad.Append ('[');
+                       bad.Append (']');
+                       bad.Append ('<');
+                       bad.Append ('>');
+                       bad.Append ('@');
+                       bad.Append (',');
+                       bad.Append (';');
+                       bad.Append (':');
+                       bad.Append ('\\');
+                       bad.Append ('"');
+                       bad.Append ('/');
+                       bad.Append ('?');
+                       bad.Append ('=');
+                       bad.Append ('{');
+                       bad.Append ('}');
+
+                       foreach (char b in bad.ToString ()){
+                               HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test3/");
+                               NetworkStream ns = CreateNS (9000);
+                               Send (ns, String.Format ("MA{0} / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n", b)); // bad method
+                               
+                               string response = Receive (ns, 512);
+                               ns.Close ();
+                               listener.Close ();
+                               Assert.AreEqual (true, response.StartsWith ("HTTP/1.1 400"), String.Format ("Failed on {0}", (int) b));
+                       }
                }
 
                [Test]
@@ -355,6 +395,210 @@ namespace MonoTests.System.Net {
                        c.Response.Close ();
                        ns.Close ();
                }
+
+               [Test]
+               public void Test17 ()
+               {
+                       HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test17/");
+                       NetworkStream ns = CreateNS (9000);
+                       Send (ns, "RANDOM /test17/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
+                       HttpListenerContext ctx = listener.GetContext ();
+                       Send (ctx.Response.OutputStream, "%%%OK%%%");
+                       string response = Receive (ns, 1024);
+                       ns.Close ();
+                       listener.Close ();
+                       Assert.IsTrue (response.StartsWith ("HTTP/1.1 200"));
+                       Assert.IsTrue (-1 != response.IndexOf ("Transfer-Encoding: chunked"));
+               }
+
+               [Test]
+               public void Test_MultipleClosesOnOuputStreamAllowed ()
+               {
+                       HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/MultipleCloses/");
+                       NetworkStream ns = CreateNS (9000);
+                       Send (ns, "GET /MultipleCloses/ HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n");
+
+                       HttpListenerContext ctx = listener.GetContext ();
+                       ctx.Response.OutputStream.Close ();
+                       ctx.Response.OutputStream.Close ();
+                       ctx.Response.OutputStream.Close ();
+                       ctx.Response.Close ();
+                       listener.Close ();
+               }
+       
+               void SendCookie ()
+               {
+                       NetworkStream ns = CreateNS (9000);
+                       Send (ns, "GET /SendCookie/ HTTP/1.1\r\nHost: 127.0.0.1\r\n"+
+                               "Cookie:$Version=\"1\"; "+
+                               "Cookie1=Value1; $Path=\"/\"; "+
+                               "CookieM=ValueM; $Path=\"/p2\"; $Domain=\"test\"; $Port=\"99\";"+
+                               "Cookie2=Value2; $Path=\"/foo\";"+
+                               "\r\n"+
+                               "\r\n");
+                       ns.Flush ();
+                       Thread.Sleep (200);
+                       ns.Close();
+               }
+
+               [Test]
+               public void ReceiveCookiesFromClient ()
+               {
+                       HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/SendCookie/");
+                       Thread clientThread = new Thread (new ThreadStart (SendCookie));
+                       clientThread.Start ();
+
+                       HttpListenerContext context = listener.GetContext();
+                       HttpListenerRequest request = context.Request;
+
+                       Assert.AreEqual (3, request.Cookies.Count, "#1");
+                       foreach (Cookie c in request.Cookies) {
+                               if (c.Name == "Cookie1") {
+                                       Assert.AreEqual ("Value1", c.Value, "#2");
+                                       Assert.AreEqual ("\"/\"", c.Path, "#3");
+                                       Assert.AreEqual (0, c.Port.Length, "#4");
+                                       Assert.AreEqual (0, c.Domain.Length, "#5");
+                               } else if (c.Name == "CookieM") {
+                                       Assert.AreEqual ("ValueM", c.Value, "#6");
+                                       Assert.AreEqual ("\"/p2\"", c.Path, "#7");
+                                       Assert.AreEqual ("\"99\"", c.Port, "#8");
+                                       Assert.AreEqual ("\"test\"", c.Domain, "#9");
+                               } else if (c.Name == "Cookie2") {
+                                       Assert.AreEqual ("Value2", c.Value, "#10");
+                                       Assert.AreEqual ("\"/foo\"", c.Path, "#11");
+                                       Assert.AreEqual (0, c.Port.Length, "#12");
+                                       Assert.AreEqual (0, c.Domain.Length, "#13");
+                               } else
+                                       Assert.Fail ("Invalid cookie name " + c.Name);
+                       }
+
+                       listener.Close ();
+               }
+
+               private object _lock = new Object();
+               private string cookieResponse;
+
+               void ReceiveCookie () {
+                       lock (_lock) {
+                               NetworkStream ns = CreateNS (9000);
+                               Send (ns, "GET /ReceiveCookie/ HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n");
+                               cookieResponse = Receive (ns, 512);
+                       }
+               }
+
+               [Test]
+               public void SendCookiestoClient ()
+               {
+                       HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/ReceiveCookie/");
+                       Thread clientThread = new Thread (new ThreadStart (ReceiveCookie));
+                       clientThread.Start ();
+
+                       HttpListenerContext context = listener.GetContext();
+                       HttpListenerRequest request = context.Request;
+                       HttpListenerResponse response = context.Response;
+
+                       Cookie cookie = new Cookie ();
+                       cookie.Name = "Name0";
+                       cookie.Value = "Value0";
+                       cookie.Domain = "blue";
+                       cookie.Path = "/path/";
+                       cookie.Port = "\"80\"";
+                       cookie.Version = 1;
+                       response.Cookies.Add (cookie);
+
+                       string responseString = "<HTML><BODY>----</BODY></HTML>";
+                       byte[] buffer = Encoding.UTF8.GetBytes(responseString);
+                       response.ContentLength64 = buffer.Length;
+                       Stream output = response.OutputStream;
+                       output.Write(buffer, 0, buffer.Length);
+                       output.Flush ();
+                       response.Close();
+                       
+                       lock (_lock) {
+                               bool foundCookie = false;
+                               foreach (String str in cookieResponse.Split ('\n')) {
+                                       if (!str.StartsWith ("Set-Cookie2"))
+                                               continue;
+                                       Dictionary<string, String> dic = new Dictionary<string, String>();
+                                       foreach (String p in str.Substring (str.IndexOf (":") + 1).Split (';')) {
+                                               String[] parts = p.Split('=');
+                                               dic.Add (parts [0].Trim (), parts [1].Trim ());
+                                       }
+                                       Assert.AreEqual ("Value0", dic ["Name0"], "#1");
+                                       Assert.AreEqual ("blue", dic ["Domain"], "#2");
+                                       Assert.AreEqual ("\"/path/\"", dic ["Path"], "#3");
+                                       Assert.AreEqual ("\"80\"", dic ["Port"], "#4");
+                                       Assert.AreEqual ("1", dic ["Version"], "#5");
+                                       foundCookie = true;
+                                       break;
+                               }
+                               Assert.IsTrue (foundCookie, "#6");
+                       }
+
+                       listener.Close ();
+               }
+
+               [Test]
+               public void MultiResponses ()
+               {
+                       Thread srv = new Thread (new ThreadStart (EchoServer));
+                       srv.Start ();
+                       Thread.Sleep (200);
+
+                       for (int i = 0; i < 10; i++) {
+                               string payload = string.Format (CultureInfo.InvariantCulture,
+                                       "Client{0}", i);
+
+                               HttpWebRequest req = (HttpWebRequest) WebRequest.Create (
+                                       "http://localhost:8888/foobar/");
+                               req.ServicePoint.Expect100Continue = false;
+                               req.ServicePoint.UseNagleAlgorithm = false;
+                               req.Method = "POST";
+                               StreamWriter w = new StreamWriter (req.GetRequestStream ());
+                               w.WriteLine (payload);
+                               w.Close ();
+
+                               HttpWebResponse resp = (HttpWebResponse) req.GetResponse ();
+                               StreamReader r = new StreamReader (resp.GetResponseStream ());
+                               Assert.AreEqual ("Hello, " + payload + "!", r.ReadToEnd ().Trim ());
+                               r.Close ();
+                       }
+
+                       manualReset.Set ();
+                       srv.Join ();
+               }
+
+               void EchoServer ()
+               {
+                       HttpListener listener = new HttpListener ();
+                       listener.Prefixes.Add ("http://*:8888/foobar/");
+                       listener.Start ();
+
+                       manualReset = new ManualResetEvent (false);
+
+                       IAsyncResult result = listener.BeginGetContext (
+                               new AsyncCallback (EchoCallback), listener);
+                       manualReset.WaitOne ();
+               }
+
+               void EchoCallback (IAsyncResult result)
+               {
+                       HttpListener listener = (HttpListener) result.AsyncState;
+                       HttpListenerContext context = listener.EndGetContext (result);
+                       HttpListenerRequest req = context.Request;
+                       StreamReader r = new StreamReader (req.InputStream);
+                       string reqBody = r.ReadToEnd ().Trim ();
+
+                       HttpListenerResponse resp = context.Response;
+                       StreamWriter o = new StreamWriter (resp.OutputStream);
+                       o.WriteLine ("Hello, " + reqBody + "!");
+                       o.Close ();
+
+                       listener.BeginGetContext (new AsyncCallback (EchoCallback), listener);
+               }
+
+               private ManualResetEvent manualReset;
+
        }
 
        [TestFixture]