Merge pull request #901 from Blewzman/FixAggregateExceptionGetBaseException
[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 #if NET_2_0
30 using System;
31 using System.Net;
32 using System.Net.Sockets;
33 using System.Threading;
34 using NUnit.Framework;
35
36 namespace MonoTests.System.Net {
37         [TestFixture]
38 #if TARGET_JVM
39         [Ignore ("The class HttpListener is not implemented")]
40 #endif
41         public class HttpListenerTest {
42 #if !TARGET_JVM
43                 [Test]
44                 public void DefaultProperties ()
45                 {
46                         HttpListener listener = new HttpListener ();
47                         Assert.AreEqual (AuthenticationSchemes.Anonymous, listener.AuthenticationSchemes, "#01");
48                         Assert.AreEqual (null, listener.AuthenticationSchemeSelectorDelegate, "#02");
49                         Assert.AreEqual (false, listener.IgnoreWriteExceptions, "#03");
50                         Assert.AreEqual (false, listener.IsListening, "#03");
51                         Assert.AreEqual (0, listener.Prefixes.Count, "#04");
52                         Assert.AreEqual (null, listener.Realm, "#05");
53                         Assert.AreEqual (false, listener.UnsafeConnectionNtlmAuthentication, "#06");
54                 }
55
56                 [Test]
57                 public void Start1 ()
58                 {
59                         HttpListener listener = new HttpListener ();
60                         listener.Start ();
61                 }
62
63                 [Test]
64                 public void Stop1 ()
65                 {
66                         HttpListener listener = new HttpListener ();
67                         listener.Stop ();
68                 }
69
70                 [Test]
71                 [ExpectedException (typeof (InvalidOperationException))]
72                 public void GetContext1 ()
73                 {
74                         HttpListener listener = new HttpListener ();
75                         // "Please call Start () before calling this method"
76                         listener.GetContext ();
77                 }
78
79                 [Test]
80                 [ExpectedException (typeof (InvalidOperationException))]
81                 public void GetContext2 ()
82                 {
83                         HttpListener listener = new HttpListener ();
84                         listener.Start ();
85                         // "Please call AddPrefix () before calling this method"
86                         listener.GetContext ();
87                 }
88
89                 [Test]
90                 [ExpectedException (typeof (InvalidOperationException))]
91                 public void BeginGetContext1 ()
92                 {
93                         HttpListener listener = new HttpListener ();
94                         // "Please call Start () before calling this method"
95                         listener.BeginGetContext (null, null);
96                 }
97
98                 [Test]
99                 public void BeginGetContext2 ()
100                 {
101                         HttpListener listener = new HttpListener ();
102                         listener.Start ();
103                         // One would expect this to fail as BeginGetContext1 does not fail and
104                         // calling EndGetContext will wait forever.
105                         // Lame. They should check that we have no prefixes.
106                         IAsyncResult ares = listener.BeginGetContext (null, null);
107                         Assert.IsFalse (ares.IsCompleted);
108                 }
109
110                 private bool CanOpenPort(int port)
111                 {
112                         try
113                         {
114                                 using(Socket socket = new Socket (AddressFamily.InterNetwork,
115                                         SocketType.Stream,
116                                         ProtocolType.Tcp))
117                                 {
118                                         socket.Bind (new IPEndPoint (IPAddress.Loopback, port));
119                                         socket.Listen(1);
120                                 }
121                         }
122                         catch(Exception ex) {
123                                 //Can be AccessDeniedException(ports 80/443 need root access) or
124                                 //SocketException because other application is listening
125                                 return false;
126                         }
127                         return true;
128                 }
129
130                 [Test]
131                 public void DefaultHttpPort ()
132                 {
133                         if (!CanOpenPort (80))
134                                 Assert.Ignore ("Can not open port 80 skipping test.");
135                         using(HttpListener listener = new HttpListener ())
136                         {
137                                 listener.Prefixes.Add ("http://127.0.0.1/");
138                                 listener.Start ();
139                                 Assert.IsFalse (CanOpenPort (80), "HttpListener is not listening on port 80.");
140                         }
141                 }
142
143                 [Test]
144                 public void DefaultHttpsPort ()
145                 {
146                         if (!CanOpenPort (443))
147                                 Assert.Ignore ("Can not open port 443 skipping test.");
148                         using(HttpListener listener = new HttpListener ())
149                         {
150                                 listener.Prefixes.Add ("https://127.0.0.1/");
151                                 listener.Start ();
152                                 Assert.IsFalse (CanOpenPort (443), "HttpListener is not listening on port 443.");
153                         }
154                 }
155
156                 [Test]
157                 public void TwoListeners_SameAddress ()
158                 {
159                         HttpListener listener1 = new HttpListener ();
160                         listener1.Prefixes.Add ("http://127.0.0.1:7777/");
161                         HttpListener listener2 = new HttpListener ();
162                         listener2.Prefixes.Add ("http://127.0.0.1:7777/hola/");
163                         listener1.Start ();
164                         listener2.Start ();
165                 }
166
167                 [Test]
168                 [ExpectedException (typeof (HttpListenerException))]
169                 public void TwoListeners_SameURL ()
170                 {
171                         HttpListener listener1 = new HttpListener ();
172                         listener1.Prefixes.Add ("http://127.0.0.1:7777/hola/");
173                         HttpListener listener2 = new HttpListener ();
174                         listener2.Prefixes.Add ("http://127.0.0.1:7777/hola/");
175                         listener1.Start ();
176                         listener2.Start ();
177                 }
178
179                 [Test]
180                 [ExpectedException (typeof (HttpListenerException))]
181                 public void MultipleSlashes ()
182                 {
183                         HttpListener listener = new HttpListener ();
184                         listener.Prefixes.Add ("http://localhost:7777/hola////");
185                         // this one throws on Start(), not when adding it.
186                         listener.Start ();
187                 }
188
189                 [Test]
190                 [ExpectedException (typeof (HttpListenerException))]
191                 public void PercentSign ()
192                 {
193                         HttpListener listener = new HttpListener ();
194                         listener.Prefixes.Add ("http://localhost:7777/hola%3E/");
195                         // this one throws on Start(), not when adding it.
196                         listener.Start ();
197                 }
198
199                 [Test]
200                 public void CloseBeforeStart ()
201                 {
202                         HttpListener listener = new HttpListener ();
203                         listener.Close ();
204                 }
205
206                 [Test]
207                 public void CloseTwice ()
208                 {
209                         HttpListener listener = new HttpListener ();
210                         listener.Prefixes.Add ("http://localhost:7777/hola/");
211                         listener.Start ();
212                         listener.Close ();
213                         listener.Close ();
214                 }
215
216                 [Test]
217                 public void StartStopStart ()
218                 {
219                         HttpListener listener = new HttpListener ();
220                         listener.Prefixes.Add ("http://localhost:7777/hola/");
221                         listener.Start ();
222                         listener.Stop ();
223                         listener.Start ();
224                         listener.Close ();
225                 }
226
227                 [Test]
228                 public void StartStopDispose ()
229                 {
230                         using (HttpListener listener = new HttpListener ()){
231                                 listener.Prefixes.Add ("http://localhost:7777/hola/");
232                                 listener.Start ();
233                                 listener.Stop ();
234                         }
235                 }
236                 
237                 [Test]
238                 public void AbortBeforeStart ()
239                 {
240                         HttpListener listener = new HttpListener ();
241                         listener.Abort ();
242                 }
243
244                 [Test]
245                 public void AbortTwice ()
246                 {
247                         HttpListener listener = new HttpListener ();
248                         listener.Prefixes.Add ("http://localhost:7777/hola/");
249                         listener.Start ();
250                         listener.Abort ();
251                         listener.Abort ();
252                 }
253
254                 [Test]
255                 public void PropertiesWhenClosed1 ()
256                 {
257                         HttpListener listener = new HttpListener ();
258                         listener.Close ();
259                         Assert.AreEqual (AuthenticationSchemes.Anonymous, listener.AuthenticationSchemes, "#01");
260                         Assert.AreEqual (null, listener.AuthenticationSchemeSelectorDelegate, "#02");
261                         Assert.AreEqual (false, listener.IgnoreWriteExceptions, "#03");
262                         Assert.AreEqual (false, listener.IsListening, "#03");
263                         Assert.AreEqual (null, listener.Realm, "#05");
264                         Assert.AreEqual (false, listener.UnsafeConnectionNtlmAuthentication, "#06");
265                 }
266
267                 [Test]
268                 [ExpectedException (typeof (ObjectDisposedException))]
269                 public void PropertiesWhenClosed2 ()
270                 {
271                         HttpListener listener = new HttpListener ();
272                         listener.Close ();
273                         HttpListenerPrefixCollection p = listener.Prefixes;
274                 }
275
276                 [Test]
277                 [ExpectedException (typeof (ObjectDisposedException))]
278                 public void PropertiesWhenClosedSet1 ()
279                 {
280                         HttpListener listener = new HttpListener ();
281                         listener.Close ();
282                         listener.AuthenticationSchemes = AuthenticationSchemes.None;
283                 }
284
285                 [Test]
286                 [ExpectedException (typeof (ObjectDisposedException))]
287                 public void PropertiesWhenClosedSet2 ()
288                 {
289                         HttpListener listener = new HttpListener ();
290                         listener.Close ();
291                         listener.AuthenticationSchemeSelectorDelegate = null;
292                 }
293
294                 [Test]
295                 [ExpectedException (typeof (ObjectDisposedException))]
296                 public void PropertiesWhenClosedSet3 ()
297                 {
298                         HttpListener listener = new HttpListener ();
299                         listener.Close ();
300                         listener.IgnoreWriteExceptions = true;
301                 }
302
303                 [Test]
304                 [ExpectedException (typeof (ObjectDisposedException))]
305                 public void PropertiesWhenClosedSet4 ()
306                 {
307                         HttpListener listener = new HttpListener ();
308                         listener.Close ();
309                         listener.Realm = "hola";
310                 }
311
312                 [Test]
313                 [ExpectedException (typeof (ObjectDisposedException))]
314                 public void PropertiesWhenClosedSet5 ()
315                 {
316                         HttpListener listener = new HttpListener ();
317                         listener.Close ();
318                         listener.UnsafeConnectionNtlmAuthentication = true;
319                 }
320
321                 [Test]
322                 public void PropertiesWhenClosed3 ()
323                 {
324                         HttpListener listener = new HttpListener ();
325                         listener.Close ();
326                         Assert.IsFalse (listener.IsListening);
327                 }
328
329                 [Test]
330                 public void CloseWhileBegin ()
331                 {
332                         HttpListener listener = new HttpListener ();
333                         listener.Prefixes.Add ("http://127.0.0.1:9001/closewhilebegin/");
334                         listener.Start ();
335                         CallMe cm = new CallMe ();
336                         listener.BeginGetContext (cm.Callback, listener);
337                         listener.Close ();
338                         if (false == cm.Event.WaitOne (3000, false))
339                                 Assert.Fail ("This should not time out.");
340                         Assert.IsNotNull (cm.Error);
341                         Assert.AreEqual (typeof (ObjectDisposedException), cm.Error.GetType (), "Exception type");
342                         cm.Dispose ();
343                 }
344
345                 [Test]
346                 public void AbortWhileBegin ()
347                 {
348                         HttpListener listener = new HttpListener ();
349                         listener.Prefixes.Add ("http://127.0.0.1:9001/abortwhilebegin/");
350                         listener.Start ();
351                         CallMe cm = new CallMe ();
352                         listener.BeginGetContext (cm.Callback, listener);
353                         listener.Abort ();
354                         if (false == cm.Event.WaitOne (3000, false))
355                                 Assert.Fail ("This should not time out.");
356                         Assert.IsNotNull (cm.Error);
357                         Assert.AreEqual (typeof (ObjectDisposedException), cm.Error.GetType (), "Exception type");
358                         cm.Dispose ();
359                 }
360
361                 [Test]
362                 [ExpectedException (typeof (HttpListenerException))]
363                 public void CloseWhileGet ()
364                 {
365                         // "System.Net.HttpListener Exception : The I/O operation has been aborted
366                         // because of either a thread exit or an application request
367                         //   at System.Net.HttpListener.GetContext()
368                         //   at MonoTests.System.Net.HttpListenerTest.CloseWhileGet()
369
370                         HttpListener listener = new HttpListener ();
371                         listener.Prefixes.Add ("http://127.0.0.1:9001/closewhileget/");
372                         listener.Start ();
373                         RunMe rm = new RunMe (1000, new ThreadStart (listener.Close), new object [0]);
374                         rm.Start ();
375                         HttpListenerContext ctx = listener.GetContext ();
376                 }
377
378                 [Test]
379                 [ExpectedException (typeof (HttpListenerException))]
380                 public void AbortWhileGet ()
381                 {
382                         // "System.Net.HttpListener Exception : The I/O operation has been aborted
383                         // because of either a thread exit or an application request
384                         //   at System.Net.HttpListener.GetContext()
385                         //   at MonoTests.System.Net.HttpListenerTest.CloseWhileGet()
386
387                         HttpListener listener = new HttpListener ();
388                         listener.Prefixes.Add ("http://127.0.0.1:9001/abortwhileget/");
389                         listener.Start ();
390                         RunMe rm = new RunMe (1000, new ThreadStart (listener.Abort), new object [0]);
391                         rm.Start ();
392                         HttpListenerContext ctx = listener.GetContext ();
393                 }
394
395                 class RunMe {
396                         Delegate d;
397                         int delay_ms;
398                         object [] args;
399                         public object Result;
400
401                         public RunMe (int delay_ms, Delegate d, object [] args)
402                         {
403                                 this.delay_ms = delay_ms;
404                                 this.d = d;
405                                 this.args = args;
406                         }
407
408                         public void Start ()
409                         {
410                                 Thread th = new Thread (new ThreadStart (Run));
411                                 th.Start ();
412                         }
413
414                         void Run ()
415                         {
416                                 Thread.Sleep (delay_ms);
417                                 Result = d.DynamicInvoke (args);
418                         }
419                 }
420
421                 class CallMe {
422                         public ManualResetEvent Event = new ManualResetEvent (false);
423                         public bool Called;
424                         public HttpListenerContext Context;
425                         public Exception Error;
426
427                         public void Reset ()
428                         {
429                                 Called = false;
430                                 Context = null;
431                                 Error = null;
432                                 Event.Reset ();
433                         }
434
435                         public void Callback (IAsyncResult ares)
436                         {
437                                 Called = true;
438                                 if (ares == null) {
439                                         Error = new ArgumentNullException ("ares");
440                                         return;
441                                 }
442                                 
443                                 try {
444                                         HttpListener listener = (HttpListener) ares.AsyncState;
445                                         Context = listener.EndGetContext (ares);
446                                 } catch (Exception e) {
447                                         Error = e;
448                                 }
449                                 Event.Set ();
450                         }
451
452                         public void Dispose ()
453                         {
454                                 Event.Close ();
455                         }
456                 }
457 #endif
458         }
459 }
460 #endif
461