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