2 // System.Web.HttpRequestTest.cs - Unit tests for System.Web.HttpRequest
5 // Sebastien Pouliot <sebastien@ximian.com>
6 // Miguel de Icaza <miguel@novell.com>
7 // Gonzalo Paniagua Javier <gonzalo@novell.com>
9 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections.Specialized;
34 using NUnit.Framework;
35 using System.Diagnostics;
36 using MonoTests.SystemWeb.Framework;
39 namespace MonoTests.System.Web {
42 public class HttpRequestTest {
46 [ExpectedException (typeof (HttpRequestValidationException))]
47 public void ValidateInput_XSS ()
49 string problem = "http://server.com/attack2.aspx?test=<script>alert('vulnerability')</script>";
50 string decoded = HttpUtility.UrlDecode (problem);
51 int n = decoded.IndexOf ('?');
52 HttpRequest request = new HttpRequest (null, decoded.Substring (0,n), decoded.Substring (n+1));
53 request.ValidateInput ();
54 // the next statement throws
55 Assert.AreEqual ("<script>alert('vulnerability')</script>", request.QueryString ["test"], "QueryString");
59 // * this is to avoid a regression that would cause Mono to
60 // fail again on item #2 of the XSS vulnerabilities listed at:
61 // http://it-project.ru/andir/docs/aspxvuln/aspxvuln.en.xml
62 // * The author notes that Microsoft has decided not to fix
63 // this issue (hence the NotDotNet category).
66 [Category ("NotDotNet")]
67 [ExpectedException (typeof (HttpRequestValidationException))]
68 public void ValidateInput_XSS_Unicode ()
70 string problem = "http://server.com/attack2.aspx?test=%uff1cscript%uff1ealert('vulnerability')%uff1c/script%uff1e";
71 string decoded = HttpUtility.UrlDecode (problem);
72 int n = decoded.IndexOf ('?');
73 HttpRequest request = new HttpRequest (null, decoded.Substring (0,n), decoded.Substring (n+1));
74 request.ValidateInput ();
75 // the next statement throws
76 Assert.AreEqual ("\xff1cscript\xff1ealert('vulnerability')\xff1c/script\xff1e", request.QueryString ["test"], "QueryString");
79 // This has affected ASP.NET 1.1 but it seems fixed now
80 // http://secunia.com/advisories/9716/
81 // http://weblogs.asp.net/kaevans/archive/2003/11/12/37169.aspx
83 [ExpectedException (typeof (HttpRequestValidationException))]
84 public void ValidateInput_XSS_Null ()
86 string problem = "http://secunia.com/?test=<%00SCRIPT>alert(document.cookie)</SCRIPT>";
87 string decoded = HttpUtility.UrlDecode (problem);
88 int n = decoded.IndexOf ('?');
89 HttpRequest request = new HttpRequest (null, decoded.Substring (0,n), decoded.Substring (n+1));
90 request.ValidateInput ();
91 // the next statement throws
92 Assert.AreEqual ("<SCRIPT>alert(document.cookie)</SCRIPT>", request.QueryString ["test"], "QueryString");
96 // Tests the properties from the simple constructor.
98 public void Test_PropertiesSimpleConstructor ()
100 string url = "http://www.gnome.org/";
101 string qs = "key=value&key2=value%32second";
103 HttpRequest r = new HttpRequest ("file", url, qs);
105 Assert.AreEqual ("/?" + qs, r.RawUrl, "U1");
106 Assert.AreEqual (url, r.Url.ToString (), "U2");
108 r = new HttpRequest ("file", "http://www.gnome.org", qs);
109 Assert.AreEqual (url, r.Url.ToString (), "U3");
111 qs = "a&b=1&c=d&e&b=2&d=";
112 r = new HttpRequest ("file", url, qs);
113 NameValueCollection nvc = r.QueryString;
115 Assert.AreEqual ("a,e", nvc [null], "U4");
116 Assert.AreEqual ("1,2", nvc ["b"], "U5");
117 Assert.AreEqual ("d", nvc ["c"], "U5");
118 Assert.AreEqual ("", nvc ["d"], "U6");
119 Assert.AreEqual (4, nvc.Count, "U6");
121 Assert.AreEqual (null, r.ApplicationPath, "U7");
125 [ExpectedException(typeof(ArgumentNullException))]
126 public void Test_AccessToVars ()
128 string url = "http://www.gnome.org/";
129 string qs = "key=value&key2=value%32second";
131 HttpRequest r = new HttpRequest ("file", url, qs);
132 string s = r.PhysicalApplicationPath;
136 public void Test_QueryStringDecoding()
138 string url = "http://www.gnome.org/";
139 string qs = "umlaut=" + HttpUtility.UrlEncode("\u00e4", Encoding.Default);
141 HttpRequest r = new HttpRequest ("file", url, qs);
142 Assert.AreEqual("\u00e4", r.QueryString["umlaut"]);
146 [Category ("NunitWeb")]
147 public void Test_PhysicalApplicationPath ()
149 WebTest t = new WebTest (new HandlerInvoker (new HandlerDelegate (
150 PhysicalApplicationPathDelegate)));
154 static public void PhysicalApplicationPathDelegate ()
156 HttpRequest r = HttpContext.Current.Request;
157 string pap = r.PhysicalApplicationPath;
158 Assert.IsTrue (pap.EndsWith (Path.DirectorySeparatorChar.ToString()), "#1");
159 Assert.AreEqual (Path.GetFullPath (pap), pap, "#2");
163 [Category ("NunitWeb")]
164 public void Test_MapPath ()
166 WebTest t = new WebTest (new HandlerInvoker (new HandlerDelegate (
171 static public void MapPathDelegate ()
173 HttpRequest r = HttpContext.Current.Request;
174 string appBase = r.PhysicalApplicationPath.TrimEnd (Path.DirectorySeparatorChar);
175 Assert.AreEqual (appBase, r.MapPath ("~"), "test1");
176 Assert.AreEqual (appBase, r.MapPath ("/NunitWeb"), "test1.1");
177 Assert.AreEqual (Path.Combine (appBase, "Web.config"),
178 r.MapPath ("Web.config"), "test2");
179 Assert.AreEqual (Path.Combine (appBase, "Web.config"),
180 r.MapPath ("~/Web.config"), "test3");
181 Assert.AreEqual (Path.Combine (appBase, "Web.config"),
182 r.MapPath ("/NunitWeb/Web.config"), "test4");
183 Assert.AreEqual (Path.Combine (appBase, "Web.config"),
184 r.MapPath ("Web.config", null, false), "test5");
185 Assert.AreEqual (Path.Combine (appBase, "Web.config"),
186 r.MapPath ("Web.config", "", false), "test6");
187 Assert.AreEqual (Path.Combine (appBase, "Web.config"),
188 r.MapPath ("Web.config", "/NunitWeb", false), "test7");
189 Assert.AreEqual (Path.Combine (appBase, "Web.config"),
190 r.MapPath ("/NunitWeb/Web.config", "/NunitWeb", false), "test8");
196 public class Test_HttpFakeRequest {
197 class FakeHttpWorkerRequest : HttpWorkerRequest {
198 public int return_kind;
200 [Conditional ("REQUEST_TEST_VERY_VERBOSE")]
203 Console.WriteLine (Environment.StackTrace);
207 public FakeHttpWorkerRequest (int re)
212 public override string GetUriPath()
218 public override string GetQueryString()
222 switch (return_kind) {
226 return "key1=value1&key2=value2";
229 return "mapa.x=10&mapa.y=20";
232 return "mapa.x=10&mapa=20";
234 return "mapa.x=10&mapa.y=20";
240 return "mapa.x=pi&mapa.y=20";
242 return "PlainString";
244 return "Plain&Arg=1";
246 return "GetQueryString";
250 public override string GetRawUrl()
256 public override string GetHttpVerbName()
259 if (return_kind == 25 || return_kind == 26)
261 if (return_kind == 30 || return_kind == 31)
266 public override string GetHttpVersion()
272 public override byte [] GetPreloadedEntityBody ()
274 if (return_kind != 30 && return_kind != 31)
275 return base.GetPreloadedEntityBody ();
277 return Encoding.UTF8.GetBytes (GetQueryString ());
280 public override bool IsEntireEntityBodyIsPreloaded ()
282 if (return_kind != 30 && return_kind != 31)
283 return base.IsEntireEntityBodyIsPreloaded ();
288 public override int GetRemotePort()
293 public override string GetLocalAddress()
298 public override string GetAppPath ()
303 public override string GetRemoteName ()
308 public override string GetRemoteAddress ()
310 return "RemoteAddress";
313 public override string GetServerName ()
318 public override int GetLocalPort()
323 public override void SendStatus(int s, string x)
327 public override void SendKnownResponseHeader(int x, string j)
331 public override void SendUnknownResponseHeader(string a, string b)
335 public override void SendResponseFromMemory(byte[] arr, int x)
339 public override void SendResponseFromFile(string a, long b , long c)
344 public override void SendResponseFromFile (IntPtr a, long b, long c)
348 public override void FlushResponse(bool x)
352 public override void EndOfRequest() {
355 public override string GetKnownRequestHeader (int index)
358 case HttpWorkerRequest.HeaderContentType:
359 switch (return_kind){
360 case 1: return "text/plain";
361 case 2: return "text/plain; charset=latin1";
362 case 3: return "text/plain; charset=iso-8859-1";
363 case 4: return "text/plain; charset=\"iso-8859-1\"";
364 case 5: return "text/plain; charset=\"iso-8859-1\" ; other";
367 return "application/x-www-form-urlencoded";
371 case HttpWorkerRequest.HeaderContentLength:
372 switch (return_kind){
373 case 0: return "1024";
374 case 1: return "-1024";
377 return GetQueryString ().Length.ToString ();
378 case -1: return "Blah";
383 case HttpWorkerRequest.HeaderCookie:
384 switch (return_kind){
385 case 10: return "Key=Value";
386 case 11: return "Key=<value>";
387 case 12: return "Key=>";
388 case 13: return "Key=\xff1c";
389 case 14: return "Key=\xff1e";
392 case HttpWorkerRequest.HeaderReferer:
393 switch (return_kind){
395 case 2: return "http://www.mono-project.com/test.aspx";
396 case 15: return "http://www.mono-project.com";
399 case HttpWorkerRequest.HeaderUserAgent:
400 switch (return_kind){
401 case 15: return "Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040913 Firefox/0.10";
404 case HttpWorkerRequest.HeaderAccept:
405 switch (return_kind){
406 case 21: return "text/xml,application/xml, application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
409 case HttpWorkerRequest.HeaderAcceptLanguage:
410 switch (return_kind){
411 case 21: return "en-us, en;q=0.5";
418 public override string [][] GetUnknownRequestHeaders ()
420 if (return_kind == 0)
421 return new string [0][];
423 if (return_kind == 3){
424 string [][] x = new string [4][];
425 x [0] = new string [] { "k1", "v1" };
426 x [1] = new string [] { "k2", "v2" };
427 x [2] = new string [] { "k3", "v3" };
428 x [3] = new string [] { "k4", "v4" };
433 if (return_kind == 4){
435 // This tests the bad values and the extra row with an error
437 string [][] x = new string [3][];
438 x [0] = new string [] { "k1", "" };
439 x [1] = new string [] { "k2", null };
440 x [2] = new string [] { "k3", " " };
445 if (return_kind == 2){
446 string [][] x = new string [2][];
447 x [0] = new string [] { "k1", "" };
449 // Returns an empty row.
457 HttpContext Cook (int re)
459 FakeHttpWorkerRequest f = new FakeHttpWorkerRequest (re);
460 HttpContext c = new HttpContext (f);
465 [Test] public void Test_BrokenContentLength ()
467 HttpContext c = Cook (-1);
468 Assert.AreEqual (0, c.Request.ContentLength, "C1");
471 Assert.AreEqual (0, c.Request.ContentLength, "C2");
475 [Test][ExpectedException(typeof(NullReferenceException))]
476 public void Test_EmptyUnknownRow ()
478 HttpContext c = Cook (2);
479 NameValueCollection x = c.Request.Headers;
482 [Test] public void Test_RequestFields ()
484 HttpContext c = Cook (1);
487 Assert.IsNull (c.Request.ApplicationPath, "A1");
489 Assert.AreEqual ("AppPath", c.Request.ApplicationPath, "A1");
491 Assert.AreEqual ("text/plain", c.Request.ContentType, "A2");
494 Assert.AreEqual (1024, c.Request.ContentLength, "A3");
497 Assert.AreEqual ("iso-8859-1", c.Request.ContentEncoding.WebName, "A4");
498 NameValueCollection x = c.Request.Headers;
500 Assert.AreEqual ("v1", x ["k1"], "K1");
501 Assert.AreEqual ("v2", x ["k2"], "K2");
502 Assert.AreEqual ("v3", x ["k3"], "K3");
503 Assert.AreEqual ("v4", x ["k4"], "K4");
504 Assert.AreEqual ("text/plain; charset=iso-8859-1", x ["Content-Type"], "K4");
505 Assert.AreEqual (5, x.Count, "K5");
508 Assert.AreEqual ("iso-8859-1", c.Request.ContentEncoding.WebName, "A5");
509 Assert.AreEqual ("text/plain; charset=latin1", c.Request.ContentType, "A5-1");
512 Assert.AreEqual ("iso-8859-1", c.Request.ContentEncoding.WebName, "A6");
513 x = c.Request.Headers;
514 Assert.AreEqual ("", x ["k1"], "K6");
515 Assert.AreEqual (null, x ["k2"], "K7");
516 Assert.AreEqual (" ", x ["k3"], "K8");
517 Assert.AreEqual (4, x.Count, "K9");
520 Assert.AreEqual ("iso-8859-1", c.Request.ContentEncoding.WebName, "A7");
522 Assert.AreEqual ("RemoteName", c.Request.UserHostName, "A8");
523 Assert.AreEqual ("RemoteAddress", c.Request.UserHostAddress, "A9");
525 // Difference between Url property and RawUrl one: one is resolved, the other is not
526 Assert.AreEqual ("/bb.aspx", c.Request.RawUrl, "A10");
527 Assert.AreEqual ("http://localhost:2020/uri.aspx?GetQueryString", c.Request.Url.ToString (), "A11");
530 [Test] public void Test_Cookies ()
535 c.Request.ValidateInput ();
536 Assert.AreEqual ("Value", c.Request.Cookies ["Key"].Value, "cookie1");
540 [ExpectedException(typeof (HttpRequestValidationException))]
541 public void Test_DangerousCookie ()
546 c.Request.ValidateInput ();
547 object a = c.Request.Cookies;
551 public void Test_DangerousCookie2 ()
556 c.Request.ValidateInput ();
557 object a = c.Request.Cookies;
561 public void Test_DangerousCookie3 ()
566 c.Request.ValidateInput ();
567 object a = c.Request.Cookies;
571 public void Test_DangerousCookie4 ()
576 c.Request.ValidateInput ();
577 object a = c.Request.Cookies;
581 public void Test_MiscHeaders ()
583 HttpContext c = Cook (15);
585 // The uri ToString contains the trailing slash.
586 Assert.AreEqual ("http://www.mono-project.com/", c.Request.UrlReferrer.ToString (), "ref1");
588 Assert.AreEqual ("Mozilla/5.0 (X11; U; Linux i686; rv:1.7.3) Gecko/20040913 Firefox/0.10", c.Request.UserAgent, "ref2");
590 // All the AcceptTypes and UserLanguages tests below here pass under MS
592 string [] at = c.Request.AcceptTypes;
593 string [] ul = c.Request.UserLanguages;
594 Assert.IsNull (at, "AT1");
595 Assert.IsNull (ul, "UL1");
597 at = c.Request.AcceptTypes;
598 Assert.IsNotNull (at, "AT2");
599 string [] expected = { "text/xml", "application/xml", "application/xhtml+xml", "text/html;q=0.9",
600 "text/plain;q=0.8", "image/png", "*/*;q=0.5" };
602 Assert.AreEqual (expected.Length, at.Length, "AT3");
603 for (int i = expected.Length - 1; i >= 0; i--)
604 Assert.AreEqual (expected [i], at [i], "AT" + (3 + i));
606 ul = c.Request.UserLanguages;
607 Assert.IsNotNull (ul, "UL2");
608 expected = new string [] { "en-us", "en;q=0.5" };
610 Assert.AreEqual (expected.Length, ul.Length, "UL3");
611 for (int i = expected.Length - 1; i >= 0; i--)
612 Assert.AreEqual (expected [i], ul [i], "UL" + (3 + i));
617 public void Empty_WorkerRequest_QueryString ()
619 HttpContext c = Cook (20);
622 // Checks that the following line does not throw an exception if
623 // the querystring returned by the HttpWorkerRequest is null.
625 NameValueCollection nvc = c.Request.QueryString;
629 public void Test_QueryString_ToString ()
631 HttpContext c = Cook (50);
633 Assert.AreEqual (c.Request.QueryString.ToString (), "PlainString", "QTS#1");
636 Assert.AreEqual (c.Request.QueryString.ToString (), "Plain&Arg=1", "QTS#2");
640 public void Leading_qm_in_QueryString ()
642 HttpContext c = Cook (16);
643 NameValueCollection nvc = c.Request.QueryString;
644 foreach (string id in nvc.AllKeys) {
645 if (id.StartsWith ("?"))
651 public void TestPath ()
653 HttpContext c = Cook (16);
655 // This used to crash, ifolder exposed this
656 string x = c.Request.Path;
660 public void MapImageCoordinatesHEAD ()
662 HttpContext c = Cook (25);
663 int [] coords = c.Request.MapImageCoordinates ("mapa");
664 Assert.IsNotNull (coords, "A1");
665 Assert.AreEqual (10, coords [0], "X");
666 Assert.AreEqual (20, coords [1], "Y");
669 coords = c.Request.MapImageCoordinates ("mapa");
670 Assert.AreEqual (null, coords, "coords");
674 public void MapImageCoordinatesGET ()
676 HttpContext c = Cook (27);
677 int [] coords = c.Request.MapImageCoordinates ("mapa");
678 Assert.AreEqual (10, coords [0], "X");
679 Assert.AreEqual (20, coords [1], "Y");
681 coords = c.Request.MapImageCoordinates ("m");
682 Assert.AreEqual (null, coords, "coords1");
685 coords = c.Request.MapImageCoordinates ("mapa");
686 Assert.AreEqual (null, coords, "coords2");
688 coords = c.Request.MapImageCoordinates ("mapa");
689 Assert.AreEqual (null, coords, "coords3");
691 coords = c.Request.MapImageCoordinates ("mapa");
692 Assert.AreEqual (null, coords, "coords4");
696 public void MapImageCoordinatesPOST ()
698 HttpContext c = Cook (30);
699 int [] coords = c.Request.MapImageCoordinates ("mapa");
700 Assert.IsNotNull (coords, "A1");
701 Assert.AreEqual (10, coords [0], "X");
702 Assert.AreEqual (20, coords [1], "Y");
705 coords = c.Request.MapImageCoordinates ("mapa");
706 Assert.AreEqual (null, coords, "coords2");
710 public void TestReferer ()
712 HttpContext c = Cook (1);
714 Assert.AreEqual (null, c.Request.UrlReferrer, "REF1");
717 Assert.AreEqual ("http://www.mono-project.com/test.aspx", c.Request.UrlReferrer.ToString (), "REF1");
722 public void NegativeContentLength ()
724 HttpContext c = Cook (1);
725 HttpRequest req = c.Request;
726 Assert.AreEqual (0, req.ContentLength, "#01");
730 // This class is defined here to make it easy to create fake
731 // HttpWorkerRequest-derived classes by only overriding the methods
732 // necessary for testing.
733 class BaseFakeHttpWorkerRequest : HttpWorkerRequest
735 public override void EndOfRequest()
739 public override void FlushResponse(bool finalFlush)
743 public override string GetHttpVerbName()
748 public override string GetHttpVersion()
753 public override string GetLocalAddress()
758 public override int GetLocalPort()
763 public override string GetQueryString()
768 public override string GetRawUrl()
770 string rawUrl = GetUriPath();
771 string queryString = GetQueryString();
772 if (queryString != null && queryString.Length > 0)
774 rawUrl += "?" + queryString;
779 public override string GetRemoteAddress()
784 public override int GetRemotePort()
789 public override string GetUriPath()
791 return "default.aspx";
794 public override void SendKnownResponseHeader(int index, string value)
798 public override void SendResponseFromFile(IntPtr handle, long offset, long length)
802 public override void SendResponseFromFile(string filename, long offset, long length)
806 public override void SendResponseFromMemory(byte[] data, int length)
810 public override void SendStatus(int statusCode, string statusDescription)
814 public override void SendUnknownResponseHeader(string name, string value)
819 // This test ensures accessing the Form property does not throw an
820 // exception when the length of data in the request exceeds the length
821 // as reported by the Content-Length header. This bug was discovered
822 // with an AJAX application using XMLHttpRequest to POST back to the
823 // server. The Content-Length header was two bytes less than the length
824 // of the buffer returned from GetPreloadedEntityBody. This was causing
825 // an exception to be thrown by Mono because it was trying to allocate
826 // a buffer that was -2 bytes in length.
828 public class Test_UrlEncodedBodyWithExtraCRLF
830 class FakeHttpWorkerRequest : BaseFakeHttpWorkerRequest
832 // This string is 9 bytes in length. That's 2 more than
833 // the Content-Length header says it should be.
834 string data = "foo=bar\r\n";
836 public override string GetKnownRequestHeader(int index)
840 case HttpWorkerRequest.HeaderContentLength:
841 return (data.Length - 2).ToString();
842 case HttpWorkerRequest.HeaderContentType:
843 return "application/x-www-form-urlencoded";
848 public override byte[] GetPreloadedEntityBody()
850 return Encoding.ASCII.GetBytes(data);
854 HttpContext context = null;
859 HttpWorkerRequest workerRequest = new FakeHttpWorkerRequest();
860 context = new HttpContext(workerRequest);
864 public void ContentLength()
866 Assert.AreEqual(7, context.Request.ContentLength);
870 public void Form_Count()
872 Assert.AreEqual(1, context.Request.Form.Count);
876 [Category ("NotDotNet")]
877 public void Form_Item()
879 // I would have expected the extra two characters to be stripped
880 // but Microsoft's CLR keeps them so Mono should, too.
881 //Assert.AreEqual("bar\r\n", context.Request.Form["foo"]);
882 Assert.AreEqual("bar", context.Request.Form["foo"]);
886 // This test ensures the HttpRequet object's Form property gets
887 // properly constructed and populated when the Content-Type header
888 // includes a charset parameter and that the charset parameter is
891 public class Test_UrlEncodedBodyWithUtf8CharsetParameter
893 class FakeHttpWorkerRequest : BaseFakeHttpWorkerRequest
895 // The two funny-looking characters are really a single
896 // accented "a" character encoded in UTF-8.
897 string data = "foo=b%C3%A1r";
899 public override string GetKnownRequestHeader(int index)
903 case HttpWorkerRequest.HeaderContentLength:
904 return data.Length.ToString();
905 case HttpWorkerRequest.HeaderContentType:
906 return "application/x-www-form-urlencoded; charset=utf-8";
911 public override byte[] GetPreloadedEntityBody()
913 return Encoding.ASCII.GetBytes(data);
917 HttpContext context = null;
922 HttpWorkerRequest workerRequest = new FakeHttpWorkerRequest();
923 context = new HttpContext(workerRequest);
927 public void Form_Count()
929 Assert.AreEqual(1, context.Request.Form.Count);
933 public void Form_Item()
935 Assert.AreEqual("b\xE1r", context.Request.Form["foo"]);