[System.Net] Add support for .pac proxy config scripts on mac
[mono.git] / mcs / class / System.Web / Test / System.Web / HttpResponseTest.cs
1 //
2 // System.Web.HttpResponseTest.cs - Unit tests for System.Web.HttpResponse
3 //
4 // Author:
5 //      Miguel de Icaza  <miguel@ximian.com>
6 //
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.Collections.Specialized;
32 using System.Configuration.Provider;
33 using System.IO;
34 using System.Text;
35 using System.Web;
36 #if NET_4_0
37 using System.Web.Routing;
38 using System.Web.Caching;
39 #endif
40
41 using NUnit.Framework;
42
43 using MonoTests.Common;
44
45 namespace MonoTests.System.Web {
46
47         public class FakeHttpWorkerRequest2 : HttpWorkerRequest {
48                 public Hashtable KnownResponseHeaders;
49                 public Hashtable UnknownResponseHeaders;
50                 public int return_kind;
51                 
52                 public FakeHttpWorkerRequest2 (int re)
53                 {
54                         KnownResponseHeaders = CollectionsUtil.CreateCaseInsensitiveHashtable();
55                         UnknownResponseHeaders = CollectionsUtil.CreateCaseInsensitiveHashtable();
56                         return_kind = re;
57                 }
58                 
59                 public override string GetUriPath()
60                 {
61                         return "/fake";
62                 }
63                 
64                 public override string GetQueryString()
65                 {
66                         return "GetQueryString";
67                 }
68                 
69                 public override string GetRawUrl()
70                 {
71                         return "/GetRawUrl";
72                 }
73                 
74                 public override string GetHttpVerbName()
75                 {
76                         return "GET";
77                 }
78                 
79                 public override string GetHttpVersion()
80                 {
81                         if (return_kind == 1)
82                                 return "HTTP/1.0";
83                         else
84                                 return "HTTP/1.1";
85                 }
86                 
87                 public override string GetRemoteAddress()
88                 {
89                         return "__GetRemoteAddress";
90                         }
91         
92                 public override int GetRemotePort()
93                 {
94                         return 1010;
95                 }
96                 
97                 public override string GetLocalAddress()
98                 {
99                         return "GetLocalAddress";
100                 }
101                 
102                 public override string GetAppPath ()
103                 {
104                         return "AppPath";
105                 }
106                 
107                 public override int GetLocalPort()
108                 {
109                         return 2020;
110                 }
111
112                 public bool status_sent;
113                 public int status_code;
114                 public string status_string;
115                 
116                 public override void SendStatus(int s, string x)
117                 {
118                         status_sent = true;
119                         status_code = s;
120                         status_string = x;
121                 }
122
123                 void AddHeader (Hashtable table, string header_name, object header)
124                 {
125                         object o = table [header_name];
126                         if (o == null)
127                                 table.Add (header_name, header);
128                         else {
129                                 ArrayList al = o as ArrayList;
130                                 if (al == null) {
131                                         al = new ArrayList ();
132                                         al.Add (o);
133                                         table [header_name] = al;
134                                 } else
135                                         al = o as ArrayList;
136                                 
137                                 al.Add (header);
138                         }
139                 }
140                 
141                 bool headers_sent;
142                 public override void SendKnownResponseHeader(int x, string j)
143                 {
144                         string header_name = HttpWorkerRequest.GetKnownRequestHeaderName (x);
145                         AddHeader (KnownResponseHeaders, header_name, new KnownResponseHeader (x, j));
146                         headers_sent = true;
147                 }
148                 
149                 public override void SendUnknownResponseHeader(string a, string b)
150                 {
151                         AddHeader (UnknownResponseHeaders, a, new UnknownResponseHeader (a, b));
152                         headers_sent = true;
153                 }
154
155                 bool data_sent;
156                 public byte [] data;
157                 public int data_len;
158                 public int total = 0;
159                 
160                 public override void SendResponseFromMemory(byte[] arr, int x)
161                 {
162                         data_sent = true;
163                         if (data != null) {
164                                 byte [] tmp = new byte [data.Length + x];
165                                 Array.Copy (data, tmp, data.Length);
166                                 Array.Copy (arr, 0, tmp, data.Length, x);
167                                 data = tmp;
168                                 data_len = data.Length;
169                         } else {
170                                 data = new byte [x];
171                                 for (int i = 0; i < x; i++)
172                                         data [i] = arr [i];
173                                 data_len = x;
174                         }
175                         total += x;
176                 }
177                 
178                 public override void SendResponseFromFile(string a, long b , long c)
179                 {
180                         data_sent = true;
181                 }
182                 
183                 public override void SendResponseFromFile (IntPtr a, long b, long c)
184                 {
185                         data_sent = true;
186                 }
187                 
188                 public override void FlushResponse(bool x)
189                 {
190                 }
191                 
192                 public override void EndOfRequest() {
193                 }
194                 
195                 public override string GetKnownRequestHeader (int index)
196                 {
197                         return null;
198                 }
199
200                 public bool OutputProduced {
201                         get {
202                                 return headers_sent || data_sent;
203                         }
204                 }
205         }
206
207         class KnownResponseHeader
208         {
209                 private int index;
210                 private string value;
211
212                 public KnownResponseHeader (int index, string value)
213                 {
214                         this.index = index;
215                         this.value = value;
216                 }
217
218                 public int Index {
219                         get { return index; }
220                 }
221
222                 public string Value {
223                         get { return value; }
224                 }
225         }
226
227         class UnknownResponseHeader
228         {
229                 private string name;
230                 private string value;
231
232                 public UnknownResponseHeader (string name, string value)
233                 {
234                         this.name = name;
235                         this.value = value;
236                 }
237
238                 public string Name {
239                         get { return name; }
240                 }
241
242                 public string Value {
243                         get { return value; }
244                 }
245         }
246
247         [TestFixture]
248         public class HttpResponseTest {
249                 public static HttpContext Cook (int re, out FakeHttpWorkerRequest2 f)
250                 {
251                         f = new FakeHttpWorkerRequest2 (re);
252                         HttpContext c = new HttpContext (f);
253
254                         return c;
255                 }
256
257                 [SetUp]
258                 public void SetUp ()
259                 {
260 #if NET_2_0
261                         AppDomain.CurrentDomain.SetData (".appPath", AppDomain.CurrentDomain.BaseDirectory);
262 #endif
263                 }
264
265                 [Test]
266 #if TARGET_JVM
267                 [Category ("NotWorking")] // char output stream in gh make this test fail
268 #endif
269                 public void Test_Response ()
270                 {
271                         FakeHttpWorkerRequest2 f;
272                         HttpContext c = Cook (1, out f);
273
274                         c.Response.Write ("a");
275                         Assert.AreEqual (false, f.OutputProduced, "T1");
276                         c.Response.Flush ();
277                         Assert.AreEqual (1, f.data_len, "T2");
278                         c.Response.Write ("Hola");
279                         Assert.AreEqual (1, f.data_len, "T3");
280                         c.Response.Flush ();
281                         Assert.AreEqual (5, f.data_len, "T4");
282                         Assert.AreEqual ((byte) 'a', f.data [0], "T5");
283                         Assert.AreEqual ((byte) 'H', f.data [1], "T6");
284                         Assert.AreEqual ((byte) 'o', f.data [2], "T7");
285                         Assert.AreEqual ((byte) 'l', f.data [3], "T8");
286                         Assert.AreEqual ((byte) 'a', f.data [4], "T9");
287                 }
288
289                 [Test]
290 #if TARGET_JVM
291                 [Category ("NotWorking")] // char output stream in gh make this test fail
292 #endif
293                 public void TestResponse_Chunked ()
294                 {
295                         FakeHttpWorkerRequest2 f;
296                         HttpContext c = Cook (2, out f);
297
298                         c.Response.Write ("a");
299                         Assert.AreEqual (false, f.OutputProduced, "CT1");
300                         c.Response.Flush ();
301                         Assert.AreEqual (6, f.total, "CT2");
302                         c.Response.Write ("Hola");
303                         Assert.AreEqual (6, f.total, "CT3");
304                         c.Response.Flush ();
305                         
306                 }
307
308                 [Test]
309                 public void Status1 ()
310                 {
311                         FakeHttpWorkerRequest2 f;
312                         HttpContext c = Cook (2, out f);
313
314                         HttpResponse resp = c.Response;
315                         resp.Status = "200 Lalala";
316                         Assert.AreEqual (200, resp.StatusCode, "ST1");
317                         Assert.AreEqual ("Lalala", resp.StatusDescription, "ST2");
318
319                         resp.Status = "10000 La la la";
320                         Assert.AreEqual (10000, resp.StatusCode, "ST3");
321                         Assert.AreEqual ("La la la", resp.StatusDescription, "ST4");
322
323                         resp.Status = "-1 La la la";
324                         Assert.AreEqual (-1, resp.StatusCode, "ST5");
325                         Assert.AreEqual ("La la la", resp.StatusDescription, "ST6");
326
327                         resp.Status = "-200 La la la";
328                         Assert.AreEqual (-200, resp.StatusCode, "ST7");
329                         Assert.AreEqual ("La la la", resp.StatusDescription, "ST8");
330
331                         resp.Status = "200 ";
332                         Assert.AreEqual (200, resp.StatusCode, "ST7");
333                         Assert.AreEqual ("", resp.StatusDescription, "ST8");
334                 }
335
336                 [Test]
337                 public void Status2 ()
338                 {
339                         FakeHttpWorkerRequest2 f;
340                         HttpContext c = Cook (2, out f);
341
342                         HttpResponse resp = c.Response;
343                         try {
344                                 resp.Status = "200";
345                                 Assert.Fail ("#1");
346                         } catch (HttpException) {
347                         }
348                 }
349
350                 [Test]
351                 public void Status3 ()
352                 {
353                         FakeHttpWorkerRequest2 f;
354                         HttpContext c = Cook (2, out f);
355
356                         HttpResponse resp = c.Response;
357                         try {
358                                 resp.Status = "200\t";
359                                 Assert.Fail ("#1");
360                         } catch (HttpException) {
361                         }
362                 }
363
364                 [Test]
365                 public void Status4 ()
366                 {
367                         FakeHttpWorkerRequest2 f;
368                         HttpContext c = Cook (2, out f);
369
370                         HttpResponse resp = c.Response;
371
372                         Assert.AreEqual (200, resp.StatusCode, "STT1");
373                         Assert.AreEqual (HttpWorkerRequest.GetStatusDescription (200), resp.StatusDescription, "STT2");
374
375                         resp.StatusCode = 400;
376                         Assert.AreEqual (400, resp.StatusCode, "STT3");
377                         Assert.AreEqual (HttpWorkerRequest.GetStatusDescription (400), resp.StatusDescription, "STT4");
378
379                         resp.StatusDescription = "Something else";
380                         Assert.AreEqual (400, resp.StatusCode, "STT5");
381                         Assert.AreEqual ("Something else", resp.StatusDescription, "STT6");
382
383                         resp.StatusDescription = null;
384                         Assert.AreEqual (400, resp.StatusCode, "STT7");
385                         Assert.AreEqual (HttpWorkerRequest.GetStatusDescription (400), resp.StatusDescription, "STT8");
386                 }
387
388                 //
389                 // TODO: Add test for BinaryWrite and the various writes to check for Chunked Mode
390                 //`
391
392                 [Test]
393                 public void SetCacheability ()
394                 {
395                         FakeHttpWorkerRequest2 f;
396                         HttpContext c = Cook (1, out f);
397
398                         //
399                         // Basically the values from CacheControl are useless once Response.Cache is used
400                         //
401                         c.Response.Cache.SetCacheability (HttpCacheability.ServerAndNoCache);
402                         Assert.AreEqual ("private", c.Response.CacheControl, "C1");
403                         
404                         c.Response.Cache.SetCacheability (HttpCacheability.ServerAndPrivate);
405                         Assert.AreEqual ("private", c.Response.CacheControl, "C2");
406                         
407                         c.Response.Cache.SetCacheability (HttpCacheability.NoCache);
408                         Assert.AreEqual ("private", c.Response.CacheControl, "C3");
409                         
410                         c.Response.Cache.SetCacheability (HttpCacheability.Private);
411                         Assert.AreEqual ("private", c.Response.CacheControl, "C4");
412                         
413                         c.Response.Cache.SetCacheability (HttpCacheability.Server);
414                         Assert.AreEqual ("private", c.Response.CacheControl, "C5");
415                         
416                         c.Response.Cache.SetCacheability (HttpCacheability.Public);
417                         Assert.AreEqual ("private", c.Response.CacheControl, "C6");
418                 }
419
420                 //
421                 // Test the values allowed;  .NET only documents private and public, but
422                 // "no-cache" from the spec is also allowed
423                 //
424                 [Test]
425                 public void CacheControl ()
426                 {
427                         FakeHttpWorkerRequest2 f;
428                         HttpContext c = Cook (1, out f);
429
430                         // Default value.
431                         Assert.AreEqual ("private", c.Response.CacheControl, "D1");
432                                          
433                         c.Response.CacheControl = "private";
434                         Assert.AreEqual ("private", c.Response.CacheControl, "D2");
435
436                         c.Response.CacheControl = "public";
437                         Assert.AreEqual ("public", c.Response.CacheControl, "D3");
438                         
439                         c.Response.CacheControl = "no-cache";
440                         Assert.AreEqual ("no-cache", c.Response.CacheControl, "D4");
441
442                         c.Response.CacheControl = null;
443                         Assert.AreEqual ("private", c.Response.CacheControl, "D5");
444
445                         c.Response.CacheControl = "";
446                         Assert.AreEqual ("private", c.Response.CacheControl, "D6");
447                 }
448
449                 //
450                 // Just checks if the AddFileDepend* methods accept values, added after bug #342511
451                 [Test]
452                 public void AddFileDependencies ()
453                 {
454                         FakeHttpWorkerRequest2 f;
455                         HttpContext c = Cook (1, out f);
456
457                         ArrayList a = new ArrayList (1);
458                         a.Add ("somefile.txt");
459                         c.Response.AddFileDependencies (a);
460
461 #if NET_2_0
462                         string[] sa = new string [1] {"somefile.txt"};
463                         c = Cook (1, out f);
464                         c.Response.AddFileDependencies (sa);
465 #endif
466
467                         c = Cook (1, out f);
468                         c.Response.AddFileDependency ("somefile.txt");
469                 }
470
471                 [Test] // bug #488702
472                 public void WriteHeaders ()
473                 {
474                         FakeHttpWorkerRequest2 f;
475                         HttpContext c = Cook (2, out f);
476
477                         HttpResponse resp = c.Response;
478                         resp.CacheControl = "public";
479                         resp.Cache.SetCacheability (HttpCacheability.NoCache);
480                         resp.ContentType = "text/xml";
481                         resp.AppendHeader ("Content-Disposition", "inline");
482                         resp.AppendHeader ("Content-Type", "application/ms-word");
483                         resp.AppendHeader ("Content-Length", "40");
484                         resp.AppendHeader ("Transfer-Encoding", "compress");
485                         resp.AppendHeader ("My-Custom-Header", "never");
486                         resp.AppendHeader ("My-Custom-Header", "always");
487
488                         Assert.AreEqual ("public", resp.CacheControl, "#A1");
489                         Assert.AreEqual ("application/ms-word", resp.ContentType, "#A2");
490                         Assert.AreEqual (0, f.KnownResponseHeaders.Count, "#A3");
491                         Assert.AreEqual (0, f.UnknownResponseHeaders.Count, "#A4");
492
493                         resp.Flush ();
494
495                         KnownResponseHeader known;
496
497                         Assert.AreEqual (6, f.KnownResponseHeaders.Count, "#B1");
498                         
499                         known = (KnownResponseHeader)f.KnownResponseHeaders ["Content-Length"];
500                         Assert.AreEqual (HttpWorkerRequest.HeaderContentLength, known.Index, "#B2");
501                         Assert.AreEqual ("40", known.Value, "#B3");
502                         
503                         known = (KnownResponseHeader)f.KnownResponseHeaders["Transfer-Encoding"];
504                         Assert.AreEqual (HttpWorkerRequest.HeaderTransferEncoding, known.Index, "#B4");
505                         Assert.AreEqual ("compress", known.Value, "#B5");
506                         
507                         known = (KnownResponseHeader)f.KnownResponseHeaders["Cache-Control"];
508                         Assert.AreEqual (HttpWorkerRequest.HeaderCacheControl, known.Index, "#B6");
509                         Assert.AreEqual ("no-cache", known.Value, "#B7");
510                         
511                         known = (KnownResponseHeader)f.KnownResponseHeaders["Pragma"];
512                         Assert.AreEqual (HttpWorkerRequest.HeaderPragma, known.Index, "#B8");
513                         Assert.AreEqual ("no-cache", known.Value, "#B9");
514                         
515                         known = (KnownResponseHeader)f.KnownResponseHeaders["Expires"];
516                         Assert.AreEqual (HttpWorkerRequest.HeaderExpires, known.Index, "#B10");
517                         Assert.AreEqual ("-1", known.Value, "#B11");
518                         
519                         known = (KnownResponseHeader)f.KnownResponseHeaders["Content-Type"];
520                         Assert.AreEqual (HttpWorkerRequest.HeaderContentType, known.Index, "#B12");
521                         Assert.AreEqual ("application/ms-word", known.Value, "#B13");
522
523                         UnknownResponseHeader unknown;
524
525                         Assert.AreEqual (3, f.UnknownResponseHeaders.Count, "#C1");
526
527                         unknown = (UnknownResponseHeader) f.UnknownResponseHeaders ["X-AspNet-Version"];
528                         Assert.AreEqual ("X-AspNet-Version", unknown.Name, "#C2");
529                         Assert.AreEqual (Environment.Version.ToString (3), unknown.Value, "#C3");
530
531                         unknown = (UnknownResponseHeader) f.UnknownResponseHeaders ["Content-Disposition"];
532                         Assert.AreEqual ("Content-Disposition", unknown.Name, "#C4");
533                         Assert.AreEqual ("inline", unknown.Value, "#C5");
534
535                         ArrayList al = f.UnknownResponseHeaders ["My-Custom-Header"] as ArrayList;
536                         Assert.AreEqual (2, al.Count, "#C6");
537
538                         unknown = (UnknownResponseHeader) al [0];
539                         Assert.AreEqual ("My-Custom-Header", unknown.Name, "#C7");
540                         Assert.AreEqual ("never", unknown.Value, "#C8");
541
542                         unknown = (UnknownResponseHeader) al [1];
543                         Assert.AreEqual ("My-Custom-Header", unknown.Name, "#C9");
544                         Assert.AreEqual ("always", unknown.Value, "#C10");
545                 }
546
547                 [Test] // pull #866
548                 public void WriteHeadersNoCharset ()
549                 {
550                         FakeHttpWorkerRequest2 f;
551                         HttpContext c = Cook (2, out f);
552
553                         HttpResponse resp = c.Response;
554                         resp.ContentType = "text/plain";
555
556                         Assert.AreEqual ("text/plain", resp.ContentType, "#A1");
557
558                         resp.Flush ();
559
560                         KnownResponseHeader known;
561
562                         Assert.LessOrEqual (1, f.KnownResponseHeaders.Count, "#B1");
563
564                         known = (KnownResponseHeader)f.KnownResponseHeaders ["Content-Type"];
565                         Assert.AreEqual (HttpWorkerRequest.HeaderContentType, known.Index, "#B2");
566                         Assert.AreEqual ("text/plain", known.Value, "#B3");
567                 }
568
569                 [Test] // pull #866
570                 public void WriteHeadersHasCharset ()
571                 {
572                         FakeHttpWorkerRequest2 f;
573                         HttpContext c = Cook (2, out f);
574
575                         HttpResponse resp = c.Response;
576                         resp.ContentType = "text/plain";
577                         resp.Charset = "big5";
578
579                         Assert.AreEqual ("text/plain", resp.ContentType, "#A1");
580                         Assert.AreEqual ("big5", resp.Charset, "#A2");
581
582                         resp.Flush ();
583
584                         KnownResponseHeader known;
585
586                         Assert.LessOrEqual (1, f.KnownResponseHeaders.Count, "#B1");
587
588                         known = (KnownResponseHeader)f.KnownResponseHeaders ["Content-Type"];
589                         Assert.AreEqual (HttpWorkerRequest.HeaderContentType, known.Index, "#B2");
590                         Assert.AreEqual ("text/plain; charset=big5", known.Value, "#B3");
591                 }
592
593                 [Test] // bug #485557
594                 [Category ("NotWorking")] // bug #488702
595                 public void ClearHeaders ()
596                 {
597                         FakeHttpWorkerRequest2 f;
598                         HttpContext c = Cook (2, out f);
599
600                         HttpResponse resp = c.Response;
601                         resp.CacheControl = "public";
602                         resp.Cache.SetCacheability (HttpCacheability.NoCache);
603                         resp.ContentType = "text/xml";
604                         resp.AppendHeader ("Content-Disposition", "inline");
605                         resp.AppendHeader ("Content-Type", "application/ms-word");
606                         resp.AppendHeader ("Content-Length", "40");
607                         resp.AppendHeader ("Transfer-Encoding", "compress");
608                         resp.AppendHeader ("My-Custom-Header", "never");
609                         resp.AppendHeader ("My-Custom-Header", "always");
610                         resp.ClearHeaders ();
611
612                         Assert.AreEqual ("private", resp.CacheControl, "#A1");
613                         Assert.AreEqual ("text/html", resp.ContentType, "#A2");
614                         Assert.AreEqual (0, f.KnownResponseHeaders.Count, "#A3");
615                         Assert.AreEqual (0, f.UnknownResponseHeaders.Count, "#A4");
616
617                         resp.Flush ();
618
619                         KnownResponseHeader known;
620
621                         Assert.AreEqual (3, f.KnownResponseHeaders.Count, "#B1");
622                         
623                         known = (KnownResponseHeader) f.KnownResponseHeaders ["Transfer-Encoding"];
624                         Assert.AreEqual (HttpWorkerRequest.HeaderTransferEncoding, known.Index, "#B2");
625                         Assert.AreEqual ("chunked", known.Value, "#B3");
626                         
627                         known = (KnownResponseHeader) f.KnownResponseHeaders ["Cache-Control"];
628                         Assert.AreEqual (HttpWorkerRequest.HeaderCacheControl, known.Index, "#B4");
629                         Assert.AreEqual ("private", known.Value, "#B5");
630                         
631                         known = (KnownResponseHeader) f.KnownResponseHeaders ["Content-Type"];
632                         Assert.AreEqual (HttpWorkerRequest.HeaderContentType, known.Index, "#B6");
633                         Assert.AreEqual ("text/html", known.Value, "#B7");
634
635 #if NET_2_0
636                         Assert.AreEqual (1, f.UnknownResponseHeaders.Count, "#C1");
637                         UnknownResponseHeader unknown = (UnknownResponseHeader) f.UnknownResponseHeaders ["X-AspNet-Version"];
638                         Assert.AreEqual ("X-AspNet-Version", unknown.Name, "#C2");
639                         Assert.AreEqual (Environment.Version.ToString (3), unknown.Value, "#C3");
640 #else
641                         Assert.AreEqual (0, f.UnknownResponseHeaders.Count, "#C1");
642 #endif
643                 }
644
645                 [Test]
646                 public void Constructor ()
647                 {
648                         var resp = new HttpResponse (null);
649                         Assert.IsNull (resp.Output, "#A1");
650                 }
651 #if NET_4_0
652                 [Test]
653                 public void RedirectPermanent ()
654                 {
655                         FakeHttpWorkerRequest2 request;
656                         HttpContext context = Cook (1, out request);
657                         AssertExtensions.Throws<ArgumentNullException> (() => {
658                                 context.Response.RedirectPermanent (null);
659                         }, "#A1");
660
661                         AssertExtensions.Throws<ArgumentException> (() => {
662                                 context.Response.RedirectPermanent ("http://invalid\nurl.com");
663                         }, "#A2");
664
665                         AssertExtensions.Throws<ArgumentNullException> (() => {
666                                 context.Response.RedirectPermanent (null, true);
667                         }, "#A3");
668
669                         AssertExtensions.Throws<ArgumentException> (() => {
670                                 context.Response.RedirectPermanent ("http://invalid\nurl.com", true);
671                         }, "#A4");
672                 }
673
674                 [Test]
675                 public void RedirectToRoute ()
676                 {
677                         var resp = new HttpResponse (new StringWriter ());
678                         // Ho, ho, ho!
679                         AssertExtensions.Throws<NullReferenceException> (() => {
680                                 resp.RedirectToRoute ("SomeRoute");
681                         }, "#A1");
682
683                         FakeHttpWorkerRequest2 request;
684                         HttpContext context = Cook (1, out request);
685
686                         // From RouteCollection.GetVirtualPath
687                         AssertExtensions.Throws<ArgumentException> (() => {
688                                 context.Response.RedirectToRoute ("SomeRoute");
689                         }, "#A2");
690
691                         AssertExtensions.Throws<InvalidOperationException> (() => {
692                                 context.Response.RedirectToRoute (new { productId = "1", category = "widgets" });
693                         }, "#A3");
694                 }
695
696                 [Test]
697                 public void RemoveOutputCacheItem ()
698                 {
699                         AssertExtensions.Throws<ArgumentNullException> (() => {
700                                 HttpResponse.RemoveOutputCacheItem (null, "MyProvider");
701                         }, "#A1");
702
703                         AssertExtensions.Throws<ArgumentException> (() => {
704                                 HttpResponse.RemoveOutputCacheItem ("badPath", null);
705                         }, "#A2");
706
707                         Assert.IsNull (OutputCache.Providers, "#A3");
708                         HttpResponse.RemoveOutputCacheItem ("/Path", null);
709
710                         AssertExtensions.Throws<ProviderException> (() => {
711                                 HttpResponse.RemoveOutputCacheItem ("/Path", String.Empty);
712                         }, "#A3");
713
714                         AssertExtensions.Throws<ProviderException> (() => {
715                                 HttpResponse.RemoveOutputCacheItem ("/Path", "MyProvider");
716                         }, "#A4");
717                 }
718
719                 [Test]
720                 public void OutputSetter ()
721                 {
722                         FakeHttpWorkerRequest2 request;
723                         HttpContext context = Cook (1, out request);
724
725                         Assert.IsNotNull (context.Response.Output, "#A1");
726                         context.Response.Output = null;
727                         Assert.IsNull (context.Response.Output, "#A2");
728
729                         // Classy...
730                         AssertExtensions.Throws<NullReferenceException> (() => {
731                                 context.Response.Write ('t');
732                         }, "#A3-1");
733
734                         AssertExtensions.Throws<NullReferenceException> (() => {
735                                 context.Response.Write ((object) 5);
736                         }, "#A3-2");
737
738                         AssertExtensions.Throws<NullReferenceException> (() => {
739                                 context.Response.Write ("string");
740                         }, "#A3-3");
741
742                         AssertExtensions.Throws<NullReferenceException> (() => {
743                                 context.Response.Write (new char [] { '1' }, 0, 1);
744                         }, "#A3-4");
745
746                         AssertExtensions.Throws<NullReferenceException> (() => {
747                                 context.Response.Write ((object) null);
748                         }, "#A3-5");
749                 }
750 #endif
751         }
752
753         [TestFixture]
754         public class HttpResponseOutputStreamTest
755         {
756                 FakeHttpWorkerRequest2 worker;
757                 HttpContext context;
758                 HttpResponse response;
759                 Stream out_stream;
760
761                 [SetUp]
762                 public void Setup ()
763                 {
764                         context = Cook (2, out worker);
765                         response = context.Response;
766                         out_stream = response.OutputStream;
767                 }
768
769                 [TearDown]
770                 public void TearDown ()
771                 {
772                         if (response != null)
773                                 response.Close ();
774                 }
775
776                 [Test]
777                 public void CanRead ()
778                 {
779                         Assert.IsFalse (out_stream.CanRead, "#1");
780                         out_stream.Close ();
781                         Assert.IsFalse (out_stream.CanRead, "#2");
782                 }
783
784                 [Test]
785                 public void CanSeek ()
786                 {
787                         Assert.IsFalse (out_stream.CanSeek, "#1");
788                         out_stream.Close ();
789                         Assert.IsFalse (out_stream.CanSeek, "#2");
790                 }
791
792                 [Test]
793                 public void CanWrite ()
794                 {
795                         Assert.IsTrue (out_stream.CanWrite, "#1");
796                         out_stream.Close ();
797                         Assert.IsTrue (out_stream.CanWrite, "#2");
798                 }
799
800                 [Test]
801                 public void Flush ()
802                 {
803                         byte [] buffer = Encoding.UTF8.GetBytes ("mono");
804                         out_stream.Write (buffer, 0, buffer.Length);
805                         out_stream.Flush ();
806                         Assert.AreEqual (0, worker.data_len);
807                 }
808
809                 [Test]
810                 public void Length ()
811                 {
812                         try {
813                                 long len = out_stream.Length;
814                                 Assert.Fail ("#1:" + len);
815                         } catch (NotSupportedException ex) {
816                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
817                                 Assert.IsNull (ex.InnerException, "#3");
818                                 Assert.IsNotNull (ex.Message, "#4");
819                         }
820                 }
821
822                 [Test]
823                 public void Position ()
824                 {
825                         try {
826                                 long pos = out_stream.Position;
827                                 Assert.Fail ("#A1:" + pos);
828                         } catch (NotSupportedException ex) {
829                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#A2");
830                                 Assert.IsNull (ex.InnerException, "#A3");
831                                 Assert.IsNotNull (ex.Message, "#A4");
832                         }
833
834                         try {
835                                 out_stream.Position = 0;
836                                 Assert.Fail ("#B1");
837                         } catch (NotSupportedException ex) {
838                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#B2");
839                                 Assert.IsNull (ex.InnerException, "#B3");
840                                 Assert.IsNotNull (ex.Message, "#B4");
841                         }
842                 }
843
844                 [Test]
845                 public void Read ()
846                 {
847                         byte [] buffer = new byte [5];
848
849                         try {
850                                 out_stream.Read (buffer, 0, buffer.Length);
851                                 Assert.Fail ("#1");
852                         } catch (NotSupportedException ex) {
853                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
854                                 Assert.IsNull (ex.InnerException, "#3");
855                                 Assert.IsNotNull (ex.Message, "#4");
856                         }
857                 }
858
859                 [Test]
860                 public void Seek ()
861                 {
862                         try {
863                                 out_stream.Seek (5, SeekOrigin.Begin);
864                                 Assert.Fail ("#1");
865                         } catch (NotSupportedException ex) {
866                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
867                                 Assert.IsNull (ex.InnerException, "#3");
868                                 Assert.IsNotNull (ex.Message, "#4");
869                         }
870                 }
871
872                 [Test]
873                 public void SetLength ()
874                 {
875                         try {
876                                 out_stream.SetLength (5L);
877                                 Assert.Fail ("#1");
878                         } catch (NotSupportedException ex) {
879                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
880                                 Assert.IsNull (ex.InnerException, "#3");
881                                 Assert.IsNotNull (ex.Message, "#4");
882                         }
883                 }
884
885                 [Test]
886                 public void Write ()
887                 {
888                         byte [] buffer;
889
890                         buffer = Encoding.UTF8.GetBytes ("mono");
891                         out_stream.Write (buffer, 0, buffer.Length);
892                         buffer = Encoding.UTF8.GetBytes ("just rocks!!");
893                         out_stream.Write (buffer, 5, 6);
894                         out_stream.Write (buffer, 0, 4);
895                         Assert.IsFalse (worker.OutputProduced, "#1");
896                         response.Flush ();
897                         Assert.IsTrue (worker.OutputProduced, "#2");
898
899                         string output = Encoding.UTF8.GetString (worker.data);
900                         Assert.AreEqual ("e\r\nmonorocks!just\r\n", output);
901                 }
902
903                 [Test]
904                 public void Write_Buffer_Null ()
905                 {
906                         try {
907                                 out_stream.Write ((byte []) null, 0, 0);
908                                 Assert.Fail ("#1");
909 #if NET_2_0
910                         } catch (ArgumentNullException ex) {
911                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
912                                 Assert.IsNull (ex.InnerException, "#3");
913                                 Assert.IsNotNull (ex.Message, "#4");
914                                 Assert.AreEqual ("buffer", ex.ParamName, "#5");
915                         }
916 #else
917                         } catch (NullReferenceException) {
918                         }
919 #endif
920                 }
921
922                 [Test]
923                 public void Write_Count_Negative ()
924                 {
925                         byte [] buffer = new byte [] { 0x0a, 0x1f, 0x2d };
926
927                         // offset < 0
928                         try {
929                                 out_stream.Write (buffer, 1, -1);
930                                 Assert.Fail ("#1");
931                         } catch (ArgumentOutOfRangeException ex) {
932                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
933                                 Assert.IsNull (ex.InnerException, "#3");
934                                 Assert.IsNotNull (ex.Message, "#4");
935                                 Assert.AreEqual ("count", ex.ParamName, "#5");
936                         }
937                 }
938
939                 [Test]
940                 public void Write_Count_Overflow ()
941                 {
942                         byte [] buffer;
943
944                         buffer = Encoding.UTF8.GetBytes ("Mono");
945                         out_stream.Write (buffer, 0, buffer.Length + 5);
946                         buffer = Encoding.UTF8.GetBytes ("Just Rocks!!");
947                         out_stream.Write (buffer, 5, buffer.Length - 2);
948                         response.Flush ();
949
950                         string output = Encoding.UTF8.GetString (worker.data);
951                         Assert.AreEqual ("b\r\nMonoRocks!!\r\n", output);
952                 }
953
954                 [Test]
955                 public void Write_Offset_Negative ()
956                 {
957                         byte [] buffer = new byte [] { 0x0a, 0x1f, 0x2d };
958
959                         // offset < 0
960                         try {
961                                 out_stream.Write (buffer, -1, 0);
962                                 Assert.Fail ("#1");
963                         } catch (ArgumentOutOfRangeException ex) {
964                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
965                                 Assert.IsNull (ex.InnerException, "#3");
966                                 Assert.IsNotNull (ex.Message, "#4");
967                                 Assert.AreEqual ("offset", ex.ParamName, "#5");
968                         }
969                 }
970
971                 [Test]
972                 public void Write_Offset_Overflow ()
973                 {
974                         byte [] buffer = new byte [] { 0x0a, 0x1f, 0x2d };
975
976                         // offset == buffer length
977 #if NET_2_0
978                         try {
979                                 out_stream.Write (buffer, buffer.Length, 0);
980                                 Assert.Fail ("#A1");
981                         } catch (ArgumentOutOfRangeException ex) {
982                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#A2");
983                                 Assert.IsNull (ex.InnerException, "#A3");
984                                 Assert.IsNotNull (ex.Message, "#A4");
985                                 Assert.AreEqual ("offset", ex.ParamName, "#A5");
986                         }
987 #else
988                         out_stream.Write (buffer, buffer.Length, 0);
989 #endif
990
991                         // offset > buffer length
992 #if NET_2_0
993                         try {
994                                 out_stream.Write (buffer, buffer.Length + 1, 0);
995                                 Assert.Fail ("#B1");
996                         } catch (ArgumentOutOfRangeException ex) {
997                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#B2");
998                                 Assert.IsNull (ex.InnerException, "#B3");
999                                 Assert.IsNotNull (ex.Message, "#B4");
1000                                 Assert.AreEqual ("offset", ex.ParamName, "#B5");
1001                         }
1002 #else
1003                         out_stream.Write (buffer, buffer.Length + 1, 0);
1004 #endif
1005
1006                         response.Flush ();
1007                         Assert.AreEqual (0, worker.data_len);
1008                 }
1009
1010                 [Test]
1011                 public void Write_Stream_Closed ()
1012                 {
1013                         byte [] buffer = Encoding.UTF8.GetBytes ("mono");
1014                         out_stream.Close ();
1015                         out_stream.Write (buffer, 0, buffer.Length);
1016                         response.Flush ();
1017
1018                         string output = Encoding.UTF8.GetString (worker.data);
1019                         Assert.AreEqual ("4\r\nmono\r\n", output);
1020                 }
1021
1022                 HttpContext Cook (int re, out FakeHttpWorkerRequest2 f)
1023                 {
1024                         f = new FakeHttpWorkerRequest2 (re);
1025                         return new HttpContext (f);
1026                 }
1027         }
1028 }