BindingFlags.Public needed here as Exception.HResult is now public in .NET 4.5. This...
[mono.git] / mcs / class / System.Net.Http / Test / System.Net.Http / HttpClientTest.cs
1 //
2 // HttpClientTest.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.Collections.Generic;
32 using NUnit.Framework;
33 using System.Net.Http;
34 using System.Net.Http.Headers;
35 using System.Threading;
36 using System.Threading.Tasks;
37 using System.Net;
38 using System.Linq;
39 using System.IO;
40
41 namespace MonoTests.System.Net.Http
42 {
43         [TestFixture]
44         public class HttpClientTest
45         {
46                 class HttpMessageHandlerMock : HttpMessageHandler
47                 {
48                         public Func<HttpRequestMessage, Task<HttpResponseMessage>> OnSend;
49                         public Func<HttpRequestMessage, CancellationToken, Task<HttpResponseMessage>> OnSendFull;
50
51                         public HttpMessageHandlerMock ()
52                         {
53                         }
54
55                         protected override Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, CancellationToken cancellationToken)
56                         {
57                                 if (OnSend != null)
58                                         return OnSend (request);
59
60                                 if (OnSendFull != null)
61                                         return OnSendFull (request, cancellationToken);
62
63                                 Assert.Fail ("Send");
64                                 return null;
65                         }
66                 }
67
68                 string port, TestHost, LocalServer;
69
70                 [SetUp]
71                 public void SetupFixture ()
72                 {
73                         if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
74                                 port = "810";
75                         } else {
76                                 port = "8810";
77                         }
78
79                         TestHost = "localhost:" + port;
80                         LocalServer = string.Format ("http://{0}/", TestHost);
81                 }
82
83                 [Test]
84                 public void Ctor_Default ()
85                 {
86                         var client = new HttpClient ();
87                         Assert.IsNull (client.BaseAddress, "#1");
88                         Assert.IsNotNull (client.DefaultRequestHeaders, "#2");  // TODO: full check
89                         Assert.AreEqual (0x10000, client.MaxResponseContentBufferSize, "#3");
90                         Assert.AreEqual (TimeSpan.FromSeconds (100), client.Timeout, "#4");
91                 }
92
93                 [Test]
94                 public void CancelPendingRequests ()
95                 {
96                         var mh = new HttpMessageHandlerMock ();
97
98                         var client = new HttpClient (mh);
99                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
100                         var mre = new ManualResetEvent (false);
101
102                         mh.OnSendFull = (l, c) => {
103                                 mre.Set ();
104                                 Assert.IsTrue (c.WaitHandle.WaitOne (1000), "#20");
105                                 Assert.IsTrue (c.IsCancellationRequested, "#21");
106                                 mre.Set ();
107                                 return Task.FromResult (new HttpResponseMessage ());
108                         };
109
110                         var t = Task.Factory.StartNew (() => {
111                                 client.SendAsync (request).Wait ();
112                         });
113
114                         Assert.IsTrue (mre.WaitOne (500), "#1");
115                         mre.Reset ();
116                         client.CancelPendingRequests ();
117                         Assert.IsTrue (t.Wait (500), "#2");
118
119                         request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
120                         mh.OnSendFull = (l, c) => {
121                                 Assert.IsFalse (c.IsCancellationRequested, "#30");
122                                 return Task.FromResult (new HttpResponseMessage ());
123                         };
124
125                         client.SendAsync (request).Wait ();
126                 }
127
128                 [Test]
129                 public void CancelPendingRequests_BeforeSend ()
130                 {
131                         var ct = new CancellationTokenSource ();
132                         ct.Cancel ();
133                         var rr = CancellationTokenSource.CreateLinkedTokenSource (new CancellationToken (), ct.Token);
134
135
136                         var mh = new HttpMessageHandlerMock ();
137
138                         var client = new HttpClient (mh);
139                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
140                         client.CancelPendingRequests ();
141
142                         mh.OnSendFull = (l, c) => {
143                                 Assert.IsFalse (c.IsCancellationRequested, "#30");
144                                 return Task.FromResult (new HttpResponseMessage ());
145                         };
146
147                         client.SendAsync (request).Wait ();
148
149                         request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
150                         client.SendAsync (request).Wait ();
151                 }
152
153                 [Test]
154                 public void Properties ()
155                 {
156                         var client = new HttpClient ();
157                         client.BaseAddress = null;
158                         client.MaxResponseContentBufferSize = int.MaxValue;
159                         client.Timeout = Timeout.InfiniteTimeSpan;
160
161                         Assert.IsNull (client.BaseAddress, "#1");
162                         Assert.AreEqual (int.MaxValue, client.MaxResponseContentBufferSize, "#2");
163                         Assert.AreEqual (Timeout.InfiniteTimeSpan, client.Timeout, "#3");
164                 }
165
166                 [Test]
167                 public void Properties_Invalid ()
168                 {
169                         var client = new HttpClient ();
170                         try {
171                                 client.MaxResponseContentBufferSize = 0;
172                                 Assert.Fail ("#1");
173                         } catch (ArgumentOutOfRangeException) {
174                         }
175
176                         try {
177                                 client.Timeout = TimeSpan.MinValue;
178                                 Assert.Fail ("#2");
179                         } catch (ArgumentOutOfRangeException) {
180                         }
181                 }
182
183                 [Test]
184                 public void Send ()
185                 {
186                         var mh = new HttpMessageHandlerMock ();
187
188                         var client = new HttpClient (mh);
189                         client.BaseAddress = new Uri ("http://xamarin.com");
190                         var request = new HttpRequestMessage ();
191                         var response = new HttpResponseMessage ();
192
193                         mh.OnSend = l => {
194                                 Assert.AreEqual (l, request, "#2");
195                                 Assert.AreEqual (client.BaseAddress, l.RequestUri, "#2");
196                                 return Task.FromResult (response);
197                         };
198
199                         Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
200                 }
201
202                 [Test]
203                 public void Send_DefaultRequestHeaders ()
204                 {
205                         var mh = new HttpMessageHandlerMock ();
206
207                         var client = new HttpClient (mh);
208                         client.DefaultRequestHeaders.Referrer = new Uri ("http://google.com");
209
210                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
211                         var response = new HttpResponseMessage ();
212
213                         mh.OnSend = l => {
214                                 Assert.AreEqual (client.DefaultRequestHeaders.Referrer, l.Headers.Referrer, "#2");
215                                 Assert.IsNotNull (l.Headers.Referrer, "#3");
216                                 return Task.FromResult (response);
217                         };
218
219                         Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
220                 }
221
222                 [Test]
223                 public void Send_Complete_Default ()
224                 {
225                         bool? failed = null;
226                         var listener = CreateListener (l => {
227                                 try {
228                                         var request = l.Request;
229         
230                                         Assert.IsNull (request.AcceptTypes, "#1");
231                                         Assert.AreEqual (0, request.ContentLength64, "#2");
232                                         Assert.IsNull (request.ContentType, "#3");
233                                         Assert.AreEqual (0, request.Cookies.Count, "#4");
234                                         Assert.IsFalse (request.HasEntityBody, "#5");
235                                         Assert.AreEqual (TestHost, request.Headers["Host"], "#6b");
236                                         Assert.AreEqual ("GET", request.HttpMethod, "#7");
237                                         Assert.IsFalse (request.IsAuthenticated, "#8");
238                                         Assert.IsTrue (request.IsLocal, "#9");
239                                         Assert.IsFalse (request.IsSecureConnection, "#10");
240                                         Assert.IsFalse (request.IsWebSocketRequest, "#11");
241                                         Assert.IsTrue (request.KeepAlive, "#12");
242                                         Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
243                                         Assert.IsNull (request.ServiceName, "#14");
244                                         Assert.IsNull (request.UrlReferrer, "#15");
245                                         Assert.IsNull (request.UserAgent, "#16");
246                                         Assert.IsNull (request.UserLanguages, "#17");
247                                         failed = false;
248                                 } catch {
249                                         failed = true;
250                                 }
251                         });
252
253                         try {
254                                 var client = new HttpClient ();
255                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
256                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
257
258                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
259                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
260                                 Assert.AreEqual (false, failed, "#102");
261                         } finally {
262                                 listener.Close ();
263                         }
264                 }
265
266                 [Test]
267                 public void Send_Complete_Version_1_0 ()
268                 {
269                         bool? failed = null;
270                         
271                         var listener = CreateListener (l => {
272                                 try {
273                                         var request = l.Request;
274         
275                                         Assert.IsNull (request.AcceptTypes, "#1");
276                                         Assert.AreEqual (0, request.ContentLength64, "#2");
277                                         Assert.IsNull (request.ContentType, "#3");
278                                         Assert.AreEqual (0, request.Cookies.Count, "#4");
279                                         Assert.IsFalse (request.HasEntityBody, "#5");
280                                         Assert.AreEqual (1, request.Headers.Count, "#6");
281                                         Assert.AreEqual (TestHost, request.Headers["Host"], "#6a");
282                                         Assert.AreEqual ("GET", request.HttpMethod, "#7");
283                                         Assert.IsFalse (request.IsAuthenticated, "#8");
284                                         Assert.IsTrue (request.IsLocal, "#9");
285                                         Assert.IsFalse (request.IsSecureConnection, "#10");
286                                         Assert.IsFalse (request.IsWebSocketRequest, "#11");
287                                         Assert.IsFalse (request.KeepAlive, "#12");
288                                         Assert.AreEqual (HttpVersion.Version10, request.ProtocolVersion, "#13");
289                                         Assert.IsNull (request.ServiceName, "#14");
290                                         Assert.IsNull (request.UrlReferrer, "#15");
291                                         Assert.IsNull (request.UserAgent, "#16");
292                                         Assert.IsNull (request.UserLanguages, "#17");
293                                         failed = false;
294                                 } catch {
295                                         failed = true;
296                                 }
297                         });
298
299                         try {
300                                 var client = new HttpClient ();
301                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
302                                 request.Version = HttpVersion.Version10;
303                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
304
305                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
306                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
307                                 Assert.AreEqual (false, failed, "#102");
308                         } finally {
309                                 listener.Close ();
310                         }
311                 }
312
313                 [Test]
314                 public void Send_Complete_ClientHandlerSettings ()
315                 {
316                         bool? failed = null;
317                         
318                         var listener = CreateListener (l => {
319                                 var request = l.Request;
320                                 
321                                 try {
322                                         Assert.IsNull (request.AcceptTypes, "#1");
323                                         Assert.AreEqual (0, request.ContentLength64, "#2");
324                                         Assert.IsNull (request.ContentType, "#3");
325                                         Assert.AreEqual (1, request.Cookies.Count, "#4");
326                                         Assert.AreEqual (new Cookie ("mycookie", "vv"), request.Cookies[0], "#4a");
327                                         Assert.IsFalse (request.HasEntityBody, "#5");
328                                         Assert.AreEqual (4, request.Headers.Count, "#6");
329                                         Assert.AreEqual (TestHost, request.Headers["Host"], "#6a");
330                                         Assert.AreEqual ("gzip", request.Headers["Accept-Encoding"], "#6b");
331                                         Assert.AreEqual ("mycookie=vv", request.Headers["Cookie"], "#6c");
332                                         Assert.AreEqual ("GET", request.HttpMethod, "#7");
333                                         Assert.IsFalse (request.IsAuthenticated, "#8");
334                                         Assert.IsTrue (request.IsLocal, "#9");
335                                         Assert.IsFalse (request.IsSecureConnection, "#10");
336                                         Assert.IsFalse (request.IsWebSocketRequest, "#11");
337                                         Assert.IsTrue (request.KeepAlive, "#12");
338                                         Assert.AreEqual (HttpVersion.Version10, request.ProtocolVersion, "#13");
339                                         Assert.IsNull (request.ServiceName, "#14");
340                                         Assert.IsNull (request.UrlReferrer, "#15");
341                                         Assert.IsNull (request.UserAgent, "#16");
342                                         Assert.IsNull (request.UserLanguages, "#17");
343                                         failed = false;
344                                 } catch {
345                                         failed = true;
346                                 }
347                         });
348
349                         try {
350                                 var chandler = new HttpClientHandler ();
351                                 chandler.AllowAutoRedirect = true;
352                                 chandler.AutomaticDecompression = DecompressionMethods.GZip;
353                                 chandler.MaxAutomaticRedirections = 33;
354                                 chandler.MaxRequestContentBufferSize = 5555;
355                                 chandler.PreAuthenticate = true;
356                                 chandler.CookieContainer.Add (new Uri (LocalServer), new Cookie ( "mycookie", "vv"));
357                                 chandler.UseCookies = true;
358                                 chandler.UseDefaultCredentials = true;
359                                 chandler.Proxy = new WebProxy ("ee");
360                                 chandler.UseProxy = true;
361
362                                 var client = new HttpClient (chandler);
363                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
364                                 request.Version = HttpVersion.Version10;
365                                 request.Headers.Add ("Keep-Alive", "false");
366                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
367
368                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
369                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
370                                 Assert.AreEqual (false, failed, "#102");
371                         } finally {
372                                 listener.Abort ();
373                                 listener.Close ();
374                         }
375                 }
376
377                 [Test]
378                 public void Send_Complete_CustomHeaders ()
379                 {
380                         bool? failed = null;
381                         
382                         var listener = CreateListener (l => {
383                                 var request = l.Request;
384                                 try {
385                                         Assert.AreEqual ("vv", request.Headers["aa"], "#1");
386         
387                                         var response = l.Response;
388                                         response.Headers.Add ("rsp", "rrr");
389                                         response.Headers.Add ("upgrade", "vvvvaa");
390                                         response.Headers.Add ("Date", "aa");
391                                         response.Headers.Add ("cache-control", "audio");
392         
393                                         response.StatusDescription = "test description";
394                                         response.ProtocolVersion = HttpVersion.Version10;
395                                         response.SendChunked = true;
396                                         response.RedirectLocation = "w3.org";
397                                         
398                                         failed = false;
399                                 } catch {
400                                         failed = true;
401                                 }
402                         });
403
404                         try {
405                                 var client = new HttpClient ();
406                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
407                                 request.Headers.AddWithoutValidation ("aa", "vv");
408                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
409
410                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
411                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
412                                 
413                                 IEnumerable<string> values;
414                                 Assert.IsTrue (response.Headers.TryGetValues ("rsp", out values), "#102");
415                                 Assert.AreEqual ("rrr", values.First (), "#102a");
416
417                                 Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#103");
418                                 Assert.AreEqual ("chunked", values.First (), "#103a");
419                                 Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#103b");
420
421                                 Assert.IsTrue (response.Headers.TryGetValues ("Date", out values), "#104");
422                                 Assert.AreEqual (1, values.Count (), "#104b");
423                                 // .NET overwrites Date, Mono does not
424                                 // Assert.IsNotNull (response.Headers.Date, "#104c");
425
426                                 Assert.AreEqual (new ProductHeaderValue ("vvvvaa"), response.Headers.Upgrade.First (), "#105");
427
428                                 Assert.AreEqual ("audio", response.Headers.CacheControl.Extensions.First ().Name, "#106");
429
430                                 Assert.AreEqual ("w3.org", response.Headers.Location.OriginalString, "#107");
431
432                                 Assert.AreEqual ("test description", response.ReasonPhrase, "#110");
433                                 Assert.AreEqual (HttpVersion.Version11, response.Version, "#111");
434                                 
435                                 Assert.AreEqual (false, failed, "#112");
436                         } finally {
437                                 listener.Close ();
438                         }
439                 }
440
441                 [Test]
442                 public void Send_Complete_Content ()
443                 {
444                         var listener = CreateListener (l => {
445                                 var request = l.Request;
446                                 l.Response.OutputStream.WriteByte (55);
447                                 l.Response.OutputStream.WriteByte (75);
448                         });
449
450                         try {
451                                 var client = new HttpClient ();
452                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
453                                 request.Headers.AddWithoutValidation ("aa", "vv");
454                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
455
456                                 Assert.AreEqual ("7K", response.Content.ReadAsStringAsync ().Result, "#100");
457                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
458
459                                 IEnumerable<string> values;
460                                 Assert.IsTrue (response.Headers.TryGetValues ("Transfer-Encoding", out values), "#102");
461                                 Assert.AreEqual ("chunked", values.First (), "#102a");
462                                 Assert.AreEqual (true, response.Headers.TransferEncodingChunked, "#102b");
463                         } finally {
464                                 listener.Close ();
465                         }
466                 }
467
468                 [Test]
469                 public void Send_Complete_Content_MaxResponseContentBufferSize ()
470                 {
471                         var listener = CreateListener (l => {
472                                 var request = l.Request;
473                                 var b = new byte[4000];
474                                 l.Response.OutputStream.Write (b, 0, b.Length);
475                         });
476
477                         try {
478                                 var client = new HttpClient ();
479                                 client.MaxResponseContentBufferSize = 1000;
480                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
481                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
482
483                                 Assert.AreEqual (4000, response.Content.ReadAsStringAsync ().Result.Length, "#100");
484                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#101");
485                         } finally {
486                                 listener.Close ();
487                         }
488                 }
489
490                 [Test]
491                 public void Send_Complete_Content_MaxResponseContentBufferSize_Error ()
492                 {
493                         var listener = CreateListener (l => {
494                                 var request = l.Request;
495                                 var b = new byte[4000];
496                                 l.Response.OutputStream.Write (b, 0, b.Length);
497                         });
498
499                         try {
500                                 var client = new HttpClient ();
501                                 client.MaxResponseContentBufferSize = 1000;
502                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
503
504                                 try {
505                                         client.SendAsync (request, HttpCompletionOption.ResponseContentRead).Wait ();
506                                         Assert.Fail ("#2");
507                                 } catch (AggregateException e) {
508                                         Assert.IsInstanceOfType (typeof (HttpRequestException), e.InnerException, "#3");
509                                 }
510
511                         } finally {
512                                 listener.Close ();
513                         }
514                 }
515
516                 [Test]
517                 public void Send_Complete_Error ()
518                 {
519                         var listener = CreateListener (l => {
520                                 var response = l.Response;
521                                 response.StatusCode = 500;
522                         });
523
524                         try {
525                                 var client = new HttpClient ();
526                                 var request = new HttpRequestMessage (HttpMethod.Get, LocalServer);
527                                 var response = client.SendAsync (request, HttpCompletionOption.ResponseHeadersRead).Result;
528
529                                 Assert.AreEqual ("", response.Content.ReadAsStringAsync ().Result, "#100");
530                                 Assert.AreEqual (HttpStatusCode.InternalServerError, response.StatusCode, "#101");
531                         } finally {
532                                 listener.Close ();
533                         }
534                 }
535
536                 [Test]
537                 public void Send_Content_Get ()
538                 {
539                         var listener = CreateListener (l => {
540                                 var request = l.Request;
541                                 l.Response.OutputStream.WriteByte (72);
542                         });
543
544                         try {
545                                 var client = new HttpClient ();
546                                 var r = new HttpRequestMessage (HttpMethod.Get, LocalServer);
547                                 var response = client.SendAsync (r).Result;
548
549                                 Assert.AreEqual ("H", response.Content.ReadAsStringAsync ().Result);
550                         } finally {
551                                 listener.Close ();
552                         }
553                 }
554
555                 [Test]
556                 public void Send_Content_Put ()
557                 {
558                         bool passed = false;
559                         var listener = CreateListener (l => {
560                                 var request = l.Request;
561                                 passed = 7 == request.ContentLength64;
562                                 passed &= request.ContentType == "text/plain; charset=utf-8";
563                                 passed &= request.InputStream.ReadByte () == 'm';
564                         });
565
566                         try {
567                                 var client = new HttpClient ();
568                                 var r = new HttpRequestMessage (HttpMethod.Put, LocalServer);
569                                 r.Content = new StringContent ("my text");
570                                 var response = client.SendAsync (r).Result;
571
572                                 Assert.AreEqual (HttpStatusCode.OK, response.StatusCode, "#1");
573                                 Assert.IsTrue (passed, "#2");
574                         } finally {
575                                 listener.Abort ();
576                                 listener.Close ();
577                         }
578                 }
579
580                 [Test]
581                 public void Send_Timeout ()
582                 {
583                         var mh = new HttpMessageHandlerMock ();
584
585                         var client = new HttpClient (mh);
586                         client.Timeout = TimeSpan.FromMilliseconds (100);
587                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
588                         var response = new HttpResponseMessage ();
589
590                         mh.OnSendFull = (l, c) => {
591                                 Assert.IsTrue (c.WaitHandle.WaitOne (500), "#2");
592                                 return Task.FromResult (response);
593                         };
594
595                         Assert.AreEqual (response, client.SendAsync (request).Result, "#1");
596                 }
597
598                 [Test]
599                 public void Send_Invalid ()
600                 {
601                         var client = new HttpClient ();
602                         try {
603                                 client.SendAsync (null).Wait ();
604                                 Assert.Fail ("#1");
605                         } catch (ArgumentNullException) {
606                         }
607
608                         try {
609                                 var request = new HttpRequestMessage ();
610                                 client.SendAsync (request).Wait ();
611                                 Assert.Fail ("#2");
612                         } catch (InvalidOperationException) {
613                         }
614                 }
615
616                 [Test]
617                 public void Send_InvalidHandler ()
618                 {
619                         var mh = new HttpMessageHandlerMock ();
620
621                         var client = new HttpClient (mh);
622                         client.BaseAddress = new Uri ("http://xamarin.com");
623                         var request = new HttpRequestMessage ();
624
625                         mh.OnSend = l => {
626                                 Assert.AreEqual (l, request, "#1");
627                                 return null;
628                         };
629
630                         try {
631                                 // Broken by design
632                                 client.SendAsync (request).Wait ();
633                                 Assert.Fail ("#2");
634                         } catch (Exception) {
635                         }
636                 }
637
638                 [Test]
639                 public void Send_SameMessage ()
640                 {
641                         var mh = new HttpMessageHandlerMock ();
642
643                         var client = new HttpClient (mh);
644                         var request = new HttpRequestMessage (HttpMethod.Get, "http://xamarin.com");
645
646                         mh.OnSend = l => Task.FromResult (new HttpResponseMessage ());
647
648                         client.SendAsync (request).Wait ();
649                         try {
650                                 client.SendAsync (request).Wait ();
651                                 Assert.Fail ("#1");
652                         } catch (InvalidOperationException) {
653                         }
654                 }
655
656                 HttpListener CreateListener (Action<HttpListenerContext> contextAssert)
657                 {
658                         var l = new HttpListener ();
659                         l.Prefixes.Add (string.Format ("http://+:{0}/", port));
660                         l.Start ();
661                         l.BeginGetContext (ar => {
662                                 var ctx = l.EndGetContext (ar);
663
664                                 try {
665                                         if (contextAssert != null)
666                                                 contextAssert (ctx);
667                                 } finally {
668                                         ctx.Response.Close ();
669                                 }
670                         }, null);
671
672                         return l;
673                 }
674         }
675 }