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