New test.
[mono.git] / mcs / class / System.Web / Test / System.Web / HttpRequestTest.cs
index c42084f9ca981e96342c74a8e217c77d6202b9ea..ffad4250d74f924216078f6bdf264824f5de9f00 100644 (file)
@@ -33,12 +33,12 @@ using System.Web;
 using System.Collections.Specialized;
 using NUnit.Framework;
 using System.Diagnostics;
+using MonoTests.SystemWeb.Framework;
+using System.IO;
 
 namespace MonoTests.System.Web {
 
        [TestFixture]
-       // Tons of failures on msft here.
-       [Category ("NotDotNet")]
        public class HttpRequestTest {
 
 #if NET_1_1
@@ -91,7 +91,7 @@ namespace MonoTests.System.Web {
                        // the next statement throws
                        Assert.AreEqual ("<SCRIPT>alert(document.cookie)</SCRIPT>", request.QueryString ["test"], "QueryString");
                }
-
+#endif
                //
                // Tests the properties from the simple constructor.
                [Test]
@@ -121,7 +121,8 @@ namespace MonoTests.System.Web {
                        Assert.AreEqual (null, r.ApplicationPath, "U7");
                }
 
-               [Test][ExpectedException(typeof(NullReferenceException))]
+               [Test]
+               [ExpectedException(typeof(ArgumentNullException))]
                public void Test_AccessToVars ()
                {
                        string url = "http://www.gnome.org/";
@@ -130,10 +131,68 @@ namespace MonoTests.System.Web {
                        HttpRequest r = new HttpRequest ("file", url, qs);
                        string s = r.PhysicalApplicationPath;
                }
+       
+               [Test]
+               public void Test_QueryStringDecoding()
+               {
+                       string url = "http://www.gnome.org/";
+                       string qs = "umlaut=" + HttpUtility.UrlEncode("\u00e4", Encoding.Default);
+
+                       HttpRequest r = new HttpRequest ("file", url, qs);
+                       Assert.AreEqual("\u00e4", r.QueryString["umlaut"]);
+               }
+
+               [Test]
+               [Category ("NunitWeb")]
+               public void Test_PhysicalApplicationPath ()
+               {
+                       WebTest t = new WebTest (new HandlerInvoker (new HandlerDelegate (
+                               PhysicalApplicationPathDelegate)));
+                       t.Run ();
+               }
+
+               static public void PhysicalApplicationPathDelegate ()
+               {
+                       HttpRequest r = HttpContext.Current.Request;
+                       string pap = r.PhysicalApplicationPath;
+                       Assert.IsTrue (pap.EndsWith (Path.DirectorySeparatorChar.ToString()), "#1");
+                       Assert.AreEqual (Path.GetFullPath (pap), pap, "#2");
+               }
+
+               [Test]
+               [Category ("NunitWeb")]
+               public void Test_MapPath ()
+               {
+                       WebTest t = new WebTest (new HandlerInvoker (new HandlerDelegate (
+                               MapPathDelegate)));
+                       t.Run ();
+               }
+
+               static public void MapPathDelegate ()
+               {
+                       HttpRequest r = HttpContext.Current.Request;
+                       string appBase = r.PhysicalApplicationPath.TrimEnd (Path.DirectorySeparatorChar);
+                       Assert.AreEqual (appBase, r.MapPath ("~"), "test1");
+                       Assert.AreEqual (appBase, r.MapPath ("/NunitWeb"), "test1.1");
+                       Assert.AreEqual (Path.Combine (appBase, "Web.config"),
+                               r.MapPath ("Web.config"), "test2");
+                       Assert.AreEqual (Path.Combine (appBase, "Web.config"),
+                               r.MapPath ("~/Web.config"), "test3");
+                       Assert.AreEqual (Path.Combine (appBase, "Web.config"),
+                               r.MapPath ("/NunitWeb/Web.config"), "test4");
+                       Assert.AreEqual (Path.Combine (appBase, "Web.config"),
+                               r.MapPath ("Web.config", null, false), "test5");
+                       Assert.AreEqual (Path.Combine (appBase, "Web.config"),
+                               r.MapPath ("Web.config", "", false), "test6");
+                       Assert.AreEqual (Path.Combine (appBase, "Web.config"),
+                               r.MapPath ("Web.config", "/NunitWeb", false), "test7");
+                       Assert.AreEqual (Path.Combine (appBase, "Web.config"),
+                               r.MapPath ("/NunitWeb/Web.config", "/NunitWeb", false), "test8");
+               }
        }
+       
 
        [TestFixture]
-       [Category ("NotDotNet")]
        public class Test_HttpFakeRequest {
                class FakeHttpWorkerRequest : HttpWorkerRequest {
                        public int return_kind;
@@ -179,6 +238,10 @@ namespace MonoTests.System.Web {
                                        return "mapa=10";
                                case 32: // GET
                                        return "mapa.x=pi&mapa.y=20";
+                               case 50:
+                                       return "PlainString";
+                               case 51:
+                                       return "Plain&Arg=1";
                                default:
                                        return "GetQueryString";
                                }
@@ -420,7 +483,11 @@ namespace MonoTests.System.Web {
                {
                        HttpContext c = Cook (1);
 
+#if NET_2_0
+                       Assert.IsNull (c.Request.ApplicationPath, "A1");
+#else
                        Assert.AreEqual ("AppPath", c.Request.ApplicationPath, "A1");
+#endif
                        Assert.AreEqual ("text/plain", c.Request.ContentType, "A2");
 
                        c = Cook (0);
@@ -469,7 +536,8 @@ namespace MonoTests.System.Web {
                        Assert.AreEqual ("Value", c.Request.Cookies ["Key"].Value, "cookie1");
                }
 
-               [Test][ExpectedException(typeof (HttpRequestValidationException))]
+               [Test]
+               [ExpectedException(typeof (HttpRequestValidationException))]
                public void Test_DangerousCookie ()
                {
                        HttpContext c;
@@ -479,7 +547,7 @@ namespace MonoTests.System.Web {
                        object a = c.Request.Cookies;
                }
                
-               [Test][ExpectedException(typeof(HttpRequestValidationException))]
+               [Test]
                public void Test_DangerousCookie2 ()
                {
                        HttpContext c;
@@ -489,7 +557,7 @@ namespace MonoTests.System.Web {
                        object a = c.Request.Cookies;
                }
                
-               [Test][ExpectedException(typeof(HttpRequestValidationException))]
+               [Test]
                public void Test_DangerousCookie3 ()
                {
                        HttpContext c;
@@ -499,7 +567,7 @@ namespace MonoTests.System.Web {
                        object a = c.Request.Cookies;
                }
                
-               [Test][ExpectedException(typeof(HttpRequestValidationException))]
+               [Test]
                public void Test_DangerousCookie4 ()
                {
                        HttpContext c;
@@ -556,7 +624,18 @@ namespace MonoTests.System.Web {
                        //
                        NameValueCollection nvc = c.Request.QueryString;
                }
-                       
+
+               [Test]
+               public void Test_QueryString_ToString ()
+               {
+                       HttpContext c = Cook (50);
+
+                       Assert.AreEqual (c.Request.QueryString.ToString (), "PlainString", "QTS#1");
+
+                       c = Cook (51);
+                       Assert.AreEqual (c.Request.QueryString.ToString (), "Plain&Arg=1", "QTS#2");
+               }
+               
                [Test]
                public void Leading_qm_in_QueryString ()
                {
@@ -647,6 +726,215 @@ namespace MonoTests.System.Web {
                        Assert.AreEqual (0, req.ContentLength, "#01");
                }
        }
-#endif
+
+       // This class is defined here to make it easy to create fake
+       // HttpWorkerRequest-derived classes by only overriding the methods
+       // necessary for testing.
+       class BaseFakeHttpWorkerRequest : HttpWorkerRequest
+       {
+               public override void EndOfRequest()
+               {
+               }
+
+               public override void FlushResponse(bool finalFlush)
+               {
+               }
+
+               public override string GetHttpVerbName()
+               {
+                       return "GET";
+               }
+
+               public override string GetHttpVersion()
+               {
+                       return "HTTP/1.1";
+               }
+
+               public override string GetLocalAddress()
+               {
+                       return "localhost";
+               }
+
+               public override int GetLocalPort()
+               {
+                       return 8080;
+               }
+
+               public override string GetQueryString()
+               {
+                       return String.Empty;
+               }
+
+               public override string GetRawUrl()
+               {
+                       string rawUrl = GetUriPath();
+                       string queryString = GetQueryString();
+                       if (queryString != null && queryString.Length > 0)
+                       {
+                               rawUrl += "?" + queryString;
+                       }
+                       return rawUrl;
+               }
+
+               public override string GetRemoteAddress()
+               {
+                       return "remotehost";
+               }
+
+               public override int GetRemotePort()
+               {
+                       return 8080;
+               }
+
+               public override string GetUriPath()
+               {
+                       return "default.aspx";
+               }
+
+               public override void SendKnownResponseHeader(int index, string value)
+               {
+               }
+
+               public override void SendResponseFromFile(IntPtr handle, long offset, long length)
+               {
+               }
+
+               public override void SendResponseFromFile(string filename, long offset, long length)
+               {
+               }
+
+               public override void SendResponseFromMemory(byte[] data, int length)
+               {
+               }
+
+               public override void SendStatus(int statusCode, string statusDescription)
+               {
+               }
+
+               public override void SendUnknownResponseHeader(string name, string value)
+               {
+               }
+       }
+
+       // This test ensures accessing the Form property does not throw an
+       // exception when the length of data in the request exceeds the length
+       // as reported by the Content-Length header. This bug was discovered
+       // with an AJAX application using XMLHttpRequest to POST back to the
+       // server. The Content-Length header was two bytes less than the length
+       // of the buffer returned from GetPreloadedEntityBody. This was causing
+       // an exception to be thrown by Mono because it was trying to allocate
+       // a buffer that was -2 bytes in length.
+       [TestFixture]
+       public class Test_UrlEncodedBodyWithExtraCRLF
+       {
+               class FakeHttpWorkerRequest : BaseFakeHttpWorkerRequest
+               {
+                       // This string is 9 bytes in length. That's 2 more than
+                       // the Content-Length header says it should be.
+                       string data = "foo=bar\r\n";
+
+                       public override string GetKnownRequestHeader(int index)
+                       {
+                               switch (index)
+                               {
+                                       case HttpWorkerRequest.HeaderContentLength:
+                                               return (data.Length - 2).ToString();
+                                       case HttpWorkerRequest.HeaderContentType:
+                                               return "application/x-www-form-urlencoded";
+                               }
+                               return String.Empty;
+                       }
+
+                       public override byte[] GetPreloadedEntityBody()
+                       {
+                               return Encoding.ASCII.GetBytes(data);
+                       }
+               }
+
+               HttpContext context = null;
+
+               [SetUp]
+               public void SetUp()
+               {
+                       HttpWorkerRequest workerRequest = new FakeHttpWorkerRequest();
+                       context = new HttpContext(workerRequest);
+               }
+
+               [Test]
+               public void ContentLength()
+               {
+                       Assert.AreEqual(7, context.Request.ContentLength);
+               }
+
+               [Test]
+               public void Form_Count()
+               {
+                       Assert.AreEqual(1, context.Request.Form.Count);
+               }
+
+               [Test]
+               [Category ("NotDotNet")]
+               public void Form_Item()
+               {
+                       // I would have expected the extra two characters to be stripped
+                       // but Microsoft's CLR keeps them so Mono should, too.
+                       //Assert.AreEqual("bar\r\n", context.Request.Form["foo"]);
+                       Assert.AreEqual("bar", context.Request.Form["foo"]);
+               }
+       }
+
+       // This test ensures the HttpRequet object's Form property gets
+       // properly constructed and populated when the Content-Type header
+       // includes a charset parameter and that the charset parameter is
+       // respected.
+       [TestFixture]
+       public class Test_UrlEncodedBodyWithUtf8CharsetParameter
+       {
+               class FakeHttpWorkerRequest : BaseFakeHttpWorkerRequest
+               {
+                       // The two funny-looking characters are really a single
+                       // accented "a" character encoded in UTF-8.
+                       string data = "foo=b%C3%A1r";
+
+                       public override string GetKnownRequestHeader(int index)
+                       {
+                               switch (index)
+                               {
+                                       case HttpWorkerRequest.HeaderContentLength:
+                                               return data.Length.ToString();
+                                       case HttpWorkerRequest.HeaderContentType:
+                                               return "application/x-www-form-urlencoded; charset=utf-8";
+                               }
+                               return String.Empty;
+                       }
+
+                       public override byte[] GetPreloadedEntityBody()
+                       {
+                               return Encoding.ASCII.GetBytes(data);
+                       }
+               }
+
+               HttpContext context = null;
+
+               [SetUp]
+               public void SetUp()
+               {
+                       HttpWorkerRequest workerRequest = new FakeHttpWorkerRequest();
+                       context = new HttpContext(workerRequest);
+               }
+
+               [Test]
+               public void Form_Count()
+               {
+                       Assert.AreEqual(1, context.Request.Form.Count);
+               }
+
+               [Test]
+               public void Form_Item()
+               {
+                       Assert.AreEqual("b\xE1r", context.Request.Form["foo"]);
+               }
+
+       }
 }