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