increase timeouts to make this work on machines under load
[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 //
9 // (C) 2003 Martin Willemoes Hansen
10 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com
11 //
12
13 using NUnit.Framework;
14 using System;
15 using System.Collections;
16 using System.Collections.Specialized;
17 using System.Globalization;
18 using System.IO;
19 using System.Net;
20 using System.Net.Sockets;
21 using System.Security.Cryptography;
22 using System.Security.Cryptography.X509Certificates;
23 using System.Text;
24 using System.Threading;
25 #if !TARGET_JVM
26 using Mono.Security.Authenticode;
27 using Mono.Security.Protocol.Tls;
28 #endif
29
30 namespace MonoTests.System.Net
31 {
32         [TestFixture]
33         public class HttpWebRequestTest
34         {
35 #if NET_2_0
36                 private Random rand = new Random();
37                 private byte[] data64KB = new byte[64 * 1024]; 
38
39                 [TestFixtureSetUp]
40                 public void Setup()
41                 {
42                     ServicePointManager.Expect100Continue = false;
43                     rand.NextBytes(data64KB);
44                 }
45 #endif
46
47                 [Test]
48 #if TARGET_JVM
49                 [Ignore ("Ignore failures in Sys.Net")]
50 #endif
51                 public void Proxy_Null ()
52                 {
53                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
54                         Assert.IsNotNull (req.Proxy, "#1");
55 #if NET_2_0
56                         req.Proxy = null;
57                         Assert.IsNull (req.Proxy, "#2");
58 #else
59                         try {
60                                 req.Proxy = null;
61                                 Assert.Fail ("#2");
62                         } catch (ArgumentNullException ex) {
63                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#3");
64                                 Assert.IsNull (ex.InnerException, "#4");
65                                 Assert.IsNotNull (ex.Message, "#5");
66                                 Assert.IsNotNull (ex.ParamName, "#6");
67                                 Assert.AreEqual ("value", ex.ParamName, "#7");
68                         }
69 #endif
70                 }
71
72                 [Test]
73                 [Category("InetAccess")]
74 #if TARGET_JVM
75                 [Ignore ("NMA - wrong cookies number returned")]
76 #endif
77                 public void Sync ()
78                 {
79                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
80                         Assert.IsNotNull (req.IfModifiedSince, "req:If Modified Since: ");
81
82                         req.UserAgent = "MonoClient v1.0";
83                         Assert.AreEqual ("User-Agent", req.Headers.GetKey (0), "#A1");
84                         Assert.AreEqual ("MonoClient v1.0", req.Headers.Get (0), "#A2");
85
86                         HttpWebResponse res = (HttpWebResponse) req.GetResponse ();
87                         Assert.AreEqual ("OK", res.StatusCode.ToString (), "#B1");
88                         Assert.AreEqual ("OK", res.StatusDescription, "#B2");
89
90                         Assert.AreEqual ("text/html; charset=ISO-8859-1", res.Headers.Get ("Content-Type"), "#C1");
91                         Assert.IsNotNull (res.LastModified, "#C2");
92                         Assert.AreEqual (0, res.Cookies.Count, "#C3");
93
94                         res.Close ();
95                 }
96
97                 [Test]
98                 public void AddRange ()
99                 {
100                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
101                         req.AddRange (10);
102                         req.AddRange (50, 90);
103                         req.AddRange ("bytes", 100); 
104                         req.AddRange ("bytes", 100, 120);
105                         Assert.AreEqual ("bytes=10-,50-90,100-,100-120", req.Headers ["Range"], "#1");
106                         try {
107                                 req.AddRange ("bits", 2000);
108                                 Assert.Fail ("#2");
109                         } catch (InvalidOperationException) {}
110                 }
111
112                 [Test] // bug #471782
113                 public void CloseRequestStreamAfterReadingResponse ()
114                 {
115                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
116                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
117
118                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
119                                 responder.Start ();
120
121                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
122                                 req.Method = "POST";
123                                 req.Timeout = 2000;
124                                 req.ReadWriteTimeout = 2000;
125
126                                 byte [] data = new byte [128];
127                                 req.ContentLength = data.Length;
128
129                                 Stream rs = req.GetRequestStream ();
130                                 rs.Write (data, 0, data.Length);
131                                 rs.Flush ();
132
133                                 HttpWebResponse response = (HttpWebResponse) req.GetResponse ();
134                                 response.Close ();
135
136                                 rs.Close ();
137
138                                 responder.Stop ();
139                         }
140                 }
141
142                 [Test]
143                 [Category("InetAccess")]
144                 public void Cookies1 ()
145                 {
146                         // The purpose of this test is to ensure that the cookies we get from a request
147                         // are stored in both, the CookieCollection in HttpWebResponse and the CookieContainer
148                         // in HttpWebRequest.
149                         // If this URL stops sending *one* and only one cookie, replace it.
150                         string url = "http://www.elmundo.es";
151                         CookieContainer cookies = new CookieContainer ();
152                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
153                         req.KeepAlive = false;
154                         req.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv; 1.7.6) Gecko/20050317 Firefox/1.0.2";
155                         req.CookieContainer = cookies;
156                         Assert.AreEqual (0, cookies.Count, "#01");
157                         using (HttpWebResponse res = (HttpWebResponse) req.GetResponse()) {
158                                 CookieCollection coll = req.CookieContainer.GetCookies (new Uri (url));
159                                 Assert.AreEqual (1, coll.Count, "#02");
160                                 Assert.AreEqual (1, res.Cookies.Count, "#03");
161                                 Cookie one = coll [0];
162                                 Cookie two = res.Cookies [0];
163                                 Assert.AreEqual (true, object.ReferenceEquals (one, two), "#04");
164                         }
165                 }
166
167 #if !TARGET_JVM //NotWorking
168                 [Test]
169                 public void SslClientBlock ()
170                 {
171                         // This tests that the write request/initread/write body sequence does not hang
172                         // when using SSL.
173                         // If there's a regression for this, the test will hang.
174                         ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
175                         try {
176                                 SslHttpServer server = new SslHttpServer ();
177                                 server.Start ();
178
179                                 string url = String.Format ("https://{0}:{1}/nothing.html", server.IPAddress, server.Port);
180                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
181                                 request.Method = "POST";
182                                 Stream stream = request.GetRequestStream ();
183                                 byte [] bytes = new byte [100];
184                                 stream.Write (bytes, 0, bytes.Length);
185                                 stream.Close ();
186                                 HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
187                                 Assert.AreEqual (200, (int) resp.StatusCode, "StatusCode");
188                                 StreamReader sr = new StreamReader (resp.GetResponseStream (), Encoding.UTF8);
189                                 string x = sr.ReadToEnd ();
190                                 sr.Close ();
191                                 resp.Close ();
192                                 server.Stop ();
193                                 if (server.Error != null)
194                                         throw server.Error;
195                         } finally {
196                                 ServicePointManager.CertificatePolicy = null;
197                         }
198                 }
199 #endif
200                 [Test]
201 #if TARGET_JVM
202                 [Category("NotWorking")]
203 #endif
204                 public void Missing_ContentEncoding ()
205                 {
206                         ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
207                         try {
208                                 BadChunkedServer server = new BadChunkedServer ();
209                                 server.Start ();
210
211                                 string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
212                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
213                                 request.Method = "GET";
214                                 HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
215                                 Assert.AreEqual ("", resp.ContentEncoding);
216                                 resp.Close ();
217                                 server.Stop ();
218                                 if (server.Error != null)
219                                         throw server.Error;
220                         } finally {
221                                 ServicePointManager.CertificatePolicy = null;
222                         }
223                 }
224
225                 [Test]
226 #if TARGET_JVM
227                 [Category ("NotWorking")]
228 #endif
229                 public void BadServer_ChunkedClose ()
230                 {
231                         // The server will send a chunked response without a 'last-chunked' mark
232                         // and then shutdown the socket for sending.
233                         BadChunkedServer server = new BadChunkedServer ();
234                         server.Start ();
235                         string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
236                         HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
237                         HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
238                         string x = null;
239                         try {
240                                 byte [] bytes = new byte [32];
241                                 // Using StreamReader+UTF8Encoding here fails on MS runtime
242                                 Stream stream = resp.GetResponseStream ();
243                                 int nread = stream.Read (bytes, 0, 32);
244                                 Assert.AreEqual (16, nread, "#01");
245                                 x = Encoding.ASCII.GetString (bytes, 0, 16);
246                         } finally {
247                                 resp.Close ();
248                                 server.Stop ();
249                         }
250
251                         if (server.Error != null)
252                                 throw server.Error;
253
254                         Assert.AreEqual ("1234567890123456", x);
255                 }
256
257                 [Test]
258                 [Ignore ("This test asserts that our code violates RFC 2616")]
259                 public void MethodCase ()
260                 {
261                         ListDictionary methods = new ListDictionary ();
262 #if NET_2_0
263                         methods.Add ("post", "POST");
264                         methods.Add ("puT", "PUT");
265 #else
266                         methods.Add ("post", "post");
267                         methods.Add ("puT", "puT");
268 #endif
269                         methods.Add ("POST", "POST");
270                         methods.Add ("whatever", "whatever");
271                         methods.Add ("PUT", "PUT");
272
273                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
274                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
275
276                         foreach (DictionaryEntry de in methods) {
277                                 SocketResponder responder = new SocketResponder (new IPEndPoint (IPAddress.Loopback, 8000), 
278                                         new SocketRequestHandler (EchoRequestHandler));
279                                 responder.Start ();
280
281                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
282                                 req.Method = (string) de.Key;
283                                 req.Timeout = 2000;
284                                 req.ReadWriteTimeout = 2000;
285                                 req.KeepAlive = false;
286                                 Stream rs = req.GetRequestStream ();
287                                 rs.Close ();
288                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
289                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
290                                                 Encoding.UTF8);
291                                         string line = sr.ReadLine ();
292                                         sr.Close ();
293                                         Assert.AreEqual (((string) de.Value) + " /test/ HTTP/1.1",
294                                                 line, req.Method);
295                                         resp.Close ();
296                                 }
297                                 responder.Stop ();
298                         }
299                 }
300
301                 [Test]
302                 public void BeginGetRequestStream_Body_NotAllowed ()
303                 {
304                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
305                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
306
307                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
308                                 responder.Start ();
309
310                                 HttpWebRequest request;
311
312                                 request = (HttpWebRequest) WebRequest.Create (url);
313                                 request.Method = "GET";
314
315                                 try {
316                                         request.BeginGetRequestStream (null, null);
317                                         Assert.Fail ("#A1");
318                                 } catch (ProtocolViolationException ex) {
319                                         // Cannot send a content-body with this
320                                         // verb-type
321                                         Assert.IsNull (ex.InnerException, "#A2");
322                                         Assert.IsNotNull (ex.Message, "#A3");
323                                 }
324
325                                 request = (HttpWebRequest) WebRequest.Create (url);
326                                 request.Method = "HEAD";
327
328                                 try {
329                                         request.BeginGetRequestStream (null, null);
330                                         Assert.Fail ("#B1");
331                                 } catch (ProtocolViolationException ex) {
332                                         // Cannot send a content-body with this
333                                         // verb-type
334                                         Assert.IsNull (ex.InnerException, "#B2");
335                                         Assert.IsNotNull (ex.Message, "#B3");
336                                 }
337                         }
338                 }
339
340                 [Test] // bug #465613
341                 public void BeginGetRequestStream_NoBuffering ()
342                 {
343                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8002);
344                         string url = "http://" + IPAddress.Loopback.ToString () + ":8002/test/";
345
346                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
347                                 responder.Start ();
348
349                                 HttpWebRequest req;
350                                 Stream rs;
351                                 IAsyncResult ar;
352
353                                 req = (HttpWebRequest) WebRequest.Create (url);
354                                 req.Method = "POST";
355                                 req.SendChunked = false;
356                                 req.KeepAlive = false;
357                                 req.AllowWriteStreamBuffering = false;
358
359                                 ar = req.BeginGetRequestStream (null, null);
360                                 rs = req.EndGetRequestStream (ar);
361                                 rs.Close ();
362
363                                 req = (HttpWebRequest) WebRequest.Create (url);
364                                 req.Method = "POST";
365                                 req.SendChunked = false;
366                                 req.KeepAlive = true;
367                                 req.AllowWriteStreamBuffering = false;
368
369                                 try {
370                                         req.BeginGetRequestStream (null, null);
371                                         Assert.Fail ("#A1");
372                                 } catch (ProtocolViolationException ex) {
373                                         // When performing a write operation with
374                                         // AllowWriteStreamBuffering set to false,
375                                         // you must either set ContentLength to a
376                                         // non-negative number or set SendChunked
377                                         // to true
378                                         Assert.IsNull (ex.InnerException, "#A2");
379                                         Assert.IsNotNull (ex.Message, "#A3");
380                                 }
381
382                                 req = (HttpWebRequest) WebRequest.Create (url);
383                                 req.Method = "POST";
384                                 req.SendChunked = false;
385                                 req.KeepAlive = true;
386                                 req.AllowWriteStreamBuffering = false;
387                                 req.ContentLength = 0;
388
389                                 ar = req.BeginGetRequestStream (null, null);
390                                 rs = req.EndGetRequestStream (ar);
391                                 rs.Close ();
392                         }
393                 }
394
395                 [Test] // bug #508027
396                 public void BeginGetResponse ()
397                 {
398                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8003);
399                         string url = "http://" + IPAddress.Loopback.ToString () + ":8003/test/";
400
401                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
402                                 responder.Start ();
403
404                                 HttpWebRequest req;
405
406                                 req = (HttpWebRequest) WebRequest.Create (url);
407                                 req.Method = "POST";
408                                 req.SendChunked = false;
409                                 req.KeepAlive = false;
410                                 req.AllowWriteStreamBuffering = false;
411                                 req.BeginGetResponse (null, null);
412                                 req.Abort ();
413
414                                 req = (HttpWebRequest) WebRequest.Create (url);
415                                 req.Method = "POST";
416                                 req.SendChunked = true;
417                                 req.KeepAlive = false;
418                                 req.AllowWriteStreamBuffering = false;
419                                 req.BeginGetResponse (null, null);
420                                 req.Abort ();
421
422                                 req = (HttpWebRequest) WebRequest.Create (url);
423                                 req.Method = "POST";
424                                 req.ContentLength = 5;
425                                 req.SendChunked = false;
426                                 req.KeepAlive = false;
427                                 req.AllowWriteStreamBuffering = false;
428                                 req.BeginGetResponse (null, null);
429                                 req.Abort ();
430
431                                 req = (HttpWebRequest) WebRequest.Create (url);
432                                 req.Method = "POST";
433                                 req.SendChunked = false;
434                                 req.KeepAlive = true;
435                                 req.AllowWriteStreamBuffering = false;
436 #if NET_2_0
437                                 req.BeginGetResponse (null, null);
438                                 req.Abort ();
439 #else
440                                 try {
441                                         req.BeginGetResponse (null, null);
442                                 } catch (ProtocolViolationException ex) {
443                                         // Either ContentLength must be set to a non-negative
444                                         // number, or SendChunked set to true in order to perform
445                                         // the write operation when AllowWriteStreamBuffering
446                                         // is disabled
447                                         Assert.IsNull (ex.InnerException, "#A2");
448                                         Assert.IsNotNull (ex.Message, "#A3");
449                                 } finally {
450                                         req.Abort ();
451                                 }
452 #endif
453
454                                 req = (HttpWebRequest) WebRequest.Create (url);
455                                 req.Method = "POST";
456                                 req.SendChunked = false;
457                                 req.KeepAlive = false;
458                                 req.AllowWriteStreamBuffering = false;
459                                 req.ContentLength = 5;
460                                 req.BeginGetResponse (null, null);
461                                 req.Abort ();
462
463                                 req = (HttpWebRequest) WebRequest.Create (url);
464                                 req.Method = "POST";
465                                 req.SendChunked = false;
466                                 req.KeepAlive = true;
467                                 req.AllowWriteStreamBuffering = false;
468                                 req.ContentLength = 5;
469                                 req.BeginGetResponse (null, null);
470                                 req.Abort ();
471
472                                 req = (HttpWebRequest) WebRequest.Create (url);
473                                 req.Method = "GET";
474                                 req.SendChunked = true;
475 #if NET_2_0
476                                 req.BeginGetResponse (null, null);
477                                 req.Abort ();
478 #else
479                                 try {
480                                         req.BeginGetResponse (null, null);
481                                         Assert.Fail ("#B1");
482                                 } catch (ProtocolViolationException ex) {
483                                         // Content-Length cannot be set for a
484                                         // non-write operation
485                                         Assert.IsNull (ex.InnerException, "#B2");
486                                         Assert.IsNotNull (ex.Message, "#B3");
487                                 } finally {
488                                         req.Abort ();
489                                 }
490 #endif
491
492                                 req = (HttpWebRequest) WebRequest.Create (url);
493                                 req.Method = "GET";
494                                 req.ContentLength = 5;
495 #if NET_2_0
496                                 req.BeginGetResponse (null, null);
497                                 req.Abort ();
498 #else
499                                 try {
500                                         req.BeginGetResponse (null, null);
501                                         Assert.Fail ("#C1");
502                                 } catch (ProtocolViolationException ex) {
503                                         // Content-Length cannot be set for a
504                                         // non-write operation
505                                         Assert.IsNull (ex.InnerException, "#C2");
506                                         Assert.IsNotNull (ex.Message, "#C3");
507                                 } finally {
508                                         req.Abort ();
509                                 }
510 #endif
511
512                                 req = (HttpWebRequest) WebRequest.Create (url);
513                                 req.Method = "GET";
514                                 req.ContentLength = 0;
515 #if NET_2_0
516                                 req.BeginGetResponse (null, null);
517                                 req.Abort ();
518 #else
519                                 try {
520                                         req.BeginGetResponse (null, null);
521                                         Assert.Fail ("#D1");
522                                 } catch (ProtocolViolationException ex) {
523                                         // Content-Length cannot be set for a
524                                         // non-write operation
525                                         Assert.IsNull (ex.InnerException, "#D2");
526                                         Assert.IsNotNull (ex.Message, "#D3");
527                                 } finally {
528                                         req.Abort ();
529                                 }
530 #endif
531                         }
532                 }
533
534                 [Test] // bug #429200
535                 public void GetRequestStream ()
536                 {
537                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
538                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
539
540                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
541                                 responder.Start ();
542
543                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
544                                 req.Method = "POST";
545                                 req.Timeout = 2000;
546                                 req.ReadWriteTimeout = 2000;
547
548                                 Stream rs1 = req.GetRequestStream ();
549                                 Stream rs2 = req.GetRequestStream ();
550
551                                 Assert.IsNotNull (rs1, "#1");
552                                 Assert.AreSame (rs1, rs2, "#2");
553
554                                 rs1.Close ();
555                         }
556                 }
557
558                 [Test] // bug #510661 and #514996
559                 [Category ("NotWorking")]
560                 public void GetRequestStream_Close_NotAllBytesWritten ()
561                 {
562                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
563                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
564
565                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
566                                 responder.Start ();
567
568                                 HttpWebRequest req;
569                                 Stream rs;
570
571                                 req = (HttpWebRequest) WebRequest.Create (url);
572                                 req.Method = "POST";
573                                 req.ContentLength = 2;
574                                 rs = req.GetRequestStream ();
575                                 try {
576                                         rs.Close ();
577                                         Assert.Fail ("#A1");
578                                 } catch (WebException ex) {
579                                         // The request was aborted: The request was canceled
580                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
581                                         Assert.IsNotNull (ex.Message, "#A3");
582                                         Assert.IsNull (ex.Response, "#A4");
583                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#A5");
584
585                                         // Cannot close stream until all bytes are written
586                                         Exception inner = ex.InnerException;
587                                         Assert.IsNotNull (inner, "#A6");
588                                         Assert.AreEqual (typeof (IOException), inner.GetType (), "#A7");
589                                         Assert.IsNull (inner.InnerException, "#A8");
590                                         Assert.IsNotNull (inner.Message, "#A9");
591                                 }
592
593                                 req = (HttpWebRequest) WebRequest.Create (url);
594                                 req.Method = "POST";
595                                 req.ContentLength = 2;
596                                 rs = req.GetRequestStream ();
597                                 rs.WriteByte (0x0d);
598                                 try {
599                                         rs.Close ();
600                                         Assert.Fail ("#B1");
601                                 } catch (WebException ex) {
602                                         // The request was aborted: The request was canceled
603                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
604                                         Assert.IsNotNull (ex.Message, "#B3");
605                                         Assert.IsNull (ex.Response, "#B4");
606                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#B5");
607
608                                         // Cannot close stream until all bytes are written
609                                         Exception inner = ex.InnerException;
610                                         Assert.IsNotNull (inner, "#B6");
611                                         Assert.AreEqual (typeof (IOException), inner.GetType (), "#B7");
612                                         Assert.IsNull (inner.InnerException, "#B8");
613                                         Assert.IsNotNull (inner.Message, "#B9");
614                                 }
615
616                                 req = (HttpWebRequest) WebRequest.Create (url);
617                                 req.Method = "POST";
618                                 req.ContentLength = 2;
619                                 rs = req.GetRequestStream ();
620                                 rs.WriteByte (0x0d);
621                                 rs.WriteByte (0x0d);
622                                 rs.Close ();
623                         }
624                 }
625
626                 [Test] // bug #510642
627                 public void GetRequestStream_Write_Overflow ()
628                 {
629                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8001);
630                         string url = "http://" + IPAddress.Loopback.ToString () + ":8001/test/";
631
632                         // buffered, non-chunked
633                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
634                                 responder.Start ();
635
636                                 HttpWebRequest req;
637                                 Stream rs;
638                                 byte [] buffer;
639
640                                 req = (HttpWebRequest) WebRequest.Create (url);
641                                 req.ProtocolVersion = HttpVersion.Version11;
642                                 req.Method = "POST";
643                                 req.Timeout = 1000;
644                                 req.ReadWriteTimeout = 2000;
645                                 req.ContentLength = 2;
646
647                                 rs = req.GetRequestStream ();
648                                 rs.WriteByte (0x2c);
649
650                                 buffer = new byte [] { 0x2a, 0x1d };
651                                 try {
652                                         rs.Write (buffer, 0, buffer.Length);
653                                         Assert.Fail ("#A1");
654                                 } catch (ProtocolViolationException ex) {
655                                         // Bytes to be written to the stream exceed
656                                         // Content-Length bytes size specified
657                                         Assert.IsNull (ex.InnerException, "#A2");
658                                         Assert.IsNotNull (ex.Message, "#A3");
659                                 } finally {
660                                         req.Abort ();
661                                 }
662
663                                 req = (HttpWebRequest) WebRequest.Create (url);
664                                 req.ProtocolVersion = HttpVersion.Version11;
665                                 req.Method = "POST";
666                                 req.Timeout = 1000;
667                                 req.ReadWriteTimeout = 2000;
668                                 req.ContentLength = 2;
669
670                                 rs = req.GetRequestStream ();
671
672                                 buffer = new byte [] { 0x2a, 0x2c, 0x1d };
673                                 try {
674                                         rs.Write (buffer, 0, buffer.Length);
675                                         Assert.Fail ("#B1");
676                                 } catch (ProtocolViolationException ex) {
677                                         // Bytes to be written to the stream exceed
678                                         // Content-Length bytes size specified
679                                         Assert.IsNull (ex.InnerException, "#B2");
680                                         Assert.IsNotNull (ex.Message, "#B3");
681                                 } finally {
682                                         req.Abort ();
683                                 }
684                         }
685
686                         // buffered, chunked
687                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
688                                 responder.Start ();
689
690                                 HttpWebRequest req;
691                                 Stream rs;
692                                 byte [] buffer;
693
694                                 /*
695                                 req = (HttpWebRequest) WebRequest.Create (url);
696                                 req.ProtocolVersion = HttpVersion.Version11;
697                                 req.Method = "POST";
698                                 req.SendChunked = true;
699                                 req.Timeout = 1000;
700                                 req.ReadWriteTimeout = 2000;
701                                 req.ContentLength = 2;
702
703                                 rs = req.GetRequestStream ();
704                                 rs.WriteByte (0x2c);
705
706                                 buffer = new byte [] { 0x2a, 0x1d };
707                                 rs.Write (buffer, 0, buffer.Length);
708                                 req.Abort ();
709                                 */
710
711                                 req = (HttpWebRequest) WebRequest.Create (url);
712                                 req.ProtocolVersion = HttpVersion.Version11;
713                                 req.Method = "POST";
714                                 req.SendChunked = true;
715                                 req.Timeout = 1000;
716                                 req.ReadWriteTimeout = 2000;
717                                 req.ContentLength = 2;
718
719                                 rs = req.GetRequestStream ();
720
721                                 buffer = new byte [] { 0x2a, 0x2c, 0x1d };
722                                 rs.Write (buffer, 0, buffer.Length);
723                                 req.Abort ();
724                         }
725
726                         // non-buffered, non-chunked
727                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
728                                 responder.Start ();
729
730                                 HttpWebRequest req;
731                                 Stream rs;
732                                 byte [] buffer;
733
734                                 req = (HttpWebRequest) WebRequest.Create (url);
735                                 req.AllowWriteStreamBuffering = false;
736                                 req.ProtocolVersion = HttpVersion.Version11;
737                                 req.Method = "POST";
738                                 req.Timeout = 1000;
739                                 req.ReadWriteTimeout = 2000;
740                                 req.ContentLength = 2;
741
742                                 rs = req.GetRequestStream ();
743                                 rs.WriteByte (0x2c);
744
745                                 buffer = new byte [] { 0x2a, 0x1d };
746                                 try {
747                                         rs.Write (buffer, 0, buffer.Length);
748                                         Assert.Fail ("#C1");
749                                 } catch (ProtocolViolationException ex) {
750                                         // Bytes to be written to the stream exceed
751                                         // Content-Length bytes size specified
752                                         Assert.IsNull (ex.InnerException, "#C2");
753                                         Assert.IsNotNull (ex.Message, "#3");
754                                 } finally {
755                                         req.Abort ();
756                                 }
757
758                                 req = (HttpWebRequest) WebRequest.Create (url);
759                                 req.AllowWriteStreamBuffering = false;
760                                 req.ProtocolVersion = HttpVersion.Version11;
761                                 req.Method = "POST";
762                                 req.Timeout = 1000;
763                                 req.ReadWriteTimeout = 2000;
764                                 req.ContentLength = 2;
765
766                                 rs = req.GetRequestStream ();
767
768                                 buffer = new byte [] { 0x2a, 0x2c, 0x1d };
769                                 try {
770                                         rs.Write (buffer, 0, buffer.Length);
771                                         Assert.Fail ("#D1");
772                                 } catch (ProtocolViolationException ex) {
773                                         // Bytes to be written to the stream exceed
774                                         // Content-Length bytes size specified
775                                         Assert.IsNull (ex.InnerException, "#D2");
776                                         Assert.IsNotNull (ex.Message, "#D3");
777                                 } finally {
778                                         req.Abort ();
779                                 }
780                         }
781
782                         // non-buffered, chunked
783                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
784                                 responder.Start ();
785
786                                 HttpWebRequest req;
787                                 Stream rs;
788                                 byte [] buffer;
789
790                                 req = (HttpWebRequest) WebRequest.Create (url);
791                                 req.AllowWriteStreamBuffering = false;
792                                 req.ProtocolVersion = HttpVersion.Version11;
793                                 req.Method = "POST";
794                                 req.SendChunked = true;
795                                 req.Timeout = 1000;
796                                 req.ReadWriteTimeout = 2000;
797                                 req.ContentLength = 2;
798
799                                 rs = req.GetRequestStream ();
800                                 rs.WriteByte (0x2c);
801
802                                 buffer = new byte [] { 0x2a, 0x1d };
803                                 rs.Write (buffer, 0, buffer.Length);
804                                 req.Abort ();
805
806                                 req = (HttpWebRequest) WebRequest.Create (url);
807                                 req.AllowWriteStreamBuffering = false;
808                                 req.ProtocolVersion = HttpVersion.Version11;
809                                 req.Method = "POST";
810                                 req.SendChunked = true;
811                                 req.Timeout = 1000;
812                                 req.ReadWriteTimeout = 2000;
813                                 req.ContentLength = 2;
814
815                                 rs = req.GetRequestStream ();
816
817                                 buffer = new byte [] { 0x2a, 0x2c, 0x1d };
818                                 rs.Write (buffer, 0, buffer.Length);
819                                 req.Abort ();
820                         }
821                 }
822
823                 [Test]
824                 [Ignore ("This test asserts that our code violates RFC 2616")]
825                 public void GetRequestStream_Body_NotAllowed ()
826                 {
827                         string [] methods = new string [] { "GET", "HEAD", "CONNECT",
828                                 "get", "HeAd", "ConNect" };
829
830                         foreach (string method in methods) {
831                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (
832                                         "http://localhost:8000");
833                                 req.Method = method;
834                                 try {
835                                         req.GetRequestStream ();
836                                         Assert.Fail ("#1:" + method);
837                                 } catch (ProtocolViolationException ex) {
838                                         Assert.AreEqual (typeof (ProtocolViolationException), ex.GetType (), "#2:" + method);
839                                         Assert.IsNull (ex.InnerException, "#3:" + method);
840                                         Assert.IsNotNull (ex.Message, "#4:" + method);
841                                 }
842                         }
843                 }
844
845                 [Test]
846 #if TARGET_JVM
847                 [Category("NotWorking")]
848 #endif
849                 [Ignore ("This does not timeout any more. That's how MS works when reading small responses")]
850                 public void ReadTimeout ()
851                 {
852                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
853                         string url = "http://" + localEP.ToString () + "/original/";
854
855                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
856                                 responder.Start ();
857
858                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
859                                 req.Method = "POST";
860                                 req.AllowAutoRedirect = false;
861                                 req.Timeout = 200;
862                                 req.ReadWriteTimeout = 2000;
863                                 req.KeepAlive = false;
864                                 Stream rs = req.GetRequestStream ();
865                                 rs.Close ();
866                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
867                                         try {
868                                                 Stream s = resp.GetResponseStream ();
869                                                 s.ReadByte ();
870                                                 Assert.Fail ("#1");
871                                         } catch (WebException ex) {
872                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
873                                                 Assert.IsNull (ex.InnerException, "#3");
874                                                 Assert.IsNull (ex.Response, "#4");
875                                                 Assert.AreEqual (WebExceptionStatus.Timeout, ex.Status, "#5");
876                                         }
877                                 }
878                                 responder.Stop ();
879                         }
880                 }
881
882                 [Test] // bug #324300
883 #if TARGET_JVM
884                 [Category("NotWorking")]
885 #endif
886                 public void AllowAutoRedirect ()
887                 {
888                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
889                         string url = "http://" + localEP.ToString () + "/original/";
890
891                         // allow autoredirect
892                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
893                                 responder.Start ();
894
895                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
896                                 req.Method = "POST";
897                                 req.Timeout = 2000;
898                                 req.ReadWriteTimeout = 2000;
899                                 req.KeepAlive = false;
900                                 Stream rs = req.GetRequestStream ();
901                                 rs.Close ();
902                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
903                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
904                                                 Encoding.UTF8);
905                                         string body = sr.ReadToEnd ();
906
907                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#A1");
908                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
909                                                 localEP.ToString () + "/moved/", "#A2");
910                                         Assert.AreEqual ("GET", resp.Method, "#A3");
911                                         Assert.AreEqual ("LOOKS OK", body, "#A4");
912                                 }
913                                 responder.Stop ();
914                         }
915
916                         // do not allow autoredirect
917                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
918                                 responder.Start ();
919
920                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
921                                 req.Method = "POST";
922                                 req.AllowAutoRedirect = false;
923                                 req.Timeout = 1000;
924                                 req.ReadWriteTimeout = 1000;
925                                 req.KeepAlive = false;
926                                 Stream rs = req.GetRequestStream ();
927                                 rs.Close ();
928                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
929                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.Found, "#B1");
930                                         Assert.AreEqual (url, resp.ResponseUri.ToString (), "#B2");
931                                         Assert.AreEqual ("POST", resp.Method, "#B3");
932                                 }
933                                 responder.Stop ();
934                         }
935                 }
936
937                 [Test] // bug #324347
938                 [Category ("NotWorking")]
939                 public void InternalServerError ()
940                 {
941                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
942                         string url = "http://" + localEP.ToString () + "/original/";
943
944                         // POST
945                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
946                                 responder.Start ();
947
948                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
949                                 req.Method = "POST";
950                                 req.Timeout = 2000;
951                                 req.ReadWriteTimeout = 2000;
952                                 req.KeepAlive = false;
953                                 Stream rs = req.GetRequestStream ();
954                                 rs.Close ();
955
956                                 try {
957                                         req.GetResponse ();
958                                         Assert.Fail ("#A1");
959                                 } catch (WebException ex) {
960                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
961                                         Assert.IsNull (ex.InnerException, "#A3");
962                                         Assert.IsNotNull (ex.Message, "#A4");
963                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A5");
964
965                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
966                                         Assert.IsNotNull (webResponse, "#A6");
967                                         Assert.AreEqual ("POST", webResponse.Method, "#A7");
968                                         webResponse.Close ();
969                                 }
970
971                                 responder.Stop ();
972                         }
973
974                         // GET
975                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
976                                 responder.Start ();
977
978                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
979                                 req.Method = "GET";
980                                 req.Timeout = 2000;
981                                 req.ReadWriteTimeout = 2000;
982                                 req.KeepAlive = false;
983
984                                 try {
985                                         req.GetResponse ();
986                                         Assert.Fail ("#B1");
987                                 } catch (WebException ex) {
988                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
989                                         Assert.IsNull (ex.InnerException, "#B3");
990                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
991
992                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
993                                         Assert.IsNotNull (webResponse, "#B5");
994                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
995                                         webResponse.Close ();
996                                 }
997
998                                 responder.Stop ();
999                         }
1000                 }
1001
1002                 [Test]
1003                 [Category ("NotWorking")] // #B3 fails; we get a SocketException: An existing connection was forcibly closed by the remote host
1004                 public void NoContentLength ()
1005                 {
1006                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
1007                         string url = "http://" + localEP.ToString () + "/original/";
1008
1009                         // POST
1010                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
1011                                 responder.Start ();
1012
1013                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1014                                 req.Method = "POST";
1015                                 req.Timeout = 2000;
1016                                 req.ReadWriteTimeout = 2000;
1017                                 req.KeepAlive = false;
1018                                 Stream rs = req.GetRequestStream ();
1019                                 rs.Close ();
1020
1021                                 try {
1022                                         req.GetResponse ();
1023                                         Assert.Fail ("#A1");
1024                                 } catch (WebException ex) {
1025 #if NET_2_0
1026                                         // The underlying connection was closed:
1027                                         // An unexpected error occurred on a
1028                                         // receive
1029                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
1030                                         Assert.IsNotNull (ex.InnerException, "#A3");
1031                                         Assert.AreEqual (WebExceptionStatus.ReceiveFailure, ex.Status, "#A4");
1032                                         Assert.AreEqual (typeof (IOException), ex.InnerException.GetType (), "#A5");
1033                                         
1034                                         // Unable to read data from the transport connection:
1035                                         // A connection attempt failed because the connected party
1036                                         // did not properly respond after a period of time, or
1037                                         // established connection failed because connected host has
1038                                         // failed to respond
1039                                         IOException ioe = (IOException) ex.InnerException;
1040                                         Assert.IsNotNull (ioe.InnerException, "#A6");
1041                                         Assert.IsNotNull (ioe.Message, "#A7");
1042                                         Assert.AreEqual (typeof (SocketException), ioe.InnerException.GetType (), "#A8");
1043
1044                                         // An existing connection was forcibly
1045                                         // closed by the remote host
1046                                         SocketException soe = (SocketException) ioe.InnerException;
1047                                         Assert.IsNull (soe.InnerException, "#A9");
1048                                         Assert.IsNotNull (soe.Message, "#A10");
1049
1050                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
1051                                         Assert.IsNull (webResponse, "#A11");
1052 #else
1053                                         // The remote server returned an error:
1054                                         // (500) Internal Server Error
1055                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
1056                                         Assert.IsNull (ex.InnerException, "#A3");
1057                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A4");
1058
1059                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
1060                                         Assert.IsNotNull (webResponse, "#A5");
1061                                         Assert.AreEqual ("POST", webResponse.Method, "#A6");
1062                                         webResponse.Close ();
1063 #endif
1064                                 }
1065
1066                                 responder.Stop ();
1067                         }
1068
1069                         // GET
1070                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
1071                                 responder.Start ();
1072
1073                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1074                                 req.Method = "GET";
1075                                 req.Timeout = 2000;
1076                                 req.ReadWriteTimeout = 2000;
1077                                 req.KeepAlive = false;
1078
1079                                 try {
1080                                         req.GetResponse ();
1081                                         Assert.Fail ("#B1");
1082                                 } catch (WebException ex) {
1083                                         // The remote server returned an error:
1084                                         // (500) Internal Server Error
1085                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
1086                                         Assert.IsNull (ex.InnerException, "#B3");
1087                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
1088
1089                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
1090                                         Assert.IsNotNull (webResponse, "#B5");
1091                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
1092                                         webResponse.Close ();
1093                                 }
1094
1095                                 responder.Stop ();
1096                         }
1097                 }
1098
1099                 [Test] // bug #513087
1100                 public void NonStandardVerb ()
1101                 {
1102                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
1103                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/moved/";
1104
1105                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (VerbEchoHandler))) {
1106                                 responder.Start ();
1107
1108                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1109                                 req.Method = "WhatEver";
1110                                 req.KeepAlive = false;
1111                                 req.Timeout = 20000;
1112                                 req.ReadWriteTimeout = 20000;
1113
1114                                 Stream rs = req.GetRequestStream ();
1115                                 rs.Close ();
1116
1117                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1118                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
1119                                                 Encoding.UTF8);
1120                                         string body = sr.ReadToEnd ();
1121
1122                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#1");
1123                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
1124                                                 ep.ToString () + "/moved/", "#2");
1125                                         Assert.AreEqual ("WhatEver", resp.Method, "#3");
1126                                         Assert.AreEqual ("WhatEver", body, "#4");
1127                                 }
1128
1129                                 responder.Stop ();
1130                         }
1131                 }
1132
1133                 [Test]
1134                 [Category ("NotWorking")] // Assert #2 fails
1135                 public void NotModifiedSince ()
1136                 {
1137                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
1138                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
1139
1140                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (NotModifiedSinceHandler))) {
1141                                 responder.Start ();
1142
1143                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1144                                 req.Method = "GET";
1145                                 req.KeepAlive = false;
1146                                 req.Timeout = 20000;
1147                                 req.ReadWriteTimeout = 20000;
1148 #if NET_2_0
1149                                 req.Headers.Add (HttpRequestHeader.IfNoneMatch, "898bbr2347056cc2e096afc66e104653");
1150 #else
1151                                 req.Headers.Add ("If-None-Match", "898bbr2347056cc2e096afc66e104653");
1152 #endif
1153                                 req.IfModifiedSince = new DateTime (2010, 01, 04);
1154
1155                                 DateTime start = DateTime.Now;
1156                                 HttpWebResponse response = null;
1157
1158                                 try {
1159                                         req.GetResponse ();
1160                                         Assert.Fail ("#1");
1161                                 } catch (WebException e) {
1162                                         response = (HttpWebResponse) e.Response;
1163                                 }
1164
1165                                 Assert.IsNotNull (response, "#2");
1166                                 using (Stream stream = response.GetResponseStream ()) {
1167                                         byte [] buffer = new byte [4096];
1168                                         int bytesRead = stream.Read (buffer, 0, buffer.Length);
1169                                         Assert.AreEqual (0, bytesRead, "#3");
1170                                 }
1171
1172                                 TimeSpan elapsed = DateTime.Now - start;
1173                                 Assert.IsTrue (elapsed.TotalMilliseconds < 2000, "#4");
1174
1175                                 responder.Stop ();
1176                         }
1177                 }
1178
1179 #if NET_2_0
1180                 [Test] // bug #324182
1181 #if TARGET_JVM
1182                 [Category ("NotWorking")]
1183 #endif
1184                 public void Stream_CanTimeout ()
1185                 {
1186                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
1187                         string url = "http://" + localEP.ToString () + "/original/";
1188
1189                         // allow autoredirect
1190                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
1191                                 responder.Start ();
1192
1193                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1194                                 req.Method = "POST";
1195                                 req.Timeout = 2000;
1196                                 req.ReadWriteTimeout = 2000;
1197                                 req.KeepAlive = false;
1198                                 Stream rs = req.GetRequestStream ();
1199                                 Assert.IsTrue (rs.CanTimeout, "#1");
1200                                 rs.Close ();
1201                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1202                                         Stream os = resp.GetResponseStream ();
1203                                         Assert.IsTrue (os.CanTimeout, "#2");
1204                                         os.Close ();
1205                                 }
1206                                 responder.Stop ();
1207                         }
1208                 }
1209 #endif
1210
1211                 [Test] // bug #353495
1212                 [Category ("NotWorking")]
1213                 public void LastModifiedKind ()
1214                 {
1215                         const string reqURL = "http://coffeefaq.com/site/node/25";
1216                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create (reqURL);
1217                         HttpWebResponse resp = (HttpWebResponse) req.GetResponse ();
1218                         DateTime lastMod = resp.LastModified;
1219                         string rawLastMod = resp.Headers ["Last-Modified"];
1220                         resp.Close ();
1221                         //Assert.AreEqual ("Tue, 15 Jan 2008 08:59:59 GMT", rawLastMod, "#1");
1222 #if NET_2_0
1223                         Assert.AreEqual (DateTimeKind.Local, lastMod.Kind, "#2");
1224 #endif
1225                         req = (HttpWebRequest) WebRequest.Create (reqURL);
1226                         req.IfModifiedSince = lastMod;
1227                         try {
1228                                 resp = (HttpWebResponse) req.GetResponse ();
1229                                 resp.Close ();
1230                                 Assert.Fail ("Should result in 304");
1231                         } catch (WebException ex) {
1232                                 Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#3");
1233                                 Assert.AreEqual (((HttpWebResponse) ex.Response).StatusCode, HttpStatusCode.NotModified, "#4");
1234                         }
1235                 }
1236
1237                 static byte [] EchoRequestHandler (Socket socket)
1238                 {
1239                         MemoryStream ms = new MemoryStream ();
1240                         byte [] buffer = new byte [4096];
1241                         int bytesReceived = socket.Receive (buffer);
1242                         while (bytesReceived > 0) {
1243                                 ms.Write (buffer, 0, bytesReceived);
1244                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1245                                  // after sending the headers
1246                                 Thread.Sleep (200);
1247                                 if (socket.Available > 0) {
1248                                         bytesReceived = socket.Receive (buffer);
1249                                 } else {
1250                                         bytesReceived = 0;
1251                                 }
1252                         }
1253                         ms.Flush ();
1254                         ms.Position = 0;
1255                         StreamReader sr = new StreamReader (ms, Encoding.UTF8);
1256                         string request = sr.ReadToEnd ();
1257
1258                         StringWriter sw = new StringWriter ();
1259                         sw.WriteLine ("HTTP/1.1 200 OK");
1260                         sw.WriteLine ("Content-Type: text/xml");
1261                         sw.WriteLine ("Content-Length: " + request.Length.ToString (CultureInfo.InvariantCulture));
1262                         sw.WriteLine ();
1263                         sw.Write (request);
1264                         sw.Flush ();
1265
1266                         return Encoding.UTF8.GetBytes (sw.ToString ());
1267                 }
1268
1269                 static byte [] RedirectRequestHandler (Socket socket)
1270                 {
1271                         MemoryStream ms = new MemoryStream ();
1272                         byte [] buffer = new byte [4096];
1273                         int bytesReceived = socket.Receive (buffer);
1274                         while (bytesReceived > 0) {
1275                                 ms.Write (buffer, 0, bytesReceived);
1276                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1277                                  // after sending the headers
1278                                 Thread.Sleep (200);
1279                                 if (socket.Available > 0) {
1280                                         bytesReceived = socket.Receive (buffer);
1281                                 } else {
1282                                         bytesReceived = 0;
1283                                 }
1284                         }
1285                         ms.Flush ();
1286                         ms.Position = 0;
1287                         string statusLine = null;
1288                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1289                                 statusLine = sr.ReadLine ();
1290                         }
1291
1292                         StringWriter sw = new StringWriter ();
1293                         if (statusLine.StartsWith ("POST /original/")) {
1294                                 sw.WriteLine ("HTTP/1.0 302 Found");
1295                                 sw.WriteLine ("Location: " + "http://" + IPAddress.Loopback.ToString () + ":8764/moved/");
1296                                 sw.WriteLine ();
1297                                 sw.Flush ();
1298                         } else if (statusLine.StartsWith ("GET /moved/")) {
1299                                 sw.WriteLine ("HTTP/1.0 200 OK");
1300                                 sw.WriteLine ("Content-Type: text/plain");
1301                                 sw.WriteLine ("Content-Length: 8");
1302                                 sw.WriteLine ();
1303                                 sw.Write ("LOOKS OK");
1304                                 sw.Flush ();
1305                         } else {
1306                                 sw.WriteLine ("HTTP/1.0 500 Too Lazy");
1307                                 sw.WriteLine ();
1308                                 sw.Flush ();
1309                         }
1310
1311                         return Encoding.UTF8.GetBytes (sw.ToString ());
1312                 }
1313
1314                 static byte [] InternalErrorHandler (Socket socket)
1315                 {
1316                         StringWriter sw = new StringWriter ();
1317                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
1318                         sw.WriteLine ("Content-Length: 0");
1319                         sw.WriteLine ();
1320                         sw.Flush ();
1321
1322                         return Encoding.UTF8.GetBytes (sw.ToString ());
1323                 }
1324
1325                 static byte [] NoContentLengthHandler (Socket socket)
1326                 {
1327                         StringWriter sw = new StringWriter ();
1328                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
1329                         sw.WriteLine ();
1330                         sw.Flush ();
1331
1332                         return Encoding.UTF8.GetBytes (sw.ToString ());
1333                 }
1334
1335                 static byte [] NotModifiedSinceHandler (Socket socket)
1336                 {
1337                         StringWriter sw = new StringWriter ();
1338                         sw.WriteLine ("HTTP/1.1 304 Not Modified");
1339                         sw.WriteLine ("Date: Fri, 06 Feb 2009 12:50:26 GMT");
1340                         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");
1341                         sw.WriteLine ("Not-Modified-Since: Sun, 08 Feb 2009 08:49:26 GMT");
1342                         sw.WriteLine ("ETag: 898bbr2347056cc2e096afc66e104653");
1343                         sw.WriteLine ("Connection: close");
1344                         sw.WriteLine ();
1345                         sw.Flush ();
1346
1347                         return Encoding.UTF8.GetBytes (sw.ToString ());
1348                 }
1349
1350                 static byte [] VerbEchoHandler (Socket socket)
1351                 {
1352                         MemoryStream ms = new MemoryStream ();
1353                         byte [] buffer = new byte [4096];
1354                         int bytesReceived = socket.Receive (buffer);
1355                         while (bytesReceived > 0) {
1356                                 ms.Write (buffer, 0, bytesReceived);
1357                                  // We don't check for Content-Length or anything else here, so we give the client a little time to write
1358                                  // after sending the headers
1359                                 Thread.Sleep (200);
1360                                 if (socket.Available > 0) {
1361                                         bytesReceived = socket.Receive (buffer);
1362                                 } else {
1363                                         bytesReceived = 0;
1364                                 }
1365                         }
1366                         ms.Flush ();
1367                         ms.Position = 0;
1368                         string statusLine = null;
1369                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1370                                 statusLine = sr.ReadLine ();
1371                         }
1372
1373                         string verb = "DEFAULT";
1374                         if (statusLine != null) {
1375                                 string [] parts = statusLine.Split (' ');
1376                                 if (parts.Length > 0)
1377                                         verb = parts [0];
1378                         }
1379
1380                         StringWriter sw = new StringWriter ();
1381                         sw.WriteLine ("HTTP/1.1 200 OK");
1382                         sw.WriteLine ("Content-Type: text/plain");
1383                         sw.WriteLine ("Content-Length: " + verb.Length);
1384                         sw.WriteLine ();
1385                         sw.Write (verb);
1386                         sw.Flush ();
1387
1388                         return Encoding.UTF8.GetBytes (sw.ToString ());
1389                 }
1390
1391                 [Test]
1392                 public void NtlmAuthentication ()
1393                 {
1394                         NtlmServer server = new NtlmServer ();
1395                         server.Start ();
1396
1397                         string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
1398                         HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
1399                         request.Timeout = 5000;
1400                         request.Credentials = new NetworkCredential ("user", "password", "domain");
1401                         HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
1402                         string res = null;
1403                         using (StreamReader reader = new StreamReader (resp.GetResponseStream ())) {
1404                                 res = reader.ReadToEnd ();      
1405                         }
1406                         resp.Close ();
1407                         server.Stop ();
1408                         Assert.AreEqual ("OK", res);
1409                 }
1410
1411                 class NtlmServer : HttpServer {
1412                         public string Where = "";
1413                         protected override void Run ()
1414                         {
1415                                 Where = "before accept";
1416                                 Socket client = sock.Accept ();
1417                                 NetworkStream ns = new NetworkStream (client, false);
1418                                 StreamReader reader = new StreamReader (ns, Encoding.ASCII);
1419                                 string line;
1420                                 Where = "first read";
1421                                 while ((line = reader.ReadLine ()) != null) {
1422                                         if (line.Trim () == String.Empty) {
1423                                                 break;
1424                                         }
1425                                 }
1426                                 Where = "first write";
1427                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
1428                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
1429                                                 "WWW-Authenticate: NTLM\r\n" +
1430                                                 "Content-Length: 5\r\n\r\nWRONG");
1431
1432                                 writer.Flush ();
1433                                 Where = "second read";
1434                                 while ((line = reader.ReadLine ()) != null) {
1435                                         if (line.Trim () == String.Empty) {
1436                                                 break;
1437                                         }
1438                                 }
1439                                 Where = "second write";
1440                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
1441                                                 "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAADgAAAABggAC8GDhqIONH3sAAAAAAAAAAAAAAAA4AAAABQLODgAAAA8=\r\n" +
1442                                                 "Content-Length: 5\r\n\r\nWRONG");
1443                                 writer.Flush ();
1444
1445                                 Where = "third read";
1446                                 while ((line = reader.ReadLine ()) != null) {
1447                                         if (line.Trim () == String.Empty) {
1448                                                 break;
1449                                         }
1450                                 }
1451                                 Where = "third write";
1452                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
1453                                                 "Keep-Alive: true\r\n" +
1454                                                 "Content-Length: 2\r\n\r\nOK");
1455                                 writer.Flush ();
1456                                 Thread.Sleep (1000);
1457                                 writer.Close ();
1458                                 reader.Close ();
1459                                 client.Close ();
1460                         }
1461                 }
1462
1463                 class BadChunkedServer : HttpServer {
1464                         protected override void Run ()
1465                         {
1466                                 Socket client = sock.Accept ();
1467                                 NetworkStream ns = new NetworkStream (client, true);
1468                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
1469                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
1470                                                 "Transfer-Encoding: chunked\r\n" +
1471                                                 "Connection: close\r\n" +
1472                                                 "Content-Type: text/plain; charset=UTF-8\r\n\r\n");
1473
1474                                 // This body lacks a 'last-chunk' (see RFC 2616)
1475                                 writer.Write ("10\r\n1234567890123456\r\n");
1476                                 writer.Flush ();
1477                                 client.Shutdown (SocketShutdown.Send);
1478                                 Thread.Sleep (1000);
1479                                 writer.Close ();
1480                         }
1481                 }
1482
1483                 class AcceptAllPolicy : ICertificatePolicy {
1484                         public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
1485                         {
1486                                 return true;
1487                         }
1488                 }
1489
1490                 abstract class HttpServer
1491                 {
1492                         protected Socket sock;
1493                         protected Exception error;
1494                         protected ManualResetEvent evt;
1495
1496                         public HttpServer ()
1497                         {
1498                                 sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
1499                                 sock.Bind (new IPEndPoint (IPAddress.Loopback, 0));
1500                                 sock.Listen (1);
1501                         }
1502
1503                         public void Start ()
1504                         {
1505                                 evt = new ManualResetEvent (false);
1506                                 Thread th = new Thread (new ThreadStart (Run));
1507                                 th.Start ();
1508                         }
1509
1510                         public void Stop ()
1511                         {
1512                                 evt.Set ();
1513                                 sock.Close ();
1514                         }
1515                         
1516                         public IPAddress IPAddress {
1517                                 get { return ((IPEndPoint) sock.LocalEndPoint).Address; }
1518                         }
1519                         
1520                         public int Port {
1521                                 get { return ((IPEndPoint) sock.LocalEndPoint).Port; }
1522                         }
1523
1524                         public Exception Error { 
1525                                 get { return error; }
1526                         }
1527
1528                         protected abstract void Run ();
1529                 }
1530
1531 #if NET_2_0
1532                 [Test]
1533                 public void BeginGetRequestStream()
1534                 {
1535                     this.DoRequest(
1536                         (r, c) =>
1537                         {
1538                             r.Method = "POST";
1539                             r.ContentLength = 0;
1540                             r.BeginGetRequestStream((a) =>
1541                             {
1542                                 using (Stream s = r.EndGetRequestStream(a)) { };
1543                                 c.Set();
1544                             },
1545                                 null);
1546                         },
1547                         (c) => { });
1548                 }
1549
1550                 [Test]
1551                 public void BeginGetRequestStreamNoClose()
1552                 {
1553                     this.DoRequest(
1554                         (r, c) => {
1555                             r.Method = "POST";
1556                             r.ContentLength = 1;
1557                             r.BeginGetRequestStream((a) => 
1558                                 {
1559                                     r.EndGetRequestStream(a);
1560                                     c.Set();
1561                                 }, 
1562                                 null);
1563                         },
1564                         (c) => {});
1565                 }
1566
1567                 [Test]
1568                 public void BeginGetRequestStreamCancelIfNotAllBytesWritten()
1569                 {
1570                     this.DoRequest(
1571                         (r, c) =>
1572                         {
1573                             r.Method = "POST";
1574                             r.ContentLength = 10;
1575                             r.BeginGetRequestStream((a) =>
1576                             {
1577                                 WebException ex = ExceptionAssert.Throws<WebException>(() =>
1578                                     { using (Stream s = r.EndGetRequestStream(a)) { }; }
1579                                 );
1580                                 Assert.AreEqual(ex.Status, WebExceptionStatus.RequestCanceled);
1581                                 c.Set();
1582                             },
1583                                 null);
1584                         },
1585                         (c) => { });
1586                 }
1587
1588                 [Test]
1589                 public void GetRequestStream2()
1590                 {
1591                     this.DoRequest(
1592                         (r, c) =>
1593                         {
1594                             r.Method = "POST";
1595                             r.ContentLength = data64KB.Length;
1596                             using (Stream s = r.GetRequestStream())
1597                             {
1598                                 s.Write(data64KB, 0, data64KB.Length);
1599                             }
1600                             c.Set();
1601                         },
1602                         (c) => { });
1603                 }
1604
1605                 [Test]
1606                 public void GetRequestStreamNotAllBytesWritten()
1607                 {
1608                     this.DoRequest(
1609                         (r, c) =>
1610                         {
1611                             r.Method = "POST";
1612                             r.ContentLength = data64KB.Length;
1613                             WebException ex = ExceptionAssert.Throws<WebException>(() => r.GetRequestStream().Close());
1614                             Assert.AreEqual(ex.Status, WebExceptionStatus.RequestCanceled);
1615                             c.Set();
1616                         },
1617                         (c) => {});
1618                 }
1619
1620                 [Test]
1621                 public void GetRequestStreamTimeout()
1622                 {
1623                     this.DoRequest(
1624                         (r, c) =>
1625                         {
1626                             r.Method = "POST";
1627                             r.ContentLength = data64KB.Length;
1628                             r.Timeout = 100;
1629                             WebException ex = ExceptionAssert.Throws<WebException>(() => r.GetRequestStream());
1630                             Assert.IsTrue(ex.Status == WebExceptionStatus.Timeout || ex.Status == WebExceptionStatus.ConnectFailure);
1631                             c.Set();
1632                         });
1633                 }
1634
1635                 [Test]
1636                 public void BeginWrite()
1637                 {
1638                     byte[] received = new byte[data64KB.Length];
1639
1640                     this.DoRequest(
1641                         (r, c) =>
1642                         {
1643                             r.Method = "POST";
1644                             r.ContentLength = data64KB.Length;
1645                             
1646                             Stream s = r.GetRequestStream();
1647
1648                             s.BeginWrite(data64KB, 0, data64KB.Length, 
1649                                 (a) =>
1650                                 {
1651                                     s.EndWrite(a);
1652                                     s.Close();
1653                                     r.GetResponse().Close();
1654                                     c.Set();
1655                                 },
1656                                 null);
1657                         },
1658                         (c) => 
1659                         {
1660                             c.Request.InputStream.ReadAll(received, 0, received.Length);
1661                             c.Response.StatusCode = 204;
1662                             c.Response.Close();
1663                         });
1664
1665                     Assert.AreEqual(data64KB, received);
1666                 }
1667
1668                 [Test]
1669                 public void BeginWriteAfterAbort()
1670                 {
1671                     byte[] received = new byte[data64KB.Length];
1672
1673                     this.DoRequest(
1674                         (r, c) =>
1675                         {
1676                             r.Method = "POST";
1677                             r.ContentLength = data64KB.Length;
1678
1679                             Stream s = r.GetRequestStream();
1680
1681                             r.Abort();
1682
1683                             WebException ex = ExceptionAssert.Throws<WebException>(() => s.BeginWrite(data64KB, 0, data64KB.Length, null, null));
1684                             Assert.AreEqual(ex.Status, WebExceptionStatus.RequestCanceled);
1685
1686                             c.Set();
1687                         },
1688                         (c) =>
1689                         {
1690                             c.Request.InputStream.ReadAll(received, 0, received.Length);
1691                             c.Response.StatusCode = 204;
1692                             c.Response.Close();
1693                         });
1694                 }
1695
1696                 [Test]
1697                 public void PrematureStreamCloseAborts()
1698                 {
1699                     byte[] received = new byte[data64KB.Length];
1700
1701                     this.DoRequest(
1702                         (r, c) =>
1703                         {
1704                             r.Method = "POST";
1705                             r.ContentLength = data64KB.Length * 2;
1706
1707                             Stream s = r.GetRequestStream();
1708                             s.Write(data64KB, 0, data64KB.Length);
1709
1710                             WebException ex = ExceptionAssert.Throws<WebException>(() => s.Close());
1711                             Assert.AreEqual(ex.Status, WebExceptionStatus.RequestCanceled);
1712
1713                             c.Set();
1714                         },
1715                         (c) =>
1716                         {
1717                             c.Request.InputStream.ReadAll(received, 0, received.Length);
1718                             c.Response.StatusCode = 204;
1719                             c.Response.Close();
1720                         });
1721                 }
1722
1723                 [Test]
1724                 public void Write()
1725                 {
1726                     byte[] received = new byte[data64KB.Length];
1727
1728                     this.DoRequest(
1729                         (r, c) =>
1730                         {
1731                             r.Method = "POST";
1732                             r.ContentLength = data64KB.Length;
1733
1734                             using (Stream s = r.GetRequestStream())
1735                             {
1736                                 s.Write(data64KB, 0, data64KB.Length);
1737                             }
1738
1739                             r.GetResponse().Close();
1740                             c.Set();
1741                         },
1742                         (c) =>
1743                         {
1744                             c.Request.InputStream.ReadAll(received, 0, received.Length);
1745                             c.Response.StatusCode = 204;
1746                             c.Response.Close();
1747                         });
1748
1749                     Assert.AreEqual(data64KB, received);
1750                 }
1751
1752                 [Test]
1753                 public void WriteServerAborts()
1754                 {
1755                     ManualResetEvent abort = new ManualResetEvent(false);
1756                     byte[] received = new byte[data64KB.Length];
1757
1758                     this.DoRequest(
1759                         (r, c) =>
1760                         {
1761                             r.Method = "POST";
1762                             r.ContentLength = data64KB.Length;
1763
1764                             using (Stream s = r.GetRequestStream())
1765                             {
1766                                 abort.Set();
1767                                 Thread.Sleep(100);
1768                                 IOException ex = ExceptionAssert.Throws<IOException>(() => s.Write(data64KB, 0, data64KB.Length));
1769                             }
1770
1771                             c.Set();
1772                         },
1773                         (c) =>
1774                         {
1775                             abort.WaitOne();
1776                             c.Response.Abort();
1777                         });
1778                 }
1779
1780                 [Test]
1781                 public void Read()
1782                 {
1783                     byte[] received = new byte[data64KB.Length];
1784
1785                     this.DoRequest(
1786                         (r, c) =>
1787                         {
1788                             using (HttpWebResponse x = (HttpWebResponse)r.GetResponse())
1789                             using (Stream s = x.GetResponseStream())
1790                             {
1791                                 s.ReadAll(received, 0, received.Length);
1792                             }
1793
1794                             c.Set();
1795                         },
1796                         (c) =>
1797                         {
1798                             c.Response.StatusCode = 200;
1799                             c.Response.ContentLength64 = data64KB.Length;
1800                             c.Response.OutputStream.Write(data64KB, 0, data64KB.Length);
1801                             c.Response.OutputStream.Close();
1802                             c.Response.Close();
1803                         });
1804
1805                     Assert.AreEqual(data64KB, received);
1806                 }
1807
1808                 [Test]
1809                 public void ReadTimeout2()
1810                 {
1811                     byte[] received = new byte[data64KB.Length];
1812
1813                     this.DoRequest(
1814                         (r, c) =>
1815                         {
1816                             r.ReadWriteTimeout = 10;
1817                             using (HttpWebResponse x = (HttpWebResponse)r.GetResponse())
1818                             using (Stream s = x.GetResponseStream())
1819                             {
1820                                 WebException ex = ExceptionAssert.Throws<WebException>(
1821                                     () => s.ReadAll(received, 0, received.Length));
1822                                 Assert.AreEqual(ex.Status, WebExceptionStatus.Timeout);
1823                             }
1824
1825                             c.Set();
1826                         },
1827                         (c) =>
1828                         {
1829                             c.Response.StatusCode = 200;
1830                             c.Response.ContentLength64 = data64KB.Length;
1831                             c.Response.OutputStream.Write(data64KB, 0, data64KB.Length / 2);
1832                             Thread.Sleep(1000);
1833                             c.Response.OutputStream.Write(data64KB, data64KB.Length / 2, data64KB.Length / 2);
1834                             c.Response.OutputStream.Close();
1835                             c.Response.Close();
1836                         });
1837                 }
1838
1839                 [Test]
1840                 public void ReadServerAborted()
1841                 {
1842                     byte[] received = new byte[data64KB.Length];
1843
1844                     this.DoRequest(
1845                         (r, c) =>
1846                         {
1847                             using (HttpWebResponse x = (HttpWebResponse)r.GetResponse())
1848                             using (Stream s = x.GetResponseStream())
1849                             {
1850                                 Assert.AreEqual(1, s.ReadAll(received, 0, received.Length));
1851                             }
1852
1853                             c.Set();
1854                         },
1855                         (c) =>
1856                         {
1857                             c.Response.StatusCode = 200;
1858                             c.Response.ContentLength64 = data64KB.Length;
1859                             c.Response.OutputStream.Write(data64KB, 0, 1);
1860                             c.Response.Abort();
1861                         });
1862                 }
1863
1864                 [Test]
1865                 public void BeginGetResponse2()
1866                 {
1867                     byte[] received = new byte[data64KB.Length];
1868
1869                     this.DoRequest(
1870                         (r, c) =>
1871                         {
1872                             r.BeginGetResponse((a) => 
1873                                 {
1874                                     using (HttpWebResponse x = (HttpWebResponse)r.EndGetResponse(a))
1875                                     using (Stream s = x.GetResponseStream())
1876                                     {
1877                                         s.ReadAll(received, 0, received.Length);
1878                                     }
1879
1880                                     c.Set();
1881                                 }, null);
1882                         },
1883                         (c) =>
1884                         {
1885                             c.Response.StatusCode = 200;
1886                             c.Response.ContentLength64 = data64KB.Length;
1887                             c.Response.OutputStream.Write(data64KB, 0, data64KB.Length);
1888                             c.Response.OutputStream.Close();
1889                             c.Response.Close();
1890                         });
1891
1892                     Assert.AreEqual(data64KB, received);
1893                 }
1894
1895                 [Test]
1896                 public void BeginGetResponseAborts()
1897                 {
1898                     ManualResetEvent aborted = new ManualResetEvent(false);
1899
1900                     this.DoRequest(
1901                         (r, c) =>
1902                         {
1903                             r.BeginGetResponse((a) =>
1904                             {
1905                                 WebException ex = ExceptionAssert.Throws<WebException>(() => r.EndGetResponse(a));
1906                                 Assert.AreEqual(ex.Status, WebExceptionStatus.RequestCanceled);
1907                                 c.Set();
1908                             }, null);
1909
1910                             aborted.WaitOne();
1911                             r.Abort();
1912                         },
1913                         (c) =>
1914                         {
1915                             aborted.Set();
1916                             Thread.Sleep (100);
1917                             c.Response.StatusCode = 200;
1918                             c.Response.ContentLength64 = 0;
1919                             c.Response.Close();
1920                         });
1921                 }
1922
1923                 private void DoRequest(Action<HttpWebRequest, EventWaitHandle> request)
1924                 {
1925                     int port = rand.Next(20000, 65535);
1926
1927                     ManualResetEvent completed = new ManualResetEvent(false);
1928                     Uri address = new Uri(string.Format("http://localhost:{0}", port));
1929                     HttpWebRequest client = (HttpWebRequest)WebRequest.Create(address);
1930
1931                     request(client, completed);
1932
1933                     if (!completed.WaitOne(10000))
1934                     {
1935                         Assert.Fail("Test hung");
1936                     }
1937                 }
1938
1939                 private void DoRequest(Action<HttpWebRequest, EventWaitHandle> request, Action<HttpListenerContext> processor)
1940                 {
1941                     int port = rand.Next(20000, 65535);
1942
1943                     ManualResetEvent[] completed = new ManualResetEvent[2];
1944                     completed[0] = new ManualResetEvent(false);
1945                     completed[1] = new ManualResetEvent(false);
1946
1947                     using (ListenerScope scope = new ListenerScope(processor, port, completed[0]))
1948                     {
1949                         ManualResetEvent clientCompleted = new ManualResetEvent(false);
1950                         Uri address = new Uri(string.Format("http://localhost:{0}", port));
1951                         HttpWebRequest client = (HttpWebRequest)WebRequest.Create(address);
1952
1953                         ThreadPool.QueueUserWorkItem((o) => request(client, completed[1]));
1954
1955                         if (!WaitHandle.WaitAll(completed, 10000))
1956                         {
1957                             Assert.Fail("Test hung.");
1958                         }
1959                     }
1960                 }
1961
1962                 private class ListenerScope : IDisposable
1963                 {
1964                     EventWaitHandle completed;
1965                     public HttpListener listener;
1966                     Action<HttpListenerContext> processor;
1967
1968                     public ListenerScope(Action<HttpListenerContext> processor, int port, EventWaitHandle completed)
1969                     {
1970                         this.processor = processor;
1971                         this.completed = completed;
1972
1973                         this.listener = new HttpListener();
1974                         this.listener.Prefixes.Add(string.Format("http://localhost:{0}/", port));
1975                         this.listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
1976                         this.listener.Start();
1977
1978                         this.listener.BeginGetContext(this.RequestHandler, null);
1979                     }
1980
1981                     private void RequestHandler(IAsyncResult result)
1982                     {
1983                         HttpListenerContext context = null;
1984
1985                         try
1986                         {
1987                             context = this.listener.EndGetContext(result);
1988                         }
1989                         catch (HttpListenerException ex)
1990                         {
1991                             // check if the thread has been aborted as in the case when we are shutting down.
1992                             if (ex.ErrorCode == 995)
1993                             {
1994                                 return;
1995                             }
1996                         }
1997                         catch (ObjectDisposedException)
1998                         {
1999                             return;
2000                         }
2001
2002                         ThreadPool.QueueUserWorkItem(
2003                             (o) => { try { this.processor(context); } catch (HttpListenerException) {} });
2004
2005                         this.completed.Set();
2006                     }
2007
2008                     public void Dispose()
2009                     {
2010                         this.listener.Stop();
2011                     }
2012                 }
2013 #endif
2014 #if !TARGET_JVM
2015                 class SslHttpServer : HttpServer {
2016                         X509Certificate _certificate;
2017
2018                         protected override void Run ()
2019                         {
2020                                 try {
2021                                         Socket client = sock.Accept ();
2022                                         NetworkStream ns = new NetworkStream (client, true);
2023                                         SslServerStream s = new SslServerStream (ns, Certificate, false, false);
2024                                         s.PrivateKeyCertSelectionDelegate += new PrivateKeySelectionCallback (GetPrivateKey);
2025
2026                                         StreamReader reader = new StreamReader (s);
2027                                         StreamWriter writer = new StreamWriter (s, Encoding.ASCII);
2028
2029                                         string line;
2030                                         string hello = "<html><body><h1>Hello World!</h1></body></html>";
2031                                         string answer = "HTTP/1.0 200\r\n" +
2032                                                         "Connection: close\r\n" +
2033                                                         "Content-Type: text/html\r\n" +
2034                                                         "Content-Encoding: " + Encoding.ASCII.WebName + "\r\n" +
2035                                                         "Content-Length: " + hello.Length + "\r\n" +
2036                                                         "\r\n" + hello;
2037
2038                                         // Read the headers
2039                                         do {
2040                                                 line = reader.ReadLine ();
2041                                         } while (line != "" && line != null && line.Length > 0);
2042
2043                                         // Now the content. We know it's 100 bytes.
2044                                         // This makes BeginRead in sslclientstream block.
2045                                         char [] cs = new char [100];
2046                                         reader.Read (cs, 0, 100);
2047
2048                                         writer.Write (answer);
2049                                         writer.Flush ();
2050                                         evt.WaitOne (50000, false);
2051                                 } catch (Exception e) {
2052                                         error = e;
2053                                 }
2054                         }
2055
2056                         X509Certificate Certificate {
2057                                 get {
2058                                         if (_certificate == null)
2059                                                 _certificate = new X509Certificate (CertData.Certificate);
2060
2061                                         return _certificate;
2062                                 }
2063                         }
2064
2065                         AsymmetricAlgorithm GetPrivateKey (X509Certificate certificate, string targetHost)
2066                         {
2067                                 PrivateKey key = new PrivateKey (CertData.PrivateKey, null);
2068                                 return key.RSA;
2069                         }
2070                 }
2071
2072                 class CertData {
2073                         public readonly static byte [] Certificate = {
2074                                 48, 130, 1, 191, 48, 130, 1, 40, 160, 3, 2, 1, 2, 2, 16, 36, 
2075                                 14, 97, 190, 146, 132, 208, 71, 175, 6, 87, 168, 185, 175, 55, 43, 48, 
2076                                 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 48, 18, 
2077                                 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 111, 110, 122, 97, 
2078                                 108, 111, 48, 30, 23, 13, 48, 53, 48, 54, 50, 50, 49, 57, 51, 48, 
2079                                 52, 54, 90, 23, 13, 51, 57, 49, 50, 51, 49, 50, 51, 53, 57, 53, 
2080                                 57, 90, 48, 18, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 
2081                                 111, 110, 122, 97, 108, 111, 48, 129, 158, 48, 13, 6, 9, 42, 134, 72, 
2082                                 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 140, 0, 48, 129, 136, 2, 
2083                                 129, 129, 0, 138, 9, 38, 25, 166, 252, 59, 26, 39, 184, 128, 216, 38, 
2084                                 73, 41, 86, 30, 228, 160, 205, 41, 135, 115, 223, 44, 62, 42, 198, 178, 
2085                                 190, 81, 11, 25, 21, 216, 49, 179, 130, 246, 52, 97, 175, 212, 94, 157, 
2086                                 231, 162, 66, 161, 103, 63, 204, 83, 141, 172, 119, 97, 225, 206, 98, 101, 
2087                                 210, 106, 2, 206, 81, 90, 173, 47, 41, 199, 209, 241, 177, 177, 96, 207, 
2088                                 254, 220, 190, 66, 180, 153, 0, 209, 14, 178, 69, 194, 3, 37, 116, 239, 
2089                                 49, 23, 185, 245, 255, 126, 35, 85, 246, 56, 244, 107, 117, 24, 14, 57, 
2090                                 9, 111, 147, 189, 220, 142, 57, 104, 153, 193, 205, 19, 14, 22, 157, 16, 
2091                                 24, 80, 201, 2, 2, 0, 17, 163, 23, 48, 21, 48, 19, 6, 3, 85, 
2092                                 29, 37, 4, 12, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, 
2093                                 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 3, 
2094                                 129, 129, 0, 64, 49, 57, 253, 218, 198, 229, 51, 189, 12, 154, 225, 183, 
2095                                 160, 147, 90, 113, 172, 69, 122, 28, 77, 97, 215, 231, 194, 150, 29, 196, 
2096                                 65, 95, 218, 99, 142, 111, 79, 205, 109, 76, 32, 92, 220, 76, 88, 53, 
2097                                 237, 80, 11, 85, 44, 91, 21, 210, 12, 34, 223, 234, 18, 187, 136, 62, 
2098                                 26, 240, 103, 180, 12, 226, 221, 250, 247, 129, 51, 23, 129, 165, 56, 67, 
2099                                 43, 83, 244, 110, 207, 24, 253, 195, 16, 46, 80, 113, 80, 18, 2, 254, 
2100                                 120, 147, 151, 164, 23, 210, 230, 100, 19, 197, 179, 28, 194, 48, 106, 159, 
2101                                 155, 144, 37, 82, 44, 160, 40, 52, 146, 174, 77, 188, 160, 230, 75, 172, 
2102                                 123, 3, 254, 
2103                         };
2104
2105                         public readonly static byte [] PrivateKey = {
2106                                 30, 241, 181, 176, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 
2107                                 0, 0, 0, 0, 84, 2, 0, 0, 7, 2, 0, 0, 0, 36, 0, 0, 
2108                                 82, 83, 65, 50, 0, 4, 0, 0, 17, 0, 0, 0, 201, 80, 24, 16, 
2109                                 157, 22, 14, 19, 205, 193, 153, 104, 57, 142, 220, 189, 147, 111, 9, 57, 
2110                                 14, 24, 117, 107, 244, 56, 246, 85, 35, 126, 255, 245, 185, 23, 49, 239, 
2111                                 116, 37, 3, 194, 69, 178, 14, 209, 0, 153, 180, 66, 190, 220, 254, 207, 
2112                                 96, 177, 177, 241, 209, 199, 41, 47, 173, 90, 81, 206, 2, 106, 210, 101, 
2113                                 98, 206, 225, 97, 119, 172, 141, 83, 204, 63, 103, 161, 66, 162, 231, 157, 
2114                                 94, 212, 175, 97, 52, 246, 130, 179, 49, 216, 21, 25, 11, 81, 190, 178, 
2115                                 198, 42, 62, 44, 223, 115, 135, 41, 205, 160, 228, 30, 86, 41, 73, 38, 
2116                                 216, 128, 184, 39, 26, 59, 252, 166, 25, 38, 9, 138, 175, 88, 190, 223, 
2117                                 27, 24, 224, 123, 190, 69, 164, 234, 129, 59, 108, 229, 248, 62, 187, 15, 
2118                                 235, 147, 162, 83, 47, 123, 170, 190, 224, 31, 215, 110, 143, 31, 227, 216, 
2119                                 85, 88, 154, 83, 207, 229, 41, 28, 237, 116, 181, 17, 37, 141, 224, 185, 
2120                                 164, 144, 141, 233, 164, 138, 177, 241, 115, 181, 230, 150, 7, 92, 139, 141, 
2121                                 113, 95, 57, 191, 211, 165, 217, 250, 197, 68, 164, 184, 168, 43, 48, 65, 
2122                                 177, 237, 173, 144, 148, 221, 62, 189, 147, 63, 216, 188, 206, 103, 226, 171, 
2123                                 32, 20, 230, 116, 144, 192, 1, 39, 202, 87, 74, 250, 6, 142, 188, 23, 
2124                                 45, 4, 112, 191, 253, 67, 69, 70, 128, 143, 44, 234, 41, 96, 195, 82, 
2125                                 202, 35, 158, 149, 240, 151, 23, 25, 166, 179, 85, 144, 58, 120, 149, 229, 
2126                                 205, 34, 8, 110, 86, 119, 130, 210, 37, 173, 65, 71, 169, 67, 8, 51, 
2127                                 20, 96, 51, 155, 3, 39, 85, 187, 40, 193, 57, 19, 99, 78, 173, 28, 
2128                                 129, 154, 108, 175, 8, 138, 237, 71, 27, 148, 129, 35, 47, 57, 101, 237, 
2129                                 168, 178, 227, 221, 212, 63, 124, 254, 253, 215, 183, 159, 49, 103, 74, 49, 
2130                                 67, 160, 171, 72, 194, 215, 108, 251, 178, 18, 184, 100, 211, 105, 21, 186, 
2131                                 39, 66, 218, 154, 72, 222, 90, 237, 179, 251, 51, 224, 212, 56, 251, 6, 
2132                                 209, 151, 198, 176, 89, 110, 35, 141, 248, 237, 223, 68, 135, 206, 207, 169, 
2133                                 254, 219, 243, 130, 71, 11, 94, 113, 233, 92, 63, 156, 169, 72, 215, 110, 
2134                                 95, 94, 191, 50, 59, 89, 187, 59, 183, 99, 161, 146, 233, 245, 219, 80, 
2135                                 87, 113, 251, 50, 144, 195, 158, 46, 189, 232, 119, 91, 75, 22, 6, 176, 
2136                                 39, 206, 25, 196, 213, 195, 219, 24, 28, 103, 104, 36, 137, 128, 4, 119, 
2137                                 163, 40, 126, 87, 18, 86, 128, 243, 213, 101, 2, 237, 78, 64, 160, 55, 
2138                                 199, 93, 90, 126, 175, 199, 55, 89, 234, 190, 5, 16, 196, 88, 28, 208, 
2139                                 28, 92, 32, 115, 204, 9, 202, 101, 15, 123, 43, 75, 90, 144, 95, 179, 
2140                                 102, 249, 57, 150, 204, 99, 147, 203, 16, 63, 81, 244, 226, 237, 82, 204, 
2141                                 20, 200, 140, 65, 83, 217, 161, 23, 123, 37, 115, 12, 100, 73, 70, 190, 
2142                                 32, 235, 174, 140, 148, 157, 47, 238, 40, 208, 228, 80, 54, 187, 156, 252, 
2143                                 253, 230, 231, 156, 138, 125, 96, 79, 3, 27, 143, 55, 146, 169, 165, 61, 
2144                                 238, 60, 227, 77, 217, 93, 117, 122, 111, 46, 173, 113, 
2145                         };
2146                 }
2147 #endif
2148         }
2149 #if NET_2_0
2150             public static class StreamExtensions
2151             {
2152                 public static int ReadAll(this Stream stream, byte[] buffer, int offset, int count)
2153                 {
2154                     int totalRead = 0;
2155
2156                     while (totalRead < count)
2157                     {
2158                         int bytesRead = stream.Read(buffer, offset + totalRead, count - totalRead);
2159
2160                         if (bytesRead == 0)
2161                         {
2162                             break;
2163                         }
2164
2165                         totalRead += bytesRead;
2166                     }
2167
2168                     return totalRead;
2169                 }
2170             }
2171
2172             public class ExceptionAssert
2173             {
2174                 /// <summary>
2175                 /// Asserts that the function throws an exception.
2176                 /// </summary>
2177                 /// <param name="f">A function execute that is expected to raise an exception.</param>
2178                 /// <typeparam name="T">The type of exception that is expected.</typeparam>
2179                 /// <returns>The exception thrown.</returns>
2180                 /// <exception cref="AssertFailedException">If the function does not throw an exception 
2181                 /// or throws a different exception.</exception>
2182                 /// <example><![CDATA[
2183                 ///     ExceptionAssert.Throws(typeof(ArgumentNullException), delegate {
2184                 ///         myObject.myFunction(null); });
2185                 /// ]]></example>
2186                 public static T Throws<T>(Action f) where T : Exception
2187                 {
2188                     Exception actualException = null;
2189
2190                     try
2191                     {
2192                         f();
2193                     }
2194                     catch (Exception ex)
2195                     {
2196                         actualException = ex;
2197                     }
2198
2199                     if (actualException == null)
2200                     {
2201                         throw new AssertionException(string.Format(
2202                             "No exception thrown. Expected '{0}'",
2203                             typeof(T).FullName));
2204                     }
2205                     else if (typeof(T) != actualException.GetType())
2206                     {
2207                         throw new AssertionException(string.Format(
2208                             "Caught exception of type '{0}'. Expected '{1}':{2}",
2209                             actualException.GetType().FullName,
2210                             typeof(T).FullName,
2211                             Environment.NewLine + actualException));
2212                     }
2213
2214                     return (T)actualException;
2215                 }
2216             }
2217 #endif
2218 }