Remove Thread.[Abort|Suspend|Resume] from TvOS/WatchOS.
[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 #if MONO_FEATURE_THREAD_ABORT
1472                                 thread.Abort ();
1473 #else
1474                                 thread.Interrupt ();
1475 #endif
1476                                 Assert.Fail ("Thread finished after triple the timeout specified has passed");
1477                         }
1478
1479                         if (!String.IsNullOrEmpty (timeoutWorker.Body)) {
1480                                 if (timeoutWorker.Body == response_of_timeout_handler) {
1481                                         Assert.Fail ("Should not be reached, timeout exception was not thrown and webrequest managed to retrieve proper body");
1482                                 }
1483                                 Assert.Fail ("Should not be reached, timeout exception was not thrown and webrequest managed to retrieve an incorrect body: " + timeoutWorker.Body);
1484                         }
1485
1486                         Assert.IsNotNull (timeoutWorker.Exception, "Exception was not thrown");
1487
1488                         var webEx = timeoutWorker.Exception as WebException;
1489                         Assert.IsNotNull (webEx, "Exception thrown should be WebException, but was: " +
1490                                           timeoutWorker.Exception.GetType ().FullName);
1491
1492                         Assert.AreEqual (expectedExceptionStatus, webEx.Status,
1493                                          "WebException was thrown, but with a wrong status (should be " + expectedExceptionStatus + "): " + webEx.Status);
1494
1495                         Assert.IsFalse (timeoutWorker.End > (timeoutWorker.Start + TimeSpan.FromMilliseconds (three_seconds_in_milliseconds + 500)),
1496                                         "Timeout exception should have been thrown shortly after timeout is reached, however it was at least half-second late");
1497                 }
1498
1499                 [Test] // 1st possible case of https://bugzilla.novell.com/show_bug.cgi?id=MONO74177
1500                 public void TestTimeoutPropertyWithServerThatExistsAndRespondsButTooLate ()
1501                 {
1502                         var ep = new IPEndPoint (IPAddress.Loopback, 8123);
1503                         string url = "http://" + ep + "/foobar/";
1504
1505                         using (var responder = new SocketResponder (ep, TimeOutHandler))
1506                         {
1507                                 responder.Start ();
1508
1509                                 TestTimeOut (url, WebExceptionStatus.Timeout);
1510
1511                                 responder.Stop ();
1512                         }
1513                 }
1514
1515                 [Test] // 2nd possible case of https://bugzilla.novell.com/show_bug.cgi?id=MONO74177
1516                 public void TestTimeoutWithEndpointThatDoesntExistThrowsConnectFailureBeforeTimeout ()
1517                 {
1518                         string url = "http://127.0.0.1:8271/"; // some endpoint that is unlikely to exist
1519
1520                         // connecting to a non-existing endpoint should throw a ConnectFailure before the timeout is reached
1521                         TestTimeOut (url, WebExceptionStatus.ConnectFailure);
1522                 }
1523
1524                 const string response_of_timeout_handler = "RESPONSE_OF_TIMEOUT_HANDLER";
1525                 const int three_seconds_in_milliseconds = 3000;
1526
1527                 private static byte[] TimeOutHandler (Socket socket)
1528                 {
1529                         socket.Receive (new byte[4096]);
1530
1531                         Thread.Sleep (three_seconds_in_milliseconds * 2);
1532
1533                         var sw = new StringWriter ();
1534                         sw.WriteLine ("HTTP/1.1 200 OK");
1535                         sw.WriteLine ("Content-Type: text/plain");
1536                         sw.WriteLine ("Content-Length: " + response_of_timeout_handler.Length);
1537                         sw.WriteLine ();
1538                         sw.Write (response_of_timeout_handler);
1539                         sw.Flush ();
1540
1541                         return Encoding.UTF8.GetBytes (sw.ToString ());
1542                 }
1543
1544                 #endregion
1545
1546                 internal static byte [] EchoRequestHandler (Socket socket)
1547                 {
1548                         MemoryStream ms = new MemoryStream ();
1549                         byte [] buffer = new byte [4096];
1550                         int bytesReceived = socket.Receive (buffer);
1551                         while (bytesReceived > 0) {
1552                                 ms.Write (buffer, 0, bytesReceived);
1553                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1554                                  // after sending the headers
1555                                 Thread.Sleep (200);
1556                                 if (socket.Available > 0) {
1557                                         bytesReceived = socket.Receive (buffer);
1558                                 } else {
1559                                         bytesReceived = 0;
1560                                 }
1561                         }
1562                         ms.Flush ();
1563                         ms.Position = 0;
1564                         StreamReader sr = new StreamReader (ms, Encoding.UTF8);
1565                         string request = sr.ReadToEnd ();
1566
1567                         StringWriter sw = new StringWriter ();
1568                         sw.WriteLine ("HTTP/1.1 200 OK");
1569                         sw.WriteLine ("Content-Type: text/xml");
1570                         sw.WriteLine ("Content-Length: " + request.Length.ToString (CultureInfo.InvariantCulture));
1571                         sw.WriteLine ();
1572                         sw.Write (request);
1573                         sw.Flush ();
1574
1575                         return Encoding.UTF8.GetBytes (sw.ToString ());
1576                 }
1577
1578                 static byte [] RedirectRequestHandler (Socket socket)
1579                 {
1580                         MemoryStream ms = new MemoryStream ();
1581                         byte [] buffer = new byte [4096];
1582                         int bytesReceived = socket.Receive (buffer);
1583                         while (bytesReceived > 0) {
1584                                 ms.Write (buffer, 0, bytesReceived);
1585                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1586                                  // after sending the headers
1587                                 Thread.Sleep (200);
1588                                 if (socket.Available > 0) {
1589                                         bytesReceived = socket.Receive (buffer);
1590                                 } else {
1591                                         bytesReceived = 0;
1592                                 }
1593                         }
1594                         ms.Flush ();
1595                         ms.Position = 0;
1596                         string statusLine = null;
1597                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1598                                 statusLine = sr.ReadLine ();
1599                         }
1600
1601                         StringWriter sw = new StringWriter ();
1602                         if (statusLine.StartsWith ("POST /original/")) {
1603                                 sw.WriteLine ("HTTP/1.0 302 Found");
1604                                 EndPoint ep = socket.LocalEndPoint;
1605                                 sw.WriteLine ("Location: " + "http://" + ep.ToString () + "/moved/");
1606                                 sw.WriteLine ();
1607                                 sw.Flush ();
1608                         } else if (statusLine.StartsWith ("GET /moved/")) {
1609                                 sw.WriteLine ("HTTP/1.0 200 OK");
1610                                 sw.WriteLine ("Content-Type: text/plain");
1611                                 sw.WriteLine ("Content-Length: 8");
1612                                 sw.WriteLine ();
1613                                 sw.Write ("LOOKS OK");
1614                                 sw.Flush ();
1615                         } else {
1616                                 sw.WriteLine ("HTTP/1.0 500 Too Lazy");
1617                                 sw.WriteLine ();
1618                                 sw.Flush ();
1619                         }
1620
1621                         return Encoding.UTF8.GetBytes (sw.ToString ());
1622                 }
1623
1624                 static byte [] InternalErrorHandler (Socket socket)
1625                 {
1626                         byte [] buffer = new byte [4096];
1627                         int bytesReceived = socket.Receive (buffer);
1628                         while (bytesReceived > 0) {
1629                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1630                                  // after sending the headers
1631                                 Thread.Sleep (200);
1632                                 if (socket.Available > 0) {
1633                                         bytesReceived = socket.Receive (buffer);
1634                                 } else {
1635                                         bytesReceived = 0;
1636                                 }
1637                         }
1638                         StringWriter sw = new StringWriter ();
1639                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
1640                         sw.WriteLine ("Content-Length: 0");
1641                         sw.WriteLine ();
1642                         sw.Flush ();
1643
1644                         return Encoding.UTF8.GetBytes (sw.ToString ());
1645                 }
1646
1647                 static byte [] NoContentLengthHandler (Socket socket)
1648                 {
1649                         StringWriter sw = new StringWriter ();
1650                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
1651                         sw.WriteLine ();
1652                         sw.Flush ();
1653
1654                         return Encoding.UTF8.GetBytes (sw.ToString ());
1655                 }
1656
1657                 static byte [] NotModifiedSinceHandler (Socket socket)
1658                 {
1659                         StringWriter sw = new StringWriter ();
1660                         sw.WriteLine ("HTTP/1.1 304 Not Modified");
1661                         sw.WriteLine ("Date: Fri, 06 Feb 2009 12:50:26 GMT");
1662                         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");
1663                         sw.WriteLine ("Not-Modified-Since: Sun, 08 Feb 2009 08:49:26 GMT");
1664                         sw.WriteLine ("ETag: 898bbr2347056cc2e096afc66e104653");
1665                         sw.WriteLine ("Connection: close");
1666                         sw.WriteLine ();
1667                         sw.Flush ();
1668
1669                         return Encoding.UTF8.GetBytes (sw.ToString ());
1670                 }
1671
1672                 static byte [] VerbEchoHandler (Socket socket)
1673                 {
1674                         MemoryStream ms = new MemoryStream ();
1675                         byte [] buffer = new byte [4096];
1676                         int bytesReceived = socket.Receive (buffer);
1677                         while (bytesReceived > 0) {
1678                                 ms.Write (buffer, 0, bytesReceived);
1679                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1680                                  // after sending the headers
1681                                 Thread.Sleep (200);
1682                                 if (socket.Available > 0) {
1683                                         bytesReceived = socket.Receive (buffer);
1684                                 } else {
1685                                         bytesReceived = 0;
1686                                 }
1687                         }
1688                         ms.Flush ();
1689                         ms.Position = 0;
1690                         string statusLine = null;
1691                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1692                                 statusLine = sr.ReadLine ();
1693                         }
1694
1695                         string verb = "DEFAULT";
1696                         if (statusLine != null) {
1697                                 string [] parts = statusLine.Split (' ');
1698                                 if (parts.Length > 0)
1699                                         verb = parts [0];
1700                         }
1701
1702                         StringWriter sw = new StringWriter ();
1703                         sw.WriteLine ("HTTP/1.1 200 OK");
1704                         sw.WriteLine ("Content-Type: text/plain");
1705                         sw.WriteLine ("Content-Length: " + verb.Length);
1706                         sw.WriteLine ();
1707                         sw.Write (verb);
1708                         sw.Flush ();
1709
1710                         return Encoding.UTF8.GetBytes (sw.ToString ());
1711                 }
1712
1713                 static byte [] PostAnd401Handler (Socket socket)
1714                 {
1715                         MemoryStream ms = new MemoryStream ();
1716                         byte [] buffer = new byte [4096];
1717                         int bytesReceived = socket.Receive (buffer);
1718                         while (bytesReceived > 0) {
1719                                 ms.Write (buffer, 0, bytesReceived);
1720                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1721                                  // after sending the headers
1722                                 Thread.Sleep (200);
1723                                 if (socket.Available > 0) {
1724                                         bytesReceived = socket.Receive (buffer);
1725                                 } else {
1726                                         bytesReceived = 0;
1727                                 }
1728                         }
1729                         ms.Flush ();
1730                         ms.Position = 0;
1731                         string statusLine = null;
1732                         bool have_auth = false;
1733                         int cl = -1;
1734                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1735                                 string l;
1736                                 while ((l = sr.ReadLine ()) != null) {
1737                                         if (statusLine == null) {
1738                                                 statusLine = l;
1739                                         } else if (l.StartsWith ("Authorization:")) {
1740                                                 have_auth = true;
1741                                         } else if (l.StartsWith ("Content-Length:")) {
1742                                                 cl = Int32.Parse (l.Substring ("content-length: ".Length));
1743                                         }
1744                                 }
1745                         }
1746
1747                         StringWriter sw = new StringWriter ();
1748                         if (!have_auth) {
1749                                 sw.WriteLine ("HTTP/1.0 401 Invalid Credentials");
1750                                 sw.WriteLine ("WWW-Authenticate: basic Yeah");
1751                                 sw.WriteLine ();
1752                                 sw.Flush ();
1753                         } else if (cl > 0 && statusLine.StartsWith ("POST ")) {
1754                                 sw.WriteLine ("HTTP/1.0 200 OK");
1755                                 sw.WriteLine ("Content-Type: text/plain");
1756                                 sw.WriteLine ("Content-Length: 8");
1757                                 sw.WriteLine ();
1758                                 sw.Write ("LOOKS OK");
1759                                 sw.Flush ();
1760                         } else {
1761                                 sw.WriteLine ("HTTP/1.0 500 test failed");
1762                                 sw.WriteLine ("Content-Length: 0");
1763                                 sw.WriteLine ();
1764                                 sw.Flush ();
1765                         }
1766
1767                         return Encoding.UTF8.GetBytes (sw.ToString ());
1768                 }
1769                 [Test]
1770                 public void NtlmAuthentication ()
1771                 {
1772                         NtlmServer server = new NtlmServer ();
1773                         server.Start ();
1774
1775                         string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
1776                         HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
1777                         request.Timeout = 5000;
1778                         request.Credentials = new NetworkCredential ("user", "password", "domain");
1779                         HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
1780                         string res = null;
1781                         using (StreamReader reader = new StreamReader (resp.GetResponseStream ())) {
1782                                 res = reader.ReadToEnd ();
1783                         }
1784                         resp.Close ();
1785                         server.Stop ();
1786                         Assert.AreEqual ("OK", res);
1787                 }
1788
1789                 class NtlmServer : HttpServer {
1790                         public string Where = "";
1791                         protected override void Run ()
1792                         {
1793                                 Where = "before accept";
1794                                 Socket client = sock.Accept ();
1795                                 NetworkStream ns = new NetworkStream (client, false);
1796                                 StreamReader reader = new StreamReader (ns, Encoding.ASCII);
1797                                 string line;
1798                                 Where = "first read";
1799                                 while ((line = reader.ReadLine ()) != null) {
1800                                         if (line.Trim () == String.Empty) {
1801                                                 break;
1802                                         }
1803                                 }
1804                                 Where = "first write";
1805                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
1806                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
1807                                                 "WWW-Authenticate: NTLM\r\n" +
1808                                                 "Content-Length: 5\r\n\r\nWRONG");
1809
1810                                 writer.Flush ();
1811                                 Where = "second read";
1812                                 while ((line = reader.ReadLine ()) != null) {
1813                                         if (line.Trim () == String.Empty) {
1814                                                 break;
1815                                         }
1816                                 }
1817                                 Where = "second write";
1818                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
1819                                                 "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAADgAAAABggAC8GDhqIONH3sAAAAAAAAAAAAAAAA4AAAABQLODgAAAA8=\r\n" +
1820                                                 "Content-Length: 5\r\n\r\nWRONG");
1821                                 writer.Flush ();
1822
1823                                 Where = "third read";
1824                                 while ((line = reader.ReadLine ()) != null) {
1825                                         if (line.Trim () == String.Empty) {
1826                                                 break;
1827                                         }
1828                                 }
1829                                 Where = "third write";
1830                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
1831                                                 "Keep-Alive: true\r\n" +
1832                                                 "Content-Length: 2\r\n\r\nOK");
1833                                 writer.Flush ();
1834                                 Thread.Sleep (1000);
1835                                 writer.Close ();
1836                                 reader.Close ();
1837                                 client.Close ();
1838                         }
1839                 }
1840
1841                 class BadChunkedServer : HttpServer {
1842                         protected override void Run ()
1843                         {
1844                                 Socket client = sock.Accept ();
1845                                 NetworkStream ns = new NetworkStream (client, true);
1846                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
1847                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
1848                                                 "Transfer-Encoding: chunked\r\n" +
1849                                                 "Connection: close\r\n" +
1850                                                 "Content-Type: text/plain; charset=UTF-8\r\n\r\n");
1851
1852                                 // This body lacks a 'last-chunk' (see RFC 2616)
1853                                 writer.Write ("10\r\n1234567890123456\r\n");
1854                                 writer.Flush ();
1855                                 client.Shutdown (SocketShutdown.Send);
1856                                 Thread.Sleep (1000);
1857                                 writer.Close ();
1858                         }
1859                 }
1860
1861                 class AcceptAllPolicy : ICertificatePolicy {
1862                         public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
1863                         {
1864                                 return true;
1865                         }
1866                 }
1867
1868                 abstract class HttpServer
1869                 {
1870                         protected Socket sock;
1871                         protected Exception error;
1872                         protected ManualResetEvent evt;
1873
1874                         public HttpServer ()
1875                         {
1876                                 sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
1877                                 sock.Bind (new IPEndPoint (IPAddress.Loopback, 0));
1878                                 sock.Listen (1);
1879                         }
1880
1881                         public void Start ()
1882                         {
1883                                 evt = new ManualResetEvent (false);
1884                                 Thread th = new Thread (new ThreadStart (Run));
1885                                 th.Start ();
1886                         }
1887
1888                         public void Stop ()
1889                         {
1890                                 evt.Set ();
1891                                 sock.Close ();
1892                         }
1893                         
1894                         public IPAddress IPAddress {
1895                                 get { return ((IPEndPoint) sock.LocalEndPoint).Address; }
1896                         }
1897                         
1898                         public int Port {
1899                                 get { return ((IPEndPoint) sock.LocalEndPoint).Port; }
1900                         }
1901
1902                         public Exception Error { 
1903                                 get { return error; }
1904                         }
1905
1906                         protected abstract void Run ();
1907                 }
1908
1909                 [Test]
1910                 public void BeginGetRequestStream ()
1911                 {
1912                         this.DoRequest (
1913                         (r, c) =>
1914                         {
1915                                 r.Method = "POST";
1916                                 r.ContentLength = 0;
1917                                 r.BeginGetRequestStream ((a) =>
1918                                 {
1919                                 using (Stream s = r.EndGetRequestStream (a)) { };
1920                                 c.Set();
1921                                 },
1922                                 null);
1923                         },
1924                         (c) => { });
1925                 }
1926
1927                 [Test]
1928                 public void BeginGetRequestStreamNoClose ()
1929                 {
1930                         this.DoRequest (
1931                         (r, c) => {
1932                                 r.Method = "POST";
1933                                 r.ContentLength = 1;
1934                                 r.BeginGetRequestStream ((a) =>
1935                                 {
1936                                         r.EndGetRequestStream (a);
1937                                         c.Set ();
1938                                 },
1939                                 null);
1940                         },
1941                         (c) => {});
1942                 }
1943
1944                 [Test]
1945                 public void BeginGetRequestStreamCancelIfNotAllBytesWritten ()
1946                 {
1947                         this.DoRequest (
1948                         (r, c) =>
1949                         {
1950                                 r.Method = "POST";
1951                                 r.ContentLength = 10;
1952                                 r.BeginGetRequestStream ((a) =>
1953                                 {
1954                                         WebException ex = ExceptionAssert.Throws<WebException> (() =>
1955                                         {
1956                                                 using (Stream s = r.EndGetRequestStream (a)) {
1957                                                 }
1958                                         }
1959                                 );
1960                                 Assert.AreEqual (ex.Status, WebExceptionStatus.RequestCanceled);
1961                                 c.Set();
1962                                 },
1963                                 null);
1964                         },
1965                         (c) => { });
1966                 }
1967
1968                 [Test]
1969                 public void GetRequestStream2 ()
1970                 {
1971                         this.DoRequest (
1972                         (r, c) =>
1973                         {
1974                                 r.Method = "POST";
1975                                 r.ContentLength = data64KB.Length;
1976                                 using (Stream s = r.GetRequestStream ()) {
1977                                         s.Write (data64KB, 0, data64KB.Length);
1978                                 }
1979                                 c.Set ();
1980                         },
1981                         (c) => { });
1982                 }
1983
1984                 [Test]
1985                 public void GetRequestStreamNotAllBytesWritten ()
1986                 {
1987                         this.DoRequest (
1988                         (r, c) =>
1989                         {
1990                                 r.Method = "POST";
1991                                 r.ContentLength = data64KB.Length;
1992                                 WebException ex = ExceptionAssert.Throws<WebException> (() => r.GetRequestStream ().Close ());
1993                                 Assert.AreEqual (ex.Status, WebExceptionStatus.RequestCanceled);
1994                                 c.Set ();
1995                         },
1996                         (c) => {});
1997                 }
1998
1999                 [Test]
2000                 public void GetRequestStreamTimeout ()
2001                 {
2002                         this.DoRequest (
2003                         (r, c) =>
2004                         {
2005                                 r.Method = "POST";
2006                                 r.ContentLength = data64KB.Length;
2007                                 r.Timeout = 100;
2008                                 WebException ex = ExceptionAssert.Throws<WebException> (() => r.GetRequestStream ());
2009                                 Assert.IsTrue (ex.Status == WebExceptionStatus.Timeout || ex.Status == WebExceptionStatus.ConnectFailure);
2010                                 c.Set();
2011                         });
2012                 }
2013
2014                 [Test]
2015                 public void BeginWrite ()
2016                 {
2017                         byte[] received = new byte[data64KB.Length];
2018
2019                         this.DoRequest (
2020                         (r, c) =>
2021                         {
2022                                 r.Method = "POST";
2023                                 r.ContentLength = data64KB.Length;
2024
2025                                 Stream s = r.GetRequestStream ();
2026                                 s.BeginWrite (data64KB, 0, data64KB.Length,
2027                                 (a) =>
2028                                 {
2029                                         s.EndWrite (a);
2030                                         s.Close ();
2031                                         r.GetResponse ().Close ();
2032                                         c.Set();
2033                                 },
2034                                 null);
2035                         },
2036                         (c) =>
2037                         {
2038                                 c.Request.InputStream.ReadAll (received, 0, received.Length);
2039                                 c.Response.StatusCode = 204;
2040                                 c.Response.Close ();
2041                         });
2042
2043                         Assert.AreEqual (data64KB, received);
2044                 }
2045
2046                 [Test]
2047                 public void BeginWriteAfterAbort ()
2048                 {
2049                         byte [] received = new byte [data64KB.Length];
2050
2051                         this.DoRequest (
2052                         (r, c) =>
2053                         {
2054                                 r.Method = "POST";
2055                                 r.ContentLength = data64KB.Length;
2056
2057                                 Stream s = r.GetRequestStream ();
2058                                 r.Abort();
2059
2060                                 WebException ex = ExceptionAssert.Throws<WebException> (() => s.BeginWrite (data64KB, 0, data64KB.Length, null, null));
2061                                 Assert.AreEqual (ex.Status, WebExceptionStatus.RequestCanceled);
2062
2063                                 c.Set();
2064                         },
2065                         (c) =>
2066                         {
2067                                 //c.Request.InputStream.ReadAll (received, 0, received.Length);
2068                                 //c.Response.StatusCode = 204;
2069                                 //c.Response.Close();
2070                         });
2071                 }
2072
2073                 [Test]
2074                 public void PrematureStreamCloseAborts ()
2075                 {
2076                         byte [] received = new byte [data64KB.Length];
2077
2078                         this.DoRequest (
2079                         (r, c) =>
2080                         {
2081                                 r.Method = "POST";
2082                                 r.ContentLength = data64KB.Length * 2;
2083
2084                                 Stream s = r.GetRequestStream ();
2085                                 s.Write (data64KB, 0, data64KB.Length);
2086
2087                                 WebException ex = ExceptionAssert.Throws<WebException>(() => s.Close());
2088                                 Assert.AreEqual(ex.Status, WebExceptionStatus.RequestCanceled);
2089
2090                                 c.Set();
2091                         },
2092                         (c) =>
2093                         {
2094                                 c.Request.InputStream.ReadAll (received, 0, received.Length);
2095 //                              c.Response.StatusCode = 204;
2096 //                              c.Response.Close ();
2097                         });
2098                 }
2099
2100                 [Test]
2101                 public void Write ()
2102                 {
2103                         byte [] received = new byte [data64KB.Length];
2104
2105                         this.DoRequest (
2106                         (r, c) =>
2107                         {
2108                                 r.Method = "POST";
2109                                 r.ContentLength = data64KB.Length;
2110
2111                                 using (Stream s = r.GetRequestStream ()) {
2112                                         s.Write (data64KB, 0, data64KB.Length);
2113                                 }
2114
2115                                 r.GetResponse ().Close ();
2116                                 c.Set ();
2117                         },
2118                         (c) =>
2119                         {
2120                                 c.Request.InputStream.ReadAll (received, 0, received.Length);
2121                                 c.Response.StatusCode = 204;
2122                                 c.Response.Close ();
2123                         });
2124
2125                         Assert.AreEqual(data64KB, received);
2126                 }
2127
2128                 /*
2129                 Invalid test: it does not work on linux.
2130                 [pid 30973] send(9, "POST / HTTP/1.1\r\nContent-Length:"..., 89, 0) = 89
2131                 Abort set
2132                 [pid 30970] send(16, "HTTP/1.1 200 OK\r\nServer: Mono-HT"..., 133, 0) = 133
2133                 Calling abort
2134                 [pid 30970] close(16)                   = 0
2135                 Closing!!!
2136                 [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
2137                 Writing...
2138                 [pid 30966] close(4)                    = 0
2139                 OK
2140                  *
2141                  The server sideis closed (FD 16) and the send on the client side (FD 9) succeeds.
2142                 [Test]
2143                 [Category("NotWorking")]
2144                 public void WriteServerAborts ()
2145                 {
2146                         ManualResetEvent abort = new ManualResetEvent (false);
2147                         byte [] received = new byte [data64KB.Length];
2148
2149                         this.DoRequest (
2150                         (r, c) =>
2151                         {
2152                                 r.Method = "POST";
2153                                 r.ContentLength = data64KB.Length;
2154
2155                                 using (Stream s = r.GetRequestStream()) {
2156                                         abort.Set();
2157                                         Thread.Sleep(100);
2158                                         IOException ex = ExceptionAssert.Throws<IOException> (() => s.Write(data64KB, 0, data64KB.Length));
2159                                 }
2160
2161                                 c.Set();
2162                         },
2163                         (c) =>
2164                         {
2165                                 abort.WaitOne();
2166                                 c.Response.Abort();
2167                         });
2168                 }
2169                 **/
2170
2171                 [Test]
2172                 public void Read ()
2173                 {
2174                         byte [] received = new byte [data64KB.Length];
2175
2176                         this.DoRequest (
2177                         (r, c) =>
2178                         {
2179                                 using (HttpWebResponse x = (HttpWebResponse) r.GetResponse ())
2180                                 using (Stream s = x.GetResponseStream()) {
2181                                         s.ReadAll (received, 0, received.Length);
2182                                 }
2183
2184                                 c.Set ();
2185                         },
2186                         (c) =>
2187                         {
2188                                 c.Response.StatusCode = 200;
2189                                 c.Response.ContentLength64 = data64KB.Length;
2190                                 c.Response.OutputStream.Write (data64KB, 0, data64KB.Length);
2191                                 c.Response.OutputStream.Close ();
2192                                 c.Response.Close ();
2193                         });
2194
2195                         Assert.AreEqual (data64KB, received);
2196                 }
2197
2198                 [Test]
2199                 public void ReadTimeout2 ()
2200                 {
2201                         byte [] received = new byte [data64KB.Length];
2202
2203                         this.DoRequest (
2204                         (r, c) =>
2205                         {
2206                                 r.ReadWriteTimeout = 10;
2207                                 using (HttpWebResponse x = (HttpWebResponse) r.GetResponse ())
2208                                 using (Stream s = x.GetResponseStream ()) {
2209                                         WebException ex = ExceptionAssert.Throws<WebException> (() => s.ReadAll (received, 0, received.Length));
2210                                         Assert.AreEqual (ex.Status, WebExceptionStatus.Timeout);
2211                                 }
2212
2213                                 c.Set();
2214                         },
2215                         (c) =>
2216                         {
2217                                 c.Response.StatusCode = 200;
2218                                 c.Response.ContentLength64 = data64KB.Length;
2219                                 c.Response.OutputStream.Write (data64KB, 0, data64KB.Length / 2);
2220                                 Thread.Sleep (1000);
2221 //                              c.Response.OutputStream.Write (data64KB, data64KB.Length / 2, data64KB.Length / 2);
2222                                 c.Response.OutputStream.Close ();
2223                                 c.Response.Close ();
2224                         });
2225                 }
2226
2227                 [Test]
2228                 public void ReadServerAborted ()
2229                 {
2230                         byte [] received = new byte [data64KB.Length];
2231
2232                         this.DoRequest (
2233                         (r, c) =>
2234                         {
2235                                 using (HttpWebResponse x = (HttpWebResponse) r.GetResponse ())
2236                                 using (Stream s = x.GetResponseStream ()) {
2237                                         Assert.AreEqual (1, s.ReadAll (received, 0, received.Length));
2238                                 }
2239
2240                                 c.Set();
2241                         },
2242                         (c) =>
2243                         {
2244                                 c.Response.StatusCode = 200;
2245                                 c.Response.ContentLength64 = data64KB.Length;
2246                                 c.Response.OutputStream.Write (data64KB, 0, 1);
2247                                 c.Response.Abort ();
2248                         });
2249                 }
2250
2251                 [Test]
2252                 public void BeginGetResponse2 ()
2253                 {
2254                         byte [] received = new byte [data64KB.Length];
2255
2256                         this.DoRequest (
2257                         (r, c) =>
2258                         {
2259                                 r.BeginGetResponse ((a) =>
2260                                 {
2261                                         using (HttpWebResponse x = (HttpWebResponse) r.EndGetResponse (a))
2262                                         using (Stream s = x.GetResponseStream ()) {
2263                                                 s.ReadAll (received, 0, received.Length);
2264                                         }
2265
2266                                         c.Set();
2267                                 }, null);
2268                         },
2269                         (c) =>
2270                         {
2271                                 c.Response.StatusCode = 200;
2272                                 c.Response.ContentLength64 = data64KB.Length;
2273                                 c.Response.OutputStream.Write (data64KB, 0, data64KB.Length);
2274                                 c.Response.OutputStream.Close ();
2275                                 c.Response.Close ();
2276                         });
2277
2278                         Assert.AreEqual (data64KB, received);
2279                 }
2280
2281                 [Test]
2282                 public void BeginGetResponseAborts ()
2283                 {
2284                         ManualResetEvent aborted = new ManualResetEvent(false);
2285
2286                         this.DoRequest (
2287                         (r, c) =>
2288                         {
2289                                 r.BeginGetResponse((a) =>
2290                                 {
2291                                         WebException ex = ExceptionAssert.Throws<WebException> (() => r.EndGetResponse (a));
2292                                         Assert.AreEqual (ex.Status, WebExceptionStatus.RequestCanceled);
2293                                         c.Set ();
2294                                 }, null);
2295
2296                                 aborted.WaitOne ();
2297                                 r.Abort ();
2298                         },
2299                         (c) =>
2300                         {
2301                                 aborted.Set ();
2302 //                              Thread.Sleep (100);
2303 //                              c.Response.StatusCode = 200;
2304 //                              c.Response.ContentLength64 = 0;
2305 //                              c.Response.Close ();
2306                         });
2307
2308                         return;
2309                 }
2310                 
2311                 [Test]
2312                 public void TestLargeDataReading ()
2313                 {
2314                         int near2GBStartPosition = rand.Next (int.MaxValue - 500, int.MaxValue);
2315                         AutoResetEvent readyGetLastPortionEvent = new AutoResetEvent (false);
2316                         Exception testException = null;
2317
2318                         DoRequest (
2319                         (request, waitHandle) =>
2320                         {
2321                                 try
2322                                 {
2323                                         const int timeoutMs = 5000;
2324
2325                                         request.Timeout = timeoutMs;
2326                                         request.ReadWriteTimeout = timeoutMs;
2327
2328                                         WebResponse webResponse = request.GetResponse ();
2329                                         Stream webResponseStream = webResponse.GetResponseStream ();
2330                                         Assert.IsNotNull (webResponseStream, null, "#1");
2331                                         
2332                                         Type webConnectionStreamType = webResponseStream.GetType ();
2333                                         FieldInfo totalReadField = webConnectionStreamType.GetField ("totalRead", BindingFlags.NonPublic | BindingFlags.Instance);
2334                                         Assert.IsNotNull (totalReadField, "#2");
2335                                         totalReadField.SetValue (webResponseStream, near2GBStartPosition);
2336                                         
2337                                         byte[] readBuffer = new byte[int.MaxValue - near2GBStartPosition];
2338                                         Assert.AreEqual (webResponseStream.Read (readBuffer, 0, readBuffer.Length), readBuffer.Length, "#3");
2339                                         readyGetLastPortionEvent.Set ();
2340                                         Assert.IsTrue (webResponseStream.Read (readBuffer, 0, readBuffer.Length) > 0);
2341                                         readyGetLastPortionEvent.Set ();
2342                                         
2343                                         webResponse.Close();
2344                                 }
2345                                 catch (Exception e)
2346                                 {
2347                                         testException = e;
2348                                 }
2349                                 finally
2350                                 {
2351                                         waitHandle.Set ();
2352                                 }
2353                         },
2354                         processor =>
2355                         {
2356                                 processor.Request.InputStream.Close ();
2357                                 
2358                                 HttpListenerResponse response = processor.Response;
2359                                 response.SendChunked = true;
2360                                 
2361                                 Stream outputStream = response.OutputStream;
2362                                 var writeBuffer = new byte[int.MaxValue - near2GBStartPosition];
2363                                 outputStream.Write (writeBuffer, 0, writeBuffer.Length);
2364                                 readyGetLastPortionEvent.WaitOne ();
2365                                 outputStream.Write (writeBuffer, 0, writeBuffer.Length);
2366                                 readyGetLastPortionEvent.WaitOne ();
2367                                 
2368                                 response.Close();
2369                         });
2370
2371                         if (testException != null)
2372                                 throw testException;
2373                 }
2374
2375                 void DoRequest (Action<HttpWebRequest, EventWaitHandle> request)
2376                 {
2377                         int port = NetworkHelpers.FindFreePort ();
2378
2379                         ManualResetEvent completed = new ManualResetEvent (false);
2380                         Uri address = new Uri (string.Format ("http://localhost:{0}", port));
2381                         HttpWebRequest client = (HttpWebRequest) WebRequest.Create (address);
2382
2383                         request (client, completed);
2384
2385                         if (!completed.WaitOne (10000))
2386                                 Assert.Fail ("Test hung");
2387                 }
2388
2389                 void DoRequest (Action<HttpWebRequest, EventWaitHandle> request, Action<HttpListenerContext> processor)
2390                 {
2391                         int port = NetworkHelpers.FindFreePort ();
2392
2393                         ManualResetEvent [] completed = new ManualResetEvent [2];
2394                         completed [0] = new ManualResetEvent (false);
2395                         completed [1] = new ManualResetEvent (false);
2396
2397                         using (ListenerScope scope = new ListenerScope (processor, port, completed [0])) {
2398                                 ManualResetEvent clientCompleted = new ManualResetEvent (false);
2399                                 Uri address = new Uri (string.Format ("http://localhost:{0}", port));
2400                                 HttpWebRequest client = (HttpWebRequest) WebRequest.Create (address);
2401
2402                                 ThreadPool.QueueUserWorkItem ((o) => request (client, completed [1]));
2403
2404                                 if (!WaitHandle.WaitAll (completed, 10000))
2405                                         Assert.Fail ("Test hung.");
2406                         }
2407                 }
2408
2409                 [Test]
2410                 [ExpectedException (typeof (ArgumentNullException))]
2411                 public void NullHost ()
2412                 {
2413                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2414                         req.Host = null;
2415                 }
2416
2417                 [Test]
2418                 public void NoHost ()
2419                 {
2420                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2421                         Assert.AreEqual (req.Host, "go-mono.com");
2422                 }
2423
2424                 [Test]
2425                 [ExpectedException (typeof (ArgumentException))]
2426                 public void EmptyHost ()
2427                 {
2428                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2429                         req.Host = "";
2430                 }
2431
2432                 [Test]
2433                 public void HostAndPort ()
2434                 {
2435                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com:80");
2436                         Assert.AreEqual ("go-mono.com", req.Host, "#01");
2437                         req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com:9000");
2438                         Assert.AreEqual ("go-mono.com:9000", req.Host, "#02");
2439                 }
2440
2441                 [Test]
2442                 public void PortRange ()
2443                 {
2444                         for (int i = 0; i < 65536; i++) {
2445                                 if (i == 80)
2446                                         continue;
2447                                 string s = i.ToString ();
2448                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com:" + s);
2449                                 Assert.AreEqual ("go-mono.com:" + s, req.Host, "#" + s);
2450                         }
2451                 }
2452
2453                 [Test]
2454                 [ExpectedException (typeof (ArgumentException))]
2455                 public void PortBelow ()
2456                 {
2457                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2458                         req.Host = "go-mono.com:-1";
2459                 }
2460
2461                 [Test]
2462                 [ExpectedException (typeof (ArgumentException))]
2463                 public void PortAbove ()
2464                 {
2465                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2466                         req.Host = "go-mono.com:65536";
2467                 }
2468
2469                 [Test]
2470                 [ExpectedException (typeof (ArgumentException))]
2471                 public void HostTooLong ()
2472                 {
2473                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2474                         string s = new string ('a', 100);
2475                         req.Host = s + "." + s + "." + s + "." + s + "." + s + "." + s; // Over 255 bytes
2476                 }
2477
2478                 [Test]
2479                 [Category ("NotWorking")] // #5490
2480                 public void InvalidNamesThatWork ()
2481                 {
2482                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2483                         req.Host = "-";
2484                         req.Host = "-.-";
2485                         req.Host = "á";
2486                         req.Host = new string ('a', 64); // Should fail. Max. is 63.
2487                 }
2488
2489                 [Test]
2490                 public void NoDate ()
2491                 {
2492                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2493                         Assert.AreEqual (DateTime.MinValue, req.Date);
2494                 }
2495
2496                 [Test]
2497                 public void UtcDate ()
2498                 {
2499                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
2500                         req.Date = DateTime.UtcNow;
2501                         DateTime date = req.Date;
2502                         Assert.AreEqual (DateTimeKind.Local, date.Kind);
2503                 }
2504
2505                 [Test]
2506                 public void AddAndRemoveDate ()
2507                 {
2508                         // Neil Armstrong set his foot on Moon
2509                         var landing = new DateTime (1969, 7, 21, 2, 56, 0, DateTimeKind.Utc);
2510                         Assert.AreEqual (621214377600000000, landing.Ticks);
2511                         var unspecified = new DateTime (1969, 7, 21, 2, 56, 0);
2512                         var local = landing.ToLocalTime ();
2513
2514                         var req = (HttpWebRequest)WebRequest.Create ("http://www.mono-project.com/");
2515                         req.Date = landing;
2516                         Assert.AreEqual (DateTimeKind.Local, req.Date.Kind);
2517                         Assert.AreEqual (local.Ticks, req.Date.Ticks);
2518                         Assert.AreEqual (local, req.Date);
2519
2520                         req.Date = unspecified;
2521                         Assert.AreEqual (DateTimeKind.Local, req.Date.Kind);
2522                         Assert.AreEqual (unspecified.Ticks, req.Date.Ticks);
2523                         Assert.AreEqual (unspecified, req.Date);
2524
2525                         req.Date = local;
2526                         Assert.AreEqual (DateTimeKind.Local, req.Date.Kind);
2527                         Assert.AreEqual (local.Ticks, req.Date.Ticks);
2528                         Assert.AreEqual (local, req.Date);
2529
2530                         req.Date = DateTime.MinValue;
2531                         Assert.AreEqual (DateTimeKind.Unspecified, DateTime.MinValue.Kind);
2532                         Assert.AreEqual (DateTimeKind.Unspecified, req.Date.Kind);
2533                         Assert.AreEqual (0, req.Date.Ticks);
2534
2535                         Assert.AreEqual (null, req.Headers.Get ("Date"));
2536                 }
2537                 
2538                 [Test]
2539                 // Bug #12393
2540                 public void TestIPv6Host ()
2541                 {
2542                         var address = "2001:0000:0000:0001:0001:0001:0157:0000";
2543                         var address2 = '[' + address + ']';
2544                         var uri = new Uri (string.Format ("http://{0}/test.css", address2));
2545                         var hwr = (HttpWebRequest)WebRequest.Create (uri);
2546
2547                         hwr.Host = address2;
2548                         Assert.AreEqual (address2, hwr.Host, "#1");
2549                 }
2550
2551                 [Test]
2552                 // Bug #12393
2553                 [Category ("NotWorking")]
2554                 public void TestIPv6Host2 ()
2555                 {
2556                         var address = "2001:0000:0000:0001:0001:0001:0157:0000";
2557                         var address2 = '[' + address + ']';
2558                         var uri = new Uri (string.Format ("http://{0}/test.css", address2));
2559                         var hwr = (HttpWebRequest)WebRequest.Create (uri);
2560
2561                         try {
2562                                 hwr.Host = address;
2563                                 Assert.Fail ("#1");
2564                         } catch (ArgumentException) {
2565                                 ;
2566                         }
2567                 }
2568
2569 #if NET_4_5
2570                 [Test]
2571                 public void AllowReadStreamBuffering ()
2572                 {
2573                         var hr = WebRequest.CreateHttp ("http://www.google.com");
2574                         Assert.IsFalse (hr.AllowReadStreamBuffering, "#1");
2575                         try {
2576                                 hr.AllowReadStreamBuffering = true;
2577                                 Assert.Fail ("#2");
2578                         } catch (InvalidOperationException) {
2579                         }
2580                 }
2581 #endif
2582
2583                 class ListenerScope : IDisposable {
2584                         EventWaitHandle completed;
2585                         public HttpListener listener;
2586                         Action<HttpListenerContext> processor;
2587
2588                         public ListenerScope (Action<HttpListenerContext> processor, int port, EventWaitHandle completed)
2589                         {
2590                                 this.processor = processor;
2591                                 this.completed = completed;
2592
2593                                 this.listener = new HttpListener ();
2594                                 this.listener.Prefixes.Add (string.Format ("http://localhost:{0}/", port));
2595                                 this.listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
2596                                 this.listener.Start ();
2597
2598                                 this.listener.BeginGetContext (this.RequestHandler, null);
2599                         }
2600
2601                         void RequestHandler (IAsyncResult result)
2602                         {
2603                                 HttpListenerContext context = null;
2604
2605                                 try {
2606                                         context = this.listener.EndGetContext (result);
2607                                 } catch (HttpListenerException ex) {
2608                                         // check if the thread has been aborted as in the case when we are shutting down.
2609                                         if (ex.ErrorCode == 995)
2610                                                 return;
2611                                 } catch (ObjectDisposedException) {
2612                                         return;
2613                                 }
2614
2615                                 ThreadPool.QueueUserWorkItem ((o) =>
2616                                 {
2617                                         try {
2618                                                 this.processor (context);
2619                                         } catch (HttpListenerException) {
2620                                         }
2621                                 });
2622
2623                                 this.completed.Set ();
2624                         }
2625
2626                         public void Dispose ()
2627                         {
2628                                 this.listener.Stop ();
2629                         }
2630                 }
2631
2632 #if !MOBILE
2633                 class SslHttpServer : HttpServer {
2634                         X509Certificate _certificate;
2635
2636                         protected override void Run ()
2637                         {
2638                                 try {
2639                                         Socket client = sock.Accept ();
2640                                         NetworkStream ns = new NetworkStream (client, true);
2641                                         SslServerStream s = new SslServerStream (ns, Certificate, false, false);
2642                                         s.PrivateKeyCertSelectionDelegate += new PrivateKeySelectionCallback (GetPrivateKey);
2643
2644                                         StreamReader reader = new StreamReader (s);
2645                                         StreamWriter writer = new StreamWriter (s, Encoding.ASCII);
2646
2647                                         string line;
2648                                         string hello = "<html><body><h1>Hello World!</h1></body></html>";
2649                                         string answer = "HTTP/1.0 200\r\n" +
2650                                                         "Connection: close\r\n" +
2651                                                         "Content-Type: text/html\r\n" +
2652                                                         "Content-Encoding: " + Encoding.ASCII.WebName + "\r\n" +
2653                                                         "Content-Length: " + hello.Length + "\r\n" +
2654                                                         "\r\n" + hello;
2655
2656                                         // Read the headers
2657                                         do {
2658                                                 line = reader.ReadLine ();
2659                                         } while (line != "" && line != null && line.Length > 0);
2660
2661                                         // Now the content. We know it's 100 bytes.
2662                                         // This makes BeginRead in sslclientstream block.
2663                                         char [] cs = new char [100];
2664                                         reader.Read (cs, 0, 100);
2665
2666                                         writer.Write (answer);
2667                                         writer.Flush ();
2668                                         if (evt.WaitOne (5000, false))
2669                                                 error = new Exception ("Timeout when stopping the server");
2670                                 } catch (Exception e) {
2671                                         error = e;
2672                                 }
2673                         }
2674
2675                         X509Certificate Certificate {
2676                                 get {
2677                                         if (_certificate == null)
2678                                                 _certificate = new X509Certificate (CertData.Certificate);
2679
2680                                         return _certificate;
2681                                 }
2682                         }
2683
2684                         AsymmetricAlgorithm GetPrivateKey (X509Certificate certificate, string targetHost)
2685                         {
2686                                 PrivateKey key = new PrivateKey (CertData.PrivateKey, null);
2687                                 return key.RSA;
2688                         }
2689                 }
2690
2691                 class CertData {
2692                         public readonly static byte [] Certificate = {
2693                                 48, 130, 1, 191, 48, 130, 1, 40, 160, 3, 2, 1, 2, 2, 16, 36, 
2694                                 14, 97, 190, 146, 132, 208, 71, 175, 6, 87, 168, 185, 175, 55, 43, 48, 
2695                                 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 48, 18, 
2696                                 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 111, 110, 122, 97, 
2697                                 108, 111, 48, 30, 23, 13, 48, 53, 48, 54, 50, 50, 49, 57, 51, 48, 
2698                                 52, 54, 90, 23, 13, 51, 57, 49, 50, 51, 49, 50, 51, 53, 57, 53, 
2699                                 57, 90, 48, 18, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 
2700                                 111, 110, 122, 97, 108, 111, 48, 129, 158, 48, 13, 6, 9, 42, 134, 72, 
2701                                 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 140, 0, 48, 129, 136, 2, 
2702                                 129, 129, 0, 138, 9, 38, 25, 166, 252, 59, 26, 39, 184, 128, 216, 38, 
2703                                 73, 41, 86, 30, 228, 160, 205, 41, 135, 115, 223, 44, 62, 42, 198, 178, 
2704                                 190, 81, 11, 25, 21, 216, 49, 179, 130, 246, 52, 97, 175, 212, 94, 157, 
2705                                 231, 162, 66, 161, 103, 63, 204, 83, 141, 172, 119, 97, 225, 206, 98, 101, 
2706                                 210, 106, 2, 206, 81, 90, 173, 47, 41, 199, 209, 241, 177, 177, 96, 207, 
2707                                 254, 220, 190, 66, 180, 153, 0, 209, 14, 178, 69, 194, 3, 37, 116, 239, 
2708                                 49, 23, 185, 245, 255, 126, 35, 85, 246, 56, 244, 107, 117, 24, 14, 57, 
2709                                 9, 111, 147, 189, 220, 142, 57, 104, 153, 193, 205, 19, 14, 22, 157, 16, 
2710                                 24, 80, 201, 2, 2, 0, 17, 163, 23, 48, 21, 48, 19, 6, 3, 85, 
2711                                 29, 37, 4, 12, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, 
2712                                 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 3, 
2713                                 129, 129, 0, 64, 49, 57, 253, 218, 198, 229, 51, 189, 12, 154, 225, 183, 
2714                                 160, 147, 90, 113, 172, 69, 122, 28, 77, 97, 215, 231, 194, 150, 29, 196, 
2715                                 65, 95, 218, 99, 142, 111, 79, 205, 109, 76, 32, 92, 220, 76, 88, 53, 
2716                                 237, 80, 11, 85, 44, 91, 21, 210, 12, 34, 223, 234, 18, 187, 136, 62, 
2717                                 26, 240, 103, 180, 12, 226, 221, 250, 247, 129, 51, 23, 129, 165, 56, 67, 
2718                                 43, 83, 244, 110, 207, 24, 253, 195, 16, 46, 80, 113, 80, 18, 2, 254, 
2719                                 120, 147, 151, 164, 23, 210, 230, 100, 19, 197, 179, 28, 194, 48, 106, 159, 
2720                                 155, 144, 37, 82, 44, 160, 40, 52, 146, 174, 77, 188, 160, 230, 75, 172, 
2721                                 123, 3, 254, 
2722                         };
2723
2724                         public readonly static byte [] PrivateKey = {
2725                                 30, 241, 181, 176, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 
2726                                 0, 0, 0, 0, 84, 2, 0, 0, 7, 2, 0, 0, 0, 36, 0, 0, 
2727                                 82, 83, 65, 50, 0, 4, 0, 0, 17, 0, 0, 0, 201, 80, 24, 16, 
2728                                 157, 22, 14, 19, 205, 193, 153, 104, 57, 142, 220, 189, 147, 111, 9, 57, 
2729                                 14, 24, 117, 107, 244, 56, 246, 85, 35, 126, 255, 245, 185, 23, 49, 239, 
2730                                 116, 37, 3, 194, 69, 178, 14, 209, 0, 153, 180, 66, 190, 220, 254, 207, 
2731                                 96, 177, 177, 241, 209, 199, 41, 47, 173, 90, 81, 206, 2, 106, 210, 101, 
2732                                 98, 206, 225, 97, 119, 172, 141, 83, 204, 63, 103, 161, 66, 162, 231, 157, 
2733                                 94, 212, 175, 97, 52, 246, 130, 179, 49, 216, 21, 25, 11, 81, 190, 178, 
2734                                 198, 42, 62, 44, 223, 115, 135, 41, 205, 160, 228, 30, 86, 41, 73, 38, 
2735                                 216, 128, 184, 39, 26, 59, 252, 166, 25, 38, 9, 138, 175, 88, 190, 223, 
2736                                 27, 24, 224, 123, 190, 69, 164, 234, 129, 59, 108, 229, 248, 62, 187, 15, 
2737                                 235, 147, 162, 83, 47, 123, 170, 190, 224, 31, 215, 110, 143, 31, 227, 216, 
2738                                 85, 88, 154, 83, 207, 229, 41, 28, 237, 116, 181, 17, 37, 141, 224, 185, 
2739                                 164, 144, 141, 233, 164, 138, 177, 241, 115, 181, 230, 150, 7, 92, 139, 141, 
2740                                 113, 95, 57, 191, 211, 165, 217, 250, 197, 68, 164, 184, 168, 43, 48, 65, 
2741                                 177, 237, 173, 144, 148, 221, 62, 189, 147, 63, 216, 188, 206, 103, 226, 171, 
2742                                 32, 20, 230, 116, 144, 192, 1, 39, 202, 87, 74, 250, 6, 142, 188, 23, 
2743                                 45, 4, 112, 191, 253, 67, 69, 70, 128, 143, 44, 234, 41, 96, 195, 82, 
2744                                 202, 35, 158, 149, 240, 151, 23, 25, 166, 179, 85, 144, 58, 120, 149, 229, 
2745                                 205, 34, 8, 110, 86, 119, 130, 210, 37, 173, 65, 71, 169, 67, 8, 51, 
2746                                 20, 96, 51, 155, 3, 39, 85, 187, 40, 193, 57, 19, 99, 78, 173, 28, 
2747                                 129, 154, 108, 175, 8, 138, 237, 71, 27, 148, 129, 35, 47, 57, 101, 237, 
2748                                 168, 178, 227, 221, 212, 63, 124, 254, 253, 215, 183, 159, 49, 103, 74, 49, 
2749                                 67, 160, 171, 72, 194, 215, 108, 251, 178, 18, 184, 100, 211, 105, 21, 186, 
2750                                 39, 66, 218, 154, 72, 222, 90, 237, 179, 251, 51, 224, 212, 56, 251, 6, 
2751                                 209, 151, 198, 176, 89, 110, 35, 141, 248, 237, 223, 68, 135, 206, 207, 169, 
2752                                 254, 219, 243, 130, 71, 11, 94, 113, 233, 92, 63, 156, 169, 72, 215, 110, 
2753                                 95, 94, 191, 50, 59, 89, 187, 59, 183, 99, 161, 146, 233, 245, 219, 80, 
2754                                 87, 113, 251, 50, 144, 195, 158, 46, 189, 232, 119, 91, 75, 22, 6, 176, 
2755                                 39, 206, 25, 196, 213, 195, 219, 24, 28, 103, 104, 36, 137, 128, 4, 119, 
2756                                 163, 40, 126, 87, 18, 86, 128, 243, 213, 101, 2, 237, 78, 64, 160, 55, 
2757                                 199, 93, 90, 126, 175, 199, 55, 89, 234, 190, 5, 16, 196, 88, 28, 208, 
2758                                 28, 92, 32, 115, 204, 9, 202, 101, 15, 123, 43, 75, 90, 144, 95, 179, 
2759                                 102, 249, 57, 150, 204, 99, 147, 203, 16, 63, 81, 244, 226, 237, 82, 204, 
2760                                 20, 200, 140, 65, 83, 217, 161, 23, 123, 37, 115, 12, 100, 73, 70, 190, 
2761                                 32, 235, 174, 140, 148, 157, 47, 238, 40, 208, 228, 80, 54, 187, 156, 252, 
2762                                 253, 230, 231, 156, 138, 125, 96, 79, 3, 27, 143, 55, 146, 169, 165, 61, 
2763                                 238, 60, 227, 77, 217, 93, 117, 122, 111, 46, 173, 113, 
2764                         };
2765                 }
2766 #endif
2767
2768                 [Test]
2769                 public void CookieContainerTest ()
2770                 {
2771                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2772                         string url = "http://" + ep.ToString ();
2773
2774                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (CookieRequestHandler))) {
2775                                 responder.Start ();
2776
2777                                 CookieContainer container = new CookieContainer ();
2778                                 container.Add(new Uri (url), new Cookie ("foo", "bar"));
2779                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
2780                                 request.CookieContainer = container;
2781                                 WebHeaderCollection headers = request.Headers;
2782                                 headers.Add("Cookie", "foo=baz");
2783                                 HttpWebResponse response = (HttpWebResponse) request.GetResponse ();
2784                                 string responseString = null;
2785                                 using (StreamReader reader = new StreamReader (response.GetResponseStream ())) {
2786                                         responseString = reader.ReadToEnd ();
2787                                 }
2788                                 response.Close ();
2789                                 Assert.AreEqual (1, response.Cookies.Count, "#01");
2790                                 Assert.AreEqual ("foo=bar", response.Headers.Get("Set-Cookie"), "#02");
2791                         }
2792
2793                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (CookieRequestHandler))) {
2794                                 responder.Start ();
2795
2796                                 CookieContainer container = new CookieContainer ();
2797                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
2798                                 request.CookieContainer = container;
2799                                 WebHeaderCollection headers = request.Headers;
2800                                 headers.Add("Cookie", "foo=baz");
2801                                 HttpWebResponse response = (HttpWebResponse) request.GetResponse ();
2802                                 string responseString = null;
2803                                 using (StreamReader reader = new StreamReader (response.GetResponseStream ())) {
2804                                         responseString = reader.ReadToEnd ();
2805                                 }
2806                                 response.Close ();
2807                                 Assert.AreEqual (0, response.Cookies.Count, "#03");
2808                                 Assert.AreEqual ("", response.Headers.Get("Set-Cookie"), "#04");
2809                         }
2810                 }
2811
2812                 internal static byte[] CookieRequestHandler (Socket socket)
2813                 {
2814                         MemoryStream ms = new MemoryStream ();
2815                         byte[] buffer = new byte[4096];
2816                         int bytesReceived = socket.Receive (buffer);
2817                         while (bytesReceived > 0) {
2818                                 ms.Write(buffer, 0, bytesReceived);
2819                                 // We don't check for Content-Length or anything else here, so we give the client a little time to write
2820                                 // after sending the headers
2821                                 Thread.Sleep(200);
2822                                 if (socket.Available > 0) {
2823                                         bytesReceived = socket.Receive (buffer);
2824                                 } else {
2825                                         bytesReceived = 0;
2826                                 }
2827                         }
2828                         ms.Flush();
2829                         ms.Position = 0;
2830                         string cookies = string.Empty;
2831                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
2832                                 string line;
2833                                 while ((line = sr.ReadLine ()) != null) {
2834                                         if (line.StartsWith ("Cookie:")) {
2835                                                 cookies = line.Substring ("cookie: ".Length);
2836                                         }
2837                                 }
2838                         }
2839
2840                         StringWriter sw = new StringWriter ();
2841                         sw.WriteLine ("HTTP/1.1 200 OK");
2842                         sw.WriteLine ("Content-Type: text/xml");
2843                         sw.WriteLine ("Set-Cookie: " + cookies);
2844                         sw.WriteLine ("Content-Length: " + cookies.Length.ToString (CultureInfo.InvariantCulture));
2845                         sw.WriteLine ();
2846                         sw.Write (cookies);
2847                         sw.Flush ();
2848
2849                         return Encoding.UTF8.GetBytes (sw.ToString ());
2850                 }
2851         }
2852
2853         [TestFixture]
2854         public class HttpRequestStreamTest
2855         {
2856                 [Test]
2857                 public void BeginRead ()
2858                 {
2859                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2860                         string url = "http://" + ep.ToString () + "/test/";
2861
2862                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2863                                 responder.Start ();
2864
2865                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2866                                 req.Method = "POST";
2867
2868                                 using (Stream rs = req.GetRequestStream ()) {
2869                                         byte [] buffer = new byte [10];
2870                                         try {
2871                                                 rs.BeginRead (buffer, 0, buffer.Length, null, null);
2872                                                 Assert.Fail ("#1");
2873                                         } catch (NotSupportedException ex) {
2874                                                 // The stream does not support reading
2875                                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
2876                                                 Assert.IsNull (ex.InnerException, "#3");
2877                                                 Assert.IsNotNull (ex.Message, "#4");
2878                                         } finally {
2879                                                 req.Abort ();
2880                                         }
2881                                 }
2882                         }
2883                 }
2884
2885                 [Test]
2886                 [Category("MobileNotWorking")]
2887                 public void BeginWrite_Request_Aborted ()
2888                 {
2889                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2890                         string url = "http://" + ep.ToString () + "/test/";
2891
2892                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2893                                 responder.Start ();
2894
2895                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2896                                 req.Method = "POST";
2897
2898                                 using (Stream rs = req.GetRequestStream ()) {
2899                                         req.Abort ();
2900                                         try {
2901                                                 rs.BeginWrite (new byte [] { 0x2a, 0x2f }, 0, 2, null, null);
2902                                                 Assert.Fail ("#1");
2903                                         } catch (WebException ex) {
2904                                                 // The request was aborted: The request was canceled
2905                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
2906                                                 Assert.IsNull (ex.InnerException, "#3");
2907                                                 Assert.IsNotNull (ex.Message, "#4");
2908                                                 Assert.IsNull (ex.Response, "#5");
2909                                                 Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
2910                                         }
2911                                 }
2912                         }
2913                 }
2914
2915                 [Test]
2916                 public void CanRead ()
2917                 {
2918                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2919                         string url = "http://" + ep.ToString () + "/test/";
2920
2921                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2922                                 responder.Start ();
2923
2924                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2925                                 req.Method = "POST";
2926
2927                                 Stream rs = req.GetRequestStream ();
2928                                 try {
2929                                         Assert.IsFalse (rs.CanRead, "#1");
2930                                         rs.Close ();
2931                                         Assert.IsFalse (rs.CanRead, "#2");
2932                                 } finally {
2933                                         rs.Close ();
2934                                         req.Abort ();
2935                                 }
2936                         }
2937                 }
2938
2939                 [Test]
2940                 public void CanSeek ()
2941                 {
2942                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2943                         string url = "http://" + ep.ToString () + "/test/";
2944
2945                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2946                                 responder.Start ();
2947
2948                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2949                                 req.Method = "POST";
2950
2951                                 Stream rs = req.GetRequestStream ();
2952                                 try {
2953                                         Assert.IsFalse (rs.CanSeek, "#1");
2954                                         rs.Close ();
2955                                         Assert.IsFalse (rs.CanSeek, "#2");
2956                                 } finally {
2957                                         rs.Close ();
2958                                         req.Abort ();
2959                                 }
2960                         }
2961                 }
2962
2963                 [Test] // bug #324182
2964                 public void CanTimeout ()
2965                 {
2966                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2967                         string url = "http://" + ep.ToString () + "/test/";
2968
2969                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2970                                 responder.Start ();
2971
2972                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2973                                 req.Method = "POST";
2974
2975                                 Stream rs = req.GetRequestStream ();
2976                                 try {
2977                                         Assert.IsTrue (rs.CanTimeout, "#1");
2978                                         rs.Close ();
2979                                         Assert.IsTrue (rs.CanTimeout, "#2");
2980                                 } finally {
2981                                         rs.Close ();
2982                                         req.Abort ();
2983                                 }
2984                         }
2985                 }
2986
2987                 [Test]
2988                 public void CanWrite ()
2989                 {
2990                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
2991                         string url = "http://" + ep.ToString () + "/test/";
2992
2993                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
2994                                 responder.Start ();
2995
2996                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
2997                                 req.Method = "POST";
2998
2999                                 Stream rs = req.GetRequestStream ();
3000                                 try {
3001                                         Assert.IsTrue (rs.CanWrite, "#1");
3002                                         rs.Close ();
3003                                         Assert.IsFalse (rs.CanWrite, "#2");
3004                                 } finally {
3005                                         rs.Close ();
3006                                         req.Abort ();
3007                                 }
3008                         }
3009                 }
3010
3011                 [Test]
3012                 public void Read ()
3013                 {
3014                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3015                         string url = "http://" + ep.ToString () + "/test/";
3016
3017                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3018                                 responder.Start ();
3019
3020                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3021                                 req.Method = "POST";
3022
3023                                 using (Stream rs = req.GetRequestStream ()) {
3024                                         byte [] buffer = new byte [10];
3025                                         try {
3026                                                 rs.Read (buffer, 0, buffer.Length);
3027                                                 Assert.Fail ("#1");
3028                                         } catch (NotSupportedException ex) {
3029                                                 // The stream does not support reading
3030                                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
3031                                                 Assert.IsNull (ex.InnerException, "#3");
3032                                                 Assert.IsNotNull (ex.Message, "#4");
3033                                         } finally {
3034                                                 req.Abort ();
3035                                         }
3036                                 }
3037                         }
3038                 }
3039
3040                 [Test]
3041                 public void ReadByte ()
3042                 {
3043                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3044                         string url = "http://" + ep.ToString () + "/test/";
3045
3046                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3047                                 responder.Start ();
3048
3049                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3050                                 req.Method = "POST";
3051
3052                                 using (Stream rs = req.GetRequestStream ()) {
3053                                         try {
3054                                                 rs.ReadByte ();
3055                                                 Assert.Fail ("#1");
3056                                         } catch (NotSupportedException ex) {
3057                                                 // The stream does not support reading
3058                                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
3059                                                 Assert.IsNull (ex.InnerException, "#3");
3060                                                 Assert.IsNotNull (ex.Message, "#4");
3061                                         } finally {
3062                                                 req.Abort ();
3063                                         }
3064                                 }
3065                         }
3066                 }
3067
3068                 [Test]
3069                 public void ReadTimeout ()
3070                 {
3071                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3072                         string url = "http://" + ep.ToString () + "/test/";
3073
3074                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3075                                 responder.Start ();
3076
3077                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3078                                 req.Method = "POST";
3079
3080                                 Stream rs = req.GetRequestStream ();
3081                                 try {
3082                                         Assert.AreEqual (300000, rs.ReadTimeout, "#1");
3083                                         rs.Close ();
3084                                         Assert.AreEqual (300000, rs.ReadTimeout, "#2");
3085                                 } finally {
3086                                         rs.Close ();
3087                                         req.Abort ();
3088                                 }
3089                         }
3090                 }
3091
3092                 [Test]
3093                 public void Seek ()
3094                 {
3095                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3096                         string url = "http://" + ep.ToString () + "/test/";
3097
3098                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3099                                 responder.Start ();
3100
3101                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3102                                 req.Method = "POST";
3103
3104                                 using (Stream rs = req.GetRequestStream ()) {
3105                                         try {
3106                                                 rs.Seek (0, SeekOrigin.Current);
3107                                                 Assert.Fail ("#1");
3108                                         } catch (NotSupportedException ex) {
3109                                                 // This stream does not support seek operations
3110                                                 Assert.AreEqual (typeof (NotSupportedException), ex.GetType (), "#2");
3111                                                 Assert.IsNull (ex.InnerException, "#3");
3112                                                 Assert.IsNotNull (ex.Message, "#4");
3113                                         } finally {
3114                                                 req.Abort ();
3115                                         }
3116                                 }
3117                         }
3118                 }
3119
3120                 [Test]
3121                 public void Write_Buffer_Null ()
3122                 {
3123                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3124                         string url = "http://" + ep.ToString () + "/test/";
3125
3126                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3127                                 responder.Start ();
3128
3129                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3130                                 req.Method = "POST";
3131
3132                                 using (Stream rs = req.GetRequestStream ()) {
3133                                         try {
3134                                                 rs.Write ((byte []) null, -1, -1);
3135                                                 Assert.Fail ("#1");
3136                                         } catch (ArgumentNullException ex) {
3137                                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
3138                                                 Assert.IsNull (ex.InnerException, "#3");
3139                                                 Assert.IsNotNull (ex.Message, "#4");
3140                                                 Assert.AreEqual ("buffer", ex.ParamName, "#5");
3141                                         }
3142                                 }
3143
3144                                 req.Abort ();
3145                         }
3146                 }
3147
3148                 [Test]
3149                 public void Write_Count_Negative ()
3150                 {
3151                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3152                         string url = "http://" + ep.ToString () + "/test/";
3153
3154                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3155                                 responder.Start ();
3156
3157                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3158                                 req.Method = "POST";
3159
3160                                 using (Stream rs = req.GetRequestStream ()) {
3161                                         byte [] buffer = new byte [] { 0x2a, 0x2c, 0x1d, 0x00, 0x0f };
3162                                         try {
3163                                                 rs.Write (buffer, 1, -1);
3164                                                 Assert.Fail ("#1");
3165                                         } catch (ArgumentOutOfRangeException ex) {
3166                                                 // Specified argument was out of the range of valid values
3167                                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#A2");
3168                                                 Assert.IsNull (ex.InnerException, "#A3");
3169                                                 Assert.IsNotNull (ex.Message, "#A4");
3170                                                 Assert.AreEqual ("size", ex.ParamName, "#A5");
3171                                         }
3172                                 }
3173
3174                                 req.Abort ();
3175                         }
3176                 }
3177
3178                 [Test]
3179                 public void Write_Count_Overflow ()
3180                 {
3181                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3182                         string url = "http://" + ep.ToString () + "/test/";
3183
3184                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3185                                 responder.Start ();
3186
3187                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3188                                 req.Method = "POST";
3189
3190                                 using (Stream rs = req.GetRequestStream ()) {
3191                                         byte [] buffer = new byte [] { 0x2a, 0x2c, 0x1d, 0x00, 0x0f };
3192                                         try {
3193                                                 rs.Write (buffer, buffer.Length - 2, 3);
3194                                                 Assert.Fail ("#1");
3195                                         } catch (ArgumentOutOfRangeException ex) {
3196                                                 // Specified argument was out of the range of valid values
3197                                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
3198                                                 Assert.IsNull (ex.InnerException, "#3");
3199                                                 Assert.IsNotNull (ex.Message, "#4");
3200                                                 Assert.AreEqual ("size", ex.ParamName, "#5");
3201                                         }
3202                                 }
3203
3204                                 req.Abort ();
3205                         }
3206                 }
3207
3208                 [Test]
3209                 public void Write_Offset_Negative ()
3210                 {
3211                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3212                         string url = "http://" + ep.ToString () + "/test/";
3213
3214                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3215                                 responder.Start ();
3216
3217                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3218                                 req.Method = "POST";
3219
3220                                 using (Stream rs = req.GetRequestStream ()) {
3221                                         byte [] buffer = new byte [] { 0x2a, 0x2c, 0x1d, 0x00, 0x0f };
3222                                         try {
3223                                                 rs.Write (buffer, -1, 0);
3224                                                 Assert.Fail ("#1");
3225                                         } catch (ArgumentOutOfRangeException ex) {
3226                                                 // Specified argument was out of the range of valid values
3227                                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
3228                                                 Assert.IsNull (ex.InnerException, "#3");
3229                                                 Assert.IsNotNull (ex.Message, "#4");
3230                                                 Assert.AreEqual ("offset", ex.ParamName, "#5");
3231                                         }
3232                                 }
3233
3234                                 req.Abort ();
3235                         }
3236                 }
3237
3238                 [Test]
3239                 public void Write_Offset_Overflow ()
3240                 {
3241                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3242                         string url = "http://" + ep.ToString () + "/test/";
3243
3244                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3245                                 responder.Start ();
3246
3247                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3248                                 req.Method = "POST";
3249
3250                                 using (Stream rs = req.GetRequestStream ()) {
3251                                         byte [] buffer = new byte [] { 0x2a, 0x2c, 0x1d, 0x00, 0x0f };
3252                                         try {
3253                                                 rs.Write (buffer, buffer.Length + 1, 0);
3254                                                 Assert.Fail ("#1");
3255                                         } catch (ArgumentOutOfRangeException ex) {
3256                                                 // Specified argument was out of the range of valid values
3257                                                 Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#2");
3258                                                 Assert.IsNull (ex.InnerException, "#3");
3259                                                 Assert.IsNotNull (ex.Message, "#4");
3260                                                 Assert.AreEqual ("offset", ex.ParamName, "#5");
3261                                         }
3262                                 }
3263
3264                                 req.Abort ();
3265                         }
3266                 }
3267
3268                 [Test]
3269                 public void Write_Request_Aborted ()
3270                 {
3271                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3272                         string url = "http://" + ep.ToString () + "/test/";
3273
3274                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3275                                 responder.Start ();
3276
3277                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3278                                 req.Method = "POST";
3279
3280                                 using (Stream rs = req.GetRequestStream ()) {
3281                                         req.Abort ();
3282                                         try {
3283                                                 rs.Write (new byte [0], 0, 0);
3284                                                 Assert.Fail ("#1");
3285                                         } catch (WebException ex) {
3286                                                 // The request was aborted: The request was canceled
3287                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
3288                                                 Assert.IsNull (ex.InnerException, "#3");
3289                                                 Assert.IsNotNull (ex.Message, "#4");
3290                                                 Assert.IsNull (ex.Response, "#5");
3291                                                 Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
3292                                         }
3293                                 }
3294                         }
3295                 }
3296
3297                 [Test]
3298                 [Category ("NotWorking")]
3299                 public void Write_Stream_Closed ()
3300                 {
3301                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3302                         string url = "http://" + ep.ToString () + "/test/";
3303
3304                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3305                                 responder.Start ();
3306
3307                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3308                                 req.Method = "POST";
3309
3310                                 using (Stream rs = req.GetRequestStream ()) {
3311                                         rs.Close ();
3312                                         try {
3313                                                 rs.Write (new byte [0], 0, 0);
3314                                                 Assert.Fail ("#1");
3315                                         } catch (WebException ex) {
3316                                                 // The request was aborted: The connection was closed unexpectedly
3317                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
3318                                                 Assert.IsNull (ex.InnerException, "#3");
3319                                                 Assert.IsNotNull (ex.Message, "#4");
3320                                                 Assert.IsNull (ex.Response, "#5");
3321                                                 Assert.AreEqual (WebExceptionStatus.ConnectionClosed, ex.Status, "#6");
3322                                         }
3323                                 }
3324                         }
3325                 }
3326
3327                 [Test]
3328                 public void WriteByte_Request_Aborted ()
3329                 {
3330                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3331                         string url = "http://" + ep.ToString () + "/test/";
3332
3333                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3334                                 responder.Start ();
3335
3336                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3337                                 req.Method = "POST";
3338
3339                                 using (Stream rs = req.GetRequestStream ()) {
3340                                         req.Abort ();
3341                                         try {
3342                                                 rs.WriteByte (0x2a);
3343                                                 Assert.Fail ("#1");
3344                                         } catch (WebException ex) {
3345                                                 // The request was aborted: The request was canceled
3346                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
3347                                                 Assert.IsNull (ex.InnerException, "#3");
3348                                                 Assert.IsNotNull (ex.Message, "#4");
3349                                                 Assert.IsNull (ex.Response, "#5");
3350                                                 Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#6");
3351                                         }
3352                                 }
3353                         }
3354                 }
3355
3356                 [Test]
3357                 public void WriteTimeout ()
3358                 {
3359                         IPEndPoint ep = NetworkHelpers.LocalEphemeralEndPoint ();
3360                         string url = "http://" + ep.ToString () + "/test/";
3361
3362                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (HttpWebRequestTest.EchoRequestHandler))) {
3363                                 responder.Start ();
3364
3365                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
3366                                 req.Method = "POST";
3367
3368                                 Stream rs = req.GetRequestStream ();
3369                                 try {
3370                                         Assert.AreEqual (300000, rs.WriteTimeout, "#1");
3371                                         rs.Close ();
3372                                         Assert.AreEqual (300000, rs.WriteTimeout, "#2");
3373                                 } finally {
3374                                         rs.Close ();
3375                                         req.Abort ();
3376                                 }
3377                         }
3378                 }
3379
3380                 [Test]
3381                 // Bug6737
3382                 // This test is supposed to fail prior to .NET 4.0
3383                 public void Post_EmptyRequestStream ()
3384                 {
3385                         var wr = HttpWebRequest.Create ("http://google.com");
3386                         wr.Method = "POST";
3387                         wr.GetRequestStream ();
3388                         
3389                         var gr = wr.BeginGetResponse (delegate { }, null);
3390                         Assert.AreEqual (true, gr.AsyncWaitHandle.WaitOne (5000), "#1");
3391                 }
3392         }
3393
3394         static class StreamExtensions {
3395                 public static int ReadAll(this Stream stream, byte[] buffer, int offset, int count)
3396                 {
3397                         int totalRead = 0;
3398
3399                         while (totalRead < count) {
3400                                 int bytesRead = stream.Read (buffer, offset + totalRead, count - totalRead);
3401                                 if (bytesRead == 0)
3402                                         break;
3403
3404                                 totalRead += bytesRead;
3405                         }
3406
3407                         return totalRead;
3408                 }
3409         }
3410
3411         static class ExceptionAssert {
3412                 /// <summary>
3413                 /// Asserts that the function throws an exception.
3414                 /// </summary>
3415                 /// <param name="f">A function execute that is expected to raise an exception.</param>
3416                 /// <typeparam name="T">The type of exception that is expected.</typeparam>
3417                 /// <returns>The exception thrown.</returns>
3418                 /// <exception cref="AssertFailedException">If the function does not throw an exception 
3419                 /// or throws a different exception.</exception>
3420                 /// <example><![CDATA[
3421                 ///     ExceptionAssert.Throws(typeof(ArgumentNullException), delegate {
3422                 ///         myObject.myFunction(null); });
3423                 /// ]]></example>
3424                 public static T Throws<T> (Action f) where T : Exception {
3425                         Exception actualException = null;
3426
3427                         try {
3428                                 f ();
3429                         } catch (Exception ex) {
3430                                 actualException = ex;
3431                         }
3432
3433                         if (actualException == null)
3434                                 throw new AssertionException (string.Format (
3435                                         "No exception thrown. Expected '{0}'",
3436                                         typeof (T).FullName));
3437                         else if (typeof(T) != actualException.GetType())
3438                                 throw new AssertionException (string.Format (
3439                                         "Caught exception of type '{0}'. Expected '{1}':{2}",
3440                                         actualException.GetType().FullName,
3441                                         typeof (T).FullName,
3442                                         Environment.NewLine + actualException));
3443
3444                         return (T) actualException;
3445                 }
3446         }
3447 }