[System] Fix tests that regressed in e6536dd.
[mono.git] / mcs / class / System / Test / System.Net / HttpListenerTest.cs
1 //
2 // HttpListenerTest.cs
3 //      - Unit tests for System.Net.HttpListener
4 //
5 // Author:
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 using System;
30 using System.IO;
31 using System.Net;
32 using System.Net.Sockets;
33 using System.Threading;
34 using System.Threading.Tasks;
35 using NUnit.Framework;
36 using MonoTests.Helpers;
37
38 namespace MonoTests.System.Net {
39         [TestFixture]
40         public class HttpListenerTest {
41
42                 int? _port;
43                 int port {
44                         get { return _port ?? (_port = NetworkHelpers.FindFreePort ()).Value; }
45                 }
46
47                 [TearDown]
48                 public void Teardown ()
49                 {
50                         _port = null;
51                 }
52
53                 [Test]
54 #if FEATURE_NO_BSD_SOCKETS
55                 [ExpectedException (typeof (PlatformNotSupportedException))]
56 #endif
57                 public void DefaultProperties ()
58                 {
59                         HttpListener listener = new HttpListener ();
60                         Assert.AreEqual (AuthenticationSchemes.Anonymous, listener.AuthenticationSchemes, "#01");
61                         Assert.AreEqual (null, listener.AuthenticationSchemeSelectorDelegate, "#02");
62                         Assert.AreEqual (false, listener.IgnoreWriteExceptions, "#03");
63                         Assert.AreEqual (false, listener.IsListening, "#03");
64                         Assert.AreEqual (0, listener.Prefixes.Count, "#04");
65                         Assert.AreEqual (null, listener.Realm, "#05");
66                         Assert.AreEqual (false, listener.UnsafeConnectionNtlmAuthentication, "#06");
67                 }
68
69                 [Test]
70 #if FEATURE_NO_BSD_SOCKETS
71                 [ExpectedException (typeof (PlatformNotSupportedException))]
72 #endif
73                 public void Start1 ()
74                 {
75                         HttpListener listener = new HttpListener ();
76                         listener.Start ();
77                 }
78
79                 [Test]
80 #if FEATURE_NO_BSD_SOCKETS
81                 [ExpectedException (typeof (PlatformNotSupportedException))]
82 #endif
83                 public void Stop1 ()
84                 {
85                         HttpListener listener = new HttpListener ();
86                         listener.Stop ();
87                 }
88
89                 [Test]
90 #if FEATURE_NO_BSD_SOCKETS
91                 [ExpectedException (typeof (PlatformNotSupportedException))]
92 #else
93                 [ExpectedException (typeof (InvalidOperationException))]
94 #endif
95                 public void GetContext1 ()
96                 {
97                         HttpListener listener = new HttpListener ();
98                         // "Please call Start () before calling this method"
99                         listener.GetContext ();
100                 }
101
102                 [Test]
103 #if FEATURE_NO_BSD_SOCKETS
104                 [ExpectedException (typeof (PlatformNotSupportedException))]
105 #else
106                 [ExpectedException (typeof (InvalidOperationException))]
107 #endif
108                 public void GetContext2 ()
109                 {
110                         HttpListener listener = new HttpListener ();
111                         listener.Start ();
112                         // "Please call AddPrefix () before calling this method"
113                         listener.GetContext ();
114                 }
115
116                 [Test]
117 #if FEATURE_NO_BSD_SOCKETS
118                 [ExpectedException (typeof (PlatformNotSupportedException))]
119 #else
120                 [ExpectedException (typeof (InvalidOperationException))]
121 #endif
122                 public void BeginGetContext1 ()
123                 {
124                         HttpListener listener = new HttpListener ();
125                         // "Please call Start () before calling this method"
126                         listener.BeginGetContext (null, null);
127                 }
128
129                 [Test]
130 #if FEATURE_NO_BSD_SOCKETS
131                 [ExpectedException (typeof (PlatformNotSupportedException))]
132 #endif
133                 public void BeginGetContext2 ()
134                 {
135                         HttpListener listener = new HttpListener ();
136                         listener.Start ();
137                         // One would expect this to fail as BeginGetContext1 does not fail and
138                         // calling EndGetContext will wait forever.
139                         // Lame. They should check that we have no prefixes.
140                         IAsyncResult ares = listener.BeginGetContext (null, null);
141                         Assert.IsFalse (ares.IsCompleted);
142                 }
143
144                 private bool CanOpenPort(int port)
145                 {
146                         try
147                         {
148                                 using(Socket socket = new Socket (AddressFamily.InterNetwork,
149                                         SocketType.Stream,
150                                         ProtocolType.Tcp))
151                                 {
152                                         socket.Bind (new IPEndPoint (IPAddress.Loopback, port));
153                                         socket.Listen(1);
154                                 }
155                         }
156                         catch(Exception) {
157                                 //Can be AccessDeniedException(ports 80/443 need root access) or
158                                 //SocketException because other application is listening
159                                 return false;
160                         }
161                         return true;
162                 }
163
164                 [Test]
165 #if FEATURE_NO_BSD_SOCKETS
166                 [ExpectedException (typeof (PlatformNotSupportedException))]
167 #endif
168                 public void DefaultHttpPort ()
169                 {
170                         if (!CanOpenPort (80))
171                                 Assert.Ignore ("Can not open port 80 skipping test.");
172                         using(HttpListener listener = new HttpListener ())
173                         {
174                                 listener.Prefixes.Add ("http://127.0.0.1/");
175                                 listener.Start ();
176                                 Assert.IsFalse (CanOpenPort (80), "HttpListener is not listening on port 80.");
177                         }
178                 }
179
180                 [Test]
181 #if FEATURE_NO_BSD_SOCKETS
182                 [ExpectedException (typeof (PlatformNotSupportedException))]
183 #endif
184                 public void DefaultHttpsPort ()
185                 {
186                         if (!CanOpenPort (443))
187                                 Assert.Ignore ("Can not open port 443 skipping test.");
188                         using(HttpListener listener = new HttpListener ())
189                         {
190                                 listener.Prefixes.Add ("https://127.0.0.1/");
191                                 listener.Start ();
192                                 Assert.IsFalse (CanOpenPort (443), "HttpListener is not listening on port 443.");
193                         }
194                 }
195
196                 [Test]
197 #if FEATURE_NO_BSD_SOCKETS
198                 [ExpectedException (typeof (PlatformNotSupportedException))]
199 #endif
200                 public void TwoListeners_SameAddress ()
201                 {
202                         if (!CanOpenPort (port))
203                                 Assert.Ignore ("port");
204                         HttpListener listener1 = new HttpListener ();
205                         listener1.Prefixes.Add ("http://127.0.0.1:" + port + "/");
206                         HttpListener listener2 = new HttpListener ();
207                         listener2.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/");
208                         listener1.Start ();
209                         listener2.Start ();
210                 }
211
212                 [Test]
213 #if FEATURE_NO_BSD_SOCKETS
214                 [ExpectedException (typeof (PlatformNotSupportedException))]
215 #else
216                 [ExpectedException (typeof (HttpListenerException))]
217 #endif
218                 public void TwoListeners_SameURL ()
219                 {
220                         if (!CanOpenPort (port))
221                                 Assert.Ignore ("port");
222                         HttpListener listener1 = new HttpListener ();
223                         listener1.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/");
224                         HttpListener listener2 = new HttpListener ();
225                         listener2.Prefixes.Add ("http://127.0.0.1:" + port + "/hola/");
226                         listener1.Start ();
227                         listener2.Start ();
228                 }
229
230                 [Test]
231 #if FEATURE_NO_BSD_SOCKETS
232                 [ExpectedException (typeof (PlatformNotSupportedException))]
233 #else
234                 [ExpectedException (typeof (HttpListenerException))]
235 #endif
236                 public void MultipleSlashes ()
237                 {
238                         if (!CanOpenPort (port))
239                                 Assert.Ignore ("port");
240                         HttpListener listener = new HttpListener ();
241                         listener.Prefixes.Add ("http://localhost:" + port + "/hola////");
242                         // this one throws on Start(), not when adding it.
243                         listener.Start ();
244                 }
245
246                 [Test]
247 #if FEATURE_NO_BSD_SOCKETS
248                 [ExpectedException (typeof (PlatformNotSupportedException))]
249 #else
250                 [ExpectedException (typeof (HttpListenerException))]
251 #endif
252                 public void PercentSign ()
253                 {
254                         if (!CanOpenPort (port))
255                                 Assert.Ignore ("port");
256                         HttpListener listener = new HttpListener ();
257                         listener.Prefixes.Add ("http://localhost:" + port + "/hola%3E/");
258                         // this one throws on Start(), not when adding it.
259                         listener.Start ();
260                 }
261
262                 [Test]
263 #if FEATURE_NO_BSD_SOCKETS
264                 [ExpectedException (typeof (PlatformNotSupportedException))]
265 #endif
266                 public void CloseBeforeStart ()
267                 {
268                         HttpListener listener = new HttpListener ();
269                         listener.Close ();
270                 }
271
272                 [Test]
273 #if FEATURE_NO_BSD_SOCKETS
274                 [ExpectedException (typeof (PlatformNotSupportedException))]
275 #endif
276                 public void CloseTwice ()
277                 {
278                         if (!CanOpenPort (port))
279                                 Assert.Ignore ("port");
280                         HttpListener listener = new HttpListener ();
281                         listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
282                         listener.Start ();
283                         listener.Close ();
284                         listener.Close ();
285                 }
286
287                 [Test]
288 #if FEATURE_NO_BSD_SOCKETS
289                 [ExpectedException (typeof (PlatformNotSupportedException))]
290 #endif
291                 public void StartStopStart ()
292                 {
293                         if (!CanOpenPort (port))
294                                 Assert.Ignore ("port");
295                         HttpListener listener = new HttpListener ();
296                         listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
297                         listener.Start ();
298                         listener.Stop ();
299                         listener.Start ();
300                         listener.Close ();
301                 }
302
303                 [Test]
304 #if FEATURE_NO_BSD_SOCKETS
305                 [ExpectedException (typeof (PlatformNotSupportedException))]
306 #endif
307                 public void StartStopDispose ()
308                 {
309                         if (!CanOpenPort (port))
310                                 Assert.Ignore ("port");
311                         using (HttpListener listener = new HttpListener ()){
312                                 listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
313                                 listener.Start ();
314                                 listener.Stop ();
315                         }
316                 }
317                 
318                 [Test]
319 #if FEATURE_NO_BSD_SOCKETS
320                 [ExpectedException (typeof (PlatformNotSupportedException))]
321 #endif
322                 public void AbortBeforeStart ()
323                 {
324                         HttpListener listener = new HttpListener ();
325                         listener.Abort ();
326                 }
327
328                 [Test]
329 #if FEATURE_NO_BSD_SOCKETS
330                 [ExpectedException (typeof (PlatformNotSupportedException))]
331 #endif
332                 public void AbortTwice ()
333                 {
334                         if (!CanOpenPort (port))
335                                 Assert.Ignore ("port");
336                         HttpListener listener = new HttpListener ();
337                         listener.Prefixes.Add ("http://localhost:" + port + "/hola/");
338                         listener.Start ();
339                         listener.Abort ();
340                         listener.Abort ();
341                 }
342
343                 [Test]
344 #if FEATURE_NO_BSD_SOCKETS
345                 [ExpectedException (typeof (PlatformNotSupportedException))]
346 #endif
347                 public void PropertiesWhenClosed1 ()
348                 {
349                         HttpListener listener = new HttpListener ();
350                         listener.Close ();
351                         Assert.AreEqual (AuthenticationSchemes.Anonymous, listener.AuthenticationSchemes, "#01");
352                         Assert.AreEqual (null, listener.AuthenticationSchemeSelectorDelegate, "#02");
353                         Assert.AreEqual (false, listener.IgnoreWriteExceptions, "#03");
354                         Assert.AreEqual (false, listener.IsListening, "#03");
355                         Assert.AreEqual (null, listener.Realm, "#05");
356                         Assert.AreEqual (false, listener.UnsafeConnectionNtlmAuthentication, "#06");
357                 }
358
359                 [Test]
360 #if FEATURE_NO_BSD_SOCKETS
361                 [ExpectedException (typeof (PlatformNotSupportedException))]
362 #else
363                 [ExpectedException (typeof (ObjectDisposedException))]
364 #endif
365                 public void PropertiesWhenClosed2 ()
366                 {
367                         HttpListener listener = new HttpListener ();
368                         listener.Close ();
369                         HttpListenerPrefixCollection p = listener.Prefixes;
370                 }
371
372                 [Test]
373 #if FEATURE_NO_BSD_SOCKETS
374                 [ExpectedException (typeof (PlatformNotSupportedException))]
375 #else
376                 [ExpectedException (typeof (ObjectDisposedException))]
377 #endif
378                 public void PropertiesWhenClosedSet1 ()
379                 {
380                         HttpListener listener = new HttpListener ();
381                         listener.Close ();
382                         listener.AuthenticationSchemes = AuthenticationSchemes.None;
383                 }
384
385                 [Test]
386 #if FEATURE_NO_BSD_SOCKETS
387                 [ExpectedException (typeof (PlatformNotSupportedException))]
388 #else
389                 [ExpectedException (typeof (ObjectDisposedException))]
390 #endif
391                 public void PropertiesWhenClosedSet2 ()
392                 {
393                         HttpListener listener = new HttpListener ();
394                         listener.Close ();
395                         listener.AuthenticationSchemeSelectorDelegate = null;
396                 }
397
398                 [Test]
399 #if FEATURE_NO_BSD_SOCKETS
400                 [ExpectedException (typeof (PlatformNotSupportedException))]
401 #else
402                 [ExpectedException (typeof (ObjectDisposedException))]
403 #endif
404                 public void PropertiesWhenClosedSet3 ()
405                 {
406                         HttpListener listener = new HttpListener ();
407                         listener.Close ();
408                         listener.IgnoreWriteExceptions = true;
409                 }
410
411                 [Test]
412 #if FEATURE_NO_BSD_SOCKETS
413                 [ExpectedException (typeof (PlatformNotSupportedException))]
414 #else
415                 [ExpectedException (typeof (ObjectDisposedException))]
416 #endif
417                 public void PropertiesWhenClosedSet4 ()
418                 {
419                         HttpListener listener = new HttpListener ();
420                         listener.Close ();
421                         listener.Realm = "hola";
422                 }
423
424                 [Test]
425 #if FEATURE_NO_BSD_SOCKETS
426                 [ExpectedException (typeof (PlatformNotSupportedException))]
427 #else
428                 [ExpectedException (typeof (ObjectDisposedException))]
429 #endif
430                 public void PropertiesWhenClosedSet5 ()
431                 {
432                         HttpListener listener = new HttpListener ();
433                         listener.Close ();
434                         listener.UnsafeConnectionNtlmAuthentication = true;
435                 }
436
437                 [Test]
438 #if FEATURE_NO_BSD_SOCKETS
439                 [ExpectedException (typeof (PlatformNotSupportedException))]
440 #endif
441                 public void PropertiesWhenClosed3 ()
442                 {
443                         HttpListener listener = new HttpListener ();
444                         listener.Close ();
445                         Assert.IsFalse (listener.IsListening);
446                 }
447
448                 [Test]
449 #if FEATURE_NO_BSD_SOCKETS
450                 [ExpectedException (typeof (PlatformNotSupportedException))]
451 #endif
452                 public void CloseWhileBegin ()
453                 {
454                         HttpListener listener = new HttpListener ();
455                         listener.Prefixes.Add ("http://127.0.0.1:" + NetworkHelpers.FindFreePort () + "/closewhilebegin/");
456                         listener.Start ();
457                         CallMe cm = new CallMe ();
458                         listener.BeginGetContext (cm.Callback, listener);
459                         listener.Close ();
460                         if (false == cm.Event.WaitOne (3000, false))
461                                 Assert.Fail ("This should not time out.");
462                         Assert.IsNotNull (cm.Error);
463                         Assert.AreEqual (typeof (ObjectDisposedException), cm.Error.GetType (), "Exception type");
464                         cm.Dispose ();
465                 }
466
467                 [Test]
468 #if FEATURE_NO_BSD_SOCKETS
469                 [ExpectedException (typeof (PlatformNotSupportedException))]
470 #endif
471                 public void AbortWhileBegin ()
472                 {
473                         HttpListener listener = new HttpListener ();
474                         listener.Prefixes.Add ("http://127.0.0.1:" + NetworkHelpers.FindFreePort () + "/abortwhilebegin/");
475                         listener.Start ();
476                         CallMe cm = new CallMe ();
477                         listener.BeginGetContext (cm.Callback, listener);
478                         listener.Abort ();
479                         if (false == cm.Event.WaitOne (3000, false))
480                                 Assert.Fail ("This should not time out.");
481                         Assert.IsNotNull (cm.Error);
482                         Assert.AreEqual (typeof (ObjectDisposedException), cm.Error.GetType (), "Exception type");
483                         cm.Dispose ();
484                 }
485
486                 [Test]
487 #if FEATURE_NO_BSD_SOCKETS
488                 [ExpectedException (typeof (PlatformNotSupportedException))]
489 #else
490                 [ExpectedException (typeof (HttpListenerException))]
491 #endif
492                 public void CloseWhileGet ()
493                 {
494                         // "System.Net.HttpListener Exception : The I/O operation has been aborted
495                         // because of either a thread exit or an application request
496                         //   at System.Net.HttpListener.GetContext()
497                         //   at MonoTests.System.Net.HttpListenerTest.CloseWhileGet()
498
499                         HttpListener listener = new HttpListener ();
500                         listener.Prefixes.Add ("http://127.0.0.1:" + NetworkHelpers.FindFreePort () + "/closewhileget/");
501                         listener.Start ();
502                         RunMe rm = new RunMe (1000, new ThreadStart (listener.Close), new object [0]);
503                         rm.Start ();
504                         HttpListenerContext ctx = listener.GetContext ();
505                 }
506
507                 [Test]
508 #if FEATURE_NO_BSD_SOCKETS
509                 [ExpectedException (typeof (PlatformNotSupportedException))]
510 #else
511                 [ExpectedException (typeof (HttpListenerException))]
512 #endif
513                 public void AbortWhileGet ()
514                 {
515                         // "System.Net.HttpListener Exception : The I/O operation has been aborted
516                         // because of either a thread exit or an application request
517                         //   at System.Net.HttpListener.GetContext()
518                         //   at MonoTests.System.Net.HttpListenerTest.CloseWhileGet()
519
520                         HttpListener listener = new HttpListener ();
521                         listener.Prefixes.Add ("http://127.0.0.1:" + NetworkHelpers.FindFreePort () + "/abortwhileget/");
522                         listener.Start ();
523                         RunMe rm = new RunMe (1000, new ThreadStart (listener.Abort), new object [0]);
524                         rm.Start ();
525                         HttpListenerContext ctx = listener.GetContext ();
526                 }
527
528                 class RunMe {
529                         Delegate d;
530                         int delay_ms;
531                         object [] args;
532                         public object Result;
533
534                         public RunMe (int delay_ms, Delegate d, object [] args)
535                         {
536                                 this.delay_ms = delay_ms;
537                                 this.d = d;
538                                 this.args = args;
539                         }
540
541                         public void Start ()
542                         {
543                                 Thread th = new Thread (new ThreadStart (Run));
544                                 th.Start ();
545                         }
546
547                         void Run ()
548                         {
549                                 Thread.Sleep (delay_ms);
550                                 Result = d.DynamicInvoke (args);
551                         }
552                 }
553
554                 class CallMe {
555                         public ManualResetEvent Event = new ManualResetEvent (false);
556                         public bool Called;
557                         public HttpListenerContext Context;
558                         public Exception Error;
559
560                         public void Reset ()
561                         {
562                                 Called = false;
563                                 Context = null;
564                                 Error = null;
565                                 Event.Reset ();
566                         }
567
568                         public void Callback (IAsyncResult ares)
569                         {
570                                 Called = true;
571                                 if (ares == null) {
572                                         Error = new ArgumentNullException ("ares");
573                                         return;
574                                 }
575                                 
576                                 try {
577                                         HttpListener listener = (HttpListener) ares.AsyncState;
578                                         Context = listener.EndGetContext (ares);
579                                 } catch (Exception e) {
580                                         Error = e;
581                                 }
582                                 Event.Set ();
583                         }
584
585                         public void Dispose ()
586                         {
587                                 Event.Close ();
588                         }
589                 }
590
591                 [Test]
592 #if FEATURE_NO_BSD_SOCKETS
593                 [ExpectedException (typeof (PlatformNotSupportedException))]
594 #endif
595                 public void ConnectionReuse ()
596                 {
597                         var uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
598
599                         HttpListener listener = new HttpListener ();
600                         listener.Prefixes.Add (uri);
601                         listener.Start ();
602
603                         IPEndPoint expectedIpEndPoint = CreateListenerRequest (listener, uri);
604
605                         Assert.AreEqual (expectedIpEndPoint, CreateListenerRequest (listener, uri), "reuse1");
606                         Assert.AreEqual (expectedIpEndPoint, CreateListenerRequest (listener, uri), "reuse2");
607                 }
608
609                 public IPEndPoint CreateListenerRequest (HttpListener listener, string uri)
610                 {
611                         IPEndPoint ipEndPoint = null;
612                         var mre = new ManualResetEventSlim ();
613                         listener.BeginGetContext (result => {
614                                 ipEndPoint = ListenerCallback (result);
615                                 mre.Set ();
616                         }, listener);
617
618                         var request = (HttpWebRequest) WebRequest.Create (uri);
619                         request.Method = "POST";
620
621                         // We need to write something
622                         request.GetRequestStream ().Write (new byte [] {(byte)'a'}, 0, 1);
623                         request.GetRequestStream ().Dispose ();
624
625                         // Send request, socket is created or reused.
626                         var response = request.GetResponse ();
627
628                         // Close response so socket can be reused.
629                         response.Close ();
630
631                         mre.Wait ();
632
633                         return ipEndPoint;
634                 }
635
636                 public static IPEndPoint ListenerCallback (IAsyncResult result)
637                 {
638                         var listener = (HttpListener) result.AsyncState;
639                         var context = listener.EndGetContext (result);
640                         var clientEndPoint = context.Request.RemoteEndPoint;
641
642                         // Disposing InputStream should not avoid socket reuse
643                         context.Request.InputStream.Dispose ();
644
645                         // Close OutputStream to send response
646                         context.Response.OutputStream.Close ();
647
648                         return clientEndPoint;
649                 }
650
651                 [Test]
652 #if FEATURE_NO_BSD_SOCKETS
653                 [ExpectedException (typeof (PlatformNotSupportedException))]
654 #endif
655                 public void UserHeaderWithDoubleMultiValue ()
656                 {
657                         string uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
658
659                         var l = new HttpListener ();
660                         l.Prefixes.Add (uri);
661                         l.Start ();
662                         l.BeginGetContext (ar => {
663                                 var ctx = l.EndGetContext (ar);
664
665                                 var response = ctx.Response;
666                                 response.Headers.Add ("X-Custom-Header", "A");
667                                 response.Headers.Add ("X-Custom-Header", "B");
668
669                                 response.Close ();
670                         }, null);
671
672                         HttpWebRequest wr = HttpWebRequest.CreateHttp (uri);
673                         var resp = wr.GetResponse ();
674                         var vls = resp.Headers.GetValues ("X-Custom-Header");
675
676                         Assert.AreEqual (2, vls.Length);
677
678                         l.Close ();
679                 }
680                 
681                 [Test]
682 #if FEATURE_NO_BSD_SOCKETS
683                 [ExpectedException (typeof (PlatformNotSupportedException))]
684 #endif
685                 public void HttpClientIsDisconnectedCheckForWriteException()
686                 {
687                         string uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
688
689                         AutoResetEvent exceptionOccuredEvent = new AutoResetEvent (false);
690                         HttpListener listener = new HttpListener {
691                                 IgnoreWriteExceptions = false
692                         };
693                         listener.Prefixes.Add (uri);
694                         listener.Start ();
695                         listener.BeginGetContext (result =>
696                         {
697                                 HttpListenerContext context = listener.EndGetContext (result);
698                                 context.Response.SendChunked = true;
699                                 context.Request.InputStream.Close ();
700                                 
701                                 var bytes = new byte [1024];
702                                 using(Stream outputStream = context.Response.OutputStream) {
703                                         try {
704                                                 while (true) 
705                                                         outputStream.Write (bytes, 0, bytes.Length);
706                                         } catch {
707                                                 exceptionOccuredEvent.Set ();
708                                         }
709                                 }
710                         }, null);
711
712                         Task.Factory.StartNew (() =>
713                         {
714                                 var webRequest = (HttpWebRequest)WebRequest.Create (uri);
715                                 webRequest.Method = "POST";
716                                 webRequest.KeepAlive = false;
717                                 Stream requestStream = webRequest.GetRequestStream ();
718                                 requestStream.WriteByte (1);
719                                 requestStream.Close ();
720                                 using (WebResponse response = webRequest.GetResponse ())
721                                 using (Stream stream = response.GetResponseStream ()) {
722                                         byte[] clientBytes = new byte [1024];
723                                         Assert.IsNotNull (stream, "#01");
724                                         stream.Read (clientBytes, 0, clientBytes.Length);
725                                 }
726                         });
727
728                         Assert.IsTrue (exceptionOccuredEvent.WaitOne (15 * 1000), "#02");
729                 }
730         }
731 }
732