Fixed HttpWebRequestTest to compile with mobile NUnit.
[mono.git] / mcs / class / System / Test / System.Net / HttpWebRequestTest.cs
1 //
2 // HttpWebRequestTest.cs - NUnit Test Cases for System.Net.HttpWebRequest
3 //
4 // Authors:
5 //   Lawrence Pit (loz@cable.a2000.nl)
6 //   Martin Willemoes Hansen (mwh@sysrq.dk)
7 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 //   Andres G. Aragoneses (andres@7digital.com)
9 //   Bogdanov Kirill (bogdanov@macroscop.com)
10 //
11 // (C) 2003 Martin Willemoes Hansen
12 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com
13 // Copyright (c) 2013 7digital Media Ltd (http://www.7digital.com)
14 //
15
16 using NUnit.Framework;
17 using System;
18 using System.Collections;
19 using System.Collections.Specialized;
20 using System.Globalization;
21 using System.IO;
22 using System.Net;
23 using System.Net.Sockets;
24 using System.Security.Cryptography;
25 using System.Security.Cryptography.X509Certificates;
26 using System.Text;
27 using System.Threading;
28 using System.Reflection;
29 using Mono.Security.Authenticode;
30 #if !MOBILE
31 using Mono.Security.Protocol.Tls;
32 #endif
33
34 using MonoTests.Helpers;
35
36 namespace MonoTests.System.Net
37 {
38         [TestFixture]
39         public class HttpWebRequestTest
40         {
41                 private Random rand = new Random ();
42                 private byte [] data64KB = new byte [64 * 1024];
43
44                 [TestFixtureSetUp]
45                 public void Setup ()
46                 {
47                                 ServicePointManager.Expect100Continue = false;
48                                 rand.NextBytes (data64KB);
49                 }
50
51                 [Test]
52                 public void Proxy_Null ()
53                 {
54                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
55                         Assert.IsNotNull (req.Proxy, "#1");
56                         req.Proxy = null;
57                         Assert.IsNull (req.Proxy, "#2");
58                 }
59
60                 [Test]
61                 [Category("InetAccess")]
62                 public void Sync ()
63                 {
64                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
65                         Assert.IsNotNull (req.IfModifiedSince, "req:If Modified Since: ");
66
67                         req.UserAgent = "MonoClient v1.0";
68                         Assert.AreEqual ("User-Agent", req.Headers.GetKey (0), "#A1");
69                         Assert.AreEqual ("MonoClient v1.0", req.Headers.Get (0), "#A2");
70
71                         HttpWebResponse res = (HttpWebResponse) req.GetResponse ();
72                         Assert.AreEqual ("OK", res.StatusCode.ToString (), "#B1");
73                         Assert.AreEqual ("OK", res.StatusDescription, "#B2");
74
75                         Assert.IsTrue (res.Headers.Get ("Content-Type").StartsWith ("text/html; charset=", StringComparison.OrdinalIgnoreCase), "#C1");
76                         Assert.IsNotNull (res.LastModified, "#C2");
77                         Assert.AreEqual (0, res.Cookies.Count, "#C3");
78
79                         res.Close ();
80                 }
81
82                 [Test]
83                 public void AddRange ()
84                 {
85                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
86                         req.AddRange (10);
87                         req.AddRange (50, 90);
88                         req.AddRange ("bytes", 100); 
89                         req.AddRange ("bytes", 100, 120);
90                         Assert.AreEqual ("bytes=10-,50-90,100-,100-120", req.Headers ["Range"], "#1");
91                         try {
92                                 req.AddRange ("bits", 2000);
93                                 Assert.Fail ("#2");
94                         } catch (InvalidOperationException) {}
95                 }
96
97                 [Test] // bug #471782
98                 public void CloseRequestStreamAfterReadingResponse ()
99                 {
100                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
101                         string url = "http://" + ep.ToString () + "/test/";
102
103                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
104                                 responder.Start ();
105
106                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
107                                 req.Method = "POST";
108                                 req.Timeout = 2000;
109                                 req.ReadWriteTimeout = 2000;
110
111                                 byte [] data = new byte [128];
112                                 req.ContentLength = data.Length;
113
114                                 Stream rs = req.GetRequestStream ();
115                                 rs.Write (data, 0, data.Length);
116                                 rs.Flush ();
117
118                                 HttpWebResponse response = (HttpWebResponse) req.GetResponse ();
119                                 response.Close ();
120
121                                 rs.Close ();
122
123                                 responder.Stop ();
124                         }
125                 }
126
127                 [Test]
128                 //[Category("InetAccess")]
129                 [Category ("NotWorking")] // Disabled until a server that meets requirements is found
130                 public void Cookies1 ()
131                 {
132                         // The purpose of this test is to ensure that the cookies we get from a request
133                         // are stored in both, the CookieCollection in HttpWebResponse and the CookieContainer
134                         // in HttpWebRequest.
135                         // If this URL stops sending *one* and only one cookie, replace it.
136                         string url = "http://xamarin.com";
137                         CookieContainer cookies = new CookieContainer ();
138                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
139                         req.KeepAlive = false;
140                         req.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv; 1.7.6) Gecko/20050317 Firefox/1.0.2";
141                         req.CookieContainer = cookies;
142                         Assert.AreEqual (0, cookies.Count, "#01");
143                         using (HttpWebResponse res = (HttpWebResponse) req.GetResponse()) {
144                                 CookieCollection coll = req.CookieContainer.GetCookies (new Uri (url));
145                                 Assert.AreEqual (1, coll.Count, "#02");
146                                 Assert.AreEqual (1, res.Cookies.Count, "#03");
147                                 Cookie one = coll [0];
148                                 Cookie two = res.Cookies [0];
149                                 Assert.AreEqual (true, object.ReferenceEquals (one, two), "#04");
150                         }
151                 }
152
153 #if !MOBILE
154                 [Test]
155                 [Ignore ("Fails on MS.NET")]
156                 public void SslClientBlock ()
157                 {
158                         // This tests that the write request/initread/write body sequence does not hang
159                         // when using SSL.
160                         // If there's a regression for this, the test will hang.
161                         ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
162                         try {
163                                 SslHttpServer server = new SslHttpServer ();
164                                 server.Start ();
165
166                                 string url = String.Format ("https://{0}:{1}/nothing.html", server.IPAddress, server.Port);
167                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
168                                 request.Method = "POST";
169                                 Stream stream = request.GetRequestStream ();
170                                 byte [] bytes = new byte [100];
171                                 stream.Write (bytes, 0, bytes.Length);
172                                 stream.Close ();
173                                 HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
174                                 Assert.AreEqual (200, (int) resp.StatusCode, "StatusCode");
175                                 StreamReader sr = new StreamReader (resp.GetResponseStream (), Encoding.UTF8);
176                                 sr.ReadToEnd ();
177                                 sr.Close ();
178                                 resp.Close ();
179                                 server.Stop ();
180                                 if (server.Error != null)
181                                         throw server.Error;
182                         } finally {
183                                 ServicePointManager.CertificatePolicy = null;
184                         }
185                 }
186 #endif
187                 [Test]
188                 public void Missing_ContentEncoding ()
189                 {
190                         ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
191                         try {
192                                 BadChunkedServer server = new BadChunkedServer ();
193                                 server.Start ();
194
195                                 string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
196                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
197                                 request.Method = "GET";
198                                 HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
199                                 Assert.AreEqual ("", resp.ContentEncoding);
200                                 resp.Close ();
201                                 server.Stop ();
202                                 if (server.Error != null)
203                                         throw server.Error;
204                         } finally {
205                                 ServicePointManager.CertificatePolicy = null;
206                         }
207                 }
208
209                 [Test]
210                 public void BadServer_ChunkedClose ()
211                 {
212                         // The server will send a chunked response without a 'last-chunked' mark
213                         // and then shutdown the socket for sending.
214                         BadChunkedServer server = new BadChunkedServer ();
215                         server.Start ();
216                         string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
217                         HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
218                         HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
219                         string x = null;
220                         try {
221                                 byte [] bytes = new byte [32];
222                                 // Using StreamReader+UTF8Encoding here fails on MS runtime
223                                 Stream stream = resp.GetResponseStream ();
224                                 int nread = stream.Read (bytes, 0, 32);
225                                 Assert.AreEqual (16, nread, "#01");
226                                 x = Encoding.ASCII.GetString (bytes, 0, 16);
227                         } finally {
228                                 resp.Close ();
229                                 server.Stop ();
230                         }
231
232                         if (server.Error != null)
233                                 throw server.Error;
234
235                         Assert.AreEqual ("1234567890123456", x);
236                 }
237
238                 [Test]
239                 [Ignore ("This test asserts that our code violates RFC 2616")]
240                 public void MethodCase ()
241                 {
242                         ListDictionary methods = new ListDictionary ();
243                         methods.Add ("post", "POST");
244                         methods.Add ("puT", "PUT");
245                         methods.Add ("POST", "POST");
246                         methods.Add ("whatever", "whatever");
247                         methods.Add ("PUT", "PUT");
248
249                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
250                         string url = "http://" + ep.ToString () + "/test/";
251
252                         foreach (DictionaryEntry de in methods) {
253                                 SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler));
254                                 responder.Start ();
255
256                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
257                                 req.Method = (string) de.Key;
258                                 req.Timeout = 2000;
259                                 req.ReadWriteTimeout = 2000;
260                                 req.KeepAlive = false;
261                                 Stream rs = req.GetRequestStream ();
262                                 rs.Close ();
263                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
264                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
265                                                 Encoding.UTF8);
266                                         string line = sr.ReadLine ();
267                                         sr.Close ();
268                                         Assert.AreEqual (((string) de.Value) + " /test/ HTTP/1.1",
269                                                 line, req.Method);
270                                         resp.Close ();
271                                 }
272                                 responder.Stop ();
273                         }
274                 }
275
276                 [Test]
277                 public void BeginGetRequestStream_Body_NotAllowed ()
278                 {
279                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
280                         string url = "http://" + ep.ToString () + "/test/";
281
282                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
283                                 responder.Start ();
284
285                                 HttpWebRequest request;
286
287                                 request = (HttpWebRequest) WebRequest.Create (url);
288                                 request.Method = "GET";
289
290                                 try {
291                                         request.BeginGetRequestStream (null, null);
292                                         Assert.Fail ("#A1");
293                                 } catch (ProtocolViolationException ex) {
294                                         // Cannot send a content-body with this
295                                         // verb-type
296                                         Assert.IsNull (ex.InnerException, "#A2");
297                                         Assert.IsNotNull (ex.Message, "#A3");
298                                 }
299
300                                 request = (HttpWebRequest) WebRequest.Create (url);
301                                 request.Method = "HEAD";
302
303                                 try {
304                                         request.BeginGetRequestStream (null, null);
305                                         Assert.Fail ("#B1");
306                                 } catch (ProtocolViolationException ex) {
307                                         // Cannot send a content-body with this
308                                         // verb-type
309                                         Assert.IsNull (ex.InnerException, "#B2");
310                                         Assert.IsNotNull (ex.Message, "#B3");
311                                 }
312                         }
313                 }
314
315                 [Test] // bug #465613
316                 public void BeginGetRequestStream_NoBuffering ()
317                 {
318                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
319                         string url = "http://" + ep.ToString () + "/test/";
320
321                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
322                                 responder.Start ();
323
324                                 HttpWebRequest req;
325                                 Stream rs;
326                                 IAsyncResult ar;
327
328                                 req = (HttpWebRequest) WebRequest.Create (url);
329                                 req.Method = "POST";
330                                 req.SendChunked = false;
331                                 req.KeepAlive = false;
332                                 req.AllowWriteStreamBuffering = false;
333
334                                 ar = req.BeginGetRequestStream (null, null);
335                                 rs = req.EndGetRequestStream (ar);
336                                 rs.Close ();
337
338                                 req = (HttpWebRequest) WebRequest.Create (url);
339                                 req.Method = "POST";
340                                 req.SendChunked = false;
341                                 req.KeepAlive = true;
342                                 req.AllowWriteStreamBuffering = false;
343
344                                 try {
345                                         req.BeginGetRequestStream (null, null);
346                                         Assert.Fail ("#A1");
347                                 } catch (ProtocolViolationException ex) {
348                                         // When performing a write operation with
349                                         // AllowWriteStreamBuffering set to false,
350                                         // you must either set ContentLength to a
351                                         // non-negative number or set SendChunked
352                                         // to true
353                                         Assert.IsNull (ex.InnerException, "#A2");
354                                         Assert.IsNotNull (ex.Message, "#A3");
355                                 }
356
357                                 req = (HttpWebRequest) WebRequest.Create (url);
358                                 req.Method = "POST";
359                                 req.SendChunked = false;
360                                 req.KeepAlive = true;
361                                 req.AllowWriteStreamBuffering = false;
362                                 req.ContentLength = 0;
363
364                                 ar = req.BeginGetRequestStream (null, null);
365                                 rs = req.EndGetRequestStream (ar);
366                                 rs.Close ();
367                         }
368                 }
369
370                 [Test] // bug #508027
371                 [Category ("NotWorking")] // #5842
372                 public void BeginGetResponse ()
373                 {
374                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
375                         string url = "http://" + ep.ToString () + "/test/";
376
377                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
378                                 responder.Start ();
379
380                                 HttpWebRequest req;
381
382                                 req = (HttpWebRequest) WebRequest.Create (url);
383                                 req.Timeout = 5000;
384                                 req.Method = "POST";
385                                 req.SendChunked = false;
386                                 req.KeepAlive = false;
387                                 req.AllowWriteStreamBuffering = false;
388                                 req.BeginGetResponse (null, null);
389                                 req.Abort ();
390
391                                 req = (HttpWebRequest) WebRequest.Create (url);
392                                 req.Timeout = 5000;
393                                 req.Method = "POST";
394                                 req.SendChunked = true;
395                                 req.KeepAlive = false;
396                                 req.AllowWriteStreamBuffering = false;
397                                 req.GetRequestStream ().WriteByte (1);
398                                 req.BeginGetResponse (null, null);
399                                 req.Abort ();
400
401                                 req = (HttpWebRequest) WebRequest.Create (url);
402                                 req.Timeout = 5000;
403                                 req.Method = "POST";
404                                 req.ContentLength = 5;
405                                 req.SendChunked = false;
406                                 req.KeepAlive = false;
407                                 req.AllowWriteStreamBuffering = false;
408                                 req.GetRequestStream ().WriteByte (5);
409                                 req.BeginGetResponse (null, null);
410                                 req.Abort ();
411
412                                 req = (HttpWebRequest) WebRequest.Create (url);
413                                 req.Timeout = 5000;
414                                 req.Method = "POST";
415                                 req.SendChunked = false;
416                                 req.KeepAlive = true;
417                                 req.AllowWriteStreamBuffering = false;
418
419                                 req.BeginGetResponse (null, null);
420                                 req.Abort ();
421
422                                 req = (HttpWebRequest) WebRequest.Create (url);
423                                 req.Timeout = 5000;
424                                 req.Method = "POST";
425                                 req.SendChunked = false;
426                                 req.KeepAlive = false;
427                                 req.AllowWriteStreamBuffering = false;
428                                 req.ContentLength = 5;
429                                 req.BeginGetResponse (null, null);
430                                 req.Abort ();
431
432                                 req = (HttpWebRequest) WebRequest.Create (url);
433                                 req.Timeout = 5000;
434                                 req.Method = "POST";
435                                 req.SendChunked = false;
436                                 req.KeepAlive = true;
437                                 req.AllowWriteStreamBuffering = false;
438                                 req.ContentLength = 5;
439                                 req.BeginGetResponse (null, null);
440                                 req.Abort ();
441
442                                 req = (HttpWebRequest) WebRequest.Create (url);
443                                 req.Timeout = 5000;
444                                 req.Method = "GET";
445                                 req.SendChunked = true;
446
447                                 req.BeginGetResponse (null, null);
448                                 req.Abort ();
449
450                                 req = (HttpWebRequest) WebRequest.Create (url);
451                                 req.Timeout = 5000;
452                                 req.Method = "GET";
453                                 req.ContentLength = 5;
454
455                                 req.BeginGetResponse (null, null);
456                                 req.Abort ();
457
458                                 req = (HttpWebRequest) WebRequest.Create (url);
459                                 req.Timeout = 5000;
460                                 req.Method = "GET";
461                                 req.ContentLength = 0;
462
463                                 req.BeginGetResponse (null, null);
464                                 req.Abort ();
465                         }
466                 }
467
468                 [Test] // bug #511851
469                 public void BeginGetRequestStream_Request_Aborted ()
470                 {
471                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
472                         string url = "http://" + ep.ToString () + "/test/";
473
474                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
475                                 responder.Start ();
476
477                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
478                                 req.Method = "POST";
479                                 req.Abort ();
480
481                                 try {
482                                         req.BeginGetRequestStream (null, null);
483                                         Assert.Fail ("#1");
484                                 } catch (WebException ex) {
485                                         // The request was aborted: The request was canceled
486                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
487                                         Assert.IsNull (ex.InnerException, "#3");
488                                         Assert.IsNotNull (ex.Message, "#4");
489                                         Assert.IsNull (ex.Response, "#5");
490                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
491                                 }
492                         }
493                 }
494
495                 [Test] // bug #511851
496                 public void BeginGetResponse_Request_Aborted ()
497                 {
498                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
499                         string url = "http://" + ep.ToString () + "/test/";
500
501                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
502                                 responder.Start ();
503
504                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
505                                 req.Method = "POST";
506                                 req.Abort ();
507
508                                 try {
509                                         req.BeginGetResponse (null, null);
510                                         Assert.Fail ("#1");
511                                 } catch (WebException ex) {
512                                         // The request was aborted: The request was canceled
513                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
514                                         Assert.IsNull (ex.InnerException, "#3");
515                                         Assert.IsNotNull (ex.Message, "#4");
516                                         Assert.IsNull (ex.Response, "#5");
517                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
518                                 }
519                         }
520                 }
521
522                 [Test]
523                 public void EndGetRequestStream_AsyncResult_Null ()
524                 {
525                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
526                         string url = "http://" + ep.ToString () + "/test/";
527
528                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
529                                 responder.Start ();
530
531                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
532                                 req.Method = "POST";
533                                 req.BeginGetRequestStream (null, null);
534
535                                 try {
536                                         req.EndGetRequestStream (null);
537                                         Assert.Fail ("#1");
538                                 } catch (ArgumentNullException ex) {
539                                         Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
540                                         Assert.IsNull (ex.InnerException, "#3");
541                                         Assert.IsNotNull (ex.Message, "#4");
542                                         Assert.AreEqual ("asyncResult", ex.ParamName, "#5");
543                                 } finally {
544                                         req.Abort ();
545                                 }
546                         }
547                 }
548
549                 [Test]
550                 [Category ("NotWorking")] // do not get consistent result on MS
551                 public void EndGetRequestStream_Request_Aborted ()
552                 {
553                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
554                         string url = "http://" + ep.ToString () + "/test/";
555
556                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
557                                 responder.Start ();
558
559                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
560                                 req.Method = "POST";
561                                 IAsyncResult ar = req.BeginGetRequestStream (null, null);
562                                 req.Abort ();
563                                 Thread.Sleep (500);
564
565                                 try {
566                                         req.EndGetRequestStream (ar);
567                                         Assert.Fail ("#1");
568                                 } catch (WebException ex) {
569                                         // The request was aborted: The request was canceled
570                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
571                                         Assert.IsNull (ex.InnerException, "#3");
572                                         Assert.IsNotNull (ex.Message, "#4");
573                                         Assert.IsNull (ex.Response, "#5");
574                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
575                                 }
576                         }
577                 }
578
579                 [Test] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=471522
580                 [Category ("NotWorking")]
581                 public void EndGetResponse_AsyncResult_Invalid ()
582                 {
583                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
584                         string url = "http://" + ep.ToString () + "/test/";
585
586                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
587                                 responder.Start ();
588
589                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
590                                 req.Method = "POST";
591                                 req.Timeout = 2000;
592                                 req.ReadWriteTimeout = 2000;
593                                 IAsyncResult ar = req.BeginGetRequestStream (null, null);
594
595                                 // AsyncResult was not returned from call to BeginGetResponse
596                                 try {
597                                         req.EndGetResponse (ar);
598                                         Assert.Fail ();
599                                 } catch (InvalidCastException) {
600                                 } finally {
601                                         req.Abort ();
602                                 }
603                         }
604                 }
605
606                 [Test]
607                 public void EndGetResponse_AsyncResult_Null ()
608                 {
609                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
610                         string url = "http://" + ep.ToString () + "/test/";
611
612                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
613                                 responder.Start ();
614
615                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
616                                 req.Timeout = 2000;
617                                 req.ReadWriteTimeout = 2000;
618                                 req.Method = "POST";
619                                 IAsyncResult ar = req.BeginGetResponse (null, null);
620
621                                 try {
622                                         req.EndGetResponse (null);
623                                         Assert.Fail ("#1");
624                                 } catch (ArgumentNullException ex) {
625                                         Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
626                                         Assert.IsNull (ex.InnerException, "#3");
627                                         Assert.IsNotNull (ex.Message, "#4");
628                                         Assert.AreEqual ("asyncResult", ex.ParamName, "#5");
629                                 } finally {
630                                         req.Abort ();
631                                         /*
632                                         using (HttpWebResponse resp = (HttpWebResponse) req.EndGetResponse (ar)) {
633                                                 resp.Close ();
634                                         }*/
635                                 }
636                         }
637                 }
638
639                 [Test] // bug #429200
640                 public void GetRequestStream ()
641                 {
642                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
643                         string url = "http://" + ep.ToString () + "/test/";
644
645                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
646                                 responder.Start ();
647
648                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
649                                 req.Method = "POST";
650                                 req.Timeout = 2000;
651                                 req.ReadWriteTimeout = 2000;
652
653                                 Stream rs1 = req.GetRequestStream ();
654                                 Stream rs2 = req.GetRequestStream ();
655
656                                 Assert.IsNotNull (rs1, "#1");
657                                 Assert.AreSame (rs1, rs2, "#2");
658
659                                 rs1.Close ();
660                         }
661                 }
662
663                 [Test] // bug #511851
664                 public void GetRequestStream_Request_Aborted ()
665                 {
666                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
667                         string url = "http://" + ep.ToString () + "/test/";
668
669                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
670                                 responder.Start ();
671
672                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
673                                 req.Method = "POST";
674                                 req.Abort ();
675
676                                 try {
677                                         req.GetRequestStream ();
678                                         Assert.Fail ("#1");
679                                 } catch (WebException ex) {
680                                         // The request was aborted: The request was canceled
681                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
682                                         Assert.IsNull (ex.InnerException, "#3");
683                                         Assert.IsNotNull (ex.Message, "#4");
684                                         Assert.IsNull (ex.Response, "#5");
685                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
686                                 }
687                         }
688                 }
689
690                 [Test] // bug #510661
691                 [Category ("NotWorking")] // #5842
692                 public void GetRequestStream_Close_NotAllBytesWritten ()
693                 {
694                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
695                         string url = "http://" + ep.ToString () + "/test/";
696
697                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
698                                 responder.Start ();
699
700                                 HttpWebRequest req;
701                                 Stream rs;
702
703                                 req = (HttpWebRequest) WebRequest.Create (url);
704                                 req.Method = "POST";
705                                 req.ContentLength = 2;
706                                 rs = req.GetRequestStream ();
707                                 try {
708                                         rs.Close ();
709                                         Assert.Fail ("#A1");
710                                 } catch (WebException ex) {
711                                         // The request was aborted: The request was canceled
712                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
713                                         Assert.IsNotNull (ex.Message, "#A3");
714                                         Assert.IsNull (ex.Response, "#A4");
715                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#A5");
716
717                                         // Cannot close stream until all bytes are written
718                                         Exception inner = ex.InnerException;
719                                         Assert.IsNotNull (inner, "#A6");
720                                         Assert.AreEqual (typeof (IOException), inner.GetType (), "#A7");
721                                         Assert.IsNull (inner.InnerException, "#A8");
722                                         Assert.IsNotNull (inner.Message, "#A9");
723                                 }
724
725                                 req = (HttpWebRequest) WebRequest.Create (url);
726                                 req.Method = "POST";
727                                 req.ContentLength = 2;
728                                 rs = req.GetRequestStream ();
729                                 rs.WriteByte (0x0d);
730                                 try {
731                                         rs.Close ();
732                                         Assert.Fail ("#B1");
733                                 } catch (WebException ex) {
734                                         // The request was aborted: The request was canceled
735                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
736                                         Assert.IsNotNull (ex.Message, "#B3");
737                                         Assert.IsNull (ex.Response, "#B4");
738                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#B5");
739
740                                         // Cannot close stream until all bytes are written
741                                         Exception inner = ex.InnerException;
742                                         Assert.IsNotNull (inner, "#B6");
743                                         Assert.AreEqual (typeof (IOException), inner.GetType (), "#B7");
744                                         Assert.IsNull (inner.InnerException, "#B8");
745                                         Assert.IsNotNull (inner.Message, "#B9");
746                                 }
747
748                                 req = (HttpWebRequest) WebRequest.Create (url);
749                                 req.Method = "POST";
750                                 req.ContentLength = 2;
751                                 rs = req.GetRequestStream ();
752                                 rs.WriteByte (0x0d);
753                                 rs.WriteByte (0x0d);
754                                 rs.Close ();
755                         }
756                 }
757
758                 [Test] // bug #510642
759                 [Category ("NotWorking")] // #5842
760                 public void GetRequestStream_Write_Overflow ()
761                 {
762                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
763                         string url = "http://" + ep.ToString () + "/test/";
764
765                         // buffered, non-chunked
766                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
767                                 responder.Start ();
768
769                                 HttpWebRequest req;
770                                 Stream rs;
771                                 byte [] buffer;
772
773                                 req = (HttpWebRequest) WebRequest.Create (url);
774                                 req.Method = "POST";
775                                 req.Timeout = 1000;
776                                 req.ReadWriteTimeout = 2000;
777                                 req.ContentLength = 2;
778
779                                 rs = req.GetRequestStream ();
780                                 rs.WriteByte (0x2c);
781
782                                 buffer = new byte [] { 0x2a, 0x1d };
783                                 try {
784                                         rs.Write (buffer, 0, buffer.Length);
785                                         Assert.Fail ("#A1");
786                                 } catch (ProtocolViolationException ex) {
787                                         // Bytes to be written to the stream exceed
788                                         // Content-Length bytes size specified
789                                         Assert.IsNull (ex.InnerException, "#A2");
790                                         Assert.IsNotNull (ex.Message, "#A3");
791                                 } finally {
792                                         req.Abort ();
793                                 }
794
795                                 req = (HttpWebRequest) WebRequest.Create (url);
796                                 req.Method = "POST";
797                                 req.Timeout = 1000;
798                                 req.ReadWriteTimeout = 2000;
799                                 req.ContentLength = 2;
800
801                                 rs = req.GetRequestStream ();
802
803                                 buffer = new byte [] { 0x2a, 0x2c, 0x1d };
804                                 try {
805                                         rs.Write (buffer, 0, buffer.Length);
806                                         Assert.Fail ("#B1");
807                                 } catch (ProtocolViolationException ex) {
808                                         // Bytes to be written to the stream exceed
809                                         // Content-Length bytes size specified
810                                         Assert.IsNull (ex.InnerException, "#B2");
811                                         Assert.IsNotNull (ex.Message, "#B3");
812                                 } finally {
813                                         req.Abort ();
814                                 }
815                         }
816
817                         // buffered, chunked
818                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
819                                 responder.Start ();
820
821                                 HttpWebRequest req;
822                                 Stream rs;
823                                 byte [] buffer;
824
825                                 /*
826                                 req = (HttpWebRequest) WebRequest.Create (url);
827                                 req.Method = "POST";
828                                 req.SendChunked = true;
829                                 req.Timeout = 1000;
830                                 req.ReadWriteTimeout = 2000;
831                                 req.ContentLength = 2;
832
833                                 rs = req.GetRequestStream ();
834                                 rs.WriteByte (0x2c);
835
836                                 buffer = new byte [] { 0x2a, 0x1d };
837                                 rs.Write (buffer, 0, buffer.Length);
838                                 req.Abort ();
839                                 */
840
841                                 req = (HttpWebRequest) WebRequest.Create (url);
842                                 req.Method = "POST";
843                                 req.SendChunked = true;
844                                 req.Timeout = 1000;
845                                 req.ReadWriteTimeout = 2000;
846                                 req.ContentLength = 2;
847
848                                 rs = req.GetRequestStream ();
849
850                                 buffer = new byte [] { 0x2a, 0x2c, 0x1d };
851                                 rs.Write (buffer, 0, buffer.Length);
852                                 req.Abort ();
853                         }
854
855                         // non-buffered, non-chunked
856                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
857                                 responder.Start ();
858
859                                 HttpWebRequest req;
860                                 Stream rs;
861                                 byte [] buffer;
862
863                                 req = (HttpWebRequest) WebRequest.Create (url);
864                                 req.AllowWriteStreamBuffering = false;
865                                 req.Method = "POST";
866                                 req.Timeout = 1000;
867                                 req.ReadWriteTimeout = 2000;
868                                 req.ContentLength = 2;
869
870                                 rs = req.GetRequestStream ();
871                                 rs.WriteByte (0x2c);
872
873                                 buffer = new byte [] { 0x2a, 0x1d };
874                                 try {
875                                         rs.Write (buffer, 0, buffer.Length);
876                                         Assert.Fail ("#C1");
877                                 } catch (ProtocolViolationException ex) {
878                                         // Bytes to be written to the stream exceed
879                                         // Content-Length bytes size specified
880                                         Assert.IsNull (ex.InnerException, "#C2");
881                                         Assert.IsNotNull (ex.Message, "#3");
882                                 } finally {
883                                         req.Abort ();
884                                 }
885
886                                 req = (HttpWebRequest) WebRequest.Create (url);
887                                 req.AllowWriteStreamBuffering = false;
888                                 req.Method = "POST";
889                                 req.Timeout = 1000;
890                                 req.ReadWriteTimeout = 2000;
891                                 req.ContentLength = 2;
892
893                                 rs = req.GetRequestStream ();
894
895                                 buffer = new byte [] { 0x2a, 0x2c, 0x1d };
896                                 try {
897                                         rs.Write (buffer, 0, buffer.Length);
898                                         Assert.Fail ("#D1");
899                                 } catch (ProtocolViolationException ex) {
900                                         // Bytes to be written to the stream exceed
901                                         // Content-Length bytes size specified
902                                         Assert.IsNull (ex.InnerException, "#D2");
903                                         Assert.IsNotNull (ex.Message, "#D3");
904                                 } finally {
905                                         req.Abort ();
906                                 }
907                         }
908
909                         // non-buffered, chunked
910                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
911                                 responder.Start ();
912
913                                 HttpWebRequest req;
914                                 Stream rs;
915                                 byte [] buffer;
916
917                                 req = (HttpWebRequest) WebRequest.Create (url);
918                                 req.AllowWriteStreamBuffering = false;
919                                 req.Method = "POST";
920                                 req.SendChunked = true;
921                                 req.Timeout = 1000;
922                                 req.ReadWriteTimeout = 2000;
923                                 req.ContentLength = 2;
924
925                                 rs = req.GetRequestStream ();
926                                 rs.WriteByte (0x2c);
927
928                                 buffer = new byte [] { 0x2a, 0x1d };
929                                 rs.Write (buffer, 0, buffer.Length);
930                                 req.Abort ();
931
932                                 req = (HttpWebRequest) WebRequest.Create (url);
933                                 req.AllowWriteStreamBuffering = false;
934                                 req.Method = "POST";
935                                 req.SendChunked = true;
936                                 req.Timeout = 1000;
937                                 req.ReadWriteTimeout = 2000;
938                                 req.ContentLength = 2;
939
940                                 rs = req.GetRequestStream ();
941
942                                 buffer = new byte [] { 0x2a, 0x2c, 0x1d };
943                                 rs.Write (buffer, 0, buffer.Length);
944                                 req.Abort ();
945                         }
946                 }
947
948                 [Test]
949                 [Ignore ("This test asserts that our code violates RFC 2616")]
950                 public void GetRequestStream_Body_NotAllowed ()
951                 {
952                         string [] methods = new string [] { "GET", "HEAD", "CONNECT",
953                                 "get", "HeAd", "ConNect" };
954
955                         foreach (string method in methods) {
956                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (
957                                         "http://localhost:8000");
958                                 req.Method = method;
959                                 try {
960                                         req.GetRequestStream ();
961                                         Assert.Fail ("#1:" + method);
962                                 } catch (ProtocolViolationException ex) {
963                                         Assert.AreEqual (typeof (ProtocolViolationException), ex.GetType (), "#2:" + method);
964                                         Assert.IsNull (ex.InnerException, "#3:" + method);
965                                         Assert.IsNotNull (ex.Message, "#4:" + method);
966                                 }
967                         }
968                 }
969
970                 [Test] // bug #511851
971                 public void GetResponse_Request_Aborted ()
972                 {
973                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
974                         string url = "http://" + ep.ToString () + "/test/";
975
976                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
977                                 responder.Start ();
978
979                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
980                                 req.Method = "POST";
981                                 req.Abort ();
982
983                                 try {
984                                         req.GetResponse ();
985                                         Assert.Fail ("#1");
986                                 } catch (WebException ex) {
987                                         // The request was aborted: The request was canceled
988                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
989                                         Assert.IsNull (ex.InnerException, "#3");
990                                         Assert.IsNotNull (ex.Message, "#4");
991                                         Assert.IsNull (ex.Response, "#5");
992                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
993                                 }
994                         }
995                 }
996
997                 [Test]
998                 [Ignore ("This does not timeout any more. That's how MS works when reading small responses")]
999                 public void ReadTimeout ()
1000                 {
1001                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
1002                         string url = "http://" + localEP.ToString () + "/original/";
1003
1004                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
1005                                 responder.Start ();
1006
1007                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1008                                 req.Method = "POST";
1009                                 req.AllowAutoRedirect = false;
1010                                 req.Timeout = 200;
1011                                 req.ReadWriteTimeout = 2000;
1012                                 req.KeepAlive = false;
1013                                 Stream rs = req.GetRequestStream ();
1014                                 rs.Close ();
1015                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1016                                         try {
1017                                                 Stream s = resp.GetResponseStream ();
1018                                                 s.ReadByte ();
1019                                                 Assert.Fail ("#1");
1020                                         } catch (WebException ex) {
1021                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
1022                                                 Assert.IsNull (ex.InnerException, "#3");
1023                                                 Assert.IsNull (ex.Response, "#4");
1024                                                 Assert.AreEqual (WebExceptionStatus.Timeout, ex.Status, "#5");
1025                                         }
1026                                 }
1027                                 responder.Stop ();
1028                         }
1029                 }
1030
1031                 [Test] // bug #324300
1032                 public void AllowAutoRedirect ()
1033                 {
1034                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8765);
1035                         string url = "http://" + localEP.ToString () + "/original/";
1036
1037                         // allow autoredirect
1038                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
1039                                 responder.Start ();
1040
1041                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1042                                 req.Method = "POST";
1043                                 req.Timeout = 2000;
1044                                 req.ReadWriteTimeout = 2000;
1045                                 req.KeepAlive = false;
1046                                 Stream rs = req.GetRequestStream ();
1047                                 rs.Close ();
1048                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1049                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
1050                                                 Encoding.UTF8);
1051                                         string body = sr.ReadToEnd ();
1052
1053                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#A1");
1054                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
1055                                                 localEP.ToString () + "/moved/", "#A2");
1056                                         Assert.AreEqual ("GET", resp.Method, "#A3");
1057                                         Assert.AreEqual ("LOOKS OK", body, "#A4");
1058                                 }
1059                                 responder.Stop ();
1060                         }
1061
1062                         // do not allow autoredirect
1063                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
1064                                 responder.Start ();
1065
1066                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1067                                 req.Method = "POST";
1068                                 req.AllowAutoRedirect = false;
1069                                 req.Timeout = 1000;
1070                                 req.ReadWriteTimeout = 1000;
1071                                 req.KeepAlive = false;
1072                                 Stream rs = req.GetRequestStream ();
1073                                 rs.Close ();
1074                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1075                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.Found, "#B1");
1076                                         Assert.AreEqual (url, resp.ResponseUri.ToString (), "#B2");
1077                                         Assert.AreEqual ("POST", resp.Method, "#B3");
1078                                 }
1079                                 responder.Stop ();
1080                         }
1081                 }
1082
1083                 [Test]
1084                 public void PostAndRedirect_NoCL ()
1085                 {
1086                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8769);
1087                         string url = "http://" + localEP.ToString () + "/original/";
1088
1089                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
1090                                 responder.Start ();
1091
1092                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1093                                 req.Method = "POST";
1094                                 req.Timeout = 2000;
1095                                 req.ReadWriteTimeout = 2000;
1096                                 Stream rs = req.GetRequestStream ();
1097                                 rs.WriteByte (10);
1098                                 rs.Close ();
1099                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1100                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
1101                                                 Encoding.UTF8);
1102                                         string body = sr.ReadToEnd ();
1103
1104                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#A1");
1105                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
1106                                                 localEP.ToString () + "/moved/", "#A2");
1107                                         Assert.AreEqual ("GET", resp.Method, "#A3");
1108                                         Assert.AreEqual ("LOOKS OK", body, "#A4");
1109                                 }
1110                                 responder.Stop ();
1111                         }
1112                 }
1113
1114                 [Test]
1115                 public void PostAndRedirect_CL ()
1116                 {
1117                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8770);
1118                         string url = "http://" + localEP.ToString () + "/original/";
1119
1120                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
1121                                 responder.Start ();
1122
1123                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1124                                 req.Method = "POST";
1125                                 req.Timeout = 2000;
1126                                 req.ReadWriteTimeout = 2000;
1127                                 req.ContentLength  = 1;
1128                                 Stream rs = req.GetRequestStream ();
1129                                 rs.WriteByte (10);
1130                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1131                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
1132                                                 Encoding.UTF8);
1133                                         string body = sr.ReadToEnd ();
1134
1135                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#A1");
1136                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
1137                                                 localEP.ToString () + "/moved/", "#A2");
1138                                         Assert.AreEqual ("GET", resp.Method, "#A3");
1139                                         Assert.AreEqual ("LOOKS OK", body, "#A4");
1140                                 }
1141                                 responder.Stop ();
1142                         }
1143                 }
1144
1145                 [Test]
1146                 public void PostAnd401 ()
1147                 {
1148                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8771);
1149                         string url = "http://" + localEP.ToString () + "/original/";
1150
1151                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
1152                                 responder.Start ();
1153
1154                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1155                                 req.Method = "POST";
1156                                 req.Timeout = 2000;
1157                                 req.ReadWriteTimeout = 2000;
1158                                 req.ContentLength  = 1;
1159                                 Stream rs = req.GetRequestStream ();
1160                                 rs.WriteByte (10);
1161                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1162                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
1163                                                 Encoding.UTF8);
1164                                         string body = sr.ReadToEnd ();
1165
1166                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#A1");
1167                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
1168                                                 localEP.ToString () + "/moved/", "#A2");
1169                                         Assert.AreEqual ("GET", resp.Method, "#A3");
1170                                         Assert.AreEqual ("LOOKS OK", body, "#A4");
1171                                 }
1172                                 responder.Stop ();
1173                         }
1174                 }
1175
1176                 [Test] // bug #324347
1177                 [Category ("NotWorking")]
1178                 public void InternalServerError ()
1179                 {
1180                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8766);
1181                         string url = "http://" + localEP.ToString () + "/original/";
1182
1183                         // POST
1184                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
1185                                 responder.Start ();
1186
1187                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1188                                 req.Method = "POST";
1189                                 req.Timeout = 2000;
1190                                 req.ReadWriteTimeout = 2000;
1191                                 req.KeepAlive = false;
1192                                 Stream rs = req.GetRequestStream ();
1193                                 rs.Close ();
1194
1195                                 try {
1196                                         req.GetResponse ();
1197                                         Assert.Fail ("#A1");
1198                                 } catch (WebException ex) {
1199                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
1200                                         Assert.IsNull (ex.InnerException, "#A3");
1201                                         Assert.IsNotNull (ex.Message, "#A4");
1202                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A5");
1203
1204                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
1205                                         Assert.IsNotNull (webResponse, "#A6");
1206                                         Assert.AreEqual ("POST", webResponse.Method, "#A7");
1207                                         webResponse.Close ();
1208                                 }
1209
1210                                 responder.Stop ();
1211                         }
1212
1213                         // GET
1214                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
1215                                 responder.Start ();
1216
1217                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1218                                 req.Method = "GET";
1219                                 req.Timeout = 2000;
1220                                 req.ReadWriteTimeout = 2000;
1221                                 req.KeepAlive = false;
1222
1223                                 try {
1224                                         req.GetResponse ();
1225                                         Assert.Fail ("#B1");
1226                                 } catch (WebException ex) {
1227                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
1228                                         Assert.IsNull (ex.InnerException, "#B3");
1229                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
1230
1231                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
1232                                         Assert.IsNotNull (webResponse, "#B5");
1233                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
1234                                         webResponse.Close ();
1235                                 }
1236
1237                                 responder.Stop ();
1238                         }
1239                 }
1240
1241                 [Test]
1242                 [Category ("NotWorking")] // #B3 fails; we get a SocketException: An existing connection was forcibly closed by the remote host
1243                 public void NoContentLength ()
1244                 {
1245                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8767);
1246                         string url = "http://" + localEP.ToString () + "/original/";
1247
1248                         // POST
1249                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
1250                                 responder.Start ();
1251
1252                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1253                                 req.Method = "POST";
1254                                 req.Timeout = 2000;
1255                                 req.ReadWriteTimeout = 2000;
1256                                 req.KeepAlive = false;
1257                                 Stream rs = req.GetRequestStream ();
1258                                 rs.Close ();
1259
1260                                 try {
1261                                         req.GetResponse ();
1262                                         Assert.Fail ("#A1");
1263                                 } catch (WebException ex) {
1264                                         // The underlying connection was closed:
1265                                         // An unexpected error occurred on a
1266                                         // receive
1267                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
1268                                         Assert.IsNotNull (ex.InnerException, "#A3");
1269                                         Assert.AreEqual (WebExceptionStatus.ReceiveFailure, ex.Status, "#A4");
1270                                         Assert.AreEqual (typeof (IOException), ex.InnerException.GetType (), "#A5");
1271                                         
1272                                         // Unable to read data from the transport connection:
1273                                         // A connection attempt failed because the connected party
1274                                         // did not properly respond after a period of time, or
1275                                         // established connection failed because connected host has
1276                                         // failed to respond
1277                                         IOException ioe = (IOException) ex.InnerException;
1278                                         Assert.IsNotNull (ioe.InnerException, "#A6");
1279                                         Assert.IsNotNull (ioe.Message, "#A7");
1280                                         Assert.AreEqual (typeof (SocketException), ioe.InnerException.GetType (), "#A8");
1281
1282                                         // An existing connection was forcibly
1283                                         // closed by the remote host
1284                                         SocketException soe = (SocketException) ioe.InnerException;
1285                                         Assert.IsNull (soe.InnerException, "#A9");
1286                                         Assert.IsNotNull (soe.Message, "#A10");
1287
1288                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
1289                                         Assert.IsNull (webResponse, "#A11");
1290                                 }
1291
1292                                 responder.Stop ();
1293                         }
1294
1295                         // GET
1296                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
1297                                 responder.Start ();
1298
1299                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1300                                 req.Method = "GET";
1301                                 req.Timeout = 2000;
1302                                 req.ReadWriteTimeout = 2000;
1303                                 req.KeepAlive = false;
1304
1305                                 try {
1306                                         req.GetResponse ();
1307                                         Assert.Fail ("#B1");
1308                                 } catch (WebException ex) {
1309                                         // The remote server returned an error:
1310                                         // (500) Internal Server Error
1311                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
1312                                         Assert.IsNull (ex.InnerException, "#B3");
1313                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
1314
1315                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
1316                                         Assert.IsNotNull (webResponse, "#B5");
1317                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
1318                                         webResponse.Close ();
1319                                 }
1320
1321                                 responder.Stop ();
1322                         }
1323                 }
1324
1325                 [Test] // bug #513087
1326                 public void NonStandardVerb ()
1327                 {
1328                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
1329                         string url = "http://" + ep.ToString () + "/moved/";
1330
1331                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (VerbEchoHandler))) {
1332                                 responder.Start ();
1333
1334                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1335                                 req.Method = "WhatEver";
1336                                 req.KeepAlive = false;
1337                                 req.Timeout = 20000;
1338                                 req.ReadWriteTimeout = 20000;
1339
1340                                 Stream rs = req.GetRequestStream ();
1341                                 rs.Close ();
1342
1343                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1344                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
1345                                                 Encoding.UTF8);
1346                                         string body = sr.ReadToEnd ();
1347
1348                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#1");
1349                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
1350                                                 ep.ToString () + "/moved/", "#2");
1351                                         Assert.AreEqual ("WhatEver", resp.Method, "#3");
1352                                         Assert.AreEqual ("WhatEver", body, "#4");
1353                                 }
1354
1355                                 responder.Stop ();
1356                         }
1357                 }
1358
1359                 [Test]
1360                 [Category ("NotWorking")] // Assert #2 fails
1361                 public void NotModifiedSince ()
1362                 {
1363                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
1364                         string url = "http://" + ep.ToString () + "/test/";
1365
1366                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (NotModifiedSinceHandler))) {
1367                                 responder.Start ();
1368
1369                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1370                                 req.Method = "GET";
1371                                 req.KeepAlive = false;
1372                                 req.Timeout = 20000;
1373                                 req.ReadWriteTimeout = 20000;
1374                                 req.Headers.Add (HttpRequestHeader.IfNoneMatch, "898bbr2347056cc2e096afc66e104653");
1375                                 req.IfModifiedSince = new DateTime (2010, 01, 04);
1376
1377                                 DateTime start = DateTime.Now;
1378                                 HttpWebResponse response = null;
1379
1380                                 try {
1381                                         req.GetResponse ();
1382                                         Assert.Fail ("#1");
1383                                 } catch (WebException e) {
1384                                         response = (HttpWebResponse) e.Response;
1385                                 }
1386
1387                                 Assert.IsNotNull (response, "#2");
1388                                 using (Stream stream = response.GetResponseStream ()) {
1389                                         byte [] buffer = new byte [4096];
1390                                         int bytesRead = stream.Read (buffer, 0, buffer.Length);
1391                                         Assert.AreEqual (0, bytesRead, "#3");
1392                                 }
1393
1394                                 TimeSpan elapsed = DateTime.Now - start;
1395                                 Assert.IsTrue (elapsed.TotalMilliseconds < 2000, "#4");
1396
1397                                 responder.Stop ();
1398                         }
1399                 }
1400
1401                 [Test] // bug #353495
1402                 [Category ("NotWorking")]
1403                 public void LastModifiedKind ()
1404                 {
1405                         const string reqURL = "http://coffeefaq.com/site/node/25";
1406                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create (reqURL);
1407                         HttpWebResponse resp = (HttpWebResponse) req.GetResponse ();
1408                         DateTime lastMod = resp.LastModified;
1409                         //string rawLastMod = resp.Headers ["Last-Modified"];
1410                         resp.Close ();
1411                         //Assert.AreEqual ("Tue, 15 Jan 2008 08:59:59 GMT", rawLastMod, "#1");
1412                         Assert.AreEqual (DateTimeKind.Local, lastMod.Kind, "#2");
1413                         req = (HttpWebRequest) WebRequest.Create (reqURL);
1414                         req.IfModifiedSince = lastMod;
1415                         try {
1416                                 resp = (HttpWebResponse) req.GetResponse ();
1417                                 resp.Close ();
1418                                 Assert.Fail ("Should result in 304");
1419                         } catch (WebException ex) {
1420                                 Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#3");
1421                                 Assert.AreEqual (((HttpWebResponse) ex.Response).StatusCode, HttpStatusCode.NotModified, "#4");
1422                         }
1423                 }
1424
1425
1426                 #region Timeout_Bug // https://bugzilla.novell.com/show_bug.cgi?id=317553
1427
1428                 class TimeoutTestHelper {
1429
1430                         string url_to_test;
1431                         internal DateTime? Start { get; private set; }
1432                         internal DateTime? End { get; private set; }
1433                         internal Exception Exception { get; private set; }
1434                         internal string Body { get; private set; }
1435                         internal int TimeOutInMilliSeconds { get; private set; }
1436
1437                         internal TimeoutTestHelper (string url, int timeoutInMilliseconds)
1438                         {
1439                                 url_to_test = url;
1440                                 TimeOutInMilliSeconds = timeoutInMilliseconds;
1441                         }
1442
1443                         internal void LaunchWebRequest ()
1444                         {
1445                                 var req = (HttpWebRequest) WebRequest.Create (url_to_test);
1446                                 req.Timeout = TimeOutInMilliSeconds;
1447
1448                                 Start = DateTime.Now;
1449                                 try {
1450                                         using (var resp = (HttpWebResponse) req.GetResponse ())
1451                                         {
1452                                                 var sr = new StreamReader (resp.GetResponseStream (), Encoding.UTF8);
1453                                                 Body = sr.ReadToEnd ();
1454                                         }
1455                                 } catch (Exception e) {
1456                                         End = DateTime.Now;
1457                                         Exception = e;
1458                                 }
1459                         }
1460                 }
1461
1462                 void TestTimeOut (string url, WebExceptionStatus expectedExceptionStatus)
1463                 {
1464                         var timeoutWorker = new TimeoutTestHelper (url, three_seconds_in_milliseconds);
1465                         var threadStart = new ThreadStart (timeoutWorker.LaunchWebRequest);
1466                         var thread = new Thread (threadStart);
1467                         thread.Start ();
1468                         Thread.Sleep (three_seconds_in_milliseconds * 3);
1469
1470                         if (timeoutWorker.End == null) {
1471                                 thread.Abort ();
1472                                 Assert.Fail ("Thread finished after triple the timeout specified has passed");
1473                         }
1474
1475                         if (!String.IsNullOrEmpty (timeoutWorker.Body)) {
1476                                 if (timeoutWorker.Body == response_of_timeout_handler) {
1477                                         Assert.Fail ("Should not be reached, timeout exception was not thrown and webrequest managed to retrieve proper body");
1478                                 }
1479                                 Assert.Fail ("Should not be reached, timeout exception was not thrown and webrequest managed to retrieve an incorrect body: " + timeoutWorker.Body);
1480                         }
1481
1482                         Assert.IsNotNull (timeoutWorker.Exception, "Exception was not thrown");
1483
1484                         var webEx = timeoutWorker.Exception as WebException;
1485                         Assert.IsNotNull (webEx, "Exception thrown should be WebException, but was: " +
1486                                           timeoutWorker.Exception.GetType ().FullName);
1487
1488                         Assert.AreEqual (expectedExceptionStatus, webEx.Status,
1489                                          "WebException was thrown, but with a wrong status (should be " + expectedExceptionStatus + "): " + webEx.Status);
1490
1491                         Assert.IsFalse (timeoutWorker.End > (timeoutWorker.Start + TimeSpan.FromMilliseconds (three_seconds_in_milliseconds + 500)),
1492                                         "Timeout exception should have been thrown shortly after timeout is reached, however it was at least half-second late");
1493                 }
1494
1495                 [Test] // 1st possible case of https://bugzilla.novell.com/show_bug.cgi?id=MONO74177
1496                 public void TestTimeoutPropertyWithServerThatExistsAndRespondsButTooLate ()
1497                 {
1498                         var ep = new IPEndPoint (IPAddress.Loopback, 8123);
1499                         string url = "http://" + ep + "/foobar/";
1500
1501                         using (var responder = new SocketResponder (ep, TimeOutHandler))
1502                         {
1503                                 responder.Start ();
1504
1505                                 TestTimeOut (url, WebExceptionStatus.Timeout);
1506
1507                                 responder.Stop ();
1508                         }
1509                 }
1510
1511                 [Test] // 2nd possible case of https://bugzilla.novell.com/show_bug.cgi?id=MONO74177
1512                 public void TestTimeoutWithEndpointThatDoesntExistThrowsConnectFailureBeforeTimeout ()
1513                 {
1514                         string url = "http://127.0.0.1:8271/"; // some endpoint that is unlikely to exist
1515
1516                         // connecting to a non-existing endpoint should throw a ConnectFailure before the timeout is reached
1517                         TestTimeOut (url, WebExceptionStatus.ConnectFailure);
1518                 }
1519
1520                 const string response_of_timeout_handler = "RESPONSE_OF_TIMEOUT_HANDLER";
1521                 const int three_seconds_in_milliseconds = 3000;
1522
1523                 private static byte[] TimeOutHandler (Socket socket)
1524                 {
1525                         socket.Receive (new byte[4096]);
1526
1527                         Thread.Sleep (three_seconds_in_milliseconds * 2);
1528
1529                         var sw = new StringWriter ();
1530                         sw.WriteLine ("HTTP/1.1 200 OK");
1531                         sw.WriteLine ("Content-Type: text/plain");
1532                         sw.WriteLine ("Content-Length: " + response_of_timeout_handler.Length);
1533                         sw.WriteLine ();
1534                         sw.Write (response_of_timeout_handler);
1535                         sw.Flush ();
1536
1537                         return Encoding.UTF8.GetBytes (sw.ToString ());
1538                 }
1539
1540                 #endregion
1541
1542                 internal static byte [] EchoRequestHandler (Socket socket)
1543                 {
1544                         MemoryStream ms = new MemoryStream ();
1545                         byte [] buffer = new byte [4096];
1546                         int bytesReceived = socket.Receive (buffer);
1547                         while (bytesReceived > 0) {
1548                                 ms.Write (buffer, 0, bytesReceived);
1549                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1550                                  // after sending the headers
1551                                 Thread.Sleep (200);
1552                                 if (socket.Available > 0) {
1553                                         bytesReceived = socket.Receive (buffer);
1554                                 } else {
1555                                         bytesReceived = 0;
1556                                 }
1557                         }
1558                         ms.Flush ();
1559                         ms.Position = 0;
1560                         StreamReader sr = new StreamReader (ms, Encoding.UTF8);
1561                         string request = sr.ReadToEnd ();
1562
1563                         StringWriter sw = new StringWriter ();
1564                         sw.WriteLine ("HTTP/1.1 200 OK");
1565                         sw.WriteLine ("Content-Type: text/xml");
1566                         sw.WriteLine ("Content-Length: " + request.Length.ToString (CultureInfo.InvariantCulture));
1567                         sw.WriteLine ();
1568                         sw.Write (request);
1569                         sw.Flush ();
1570
1571                         return Encoding.UTF8.GetBytes (sw.ToString ());
1572                 }
1573
1574                 static byte [] RedirectRequestHandler (Socket socket)
1575                 {
1576                         MemoryStream ms = new MemoryStream ();
1577                         byte [] buffer = new byte [4096];
1578                         int bytesReceived = socket.Receive (buffer);
1579                         while (bytesReceived > 0) {
1580                                 ms.Write (buffer, 0, bytesReceived);
1581                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1582                                  // after sending the headers
1583                                 Thread.Sleep (200);
1584                                 if (socket.Available > 0) {
1585                                         bytesReceived = socket.Receive (buffer);
1586                                 } else {
1587                                         bytesReceived = 0;
1588                                 }
1589                         }
1590                         ms.Flush ();
1591                         ms.Position = 0;
1592                         string statusLine = null;
1593                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1594                                 statusLine = sr.ReadLine ();
1595                         }
1596
1597                         StringWriter sw = new StringWriter ();
1598                         if (statusLine.StartsWith ("POST /original/")) {
1599                                 sw.WriteLine ("HTTP/1.0 302 Found");
1600                                 EndPoint ep = socket.LocalEndPoint;
1601                                 sw.WriteLine ("Location: " + "http://" + ep.ToString () + "/moved/");
1602                                 sw.WriteLine ();
1603                                 sw.Flush ();
1604                         } else if (statusLine.StartsWith ("GET /moved/")) {
1605                                 sw.WriteLine ("HTTP/1.0 200 OK");
1606                                 sw.WriteLine ("Content-Type: text/plain");
1607                                 sw.WriteLine ("Content-Length: 8");
1608                                 sw.WriteLine ();
1609                                 sw.Write ("LOOKS OK");
1610                                 sw.Flush ();
1611                         } else {
1612                                 sw.WriteLine ("HTTP/1.0 500 Too Lazy");
1613                                 sw.WriteLine ();
1614                                 sw.Flush ();
1615                         }
1616
1617                         return Encoding.UTF8.GetBytes (sw.ToString ());
1618                 }
1619
1620                 static byte [] InternalErrorHandler (Socket socket)
1621                 {
1622                         byte [] buffer = new byte [4096];
1623                         int bytesReceived = socket.Receive (buffer);
1624                         while (bytesReceived > 0) {
1625                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1626                                  // after sending the headers
1627                                 Thread.Sleep (200);
1628                                 if (socket.Available > 0) {
1629                                         bytesReceived = socket.Receive (buffer);
1630                                 } else {
1631                                         bytesReceived = 0;
1632                                 }
1633                         }
1634                         StringWriter sw = new StringWriter ();
1635                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
1636                         sw.WriteLine ("Content-Length: 0");
1637                         sw.WriteLine ();
1638                         sw.Flush ();
1639
1640                         return Encoding.UTF8.GetBytes (sw.ToString ());
1641                 }
1642
1643                 static byte [] NoContentLengthHandler (Socket socket)
1644                 {
1645                         StringWriter sw = new StringWriter ();
1646                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
1647                         sw.WriteLine ();
1648                         sw.Flush ();
1649
1650                         return Encoding.UTF8.GetBytes (sw.ToString ());
1651                 }
1652
1653                 static byte [] NotModifiedSinceHandler (Socket socket)
1654                 {
1655                         StringWriter sw = new StringWriter ();
1656                         sw.WriteLine ("HTTP/1.1 304 Not Modified");
1657                         sw.WriteLine ("Date: Fri, 06 Feb 2009 12:50:26 GMT");
1658                         sw.WriteLine ("Server: Apache/2.2.6 (Debian) PHP/5.2.6-2+b1 with Suhosin-Patch mod_ssl/2.2.6 OpenSSL/0.9.8g");
1659                         sw.WriteLine ("Not-Modified-Since: Sun, 08 Feb 2009 08:49:26 GMT");
1660                         sw.WriteLine ("ETag: 898bbr2347056cc2e096afc66e104653");
1661                         sw.WriteLine ("Connection: close");
1662                         sw.WriteLine ();
1663                         sw.Flush ();
1664
1665                         return Encoding.UTF8.GetBytes (sw.ToString ());
1666                 }
1667
1668                 static byte [] VerbEchoHandler (Socket socket)
1669                 {
1670                         MemoryStream ms = new MemoryStream ();
1671                         byte [] buffer = new byte [4096];
1672                         int bytesReceived = socket.Receive (buffer);
1673                         while (bytesReceived > 0) {
1674                                 ms.Write (buffer, 0, bytesReceived);
1675                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1676                                  // after sending the headers
1677                                 Thread.Sleep (200);
1678                                 if (socket.Available > 0) {
1679                                         bytesReceived = socket.Receive (buffer);
1680                                 } else {
1681                                         bytesReceived = 0;
1682                                 }
1683                         }
1684                         ms.Flush ();
1685                         ms.Position = 0;
1686                         string statusLine = null;
1687                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1688                                 statusLine = sr.ReadLine ();
1689                         }
1690
1691                         string verb = "DEFAULT";
1692                         if (statusLine != null) {
1693                                 string [] parts = statusLine.Split (' ');
1694                                 if (parts.Length > 0)
1695                                         verb = parts [0];
1696                         }
1697
1698                         StringWriter sw = new StringWriter ();
1699                         sw.WriteLine ("HTTP/1.1 200 OK");
1700                         sw.WriteLine ("Content-Type: text/plain");
1701                         sw.WriteLine ("Content-Length: " + verb.Length);
1702                         sw.WriteLine ();
1703                         sw.Write (verb);
1704                         sw.Flush ();
1705
1706                         return Encoding.UTF8.GetBytes (sw.ToString ());
1707                 }
1708
1709                 static byte [] PostAnd401Handler (Socket socket)
1710                 {
1711                         MemoryStream ms = new MemoryStream ();
1712                         byte [] buffer = new byte [4096];
1713                         int bytesReceived = socket.Receive (buffer);
1714                         while (bytesReceived > 0) {
1715                                 ms.Write (buffer, 0, bytesReceived);
1716                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1717                                  // after sending the headers
1718                                 Thread.Sleep (200);
1719                                 if (socket.Available > 0) {
1720                                         bytesReceived = socket.Receive (buffer);
1721                                 } else {
1722                                         bytesReceived = 0;
1723                                 }
1724                         }
1725                         ms.Flush ();
1726                         ms.Position = 0;
1727                         string statusLine = null;
1728                         bool have_auth = false;
1729                         int cl = -1;
1730                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1731                                 string l;
1732                                 while ((l = sr.ReadLine ()) != null) {
1733                                         if (statusLine == null) {
1734                                                 statusLine = l;
1735                                         } else if (l.StartsWith ("Authorization:")) {
1736                                                 have_auth = true;
1737                                         } else if (l.StartsWith ("Content-Length:")) {
1738                                                 cl = Int32.Parse (l.Substring ("content-length: ".Length));
1739                                         }
1740                                 }
1741                         }
1742
1743                         StringWriter sw = new StringWriter ();
1744                         if (!have_auth) {
1745                                 sw.WriteLine ("HTTP/1.0 401 Invalid Credentials");
1746                                 sw.WriteLine ("WWW-Authenticate: basic Yeah");
1747                                 sw.WriteLine ();
1748                                 sw.Flush ();
1749                         } else if (cl > 0 && statusLine.StartsWith ("POST ")) {
1750                                 sw.WriteLine ("HTTP/1.0 200 OK");
1751                                 sw.WriteLine ("Content-Type: text/plain");
1752                                 sw.WriteLine ("Content-Length: 8");
1753                                 sw.WriteLine ();
1754                                 sw.Write ("LOOKS OK");
1755                                 sw.Flush ();
1756                         } else {
1757                                 sw.WriteLine ("HTTP/1.0 500 test failed");
1758                                 sw.WriteLine ("Content-Length: 0");
1759                                 sw.WriteLine ();
1760                                 sw.Flush ();
1761                         }
1762
1763                         return Encoding.UTF8.GetBytes (sw.ToString ());
1764                 }
1765                 [Test]
1766                 public void NtlmAuthentication ()
1767                 {
1768                         NtlmServer server = new NtlmServer ();
1769                         server.Start ();
1770
1771                         string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
1772                         HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
1773                         request.Timeout = 5000;
1774                         request.Credentials = new NetworkCredential ("user", "password", "domain");
1775                         HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
1776                         string res = null;
1777                         using (StreamReader reader = new StreamReader (resp.GetResponseStream ())) {
1778                                 res = reader.ReadToEnd ();
1779                         }
1780                         resp.Close ();
1781                         server.Stop ();
1782                         Assert.AreEqual ("OK", res);
1783                 }
1784
1785                 class NtlmServer : HttpServer {
1786                         public string Where = "";
1787                         protected override void Run ()
1788                         {
1789                                 Where = "before accept";
1790                                 Socket client = sock.Accept ();
1791                                 NetworkStream ns = new NetworkStream (client, false);
1792                                 StreamReader reader = new StreamReader (ns, Encoding.ASCII);
1793                                 string line;
1794                                 Where = "first read";
1795                                 while ((line = reader.ReadLine ()) != null) {
1796                                         if (line.Trim () == String.Empty) {
1797                                                 break;
1798                                         }
1799                                 }
1800                                 Where = "first write";
1801                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
1802                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
1803                                                 "WWW-Authenticate: NTLM\r\n" +
1804                                                 "Content-Length: 5\r\n\r\nWRONG");
1805
1806                                 writer.Flush ();
1807                                 Where = "second read";
1808                                 while ((line = reader.ReadLine ()) != null) {
1809                                         if (line.Trim () == String.Empty) {
1810                                                 break;
1811                                         }
1812                                 }
1813                                 Where = "second write";
1814                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
1815                                                 "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAADgAAAABggAC8GDhqIONH3sAAAAAAAAAAAAAAAA4AAAABQLODgAAAA8=\r\n" +
1816                                                 "Content-Length: 5\r\n\r\nWRONG");
1817                                 writer.Flush ();
1818
1819                                 Where = "third read";
1820                                 while ((line = reader.ReadLine ()) != null) {
1821                                         if (line.Trim () == String.Empty) {
1822                                                 break;
1823                                         }
1824                                 }
1825                                 Where = "third write";
1826                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
1827                                                 "Keep-Alive: true\r\n" +
1828                                                 "Content-Length: 2\r\n\r\nOK");
1829                                 writer.Flush ();
1830                                 Thread.Sleep (1000);
1831                                 writer.Close ();
1832                                 reader.Close ();
1833                                 client.Close ();
1834                         }
1835                 }
1836
1837                 class BadChunkedServer : HttpServer {
1838                         protected override void Run ()
1839                         {
1840                                 Socket client = sock.Accept ();
1841                                 NetworkStream ns = new NetworkStream (client, true);
1842                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
1843                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
1844                                                 "Transfer-Encoding: chunked\r\n" +
1845                                                 "Connection: close\r\n" +
1846                                                 "Content-Type: text/plain; charset=UTF-8\r\n\r\n");
1847
1848                                 // This body lacks a 'last-chunk' (see RFC 2616)
1849                                 writer.Write ("10\r\n1234567890123456\r\n");
1850                                 writer.Flush ();
1851                                 client.Shutdown (SocketShutdown.Send);
1852                                 Thread.Sleep (1000);
1853                                 writer.Close ();
1854                         }
1855                 }
1856
1857                 class AcceptAllPolicy : ICertificatePolicy {
1858                         public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
1859                         {
1860                                 return true;
1861                         }
1862                 }
1863
1864                 abstract class HttpServer
1865                 {
1866                         protected Socket sock;
1867                         protected Exception error;
1868                         protected ManualResetEvent evt;
1869
1870                         public HttpServer ()
1871                         {
1872                                 sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
1873                                 sock.Bind (new IPEndPoint (IPAddress.Loopback, 0));
1874                                 sock.Listen (1);
1875                         }
1876
1877                         public void Start ()
1878                         {
1879                                 evt = new ManualResetEvent (false);
1880                                 Thread th = new Thread (new ThreadStart (Run));
1881                                 th.Start ();
1882                         }
1883
1884                         public void Stop ()
1885                         {
1886                                 evt.Set ();
1887                                 sock.Close ();
1888                         }
1889                         
1890                         public IPAddress IPAddress {
1891                                 get { return ((IPEndPoint) sock.LocalEndPoint).Address; }
1892                         }
1893                         
1894                         public int Port {
1895                                 get { return ((IPEndPoint) sock.LocalEndPoint).Port; }
1896                         }
1897
1898                         public Exception Error { 
1899                                 get { return error; }
1900                         }
1901
1902                         protected abstract void Run ();
1903                 }
1904
1905                 [Test]
1906                 public void BeginGetRequestStream ()
1907                 {
1908                         this.DoRequest (
1909                         (r, c) =>
1910                         {
1911                                 r.Method = "POST";
1912                                 r.ContentLength = 0;
1913                                 r.BeginGetRequestStream ((a) =>
1914                                 {
1915                                 using (Stream s = r.EndGetRequestStream (a)) { };
1916                                 c.Set();
1917                                 },
1918                                 null);
1919                         },
1920                         (c) => { });
1921                 }
1922
1923                 [Test]
1924                 public void BeginGetRequestStreamNoClose ()
1925                 {
1926                         this.DoRequest (
1927                         (r, c) => {
1928                                 r.Method = "POST";
1929                                 r.ContentLength = 1;
1930                                 r.BeginGetRequestStream ((a) =>
1931                                 {
1932                                         r.EndGetRequestStream (a);
1933                                         c.Set ();
1934                                 },
1935                                 null);
1936                         },
1937                         (c) => {});
1938                 }
1939
1940                 [Test]
1941                 public void BeginGetRequestStreamCancelIfNotAllBytesWritten ()
1942                 {
1943                         this.DoRequest (
1944                         (r, c) =>
1945                         {
1946                                 r.Method = "POST";
1947                                 r.ContentLength = 10;
1948                                 r.BeginGetRequestStream ((a) =>
1949                                 {
1950                                         WebException ex = ExceptionAssert.Throws<WebException> (() =>
1951                                         {
1952                                                 using (Stream s = r.EndGetRequestStream (a)) {
1953                                                 }
1954                                         }
1955                                 );
1956                                 Assert.AreEqual (ex.Status, WebExceptionStatus.RequestCanceled);
1957                                 c.Set();
1958                                 },
1959                                 null);
1960                         },
1961                         (c) => { });
1962                 }
1963
1964                 [Test]
1965                 public void GetRequestStream2 ()
1966                 {
1967                         this.DoRequest (
1968                         (r, c) =>
1969                         {
1970                                 r.Method = "POST";
1971                                 r.ContentLength = data64KB.Length;
1972                                 using (Stream s = r.GetRequestStream ()) {
1973                                         s.Write (data64KB, 0, data64KB.Length);
1974                                 }
1975                                 c.Set ();
1976                         },
1977                         (c) => { });
1978                 }
1979
1980                 [Test]
1981                 public void GetRequestStreamNotAllBytesWritten ()
1982                 {
1983                         this.DoRequest (
1984                         (r, c) =>
1985                         {
1986                                 r.Method = "POST";
1987                                 r.ContentLength = data64KB.Length;
1988                                 WebException ex = ExceptionAssert.Throws<WebException> (() => r.GetRequestStream ().Close ());
1989                                 Assert.AreEqual (ex.Status, WebExceptionStatus.RequestCanceled);
1990                                 c.Set ();
1991                         },
1992                         (c) => {});
1993                 }
1994
1995                 [Test]
1996                 public void GetRequestStreamTimeout ()
1997                 {
1998                         this.DoRequest (
1999                         (r, c) =>
2000                         {
2001                                 r.Method = "POST";
2002                                 r.ContentLength = data64KB.Length;
2003                                 r.Timeout = 100;
2004                                 WebException ex = ExceptionAssert.Throws<WebException> (() => r.GetRequestStream ());
2005                                 Assert.IsTrue (ex.Status == WebExceptionStatus.Timeout || ex.Status == WebExceptionStatus.ConnectFailure);
2006                                 c.Set();
2007                         });
2008                 }
2009
2010                 [Test]
2011                 public void BeginWrite ()
2012                 {
2013                         byte[] received = new byte[data64KB.Length];
2014
2015                         this.DoRequest (
2016                         (r, c) =>
2017                         {
2018                                 r.Method = "POST";
2019                                 r.ContentLength = data64KB.Length;
2020
2021                                 Stream s = r.GetRequestStream ();
2022                                 s.BeginWrite (data64KB, 0, data64KB.Length,
2023                                 (a) =>
2024                                 {
2025                                         s.EndWrite (a);
2026                                         s.Close ();
2027                                         r.GetResponse ().Close ();
2028                                         c.Set();
2029                                 },
2030                                 null);
2031                         },
2032                         (c) =>
2033                         {
2034                                 c.Request.InputStream.ReadAll (received, 0, received.Length);
2035                                 c.Response.StatusCode = 204;
2036                                 c.Response.Close ();
2037                         });
2038
2039                         Assert.AreEqual (data64KB, received);
2040                 }
2041
2042                 [Test]
2043                 public void BeginWriteAfterAbort ()
2044                 {
2045                         byte [] received = new byte [data64KB.Length];
2046
2047                         this.DoRequest (
2048                         (r, c) =>
2049                         {
2050                                 r.Method = "POST";
2051                                 r.ContentLength = data64KB.Length;
2052
2053                                 Stream s = r.GetRequestStream ();
2054                                 r.Abort();
2055
2056                                 WebException ex = ExceptionAssert.Throws<WebException> (() => s.BeginWrite (data64KB, 0, data64KB.Length, null, null));
2057                                 Assert.AreEqual (ex.Status, WebExceptionStatus.RequestCanceled);
2058
2059                                 c.Set();
2060                         },
2061                         (c) =>
2062                         {
2063                                 //c.Request.InputStream.ReadAll (received, 0, received.Length);
2064                                 //c.Response.StatusCode = 204;
2065                                 //c.Response.Close();
2066                         });
2067                 }
2068
2069                 [Test]
2070                 public void PrematureStreamCloseAborts ()
2071                 {
2072                         byte [] received = new byte [data64KB.Length];
2073
2074                         this.DoRequest (
2075                         (r, c) =>
2076                         {
2077                                 r.Method = "POST";
2078                                 r.ContentLength = data64KB.Length * 2;
2079
2080                                 Stream s = r.GetRequestStream ();
2081                                 s.Write (data64KB, 0, data64KB.Length);
2082
2083                                 WebException ex = ExceptionAssert.Throws<WebException>(() => s.Close());
2084                                 Assert.AreEqual(ex.Status, WebExceptionStatus.RequestCanceled);
2085
2086                                 c.Set();
2087                         },
2088                         (c) =>
2089                         {
2090                                 c.Request.InputStream.ReadAll (received, 0, received.Length);
2091 //                              c.Response.StatusCode = 204;
2092 //                              c.Response.Close ();
2093                         });
2094                 }
2095
2096                 [Test]
2097                 public void Write ()
2098                 {
2099                         byte [] received = new byte [data64KB.Length];
2100
2101                         this.DoRequest (
2102                         (r, c) =>
2103                         {
2104                                 r.Method = "POST";
2105                                 r.ContentLength = data64KB.Length;
2106
2107                                 using (Stream s = r.GetRequestStream ()) {
2108                                         s.Write (data64KB, 0, data64KB.Length);
2109                                 }
2110
2111                                 r.GetResponse ().Close ();
2112                                 c.Set ();
2113                         },
2114                         (c) =>
2115                         {
2116                                 c.Request.InputStream.ReadAll (received, 0, received.Length);
2117                                 c.Response.StatusCode = 204;
2118                                 c.Response.Close ();
2119                         });
2120
2121                         Assert.AreEqual(data64KB, received);
2122                 }
2123
2124                 /*
2125                 Invalid test: it does not work on linux.
2126                 [pid 30973] send(9, "POST / HTTP/1.1\r\nContent-Length:"..., 89, 0) = 89
2127                 Abort set
2128                 [pid 30970] send(16, "HTTP/1.1 200 OK\r\nServer: Mono-HT"..., 133, 0) = 133
2129                 Calling abort
2130                 [pid 30970] close(16)                   = 0
2131                 Closing!!!
2132                 [pid 30980] send(9, "\213t\326\350\312u\36n\234\351\225L\r\243a\200\226\371\350F\271~oZ\32\270\24\226z4\211\345"..., 65536, 0) = 65536
2133                 Writing...
2134                 [pid 30966] close(4)                    = 0
2135                 OK
2136                  *
2137                  The server sideis closed (FD 16) and the send on the client side (FD 9) succeeds.
2138                 [Test]
2139                 [Category("NotWorking")]
2140                 public void WriteServerAborts ()
2141                 {
2142                         ManualResetEvent abort = new ManualResetEvent (false);
2143                         byte [] received = new byte [data64KB.Length];
2144
2145                         this.DoRequest (
2146                         (r, c) =>
2147                         {
2148                                 r.Method = "POST";
2149                                 r.ContentLength = data64KB.Length;
2150
2151                                 using (Stream s = r.GetRequestStream()) {
2152                                         abort.Set();
2153                                         Thread.Sleep(100);
2154                                         IOException ex = ExceptionAssert.Throws<IOException> (() => s.Write(data64KB, 0, data64KB.Length));
2155                                 }
2156
2157                                 c.Set();
2158                         },
2159                         (c) =>
2160                         {
2161                                 abort.WaitOne();
2162                                 c.Response.Abort();
2163                         });
2164                 }
2165                 **/
2166
2167                 [Test]
2168                 public void Read ()
2169                 {
2170                         byte [] received = new byte [data64KB.Length];
2171
2172                         this.DoRequest (
2173                         (r, c) =>
2174                         {
2175                                 using (HttpWebResponse x = (HttpWebResponse) r.GetResponse ())
2176                                 using (Stream s = x.GetResponseStream()) {
2177                                         s.ReadAll (received, 0, received.Length);
2178                                 }
2179
2180                                 c.Set ();
2181                         },
2182                         (c) =>
2183                         {
2184                                 c.Response.StatusCode = 200;
2185                                 c.Response.ContentLength64 = data64KB.Length;
2186                                 c.Response.OutputStream.Write (data64KB, 0, data64KB.Length);
2187                                 c.Response.OutputStream.Close ();
2188                                 c.Response.Close ();
2189                         });
2190
2191                         Assert.AreEqual (data64KB, received);
2192                 }
2193
2194                 [Test]
2195                 public void ReadTimeout2 ()
2196                 {
2197                         byte [] received = new byte [data64KB.Length];
2198
2199                         this.DoRequest (
2200                         (r, c) =>
2201                         {
2202                                 r.ReadWriteTimeout = 10;
2203                                 using (HttpWebResponse x = (HttpWebResponse) r.GetResponse ())
2204                                 using (Stream s = x.GetResponseStream ()) {
2205                                         WebException ex = ExceptionAssert.Throws<WebException> (() => s.ReadAll (received, 0, received.Length));
2206                                         Assert.AreEqual (ex.Status, WebExceptionStatus.Timeout);
2207                                 }
2208
2209                                 c.Set();
2210                         },
2211                         (c) =>
2212                         {
2213                                 c.Response.StatusCode = 200;
2214                                 c.Response.ContentLength64 = data64KB.Length;
2215                                 c.Response.OutputStream.Write (data64KB, 0, data64KB.Length / 2);
2216                                 Thread.Sleep (1000);
2217 //                              c.Response.OutputStream.Write (data64KB, data64KB.Length / 2, data64KB.Length / 2);
2218                                 c.Response.OutputStream.Close ();
2219                                 c.Response.Close ();
2220                         });
2221                 }
2222
2223                 [Test]
2224                 public void ReadServerAborted ()
2225                 {
2226                         byte [] received = new byte [data64KB.Length];
2227
2228                         this.DoRequest (
2229                         (r, c) =>
2230                         {
2231                                 using (HttpWebResponse x = (HttpWebResponse) r.GetResponse ())
2232                                 using (Stream s = x.GetResponseStream ()) {
2233                                         Assert.AreEqual (1, s.ReadAll (received, 0, received.Length));
2234                                 }
2235
2236                                 c.Set();
2237                         },
2238                         (c) =>
2239                         {
2240                                 c.Response.StatusCode = 200;
2241                                 c.Response.ContentLength64 = data64KB.Length;
2242                                 c.Response.OutputStream.Write (data64KB, 0, 1);
2243                                 c.Response.Abort ();
2244                         });
2245                 }
2246
2247                 [Test]
2248                 public void BeginGetResponse2 ()
2249                 {
2250                         byte [] received = new byte [data64KB.Length];
2251
2252                         this.DoRequest (
2253                         (r, c) =>
2254                         {
2255                                 r.BeginGetResponse ((a) =>
2256                                 {
2257                                         using (HttpWebResponse x = (HttpWebResponse) r.EndGetResponse (a))
2258                                         using (Stream s = x.GetResponseStream ()) {
2259                                                 s.ReadAll (received, 0, received.Length);
2260                                         }
2261
2262                                         c.Set();
2263                                 }, null);
2264                         },
2265                         (c) =>
2266                         {
2267                                 c.Response.StatusCode = 200;
2268                                 c.Response.ContentLength64 = data64KB.Length;
2269                                 c.Response.OutputStream.Write (data64KB, 0, data64KB.Length);
2270                                 c.Response.OutputStream.Close ();
2271                                 c.Response.Close ();
2272                         });
2273
2274                         Assert.AreEqual (data64KB, received);
2275                 }
2276
2277                 [Test]
2278                 public void BeginGetResponseAborts ()
2279                 {
2280                         ManualResetEvent aborted = new ManualResetEvent(false);
2281
2282                         this.DoRequest (
2283                         (r, c) =>
2284                         {
2285                                 r.BeginGetResponse((a) =>
2286                                 {
2287                                         WebException ex = ExceptionAssert.Throws<WebException> (() => r.EndGetResponse (a));
2288                                         Assert.AreEqual (ex.Status, WebExceptionStatus.RequestCanceled);
2289                                         c.Set ();
2290                                 }, null);
2291
2292                                 aborted.WaitOne ();
2293                                 r.Abort ();
2294                         },
2295                         (c) =>
2296                         {
2297                                 aborted.Set ();
2298 //                              Thread.Sleep (100);
2299 //                              c.Response.StatusCode = 200;
2300 //                              c.Response.ContentLength64 = 0;
2301 //                              c.Response.Close ();
2302                         });
2303
2304                         return;
2305                 }
2306                 
2307                 [Test]
2308                 public void TestLargeDataReading ()
2309                 {
2310                         int near2GBStartPosition = rand.Next (int.MaxValue - 500, int.MaxValue);
2311                         AutoResetEvent readyGetLastPortionEvent = new AutoResetEvent (false);
2312                         Exception testException = null;
2313
2314                         DoRequest (
2315                         (request, waitHandle) =>
2316                         {
2317                                 try
2318                                 {
2319                                         const int timeoutMs = 5000;
2320
2321                                         request.Timeout = timeoutMs;
2322                                         request.ReadWriteTimeout = timeoutMs;
2323
2324                                         WebResponse webResponse = request.GetResponse ();
2325                                         Stream webResponseStream = webResponse.GetResponseStream ();
2326                                         Assert.IsNotNull (webResponseStream, null, "#1");
2327                                         
2328                                         Type webConnectionStreamType = webResponseStream.GetType ();
2329                                         FieldInfo totalReadField = webConnectionStreamType.GetField ("totalRead", BindingFlags.NonPublic | BindingFlags.Instance);
2330                                         Assert.IsNotNull (totalReadField, "#2");
2331                                         totalReadField.SetValue (webResponseStream, near2GBStartPosition);
2332                                         
2333                                         byte[] readBuffer = new byte[int.MaxValue - near2GBStartPosition];
2334                                         Assert.AreEqual (webResponseStream.Read (readBuffer, 0, readBuffer.Length), readBuffer.Length, "#3");
2335                                         readyGetLastPortionEvent.Set ();
2336                                         Assert.IsTrue (webResponseStream.Read (readBuffer, 0, readBuffer.Length) > 0);
2337                                         readyGetLastPortionEvent.Set ();
2338                                         
2339                                         webResponse.Close();
2340                                 }
2341                                 catch (Exception e)
2342                                 {
2343                                         testException = e;
2344                                 }
2345                                 finally
2346                                 {
2347                                         waitHandle.Set ();
2348                                 }
2349                         },
2350                         processor =>
2351                         {
2352                                 processor.Request.InputStream.Close ();
2353                                 
2354                                 HttpListenerResponse response = processor.Response;
2355                                 response.SendChunked = true;
2356                                 
2357                                 Stream outputStream = response.OutputStream;
2358                                 var writeBuffer = new byte[int.MaxValue - near2GBStartPosition];
2359                                 outputStream.Write (writeBuffer, 0, writeBuffer.Length);
2360                                 readyGetLastPortionEvent.WaitOne ();
2361                                 outputStream.Write (writeBuffer, 0, writeBuffer.Length);
2362                                 readyGetLastPortionEvent.WaitOne ();
2363                                 
2364                                 response.Close();
2365                         });
2366
2367                         if (testException != null)
2368                                 throw testException;
2369                 }
2370
2371                 void DoRequest (Action<HttpWebRequest, EventWaitHandle> request)
2372                 {
2373                         int port = NetworkHelpers.FindFreePort ();
2374
2375                         ManualResetEvent completed = new ManualResetEvent (false);
2376                         Uri address = new Uri (string.Format ("http://localhost:{0}", port));
2377                         HttpWebRequest client = (HttpWebRequest) WebRequest.Create (address);
2378
2379                         request (client, completed);
2380
2381                         if (!completed.WaitOne (10000))
2382                                 Assert.Fail ("Test hung");
2383                 }
2384
2385                 void DoRequest (Action<HttpWebRequest, EventWaitHandle> request, Action<HttpListenerContext> processor)
2386                 {
2387                         int port = NetworkHelpers.FindFreePort ();
2388
2389                         ManualResetEvent [] completed = new ManualResetEvent [2];
2390                         completed [0] = new ManualResetEvent (false);
2391                         completed [1] = new ManualResetEvent (false);
2392
2393                         using (ListenerScope scope = new ListenerScope (processor, port, completed [0])) {
2394                                 ManualResetEvent clientCompleted = new ManualResetEvent (false);
2395                                 Uri address = new Uri (string.Format ("http://localhost:{0}", port));
2396                                 HttpWebRequest client = (HttpWebRequest) WebRequest.Create (address);
2397
2398                                 ThreadPool.QueueUserWorkItem ((o) => request (client, completed [1]));
2399
2400                                 if (!WaitHandle.WaitAll (completed, 10000))
2401                                         Assert.Fail ("Test hung.");
2402                         }
2403                 }
2404
2405                 [Test]
2406                 [ExpectedException (typeof (ArgumentNullException))]
2407                 public void NullHost ()
2408                 {
2409                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2410                         req.Host = null;
2411                 }
2412
2413                 [Test]
2414                 public void NoHost ()
2415                 {
2416                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2417                         Assert.AreEqual (req.Host, "go-mono.com");
2418                 }
2419
2420                 [Test]
2421                 [ExpectedException (typeof (ArgumentException))]
2422                 public void EmptyHost ()
2423                 {
2424                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2425                         req.Host = "";
2426                 }
2427
2428                 [Test]
2429                 public void HostAndPort ()
2430                 {
2431                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com:80");
2432                         Assert.AreEqual ("go-mono.com", req.Host, "#01");
2433                         req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com:9000");
2434                         Assert.AreEqual ("go-mono.com:9000", req.Host, "#02");
2435                 }
2436
2437                 [Test]
2438                 public void PortRange ()
2439                 {
2440                         for (int i = 0; i < 65536; i++) {
2441                                 if (i == 80)
2442                                         continue;
2443                                 string s = i.ToString ();
2444                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com:" + s);
2445                                 Assert.AreEqual ("go-mono.com:" + s, req.Host, "#" + s);
2446                         }
2447                 }
2448
2449                 [Test]
2450                 [ExpectedException (typeof (ArgumentException))]
2451                 public void PortBelow ()
2452                 {
2453                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2454                         req.Host = "go-mono.com:-1";
2455                 }
2456
2457                 [Test]
2458                 [ExpectedException (typeof (ArgumentException))]
2459                 public void PortAbove ()
2460                 {
2461                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2462                         req.Host = "go-mono.com:65536";
2463                 }
2464
2465                 [Test]
2466                 [ExpectedException (typeof (ArgumentException))]
2467                 public void HostTooLong ()
2468                 {
2469                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2470                         string s = new string ('a', 100);
2471                         req.Host = s + "." + s + "." + s + "." + s + "." + s + "." + s; // Over 255 bytes
2472                 }
2473
2474                 [Test]
2475                 [Category ("NotWorking")] // #5490
2476                 public void InvalidNamesThatWork ()
2477                 {
2478                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2479                         req.Host = "-";
2480                         req.Host = "-.-";
2481                         req.Host = "á";
2482                         req.Host = new string ('a', 64); // Should fail. Max. is 63.
2483                 }
2484
2485                 [Test]
2486                 public void NoDate ()
2487                 {
2488                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2489                         Assert.AreEqual (DateTime.MinValue, req.Date);
2490                 }
2491
2492                 [Test]
2493                 public void UtcDate ()
2494                 {
2495                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2496                         req.Date = DateTime.UtcNow;
2497                         DateTime date = req.Date;
2498                         Assert.AreEqual (DateTimeKind.Local, date.Kind);
2499                 }
2500
2501                 [Test]
2502                 public void AddAndRemoveDate ()
2503                 {
2504                         // Neil Armstrong set his foot on Moon
2505                         var landing = new DateTime (1969, 7, 21, 2, 56, 0, DateTimeKind.Utc);
2506                         Assert.AreEqual (621214377600000000, landing.Ticks);
2507                         var unspecified = new DateTime (1969, 7, 21, 2, 56, 0);
2508                         var local = landing.ToLocalTime ();
2509
2510                         var req = (HttpWebRequest)WebRequest.Create ("http://www.mono-project.com/");
2511                         req.Date = landing;
2512                         Assert.AreEqual (DateTimeKind.Local, req.Date.Kind);
2513                         Assert.AreEqual (local.Ticks, req.Date.Ticks);
2514                         Assert.AreEqual (local, req.Date);
2515
2516                         req.Date = unspecified;
2517                         Assert.AreEqual (DateTimeKind.Local, req.Date.Kind);
2518                         Assert.AreEqual (unspecified.Ticks, req.Date.Ticks);
2519                         Assert.AreEqual (unspecified, req.Date);
2520
2521                         req.Date = local;
2522                         Assert.AreEqual (DateTimeKind.Local, req.Date.Kind);
2523                         Assert.AreEqual (local.Ticks, req.Date.Ticks);
2524                         Assert.AreEqual (local, req.Date);
2525
2526                         req.Date = DateTime.MinValue;
2527                         Assert.AreEqual (DateTimeKind.Unspecified, DateTime.MinValue.Kind);
2528                         Assert.AreEqual (DateTimeKind.Unspecified, req.Date.Kind);
2529                         Assert.AreEqual (0, req.Date.Ticks);
2530
2531                         Assert.AreEqual (null, req.Headers.Get ("Date"));
2532                 }
2533                 
2534                 [Test]
2535                 // Bug #12393
2536                 public void TestIPv6Host ()
2537                 {
2538                         var address = "2001:0000:0000:0001:0001:0001:0157:0000";
2539                         var address2 = '[' + address + ']';
2540                         var uri = new Uri (string.Format ("http://{0}/test.css", address2));
2541                         var hwr = (HttpWebRequest)WebRequest.Create (uri);
2542
2543                         hwr.Host = address2;
2544                         Assert.AreEqual (address2, hwr.Host, "#1");
2545                 }
2546
2547                 [Test]
2548                 // Bug #12393
2549                 [Category ("NotWorking")]
2550                 public void TestIPv6Host2 ()
2551                 {
2552                         var address = "2001:0000:0000:0001:0001:0001:0157:0000";
2553                         var address2 = '[' + address + ']';
2554                         var uri = new Uri (string.Format ("http://{0}/test.css", address2));
2555                         var hwr = (HttpWebRequest)WebRequest.Create (uri);
2556
2557                         try {
2558                                 hwr.Host = address;
2559                                 Assert.Fail ("#1");
2560                         } catch (ArgumentException) {
2561                                 ;
2562                         }
2563                 }
2564
2565 #if NET_4_5
2566                 [Test]
2567                 public void AllowReadStreamBuffering ()
2568                 {
2569                         var hr = WebRequest.CreateHttp ("http://www.google.com");
2570                         Assert.IsFalse (hr.AllowReadStreamBuffering, "#1");
2571                         try {
2572                                 hr.AllowReadStreamBuffering = true;
2573                                 Assert.Fail ("#2");
2574                         } catch (InvalidOperationException) {
2575                         }
2576                 }
2577 #endif
2578
2579                 class ListenerScope : IDisposable {
2580                         EventWaitHandle completed;
2581                         public HttpListener listener;
2582                         Action<HttpListenerContext> processor;
2583
2584                         public ListenerScope (Action<HttpListenerContext> processor, int port, EventWaitHandle completed)
2585                         {
2586                                 this.processor = processor;
2587                                 this.completed = completed;
2588
2589                                 this.listener = new HttpListener ();
2590                                 this.listener.Prefixes.Add (string.Format ("http://localhost:{0}/", port));
2591                                 this.listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
2592                                 this.listener.Start ();
2593
2594                                 this.listener.BeginGetContext (this.RequestHandler, null);
2595                         }
2596
2597                         void RequestHandler (IAsyncResult result)
2598                         {
2599                                 HttpListenerContext context = null;
2600
2601                                 try {
2602                                         context = this.listener.EndGetContext (result);
2603                                 } catch (HttpListenerException ex) {
2604                                         // check if the thread has been aborted as in the case when we are shutting down.
2605                                         if (ex.ErrorCode == 995)
2606                                                 return;
2607                                 } catch (ObjectDisposedException) {
2608                                         return;
2609                                 }
2610
2611                                 ThreadPool.QueueUserWorkItem ((o) =>
2612                                 {
2613                                         try {
2614                                                 this.processor (context);
2615                                         } catch (HttpListenerException) {
2616                                         }
2617                                 });
2618
2619                                 this.completed.Set ();
2620                         }
2621
2622                         public void Dispose ()
2623                         {
2624                                 this.listener.Stop ();
2625                         }
2626                 }
2627
2628 #if !MOBILE
2629                 class SslHttpServer : HttpServer {
2630                         X509Certificate _certificate;
2631
2632                         protected override void Run ()
2633                         {
2634                                 try {
2635                                         Socket client = sock.Accept ();
2636                                         NetworkStream ns = new NetworkStream (client, true);
2637                                         SslServerStream s = new SslServerStream (ns, Certificate, false, false);
2638                                         s.PrivateKeyCertSelectionDelegate += new PrivateKeySelectionCallback (GetPrivateKey);
2639
2640                                         StreamReader reader = new StreamReader (s);
2641                                         StreamWriter writer = new StreamWriter (s, Encoding.ASCII);
2642
2643                                         string line;
2644                                         string hello = "<html><body><h1>Hello World!</h1></body></html>";
2645                                         string answer = "HTTP/1.0 200\r\n" +
2646                                                         "Connection: close\r\n" +
2647                                                         "Content-Type: text/html\r\n" +
2648                                                         "Content-Encoding: " + Encoding.ASCII.WebName + "\r\n" +
2649                                                         "Content-Length: " + hello.Length + "\r\n" +
2650                                                         "\r\n" + hello;
2651
2652                                         // Read the headers
2653                                         do {
2654                                                 line = reader.ReadLine ();
2655                                         } while (line != "" && line != null && line.Length > 0);
2656
2657                                         // Now the content. We know it's 100 bytes.
2658                                         // This makes BeginRead in sslclientstream block.
2659                                         char [] cs = new char [100];
2660                                         reader.Read (cs, 0, 100);
2661
2662                                         writer.Write (answer);
2663                                         writer.Flush ();
2664                                         if (evt.WaitOne (5000, false))
2665                                                 error = new Exception ("Timeout when stopping the server");
2666                                 } catch (Exception e) {
2667                                         error = e;
2668                                 }
2669                         }
2670
2671                         X509Certificate Certificate {
2672                                 get {
2673                                         if (_certificate == null)
2674                                                 _certificate = new X509Certificate (CertData.Certificate);
2675
2676                                         return _certificate;
2677                                 }
2678                         }
2679
2680                         AsymmetricAlgorithm GetPrivateKey (X509Certificate certificate, string targetHost)
2681                         {
2682                                 PrivateKey key = new PrivateKey (CertData.PrivateKey, null);
2683                                 return key.RSA;
2684                         }
2685                 }
2686
2687                 class CertData {
2688                         public readonly static byte [] Certificate = {
2689                                 48, 130, 1, 191, 48, 130, 1, 40, 160, 3, 2, 1, 2, 2, 16, 36, 
2690                                 14, 97, 190, 146, 132, 208, 71, 175, 6, 87, 168, 185, 175, 55, 43, 48, 
2691                                 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 48, 18, 
2692                                 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 111, 110, 122, 97, 
2693                                 108, 111, 48, 30, 23, 13, 48, 53, 48, 54, 50, 50, 49, 57, 51, 48, 
2694                                 52, 54, 90, 23, 13, 51, 57, 49, 50, 51, 49, 50, 51, 53, 57, 53, 
2695                                 57, 90, 48, 18, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 
2696                                 111, 110, 122, 97, 108, 111, 48, 129, 158, 48, 13, 6, 9, 42, 134, 72, 
2697                                 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 140, 0, 48, 129, 136, 2, 
2698                                 129, 129, 0, 138, 9, 38, 25, 166, 252, 59, 26, 39, 184, 128, 216, 38, 
2699                                 73, 41, 86, 30, 228, 160, 205, 41, 135, 115, 223, 44, 62, 42, 198, 178, 
2700                                 190, 81, 11, 25, 21, 216, 49, 179, 130, 246, 52, 97, 175, 212, 94, 157, 
2701                                 231, 162, 66, 161, 103, 63, 204, 83, 141, 172, 119, 97, 225, 206, 98, 101, 
2702                                 210, 106, 2, 206, 81, 90, 173, 47, 41, 199, 209, 241, 177, 177, 96, 207, 
2703                                 254, 220, 190, 66, 180, 153, 0, 209, 14, 178, 69, 194, 3, 37, 116, 239, 
2704                                 49, 23, 185, 245, 255, 126, 35, 85, 246, 56, 244, 107, 117, 24, 14, 57, 
2705                                 9, 111, 147, 189, 220, 142, 57, 104, 153, 193, 205, 19, 14, 22, 157, 16, 
2706                                 24, 80, 201, 2, 2, 0, 17, 163, 23, 48, 21, 48, 19, 6, 3, 85, 
2707                                 29, 37, 4, 12, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, 
2708                                 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 3, 
2709                                 129, 129, 0, 64, 49, 57, 253, 218, 198, 229, 51, 189, 12, 154, 225, 183, 
2710                                 160, 147, 90, 113, 172, 69, 122, 28, 77, 97, 215, 231, 194, 150, 29, 196, 
2711                                 65, 95, 218, 99, 142, 111, 79, 205, 109, 76, 32, 92, 220, 76, 88, 53, 
2712                                 237, 80, 11, 85, 44, 91, 21, 210, 12, 34, 223, 234, 18, 187, 136, 62, 
2713                                 26, 240, 103, 180, 12, 226, 221, 250, 247, 129, 51, 23, 129, 165, 56, 67, 
2714                                 43, 83, 244, 110, 207, 24, 253, 195, 16, 46, 80, 113, 80, 18, 2, 254, 
2715                                 120, 147, 151, 164, 23, 210, 230, 100, 19, 197, 179, 28, 194, 48, 106, 159, 
2716                                 155, 144, 37, 82, 44, 160, 40, 52, 146, 174, 77, 188, 160, 230, 75, 172, 
2717                                 123, 3, 254, 
2718                         };
2719
2720                         public readonly static byte [] PrivateKey = {
2721                                 30, 241, 181, 176, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 
2722                                 0, 0, 0, 0, 84, 2, 0, 0, 7, 2, 0, 0, 0, 36, 0, 0, 
2723                                 82, 83, 65, 50, 0, 4, 0, 0, 17, 0, 0, 0, 201, 80, 24, 16, 
2724                                 157, 22, 14, 19, 205, 193, 153, 104, 57, 142, 220, 189, 147, 111, 9, 57, 
2725                                 14, 24, 117, 107, 244, 56, 246, 85, 35, 126, 255, 245, 185, 23, 49, 239, 
2726                                 116, 37, 3, 194, 69, 178, 14, 209, 0, 153, 180, 66, 190, 220, 254, 207, 
2727                                 96, 177, 177, 241, 209, 199, 41, 47, 173, 90, 81, 206, 2, 106, 210, 101, 
2728                                 98, 206, 225, 97, 119, 172, 141, 83, 204, 63, 103, 161, 66, 162, 231, 157, 
2729                                 94, 212, 175, 97, 52, 246, 130, 179, 49, 216, 21, 25, 11, 81, 190, 178, 
2730                                 198, 42, 62, 44, 223, 115, 135, 41, 205, 160, 228, 30, 86, 41, 73, 38, 
2731                                 216, 128, 184, 39, 26, 59, 252, 166, 25, 38, 9, 138, 175, 88, 190, 223, 
2732                                 27, 24, 224, 123, 190, 69, 164, 234, 129, 59, 108, 229, 248, 62, 187, 15, 
2733                                 235, 147, 162, 83, 47, 123, 170, 190, 224, 31, 215, 110, 143, 31, 227, 216, 
2734                                 85, 88, 154, 83, 207, 229, 41, 28, 237, 116, 181, 17, 37, 141, 224, 185, 
2735                                 164, 144, 141, 233, 164, 138, 177, 241, 115, 181, 230, 150, 7, 92, 139, 141, 
2736                                 113, 95, 57, 191, 211, 165, 217, 250, 197, 68, 164, 184, 168, 43, 48, 65, 
2737                                 177, 237, 173, 144, 148, 221, 62, 189, 147, 63, 216, 188, 206, 103, 226, 171, 
2738                                 32, 20, 230, 116, 144, 192, 1, 39, 202, 87, 74, 250, 6, 142, 188, 23, 
2739                                 45, 4, 112, 191, 253, 67, 69, 70, 128, 143, 44, 234, 41, 96, 195, 82, 
2740                                 202, 35, 158, 149, 240, 151, 23, 25, 166, 179, 85, 144, 58, 120, 149, 229, 
2741                                 205, 34, 8, 110, 86, 119, 130, 210, 37, 173, 65, 71, 169, 67, 8, 51, 
2742                                 20, 96, 51, 155, 3, 39, 85, 187, 40, 193, 57, 19, 99, 78, 173, 28, 
2743                                 129, 154, 108, 175, 8, 138, 237, 71, 27, 148, 129, 35, 47, 57, 101, 237, 
2744                                 168, 178, 227, 221, 212, 63, 124, 254, 253, 215, 183, 159, 49, 103, 74, 49, 
2745                                 67, 160, 171, 72, 194, 215, 108, 251, 178, 18, 184, 100, 211, 105, 21, 186, 
2746                                 39, 66, 218, 154, 72, 222, 90, 237, 179, 251, 51, 224, 212, 56, 251, 6, 
2747                                 209, 151, 198, 176, 89, 110, 35, 141, 248, 237, 223, 68, 135, 206, 207, 169, 
2748                                 254, 219, 243, 130, 71, 11, 94, 113, 233, 92, 63, 156, 169, 72, 215, 110, 
2749                                 95, 94, 191, 50, 59, 89, 187, 59, 183, 99, 161, 146, 233, 245, 219, 80, 
2750                                 87, 113, 251, 50, 144, 195, 158, 46, 189, 232, 119, 91, 75, 22, 6, 176, 
2751                                 39, 206, 25, 196, 213, 195, 219, 24, 28, 103, 104, 36, 137, 128, 4, 119, 
2752                                 163, 40, 126, 87, 18, 86, 128, 243, 213, 101, 2, 237, 78, 64, 160, 55, 
2753                                 199, 93, 90, 126, 175, 199, 55, 89, 234, 190, 5, 16, 196, 88, 28, 208, 
2754                                 28, 92, 32, 115, 204, 9, 202, 101, 15, 123, 43, 75, 90, 144, 95, 179, 
2755                                 102, 249, 57, 150, 204, 99, 147, 203, 16, 63, 81, 244, 226, 237, 82, 204, 
2756                                 20, 200, 140, 65, 83, 217, 161, 23, 123, 37, 115, 12, 100, 73, 70, 190, 
2757                                 32, 235, 174, 140, 148, 157, 47, 238, 40, 208, 228, 80, 54, 187, 156, 252, 
2758                                 253, 230, 231, 156, 138, 125, 96, 79, 3, 27, 143, 55, 146, 169, 165, 61, 
2759                                 238, 60, 227, 77, 217, 93, 117, 122, 111, 46, 173, 113, 
2760                         };
2761                 }
2762 #endif
2763
2764                 [Test]
2765                 public void CookieContainerTest ()
2766                 {
2767                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2768                         string url = "http://" + ep.ToString ();
2769
2770                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (CookieRequestHandler))) {
2771                                 responder.Start ();
2772
2773                                 CookieContainer container = new CookieContainer ();
2774                                 container.Add(new Uri (url), new Cookie ("foo", "bar"));
2775                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
2776                                 request.CookieContainer = container;
2777                                 WebHeaderCollection headers = request.Headers;
2778                                 headers.Add("Cookie", "foo=baz");
2779                                 HttpWebResponse response = (HttpWebResponse) request.GetResponse ();
2780                                 string responseString = null;
2781                                 using (StreamReader reader = new StreamReader (response.GetResponseStream ())) {
2782                                         responseString = reader.ReadToEnd ();
2783                                 }
2784                                 response.Close ();
2785                                 Assert.AreEqual (1, response.Cookies.Count, "#01");
2786                                 Assert.AreEqual ("foo=bar", response.Headers.Get("Set-Cookie"), "#02");
2787                         }
2788
2789                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (CookieRequestHandler))) {
2790                                 responder.Start ();
2791
2792                                 CookieContainer container = new CookieContainer ();
2793                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
2794                                 request.CookieContainer = container;
2795                                 WebHeaderCollection headers = request.Headers;
2796                                 headers.Add("Cookie", "foo=baz");
2797                                 HttpWebResponse response = (HttpWebResponse) request.GetResponse ();
2798                                 string responseString = null;
2799                                 using (StreamReader reader = new StreamReader (response.GetResponseStream ())) {
2800                                         responseString = reader.ReadToEnd ();
2801                                 }
2802                                 response.Close ();
2803                                 Assert.AreEqual (0, response.Cookies.Count, "#03");
2804                                 Assert.AreEqual ("", response.Headers.Get("Set-Cookie"), "#04");
2805                         }
2806                 }
2807
2808                 internal static byte[] CookieRequestHandler (Socket socket)
2809                 {
2810                         MemoryStream ms = new MemoryStream ();
2811                         byte[] buffer = new byte[4096];
2812                         int bytesReceived = socket.Receive (buffer);
2813                         while (bytesReceived > 0) {
2814                                 ms.Write(buffer, 0, bytesReceived);
2815                                 // We don't check for Content-Length or anything else here, so we give the client a little time to write
2816                                 // after sending the headers
2817                                 Thread.Sleep(200);
2818                                 if (socket.Available > 0) {
2819                                         bytesReceived = socket.Receive (buffer);
2820                                 } else {
2821                                         bytesReceived = 0;
2822                                 }
2823                         }
2824                         ms.Flush();
2825                         ms.Position = 0;
2826                         string cookies = string.Empty;
2827                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
2828                                 string line;
2829                                 while ((line = sr.ReadLine ()) != null) {
2830                                         if (line.StartsWith ("Cookie:")) {
2831                                                 cookies = line.Substring ("cookie: ".Length);
2832                                         }
2833                                 }
2834                         }
2835
2836                         StringWriter sw = new StringWriter ();
2837                         sw.WriteLine ("HTTP/1.1 200 OK");
2838                         sw.WriteLine ("Content-Type: text/xml");
2839                         sw.WriteLine ("Set-Cookie: " + cookies);
2840                         sw.WriteLine ("Content-Length: " + cookies.Length.ToString (CultureInfo.InvariantCulture));
2841                         sw.WriteLine ();
2842                         sw.Write (cookies);
2843                         sw.Flush ();
2844
2845                         return Encoding.UTF8.GetBytes (sw.ToString ());
2846                 }
2847         }
2848
2849         [TestFixture]
2850         public class HttpRequestStreamTest
2851         {
2852                 [Test]
2853                 public void BeginRead ()
2854                 {
2855                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2856                         string url = "http://" + ep.ToString () + "/test/";
2857
2858                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2859                                 responder.Start ();
2860
2861                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2862                                 req.Method = "POST";
2863
2864                                 using (Stream rs = req.GetRequestStream ()) {
2865                                         byte [] buffer = new byte [10];
2866                                         try {
2867                                                 rs.BeginRead (buffer, 0, buffer.Length, null, null);
2868                                                 Assert.Fail ("#1");
2869                                         } catch (NotSupportedException ex) {
2870                                                 // The stream does not support reading
2871                                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
2872                                                 Assert.IsNull (ex.InnerException, "#3");
2873                                                 Assert.IsNotNull (ex.Message, "#4");
2874                                         } finally {
2875                                                 req.Abort ();
2876                                         }
2877                                 }
2878                         }
2879                 }
2880
2881                 [Test]
2882                 [Category("MobileNotWorking")]
2883                 public void BeginWrite_Request_Aborted ()
2884                 {
2885                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2886                         string url = "http://" + ep.ToString () + "/test/";
2887
2888                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2889                                 responder.Start ();
2890
2891                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2892                                 req.Method = "POST";
2893
2894                                 using (Stream rs = req.GetRequestStream ()) {
2895                                         req.Abort ();
2896                                         try {
2897                                                 rs.BeginWrite (new byte [] { 0x2a, 0x2f }, 0, 2, null, null);
2898                                                 Assert.Fail ("#1");
2899                                         } catch (WebException ex) {
2900                                                 // The request was aborted: The request was canceled
2901                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
2902                                                 Assert.IsNull (ex.InnerException, "#3");
2903                                                 Assert.IsNotNull (ex.Message, "#4");
2904                                                 Assert.IsNull (ex.Response, "#5");
2905                                                 Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
2906                                         }
2907                                 }
2908                         }
2909                 }
2910
2911                 [Test]
2912                 public void CanRead ()
2913                 {
2914                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2915                         string url = "http://" + ep.ToString () + "/test/";
2916
2917                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2918                                 responder.Start ();
2919
2920                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2921                                 req.Method = "POST";
2922
2923                                 Stream rs = req.GetRequestStream ();
2924                                 try {
2925                                         Assert.IsFalse (rs.CanRead, "#1");
2926                                         rs.Close ();
2927                                         Assert.IsFalse (rs.CanRead, "#2");
2928                                 } finally {
2929                                         rs.Close ();
2930                                         req.Abort ();
2931                                 }
2932                         }
2933                 }
2934
2935                 [Test]
2936                 public void CanSeek ()
2937                 {
2938                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2939                         string url = "http://" + ep.ToString () + "/test/";
2940
2941                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2942                                 responder.Start ();
2943
2944                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2945                                 req.Method = "POST";
2946
2947                                 Stream rs = req.GetRequestStream ();
2948                                 try {
2949                                         Assert.IsFalse (rs.CanSeek, "#1");
2950                                         rs.Close ();
2951                                         Assert.IsFalse (rs.CanSeek, "#2");
2952                                 } finally {
2953                                         rs.Close ();
2954                                         req.Abort ();
2955                                 }
2956                         }
2957                 }
2958
2959                 [Test] // bug #324182
2960                 public void CanTimeout ()
2961                 {
2962                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2963                         string url = "http://" + ep.ToString () + "/test/";
2964
2965                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2966                                 responder.Start ();
2967
2968                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2969                                 req.Method = "POST";
2970
2971                                 Stream rs = req.GetRequestStream ();
2972                                 try {
2973                                         Assert.IsTrue (rs.CanTimeout, "#1");
2974                                         rs.Close ();
2975                                         Assert.IsTrue (rs.CanTimeout, "#2");
2976                                 } finally {
2977                                         rs.Close ();
2978                                         req.Abort ();
2979                                 }
2980                         }
2981                 }
2982
2983                 [Test]
2984                 public void CanWrite ()
2985                 {
2986                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2987                         string url = "http://" + ep.ToString () + "/test/";
2988
2989                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2990                                 responder.Start ();
2991
2992                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2993                                 req.Method = "POST";
2994
2995                                 Stream rs = req.GetRequestStream ();
2996                                 try {
2997                                         Assert.IsTrue (rs.CanWrite, "#1");
2998                                         rs.Close ();
2999                                         Assert.IsFalse (rs.CanWrite, "#2");
3000                                 } finally {
3001                                         rs.Close ();
3002                                         req.Abort ();
3003                                 }
3004                         }
3005                 }
3006
3007                 [Test]
3008                 public void Read ()
3009                 {
3010                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3011                         string url = "http://" + ep.ToString () + "/test/";
3012
3013                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3014                                 responder.Start ();
3015
3016                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3017                                 req.Method = "POST";
3018
3019                                 using (Stream rs = req.GetRequestStream ()) {
3020                                         byte [] buffer = new byte [10];
3021                                         try {
3022                                                 rs.Read (buffer, 0, buffer.Length);
3023                                                 Assert.Fail ("#1");
3024                                         } catch (NotSupportedException ex) {
3025                                                 // The stream does not support reading
3026                                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
3027                                                 Assert.IsNull (ex.InnerException, "#3");
3028                                                 Assert.IsNotNull (ex.Message, "#4");
3029                                         } finally {
3030                                                 req.Abort ();
3031                                         }
3032                                 }
3033                         }
3034                 }
3035
3036                 [Test]
3037                 public void ReadByte ()
3038                 {
3039                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3040                         string url = "http://" + ep.ToString () + "/test/";
3041
3042                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3043                                 responder.Start ();
3044
3045                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3046                                 req.Method = "POST";
3047
3048                                 using (Stream rs = req.GetRequestStream ()) {
3049                                         try {
3050                                                 rs.ReadByte ();
3051                                                 Assert.Fail ("#1");
3052                                         } catch (NotSupportedException ex) {
3053                                                 // The stream does not support reading
3054                                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
3055                                                 Assert.IsNull (ex.InnerException, "#3");
3056                                                 Assert.IsNotNull (ex.Message, "#4");
3057                                         } finally {
3058                                                 req.Abort ();
3059                                         }
3060                                 }
3061                         }
3062                 }
3063
3064                 [Test]
3065                 public void ReadTimeout ()
3066                 {
3067                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3068                         string url = "http://" + ep.ToString () + "/test/";
3069
3070                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3071                                 responder.Start ();
3072
3073                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3074                                 req.Method = "POST";
3075
3076                                 Stream rs = req.GetRequestStream ();
3077                                 try {
3078                                         Assert.AreEqual (300000, rs.ReadTimeout, "#1");
3079                                         rs.Close ();
3080                                         Assert.AreEqual (300000, rs.ReadTimeout, "#2");
3081                                 } finally {
3082                                         rs.Close ();
3083                                         req.Abort ();
3084                                 }
3085                         }
3086                 }
3087
3088                 [Test]
3089                 public void Seek ()
3090                 {
3091                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3092                         string url = "http://" + ep.ToString () + "/test/";
3093
3094                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3095                                 responder.Start ();
3096
3097                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3098                                 req.Method = "POST";
3099
3100                                 using (Stream rs = req.GetRequestStream ()) {
3101                                         try {
3102                                                 rs.Seek (0, SeekOrigin.Current);
3103                                                 Assert.Fail ("#1");
3104                                         } catch (NotSupportedException ex) {
3105                                                 // This stream does not support seek operations
3106                                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
3107                                                 Assert.IsNull (ex.InnerException, "#3");
3108                                                 Assert.IsNotNull (ex.Message, "#4");
3109                                         } finally {
3110                                                 req.Abort ();
3111                                         }
3112                                 }
3113                         }
3114                 }
3115
3116                 [Test]
3117                 public void Write_Buffer_Null ()
3118                 {
3119                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3120                         string url = "http://" + ep.ToString () + "/test/";
3121
3122                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3123                                 responder.Start ();
3124
3125                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3126                                 req.Method = "POST";
3127
3128                                 using (Stream rs = req.GetRequestStream ()) {
3129                                         try {
3130                                                 rs.Write ((byte []) null, -1, -1);
3131                                                 Assert.Fail ("#1");
3132                                         } catch (ArgumentNullException ex) {
3133                                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
3134                                                 Assert.IsNull (ex.InnerException, "#3");
3135                                                 Assert.IsNotNull (ex.Message, "#4");
3136                                                 Assert.AreEqual ("buffer", ex.ParamName, "#5");
3137                                         }
3138                                 }
3139
3140                                 req.Abort ();
3141                         }
3142                 }
3143
3144                 [Test]
3145                 public void Write_Count_Negative ()
3146                 {
3147                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3148                         string url = "http://" + ep.ToString () + "/test/";
3149
3150                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3151                                 responder.Start ();
3152
3153                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3154                                 req.Method = "POST";
3155
3156                                 using (Stream rs = req.GetRequestStream ()) {
3157                                         byte [] buffer = new byte [] { 0x2a, 0x2c, 0x1d, 0x00, 0x0f };
3158                                         try {
3159                                                 rs.Write (buffer, 1, -1);
3160                                                 Assert.Fail ("#1");
3161                                         } catch (ArgumentOutOfRangeException ex) {
3162                                                 // Specified argument was out of the range of valid values
3163                                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#A2");
3164                                                 Assert.IsNull (ex.InnerException, "#A3");
3165                                                 Assert.IsNotNull (ex.Message, "#A4");
3166                                                 Assert.AreEqual ("size", ex.ParamName, "#A5");
3167                                         }
3168                                 }
3169
3170                                 req.Abort ();
3171                         }
3172                 }
3173
3174                 [Test]
3175                 public void Write_Count_Overflow ()
3176                 {
3177                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3178                         string url = "http://" + ep.ToString () + "/test/";
3179
3180                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3181                                 responder.Start ();
3182
3183                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3184                                 req.Method = "POST";
3185
3186                                 using (Stream rs = req.GetRequestStream ()) {
3187                                         byte [] buffer = new byte [] { 0x2a, 0x2c, 0x1d, 0x00, 0x0f };
3188                                         try {
3189                                                 rs.Write (buffer, buffer.Length - 2, 3);
3190                                                 Assert.Fail ("#1");
3191                                         } catch (ArgumentOutOfRangeException ex) {
3192                                                 // Specified argument was out of the range of valid values
3193                                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
3194                                                 Assert.IsNull (ex.InnerException, "#3");
3195                                                 Assert.IsNotNull (ex.Message, "#4");
3196                                                 Assert.AreEqual ("size", ex.ParamName, "#5");
3197                                         }
3198                                 }
3199
3200                                 req.Abort ();
3201                         }
3202                 }
3203
3204                 [Test]
3205                 public void Write_Offset_Negative ()
3206                 {
3207                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3208                         string url = "http://" + ep.ToString () + "/test/";
3209
3210                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3211                                 responder.Start ();
3212
3213                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3214                                 req.Method = "POST";
3215
3216                                 using (Stream rs = req.GetRequestStream ()) {
3217                                         byte [] buffer = new byte [] { 0x2a, 0x2c, 0x1d, 0x00, 0x0f };
3218                                         try {
3219                                                 rs.Write (buffer, -1, 0);
3220                                                 Assert.Fail ("#1");
3221                                         } catch (ArgumentOutOfRangeException ex) {
3222                                                 // Specified argument was out of the range of valid values
3223                                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
3224                                                 Assert.IsNull (ex.InnerException, "#3");
3225                                                 Assert.IsNotNull (ex.Message, "#4");
3226                                                 Assert.AreEqual ("offset", ex.ParamName, "#5");
3227                                         }
3228                                 }
3229
3230                                 req.Abort ();
3231                         }
3232                 }
3233
3234                 [Test]
3235                 public void Write_Offset_Overflow ()
3236                 {
3237                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3238                         string url = "http://" + ep.ToString () + "/test/";
3239
3240                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3241                                 responder.Start ();
3242
3243                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3244                                 req.Method = "POST";
3245
3246                                 using (Stream rs = req.GetRequestStream ()) {
3247                                         byte [] buffer = new byte [] { 0x2a, 0x2c, 0x1d, 0x00, 0x0f };
3248                                         try {
3249                                                 rs.Write (buffer, buffer.Length + 1, 0);
3250                                                 Assert.Fail ("#1");
3251                                         } catch (ArgumentOutOfRangeException ex) {
3252                                                 // Specified argument was out of the range of valid values
3253                                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
3254                                                 Assert.IsNull (ex.InnerException, "#3");
3255                                                 Assert.IsNotNull (ex.Message, "#4");
3256                                                 Assert.AreEqual ("offset", ex.ParamName, "#5");
3257                                         }
3258                                 }
3259
3260                                 req.Abort ();
3261                         }
3262                 }
3263
3264                 [Test]
3265                 public void Write_Request_Aborted ()
3266                 {
3267                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3268                         string url = "http://" + ep.ToString () + "/test/";
3269
3270                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3271                                 responder.Start ();
3272
3273                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3274                                 req.Method = "POST";
3275
3276                                 using (Stream rs = req.GetRequestStream ()) {
3277                                         req.Abort ();
3278                                         try {
3279                                                 rs.Write (new byte [0], 0, 0);
3280                                                 Assert.Fail ("#1");
3281                                         } catch (WebException ex) {
3282                                                 // The request was aborted: The request was canceled
3283                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
3284                                                 Assert.IsNull (ex.InnerException, "#3");
3285                                                 Assert.IsNotNull (ex.Message, "#4");
3286                                                 Assert.IsNull (ex.Response, "#5");
3287                                                 Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
3288                                         }
3289                                 }
3290                         }
3291                 }
3292
3293                 [Test]
3294                 [Category ("NotWorking")]
3295                 public void Write_Stream_Closed ()
3296                 {
3297                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3298                         string url = "http://" + ep.ToString () + "/test/";
3299
3300                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3301                                 responder.Start ();
3302
3303                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3304                                 req.Method = "POST";
3305
3306                                 using (Stream rs = req.GetRequestStream ()) {
3307                                         rs.Close ();
3308                                         try {
3309                                                 rs.Write (new byte [0], 0, 0);
3310                                                 Assert.Fail ("#1");
3311                                         } catch (WebException ex) {
3312                                                 // The request was aborted: The connection was closed unexpectedly
3313                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
3314                                                 Assert.IsNull (ex.InnerException, "#3");
3315                                                 Assert.IsNotNull (ex.Message, "#4");
3316                                                 Assert.IsNull (ex.Response, "#5");
3317                                                 Assert.AreEqual (WebExceptionStatus.ConnectionClosed, ex.Status, "#6");
3318                                         }
3319                                 }
3320                         }
3321                 }
3322
3323                 [Test]
3324                 public void WriteByte_Request_Aborted ()
3325                 {
3326                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3327                         string url = "http://" + ep.ToString () + "/test/";
3328
3329                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3330                                 responder.Start ();
3331
3332                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3333                                 req.Method = "POST";
3334
3335                                 using (Stream rs = req.GetRequestStream ()) {
3336                                         req.Abort ();
3337                                         try {
3338                                                 rs.WriteByte (0x2a);
3339                                                 Assert.Fail ("#1");
3340                                         } catch (WebException ex) {
3341                                                 // The request was aborted: The request was canceled
3342                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
3343                                                 Assert.IsNull (ex.InnerException, "#3");
3344                                                 Assert.IsNotNull (ex.Message, "#4");
3345                                                 Assert.IsNull (ex.Response, "#5");
3346                                                 Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
3347                                         }
3348                                 }
3349                         }
3350                 }
3351
3352                 [Test]
3353                 public void WriteTimeout ()
3354                 {
3355                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3356                         string url = "http://" + ep.ToString () + "/test/";
3357
3358                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3359                                 responder.Start ();
3360
3361                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3362                                 req.Method = "POST";
3363
3364                                 Stream rs = req.GetRequestStream ();
3365                                 try {
3366                                         Assert.AreEqual (300000, rs.WriteTimeout, "#1");
3367                                         rs.Close ();
3368                                         Assert.AreEqual (300000, rs.WriteTimeout, "#2");
3369                                 } finally {
3370                                         rs.Close ();
3371                                         req.Abort ();
3372                                 }
3373                         }
3374                 }
3375
3376                 [Test]
3377                 // Bug6737
3378                 // This test is supposed to fail prior to .NET 4.0
3379                 public void Post_EmptyRequestStream ()
3380                 {
3381                         var wr = HttpWebRequest.Create ("http://google.com");
3382                         wr.Method = "POST";
3383                         wr.GetRequestStream ();
3384                         
3385                         var gr = wr.BeginGetResponse (delegate { }, null);
3386                         Assert.AreEqual (true, gr.AsyncWaitHandle.WaitOne (5000), "#1");
3387                 }
3388         }
3389
3390         static class StreamExtensions {
3391                 public static int ReadAll(this Stream stream, byte[] buffer, int offset, int count)
3392                 {
3393                         int totalRead = 0;
3394
3395                         while (totalRead < count) {
3396                                 int bytesRead = stream.Read (buffer, offset + totalRead, count - totalRead);
3397                                 if (bytesRead == 0)
3398                                         break;
3399
3400                                 totalRead += bytesRead;
3401                         }
3402
3403                         return totalRead;
3404                 }
3405         }
3406
3407         static class ExceptionAssert {
3408                 /// <summary>
3409                 /// Asserts that the function throws an exception.
3410                 /// </summary>
3411                 /// <param name="f">A function execute that is expected to raise an exception.</param>
3412                 /// <typeparam name="T">The type of exception that is expected.</typeparam>
3413                 /// <returns>The exception thrown.</returns>
3414                 /// <exception cref="AssertFailedException">If the function does not throw an exception 
3415                 /// or throws a different exception.</exception>
3416                 /// <example><![CDATA[
3417                 ///     ExceptionAssert.Throws(typeof(ArgumentNullException), delegate {
3418                 ///         myObject.myFunction(null); });
3419                 /// ]]></example>
3420                 public static T Throws<T> (Action f) where T : Exception {
3421                         Exception actualException = null;
3422
3423                         try {
3424                                 f ();
3425                         } catch (Exception ex) {
3426                                 actualException = ex;
3427                         }
3428
3429                         if (actualException == null)
3430                                 throw new AssertionException (string.Format (
3431                                         "No exception thrown. Expected '{0}'",
3432                                         typeof (T).FullName));
3433                         else if (typeof(T) != actualException.GetType())
3434                                 throw new AssertionException (string.Format (
3435                                         "Caught exception of type '{0}'. Expected '{1}':{2}",
3436                                         actualException.GetType().FullName,
3437                                         typeof (T).FullName,
3438                                         Environment.NewLine + actualException));
3439
3440                         return (T) actualException;
3441                 }
3442         }
3443 }