[bcl] Remove NET_4_0 defines from class libs
[mono.git] / mcs / class / System.Web.Routing / Test / System.Web.Routing / RouteTest.cs
1 //
2 // RouteTest.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2008-2009 Novell Inc. http://novell.com
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 using System;
31 using System.IO;
32 using System.Web;
33 using System.Web.Routing;
34 using NUnit.Framework;
35
36 namespace MonoTests.System.Web.Routing
37 {
38         class TestUrl
39         {
40                 public string Url { get; set; }
41                 public string Expected { get; set; }
42                 public string Label { get; set; }
43                 public Type ExpectedExceptionType { get; set; } 
44         }
45
46         [TestFixture]
47         public class RouteTest
48         {
49                 [Test]
50                 public void ConstructorNullArgs ()
51                 {
52                         var r = new Route (null, null);
53                         Assert.AreEqual (String.Empty, r.Url);
54                         Assert.IsNull (r.RouteHandler);
55                 }
56
57                 [Test]
58                 public void SetNullUrl ()
59                 {
60                         var r = new Route (null, null);
61                         r.Url = "urn:foo";
62                         r.Url = null;
63                         Assert.AreEqual (String.Empty, r.Url);
64                 }
65
66                 static readonly TestUrl[] __invalidUrls = {
67                         // cannot start with '~'
68                         new TestUrl () { Url = "~", ExpectedExceptionType = typeof (ArgumentException), Label = "#1" },
69
70                         // cannot start with '/'
71                         new TestUrl () { Url = "/", ExpectedExceptionType = typeof (ArgumentException), Label = "#2" },
72
73                         // cannot contain '?'
74                         new TestUrl () { Url = "foo?bar", ExpectedExceptionType = typeof (ArgumentException), Label = "#3" },
75
76                         // unmatched '{'
77                         new TestUrl () { Url = "foo/{bar", ExpectedExceptionType = typeof (ArgumentException), Label = "#4" },
78
79                         // unmatched '}'
80                         new TestUrl () { Url = "foo/bar}", ExpectedExceptionType = typeof (ArgumentException), Label = "#5"  },
81
82                         // "" is an invalid parameter name.
83                         new TestUrl () { Url = "foo/{}", ExpectedExceptionType = typeof (ArgumentException), Label = "#6" },
84
85                         // incomplete parameter in path segment.
86                         new TestUrl () { Url = "foo/{x/y/z}", ExpectedExceptionType = typeof (ArgumentException), Label = "#7" },
87
88                         // regarded as an incomplete parameter
89                         new TestUrl () { Url = "foo/{a{{b}}c}", ExpectedExceptionType = typeof (ArgumentException), Label = "#8" },
90
91                         // consecutive parameters are not allowed
92                         new TestUrl () { Url = "foo/{a}{b}", ExpectedExceptionType = typeof (ArgumentException), Label = "#9" },
93
94                         // consecutive segment separators '/' are not allowed
95                         new TestUrl () { Url = "foo//bar", ExpectedExceptionType = typeof (ArgumentException), Label = "#10" },
96
97                         // A catch-all parameter can only appear as the last segment of the route URL
98                         new TestUrl () { Url = "{first}/{*rest}/{foo}", ExpectedExceptionType = typeof (ArgumentException), Label = "#11" },
99
100                         // A path segment that contains more than one section, such as a literal section or a parameter, cannot contain a catch-all parameter.
101                         new TestUrl () { Url = "{first}/{*rest}-{foo}", ExpectedExceptionType = typeof (ArgumentException), Label = "#12" },
102
103                         // A path segment that contains more than one section, such as a literal section or a parameter, cannot contain a catch-all parameter.
104                         new TestUrl () { Url = "{first}/{foo}-{*rest}", ExpectedExceptionType = typeof (ArgumentException), Label = "#13" },
105
106                         // A path segment that contains more than one section, such as a literal section or a parameter, cannot contain a catch-all parameter.
107                         new TestUrl () { Url = "-{*rest}", ExpectedExceptionType = typeof (ArgumentException), Label = "#14" },
108                 };
109                 
110                 [Test]
111                 public void InvalidUrls ()
112                 {
113                         Route r;
114
115                         foreach (TestUrl tu in __invalidUrls) {
116                                 AssertExtensions.Throws (tu.ExpectedExceptionType, () => r = new Route (tu.Url, null), tu.Label);
117                         }
118                 }
119
120                 static readonly TestUrl[] __validUrls = {
121                         new TestUrl () { Url = "{foo}/{bar}", Expected = "{foo}/{bar}", Label = "#1" },
122                         new TestUrl () { Url = "a~c", Expected = "a~c", Label = "#2" },
123                         new TestUrl () { Url = "foo/", Expected = "foo/", Label = "#3" },
124                         new TestUrl () { Url = "summary/{action}-{type}/{page}", Expected = "summary/{action}-{type}/{page}", Label = "#4" },
125                         new TestUrl () { Url = "{first}/{*rest}", Expected = "{first}/{*rest}", Label = "#5" },
126                         new TestUrl () { Url = "{language}-{country}/{controller}/{action}", Expected = "{language}-{country}/{controller}/{action}", Label = "#6" },
127                         new TestUrl () { Url = "{controller}.{action}.{id}", Expected = "{controller}.{action}.{id}", Label = "#7" },
128                         new TestUrl () { Url = "{reporttype}/{year}/{month}/{date}", Expected = "{reporttype}/{year}/{month}/{date}", Label = "#8" },
129                         new TestUrl () { Url = "Book{title}and{foo}", Expected = "Book{title}and{foo}", Label = "#9" },
130                         new TestUrl () { Url = "foo/{ }", Expected = "foo/{ }", Label = "#10" },
131                         new TestUrl () { Url = "foo/{ \t}", Expected = "foo/{ \t}", Label = "#11" },
132                         new TestUrl () { Url = "foo/{ \n}", Expected = "foo/{ \n}", Label = "#12" },
133                         new TestUrl () { Url = "foo/{ \t\n}", Expected = "foo/{ \t\n}", Label = "#13" },
134                         new TestUrl () { Url = "-{foo}", Expected = "-{foo}", Label = "#14" },
135                 };
136
137                 [Test]
138                 public void ValidUrls ()
139                 {
140                         Route r;
141
142                         foreach (TestUrl tu in __validUrls) {
143                                 r = new Route (tu.Url, null);
144                                 Assert.AreEqual (tu.Expected, r.Url, tu.Label);
145                                 Assert.IsNull (r.DataTokens, tu.Label + "-2");
146                                 Assert.IsNull (r.Defaults, tu.Label + "-3");
147                                 Assert.IsNull (r.Constraints, tu.Label + "-4");
148                         }
149                 }
150
151                 [Test]
152                 public void RoutingHandler ()
153                 {
154                         var r = new Route (null, new StopRoutingHandler ());
155                         Assert.AreEqual (typeof (StopRoutingHandler), r.RouteHandler.GetType (), "#1");
156                 }
157
158                 [Test]
159                 public void GetRouteDataNoTemplate ()
160                 {
161                         var r = new Route ("foo/bar", null);
162                         var hc = new HttpContextStub ("~/foo/bar", String.Empty);
163                         var rd = r.GetRouteData (hc);
164                         Assert.IsNotNull (rd, "#1");
165                         Assert.AreEqual (r, rd.Route, "#2");
166                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
167                         Assert.AreEqual (0, rd.Values.Count, "#4");
168                 }
169
170                 [Test]
171                 [ExpectedException (typeof (InvalidOperationException))]
172                 public void InvalidConstraint ()
173                 {
174                         var r = new Route ("{foo}/{bar}", new StopRoutingHandler ());
175                         var c = new RouteValueDictionary ();
176                         c ["foo"] = Guid.NewGuid ();
177                         r.Constraints = c;
178                         var hc = new HttpContextStub ("~/x/y", String.Empty);
179                         var rd = r.GetRouteData (hc);
180                 }
181
182                 [Test]
183                 public void GetRouteData ()
184                 {
185                         var r = new Route ("{foo}/{bar}", null);
186                         var hc = new HttpContextStub ("~/x/y", String.Empty);
187                         var rd = r.GetRouteData (hc);
188                         Assert.IsNotNull (rd, "#1");
189                         Assert.AreEqual (r, rd.Route, "#2");
190                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
191                         Assert.AreEqual (2, rd.Values.Count, "#4");
192                         Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
193                         Assert.AreEqual ("y", rd.Values ["bar"], "#4-2");
194                 }
195
196                 [Test]
197                 public void GetRouteData2 ()
198                 {
199                         // {} matches and substitutes even at partial state ...
200                         var r = new Route ("{foo}/bar{baz}", null);
201                         var hc = new HttpContextStub ("~/x/bart", String.Empty);
202                         var rd = r.GetRouteData (hc);
203                         Assert.IsNotNull (rd, "#1");
204                         Assert.AreEqual (r, rd.Route, "#2");
205                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
206                         Assert.AreEqual (2, rd.Values.Count, "#4");
207                         Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
208                         Assert.AreEqual ("t", rd.Values ["baz"], "#4-2");
209                 }
210
211                 [Test]
212                 public void GetRouteData3 ()
213                 {
214                         var r = new Route ("{foo}/{bar}", null);
215                         var hc = new HttpContextStub ("~/x/y/z", String.Empty);
216                         var rd = r.GetRouteData (hc);
217                         Assert.IsNull (rd); // mismatch
218                 }
219
220                 [Test]
221                 public void GetRouteData4 ()
222                 {
223                         var r = new Route ("{foo}/{bar}", null);
224                         var hc = new HttpContextStub ("~/x", String.Empty);
225                         var rd = r.GetRouteData (hc);
226                         Assert.IsNull (rd); // mismatch
227                 }
228
229                 [Test]
230                 public void GetRouteData5 ()
231                 {
232                         var r = new Route ("{foo}/{bar}", new StopRoutingHandler ());
233                         var rd = r.GetRouteData (new HttpContextStub ("x/y", String.Empty));
234                         Assert.IsNull (rd, "#1");
235                         rd = r.GetRouteData (new HttpContextStub ("~/x/y", String.Empty));
236                         Assert.IsNotNull (rd, "#2");
237                         rd = r.GetRouteData (new HttpContextStub ("~/x/y/z", String.Empty));
238                         Assert.IsNull (rd, "#3");
239                         rd = r.GetRouteData (new HttpContextStub ("~x/y", String.Empty));
240                         Assert.IsNull (rd, "#4");
241                         rd = r.GetRouteData (new HttpContextStub ("/x/y", String.Empty));
242                         Assert.IsNull (rd, "#5");
243
244                         rd = r.GetRouteData (new HttpContextStub ("{foo}/{bar}/baz", String.Empty));
245                         Assert.IsNull (rd, "#6");
246                         rd = r.GetRouteData (new HttpContextStub ("{foo}/{bar}", String.Empty));
247                         Assert.IsNotNull (rd, "#7");
248                         Assert.AreEqual (0, rd.DataTokens.Count, "#7-2");
249                         Assert.AreEqual (2, rd.Values.Count, "#7-3");
250                 }
251
252                 [Test]
253                 public void GetRouteData6 ()
254                 {
255                         var r = new Route ("{table}/{action}.aspx", null);
256                         var rd = r.GetRouteData (new HttpContextStub ("~/FooTable/List.aspx", String.Empty));
257                         Assert.IsNotNull (rd, "#1");
258                         Assert.AreEqual ("FooTable", rd.Values ["table"], "#2");
259                         Assert.AreEqual ("List", rd.Values ["action"], "#3");
260                 }
261
262                 [Test]
263                 public void GetRouteData7 ()
264                 {
265                         var r = new Route ("{table}/{action}.aspx", null);
266                         var rd = r.GetRouteData (new HttpContextStub ("~/FooTable/", String.Empty));
267                         Assert.IsNull (rd, "#1");
268                 }
269
270                 [Test]
271                 public void GetRouteData8 ()
272                 {
273                         var r = new Route ("{first}/{*rest}", null);
274                         var hc = new HttpContextStub ("~/a/b/c/d", String.Empty);
275                         var rd = r.GetRouteData (hc);
276                         Assert.IsNotNull (rd, "#1");
277                         Assert.AreEqual (r, rd.Route, "#2");
278                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
279                         Assert.AreEqual (2, rd.Values.Count, "#4");
280                         Assert.AreEqual ("a", rd.Values ["first"], "#4-1");
281                         Assert.AreEqual ("b/c/d", rd.Values ["rest"], "#4-2");
282                 }
283
284                 [Test]
285                 public void GetRouteData9 ()
286                 {
287                         var r = new Route ("summary/{action}-{type}/{page}", null);
288                         var hc = new HttpContextStub ("~/summary/test-xml/1", String.Empty);
289                         var rd = r.GetRouteData (hc);
290
291                         Assert.IsNotNull (rd, "#1");
292                         Assert.AreEqual (r, rd.Route, "#2");
293                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
294                         Assert.AreEqual (3, rd.Values.Count, "#4");
295                         Assert.AreEqual ("test", rd.Values["action"], "#4-1");
296                         Assert.AreEqual ("xml", rd.Values["type"], "#4-2");
297                         Assert.AreEqual ("1", rd.Values["page"], "#4-2");
298                 }
299
300                 [Test]
301                 public void GetRouteData10 ()
302                 {
303                         var r = new Route ("summary/{action}-{type}/{page}", null);
304                         var hc = new HttpContextStub ("~/summary/-xml/1", String.Empty);
305                         var rd = r.GetRouteData (hc);
306
307                         Assert.IsNull (rd, "#1"); // mismatch, missing action
308                 }
309
310                 [Test]
311                 public void GetRouteData11 ()
312                 {
313                         var r = new Route ("summary/{action}-{type}/{page}", null);
314                         var hc = new HttpContextStub ("~/summary/test-/1", String.Empty);
315                         var rd = r.GetRouteData (hc);
316
317                         Assert.IsNull (rd, "#1"); // mismatch, missing type
318                 }
319
320                 [Test]
321                 public void GetRouteData12 ()
322                 {
323                         var r = new Route ("summary/{action}-{type}/{page}", null);
324                         var hc = new HttpContextStub ("~/summary/test-xml", String.Empty);
325                         var rd = r.GetRouteData (hc);
326
327                         Assert.IsNull (rd, "#1"); // mismatch, missing page
328                 }
329
330                 [Test]
331                 public void GetRouteData13 ()
332                 {
333                         var r = new Route ("summary/{action}-{type}/{page}", null) {
334                                         Defaults = new RouteValueDictionary (new { action = "Index", page = 1 } )
335                                                 };
336                         var hc = new HttpContextStub ("~/summary/test-xml/1", String.Empty);
337                         var rd = r.GetRouteData (hc);
338
339                         Assert.IsNotNull (rd, "#1");
340                         Assert.AreEqual (r, rd.Route, "#2");
341                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
342                         Assert.AreEqual (3, rd.Values.Count, "#4");
343                         Assert.AreEqual ("test", rd.Values["action"], "#4-1");
344                         Assert.AreEqual ("xml", rd.Values["type"], "#4-2");
345                         Assert.AreEqual ("1", rd.Values["page"], "#4-3");
346                 }
347
348                 [Test]
349                 public void GetRouteData14 ()
350                 {
351                         var r = new Route ("{filename}.{ext}", null);
352                         var hc = new HttpContextStub ("~/Foo.xml.aspx", String.Empty);
353                         var rd = r.GetRouteData (hc);
354
355                         Assert.IsNotNull (rd, "#1");
356                         Assert.AreEqual (r, rd.Route, "#2");
357                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
358                         Assert.AreEqual (2, rd.Values.Count, "#4");
359                         Assert.AreEqual ("Foo.xml", rd.Values["filename"], "#4-1");
360                         Assert.AreEqual ("aspx", rd.Values["ext"], "#4-2");
361                 }
362
363                 [Test]
364                 public void GetRouteData15 ()
365                 {
366                         var r = new Route ("My{location}-{sublocation}", null);
367                         var hc = new HttpContextStub ("~/MyHouse-LivingRoom", String.Empty);
368                         var rd = r.GetRouteData (hc);
369
370                         Assert.IsNotNull (rd, "#1");
371                         Assert.AreEqual (r, rd.Route, "#2");
372                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
373                         Assert.AreEqual (2, rd.Values.Count, "#4");
374                         Assert.AreEqual ("House", rd.Values["location"], "#4-1");
375                         Assert.AreEqual ("LivingRoom", rd.Values["sublocation"], "#4-2");
376                 }
377
378                 [Test]
379                 public void GetRouteData16 ()
380                 {
381                         var r = new Route ("My{location}---{sublocation}", null);
382                         var hc = new HttpContextStub ("~/MyHouse-LivingRoom", String.Empty);
383                         var rd = r.GetRouteData (hc);
384
385                         Assert.IsNull (rd, "#1");
386                 }
387
388                 [Test]
389                 public void GetRouteData17 ()
390                 {
391                         var r = new Route ("{foo}xyz{bar}", null);
392                         var hc = new HttpContextStub ("~/xyzxyzxyzblah", String.Empty);
393                         var rd = r.GetRouteData (hc);
394
395                         Assert.IsNotNull (rd, "#1");
396                         Assert.AreEqual (r, rd.Route, "#2");
397                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
398                         Assert.AreEqual (2, rd.Values.Count, "#4");
399                         Assert.AreEqual ("xyzxyz", rd.Values["foo"], "#4-1");
400                         Assert.AreEqual ("blah", rd.Values["bar"], "#4-2");
401                 }
402
403                 [Test]
404                 public void GetRouteData18 ()
405                 {
406                         var r = new Route ("foo/{ }", null);
407                         var hc = new HttpContextStub ("~/foo/stuff", String.Empty);
408                         var rd = r.GetRouteData (hc);
409
410                         Assert.IsNotNull (rd, "#1");
411                         Assert.AreEqual (r, rd.Route, "#2");
412                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
413                         Assert.AreEqual (1, rd.Values.Count, "#4");
414                         Assert.AreEqual ("stuff", rd.Values[" "], "#4-1");
415                 }
416
417                 [Test]
418                 public void GetRouteData19 ()
419                 {
420                         var r = new Route ("foo/{ \t}", null);
421                         var hc = new HttpContextStub ("~/foo/stuff", String.Empty);
422                         var rd = r.GetRouteData (hc);
423
424                         Assert.IsNotNull (rd, "#1");
425                         Assert.AreEqual (r, rd.Route, "#2");
426                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
427                         Assert.AreEqual (1, rd.Values.Count, "#4");
428                         Assert.AreEqual ("stuff", rd.Values[" \t"], "#4-1");
429                 }
430
431                 [Test]
432                 public void GetRouteData20 ()
433                 {
434                         var r = new Route ("foo/{ \n}", null);
435                         var hc = new HttpContextStub ("~/foo/stuff", String.Empty);
436                         var rd = r.GetRouteData (hc);
437
438                         Assert.IsNotNull (rd, "#1");
439                         Assert.AreEqual (r, rd.Route, "#2");
440                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
441                         Assert.AreEqual (1, rd.Values.Count, "#4");
442                         Assert.AreEqual ("stuff", rd.Values[" \n"], "#4-1");
443                 }
444
445                 [Test]
446                 public void GetRouteData21 ()
447                 {
448                         var r = new Route ("foo/{ \t\n}", null);
449                         var hc = new HttpContextStub ("~/foo/stuff", String.Empty);
450                         var rd = r.GetRouteData (hc);
451
452                         Assert.IsNotNull (rd, "#1");
453                         Assert.AreEqual (r, rd.Route, "#2");
454                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
455                         Assert.AreEqual (1, rd.Values.Count, "#4");
456                         Assert.AreEqual ("stuff", rd.Values[" \t\n"], "#4-1");
457                 }
458
459                 [Test]
460                 public void GetRouteData22 ()
461                 {
462                         var r = new Route ("foo/{ \t\n}", null);
463                         var hc = new HttpContextStub ("~/FOO/stuff", String.Empty);
464                         var rd = r.GetRouteData (hc);
465
466                         Assert.IsNotNull (rd, "#1");
467                         Assert.AreEqual (r, rd.Route, "#2");
468                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
469                         Assert.AreEqual (1, rd.Values.Count, "#4");
470                         Assert.AreEqual ("stuff", rd.Values[" \t\n"], "#4-1");
471                 }
472
473                 [Test]
474                 public void GetRouteData23 ()
475                 {
476                         var r = new Route ("foo/{bar}-{baz}/{dancefloor}", null) {
477                                         Defaults = new RouteValueDictionary (new { bar = "BlueOyster", dancefloor = 1 })
478                         };
479                                 
480                         var hc = new HttpContextStub ("~/foo/-nyc/1", String.Empty);
481                         var rd = r.GetRouteData (hc);
482                         Assert.IsNull (rd, "#1");
483
484                         hc = new HttpContextStub ("~/foo/blueoyster-nyc", String.Empty);
485                         rd = r.GetRouteData (hc);
486                         Assert.IsNotNull (rd, "#2");
487                         Assert.AreEqual (r, rd.Route, "#2-1");
488                         Assert.AreEqual (0, rd.DataTokens.Count, "#2-2");
489                         Assert.AreEqual (3, rd.Values.Count, "#2-3");
490                         Assert.AreEqual ("blueoyster", rd.Values["bar"], "#2-4");
491                         Assert.AreEqual ("nyc", rd.Values["baz"], "#2-5");
492                         Assert.AreEqual (1, rd.Values["dancefloor"], "#2-6");
493                         Assert.IsTrue (typeof (int) == rd.Values["dancefloor"].GetType (), "#2-7");
494                 }
495
496                 [Test]
497                 public void GetRouteData24 ()
498                 {
499                         var r = new Route ("foo/{bar}-{baz}/{dancefloor}", null) {
500                                         Defaults = new RouteValueDictionary (new { baz = "nyc", dancefloor = 1 })
501                         };
502                                 
503                         var hc = new HttpContextStub ("~/foo/BlueOyster-/1", String.Empty);
504                         var rd = r.GetRouteData (hc);
505                         Assert.IsNull (rd, "#1");
506
507                         hc = new HttpContextStub ("~/foo/blueoyster-", String.Empty);
508                         rd = r.GetRouteData (hc);
509                         Assert.IsNull (rd, "#2");
510
511                         hc = new HttpContextStub ("~/foo/blueoyster-nyc", String.Empty);
512                         rd = r.GetRouteData (hc);
513                         
514                         Assert.IsNotNull (rd, "#3");
515                         Assert.AreEqual (r, rd.Route, "#3-1");
516                         Assert.AreEqual (0, rd.DataTokens.Count, "#3-2");
517                         Assert.AreEqual (3, rd.Values.Count, "#3-3");
518                         Assert.AreEqual ("blueoyster", rd.Values["bar"], "#3-4");
519                         Assert.AreEqual ("nyc", rd.Values["baz"], "#3-5");
520                         Assert.AreEqual (1, rd.Values["dancefloor"], "#3-6");
521                         Assert.IsTrue (typeof (int) == rd.Values["dancefloor"].GetType (), "#3-7");
522
523                         hc = new HttpContextStub ("~/foo/blueoyster-nyc/4", String.Empty);
524                         rd = r.GetRouteData (hc);
525                         
526                         Assert.IsNotNull (rd, "#4");
527                         Assert.AreEqual (r, rd.Route, "#4-1");
528                         Assert.AreEqual (0, rd.DataTokens.Count, "#4-2");
529                         Assert.AreEqual (3, rd.Values.Count, "#4-3");
530                         Assert.AreEqual ("blueoyster", rd.Values["bar"], "#4-4");
531                         Assert.AreEqual ("nyc", rd.Values["baz"], "#4-5");
532                         Assert.AreEqual ("4", rd.Values["dancefloor"], "#4-6");
533                         Assert.IsTrue (typeof (string) == rd.Values["dancefloor"].GetType (), "#4-7");
534                 }
535
536                 [Test]
537                 public void GetRouteData25 ()
538                 {
539                         var r = new Route ("foo/{bar}/{baz}/{dancefloor}", null) {
540                                         Defaults = new RouteValueDictionary (new { baz = "nyc", dancefloor = 1 })
541                         };
542                                 
543                         var hc = new HttpContextStub ("~/foo/BlueOyster", String.Empty);
544                         var rd = r.GetRouteData (hc);
545                         Assert.IsNotNull (rd, "#1");
546                         Assert.AreEqual (r, rd.Route, "#1-1");
547                         Assert.AreEqual (0, rd.DataTokens.Count, "#1-2");
548                         Assert.AreEqual (3, rd.Values.Count, "#1-3");
549                         Assert.AreEqual ("BlueOyster", rd.Values["bar"], "#1-4");
550                         Assert.AreEqual ("nyc", rd.Values["baz"], "#1-5");
551                         Assert.AreEqual (1, rd.Values["dancefloor"], "#1-6");
552                         Assert.IsTrue (typeof (int) == rd.Values["dancefloor"].GetType (), "#1-7");
553                         
554                         hc = new HttpContextStub ("~/foo/blueoyster/bigapple", String.Empty);
555                         rd = r.GetRouteData (hc);
556                         Assert.IsNotNull (rd, "#2");
557                         Assert.AreEqual (r, rd.Route, "#2-1");
558                         Assert.AreEqual (0, rd.DataTokens.Count, "#2-2");
559                         Assert.AreEqual (3, rd.Values.Count, "#2-3");
560                         Assert.AreEqual ("blueoyster", rd.Values["bar"], "#2-4");
561                         Assert.AreEqual ("bigapple", rd.Values["baz"], "#2-5");
562                         Assert.AreEqual (1, rd.Values["dancefloor"], "#2-6");
563                         Assert.IsTrue (typeof (int) == rd.Values["dancefloor"].GetType (), "#2-7");
564                         
565                         hc = new HttpContextStub ("~/foo/blueoyster/bigapple/3", String.Empty);
566                         rd = r.GetRouteData (hc);
567                         
568                         Assert.IsNotNull (rd, "#3");
569                         Assert.AreEqual (r, rd.Route, "#3-1");
570                         Assert.AreEqual (0, rd.DataTokens.Count, "#3-2");
571                         Assert.AreEqual (3, rd.Values.Count, "#3-3");
572                         Assert.AreEqual ("blueoyster", rd.Values["bar"], "#3-4");
573                         Assert.AreEqual ("bigapple", rd.Values["baz"], "#3-5");
574                         Assert.AreEqual ("3", rd.Values["dancefloor"], "#3-6");
575                         Assert.IsTrue (typeof (string) == rd.Values["dancefloor"].GetType (), "#3-7");
576                 }
577
578                 [Test]
579                 public void GetRouteData26 ()
580                 {
581                         var r = new Route ("foo/{bar}/{baz}-{dancefloor}", null) {
582                                         Defaults = new RouteValueDictionary (new { baz = "nyc", dancefloor = 1 })
583                         };
584                                 
585                         var hc = new HttpContextStub ("~/foo/BlueOyster", String.Empty);
586                         var rd = r.GetRouteData (hc);
587                         Assert.IsNull (rd, "#1");
588                         
589                         hc = new HttpContextStub ("~/foo/blueoyster/bigapple", String.Empty);
590                         rd = r.GetRouteData (hc);
591                         Assert.IsNull (rd, "#2");
592                         
593                         hc = new HttpContextStub ("~/foo/blueoyster/bigapple-3", String.Empty);
594                         rd = r.GetRouteData (hc);
595                         
596                         Assert.IsNotNull (rd, "#3");
597                         Assert.AreEqual (r, rd.Route, "#3-1");
598                         Assert.AreEqual (0, rd.DataTokens.Count, "#3-2");
599                         Assert.AreEqual (3, rd.Values.Count, "#3-3");
600                         Assert.AreEqual ("blueoyster", rd.Values["bar"], "#3-4");
601                         Assert.AreEqual ("bigapple", rd.Values["baz"], "#3-5");
602                         Assert.AreEqual ("3", rd.Values["dancefloor"], "#3-6");
603                         Assert.IsTrue (typeof (string) == rd.Values["dancefloor"].GetType (), "#3-7");
604
605                         hc = new HttpContextStub ("~/foo/blueoyster/-", String.Empty);
606                         rd = r.GetRouteData (hc);
607                         
608                         Assert.IsNull (rd, "#4");
609                 }
610
611                 [Test]
612                 public void GetRouteData27 ()
613                 {
614                         var r = new Route ("foo/{bar}/{baz}/{dancefloor}", null) {
615                                         Defaults = new RouteValueDictionary (new { bar = "BlueOyster", dancefloor = 1 })
616                         };
617                                 
618                         var hc = new HttpContextStub ("~/foo/nyc", String.Empty);
619                         var rd = r.GetRouteData (hc);
620                         Assert.IsNull (rd, "#1");
621                 }
622
623                 [Test]
624                 public void GetRouteData28 ()
625                 {
626                         var r = new Route ("{foo}xyz{bar}xyz{baz}", null);
627                         var hc = new HttpContextStub ("~/xyzxyzxyzxyzblah", String.Empty);
628                         var rd = r.GetRouteData (hc);
629
630                         // When running on Mono this test succeeds - it was a bug in .NET routing for 3.5 which
631                         // we don't reproduce anymore.
632                         Assert.IsNotNull (rd, "#1");
633                         Assert.AreEqual (r, rd.Route, "#2");
634                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
635                         Assert.AreEqual (3, rd.Values.Count, "#4");
636                         Assert.AreEqual ("xyz", rd.Values ["foo"], "#4-1");
637                         Assert.AreEqual ("xyz", rd.Values ["bar"], "#4-2");
638                         Assert.AreEqual ("blah", rd.Values ["baz"], "#4-3");
639                 }
640
641                 [Test]
642                 public void GetRouteData29 ()
643                 {
644                         var r = new Route ("{foo}xyz{bar}", null);
645                         var hc = new HttpContextStub ("~/xyzxyzxyzxyzblah", String.Empty);
646                         var rd = r.GetRouteData (hc);
647
648                         Assert.IsNotNull (rd, "#1");
649                         Assert.AreEqual (r, rd.Route, "#2");
650                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
651                         Assert.AreEqual (2, rd.Values.Count, "#4");
652                         Assert.AreEqual ("xyzxyzxyz", rd.Values["foo"], "#4-1");
653                         Assert.AreEqual ("blah", rd.Values["bar"], "#4-2");
654                 }
655
656                 [Test]
657                 public void GetRouteData30 ()
658                 {
659                         var r = new Route ("{foo}/bar/{baz}/boo/{blah}", null) {
660                                         Defaults = new RouteValueDictionary (new { baz = "meep", blah = "blurb" })
661                         };
662                                 
663                         var hc = new HttpContextStub ("~/foo/bar", String.Empty);
664                         var rd = r.GetRouteData (hc);
665
666                         Assert.IsNull (rd, "#1");
667
668                         hc = new HttpContextStub ("~/foo/bar/baz/boo", String.Empty);
669                         rd = r.GetRouteData (hc);
670
671                         Assert.IsNotNull (rd, "#2");
672                         Assert.AreEqual (r, rd.Route, "#3");
673                         Assert.AreEqual (0, rd.DataTokens.Count, "#4");
674                         Assert.AreEqual (3, rd.Values.Count, "#4");
675                         Assert.AreEqual ("foo", rd.Values["foo"], "#4-1");
676                         Assert.AreEqual ("baz", rd.Values["baz"], "#4-2");
677                         Assert.AreEqual ("blurb", rd.Values["blah"], "#4-3");
678                 }
679
680                 [Test(Description = "Bug #523330")]
681                 public void GetRouteData31()
682                 {
683                         var r = new Route("{controller}/{action}", null)
684                         {
685                                 Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index" }),
686                                 DataTokens = new RouteValueDictionary(new { foobar = "bar" })
687                         };
688
689                         var hc = new HttpContextStub("~/", String.Empty);
690                         var rd = r.GetRouteData(hc);
691
692                         Assert.IsNotNull(rd, "#1");
693                         Assert.AreEqual(r, rd.Route, "#2");
694                         Assert.AreEqual(1, rd.DataTokens.Count, "#3");
695                         Assert.AreEqual(2, rd.Values.Count, "#4");
696                         Assert.AreEqual("Home", rd.Values["controller"], "#4-1");
697                         Assert.AreEqual("Index", rd.Values["action"], "#4-2");
698                         Assert.IsNull(rd.Values["foobar"], "#4-3");
699                         Assert.IsNotNull(rd.DataTokens, "#5");
700                         Assert.AreEqual(1, rd.DataTokens.Count, "#6");
701                         Assert.AreEqual("bar", rd.DataTokens["foobar"], "#6-1");
702                 }
703
704                 [Test (Description = "Bug #537751")]
705                 public void GetRouteData32 ()
706                 {
707                         var r = new Route ("", null);
708                         var hc = new HttpContextStub ("~/", String.Empty);
709                         var rd = r.GetRouteData (hc);
710
711                         Assert.IsNotNull (rd, "#1");
712                         Assert.AreEqual (r, rd.Route, "#2");
713                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
714                         Assert.AreEqual (0, rd.Values.Count, "#4");
715                 }
716
717                 [Test (Description = "Bug #537751")]
718                 public void GetRouteData33 ()
719                 {
720                         var r = new Route (null, null);
721                         var hc = new HttpContextStub ("~/", String.Empty);
722                         var rd = r.GetRouteData (hc);
723
724                         Assert.IsNotNull (rd, "#1");
725                         Assert.AreEqual (r, rd.Route, "#2");
726                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
727                         Assert.AreEqual (0, rd.Values.Count, "#4");
728                 }
729
730                 [Test]
731                 public void GetRouteData34 ()
732                 {
733                         var r = new Route ("{foo}xyz{bar}xyz{baz}", null);
734                         var hc = new HttpContextStub ("~/xyzxyzxyzxyzxyzxyzblah", String.Empty);
735                         var rd = r.GetRouteData (hc);
736
737                         // When running on Mono this test succeeds - it was a bug in .NET routing for 3.5 which
738                         // we don't reproduce anymore.
739                         Assert.IsNotNull (rd, "#1");
740                         Assert.AreEqual (r, rd.Route, "#2");
741                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
742                         Assert.AreEqual (3, rd.Values.Count, "#4");
743                         Assert.AreEqual ("xyzxyzxyz", rd.Values ["foo"], "#4-1");
744                         Assert.AreEqual ("xyz", rd.Values ["bar"], "#4-2");
745                         Assert.AreEqual ("blah", rd.Values ["baz"], "#4-3");
746                 }
747
748                 [Test]
749                 public void GetRouteData35 ()
750                 {
751                         var r = new Route ("{foo}xyz{bar}xyz{baz}", null);
752                         var hc = new HttpContextStub ("~/xyzxyzxyzdabxyzblah", String.Empty);
753                         var rd = r.GetRouteData (hc);
754
755                         Assert.IsNotNull (rd, "#1");
756                         Assert.AreEqual (r, rd.Route, "#2");
757                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
758                         Assert.AreEqual (3, rd.Values.Count, "#4");
759                         Assert.AreEqual ("xyzxyz", rd.Values ["foo"], "#4-1");
760                         Assert.AreEqual ("dab", rd.Values ["bar"], "#4-2");
761                         Assert.AreEqual ("blah", rd.Values ["baz"], "#4-3");
762                 }
763
764                 [Test]
765                 public void GetRouteData36 ()
766                 {
767                         var r = new Route ("xyz{foo}xyz{bar}xyz{baz}", null);
768                         var hc = new HttpContextStub ("~/xyzxyzxyzdabxyzblah", String.Empty);
769                         var rd = r.GetRouteData (hc);
770
771                         // When running on Mono this test succeeds - it was a bug in .NET routing for 3.5 which
772                         // we don't reproduce anymore.
773                         Assert.IsNotNull (rd, "#1");
774                         Assert.AreEqual (r, rd.Route, "#2");
775                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
776                         Assert.AreEqual (3, rd.Values.Count, "#4");
777                         Assert.AreEqual ("xyz", rd.Values ["foo"], "#4-1");
778                         Assert.AreEqual ("dab", rd.Values ["bar"], "#4-2");
779                         Assert.AreEqual ("blah", rd.Values ["baz"], "#4-3");
780                 }
781
782                 [Test]
783                 public void GetRouteData37 ()
784                 {
785                         var r = new Route ("{foo}xyz{bar}xyz{baz}", null);
786                         var hc = new HttpContextStub ("~/xyzxyzxyzxyzxyz", String.Empty);
787                         var rd = r.GetRouteData (hc);
788
789                         // When running on Mono this test succeeds - it was a bug in .NET routing for 3.5 which
790                         // we don't reproduce anymore.
791                         Assert.IsNotNull (rd, "#1");
792                         Assert.AreEqual (r, rd.Route, "#2");
793                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
794                         Assert.AreEqual (3, rd.Values.Count, "#4");
795                         Assert.AreEqual ("xyz", rd.Values ["foo"], "#4-1");
796                         Assert.AreEqual ("xyz", rd.Values ["bar"], "#4-2");
797                         Assert.AreEqual ("xyz", rd.Values ["baz"], "#4-3");
798                 }
799
800                 [Test]
801                 public void GetRouteData38 ()
802                 {
803                         // {} matches and substitutes even at partial state ...
804                         var r = new Route ("{foo}/bar{baz}", null);
805                         var hc = new HttpContextStub ("~/x/bartest", String.Empty);
806                         var rd = r.GetRouteData (hc);
807                         Assert.IsNotNull (rd, "#1");
808                         Assert.AreEqual (r, rd.Route, "#2");
809                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
810                         Assert.AreEqual (2, rd.Values.Count, "#4");
811                         Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
812                         Assert.AreEqual ("test", rd.Values ["baz"], "#4-2");
813                 }
814
815                 [Test]
816                 public void GetRouteData39 ()
817                 {
818                         // {} matches and substitutes even at partial state ...
819                         var r = new Route ("{foo}/bar{baz}", null);
820                         var hc = new HttpContextStub ("~/x/barte", String.Empty);
821                         var rd = r.GetRouteData (hc);
822                         Assert.IsNotNull (rd, "#1");
823                         Assert.AreEqual (r, rd.Route, "#2");
824                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
825                         Assert.AreEqual (2, rd.Values.Count, "#4");
826                         Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
827                         Assert.AreEqual ("te", rd.Values ["baz"], "#4-2");
828                 }
829
830                 [Test]
831                 public void GetRouteData40 ()
832                 {
833                         // {} matches and substitutes even at partial state ...
834                         var r = new Route ("{foo}/bar{baz}", null);
835                         var hc = new HttpContextStub ("~/x/bartes", String.Empty);
836                         var rd = r.GetRouteData (hc);
837                         Assert.IsNotNull (rd, "#1");
838                         Assert.AreEqual (r, rd.Route, "#2");
839                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
840                         Assert.AreEqual (2, rd.Values.Count, "#4");
841                         Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
842                         Assert.AreEqual ("tes", rd.Values ["baz"], "#4-2");
843                 }
844
845                 [Test]
846                 public void GetRouteData41 ()
847                 {
848                         // {} matches and substitutes even at partial state ...
849                         var r = new Route ("{foo}/bartes{baz}", null);
850                         var hc = new HttpContextStub ("~/x/bartest", String.Empty);
851                         var rd = r.GetRouteData (hc);
852                         Assert.IsNotNull (rd, "#1");
853                         Assert.AreEqual (r, rd.Route, "#2");
854                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
855                         Assert.AreEqual (2, rd.Values.Count, "#4");
856                         Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
857                         Assert.AreEqual ("t", rd.Values ["baz"], "#4-2");
858                 }
859
860                 [Test]
861                 public void GetRouteData42 ()
862                 {
863                         // {} matches and substitutes even at partial state ...
864                         var r = new Route ("{foo}/bartes{baz}", null);
865                         var hc = new HttpContextStub ("~/x/bartest1", String.Empty);
866                         var rd = r.GetRouteData (hc);
867                         Assert.IsNotNull (rd, "#1");
868                         Assert.AreEqual (r, rd.Route, "#2");
869                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
870                         Assert.AreEqual (2, rd.Values.Count, "#4");
871                         Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
872                         Assert.AreEqual ("t1", rd.Values ["baz"], "#4-2");
873                 }
874
875                 [Test]
876                 public void GetRouteData43 ()
877                 {
878                         // {} matches and substitutes even at partial state ...
879                         var r = new Route ("{foo}-{bar}-{baz}", null);
880                         var hc = new HttpContextStub ("~/--", String.Empty);
881                         var rd = r.GetRouteData (hc);
882                         Assert.IsNull (rd, "#1");
883
884                         hc = new HttpContextStub ("~/1-2-3", String.Empty);
885                         rd = r.GetRouteData (hc);
886                         Assert.IsNotNull (rd, "#2");
887                         Assert.AreEqual (r, rd.Route, "#2");
888                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
889                         Assert.AreEqual (3, rd.Values.Count, "#4");
890                         Assert.AreEqual ("1", rd.Values ["foo"], "#4-1");
891                         Assert.AreEqual ("2", rd.Values ["bar"], "#4-2");
892                         Assert.AreEqual ("3", rd.Values ["baz"], "#4-2");
893                 }
894
895                 [Test]
896                 public void GetRouteData44 ()
897                 {
898                         // {} matches and substitutes even at partial state ...
899                         var r = new Route ("{foo}/bartes{baz}", null);
900                         var hc = new HttpContextStub ("~/x/bartest/", String.Empty);
901                         var rd = r.GetRouteData (hc);
902                         Assert.IsNotNull (rd, "#1");
903                         Assert.AreEqual (r, rd.Route, "#2");
904                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
905                         Assert.AreEqual (2, rd.Values.Count, "#4");
906                         Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
907                         Assert.AreEqual ("t", rd.Values ["baz"], "#4-2");
908                 }
909
910                 [Test]
911                 public void GetRouteData45 ()
912                 {
913                         var r = new Route ("{foo}/{bar}", null);
914                         var hc = new HttpContextStub ("~/x/y/", String.Empty);
915                         var rd = r.GetRouteData (hc);
916                         Assert.IsNotNull (rd, "#1");
917                         Assert.AreEqual (r, rd.Route, "#2");
918                         Assert.AreEqual (0, rd.DataTokens.Count, "#3");
919                         Assert.AreEqual (2, rd.Values.Count, "#4");
920                         Assert.AreEqual ("x", rd.Values ["foo"], "#4-1");
921                         Assert.AreEqual ("y", rd.Values ["bar"], "#4-2");
922                 }
923
924                 [Test (Description="Bug #651593")]
925                 public void GetRouteData46 ()
926                 {
927                         var r = new Route ("Foo", null) {
928                                 Defaults = new RouteValueDictionary (new {
929                                         controller = "Foo",
930                                         action = "Index"
931                                 })
932                         };
933                         var hc = new HttpContextStub ("/Foo/123", String.Empty);
934                         var rd = r.GetRouteData (hc);
935                         Assert.IsNull (rd, "#1");
936
937                         r = new Route ("Foo", null) {
938                                 Defaults = new RouteValueDictionary (new {
939                                         controller = "Foo",
940                                         action = "Index"
941                                 })
942                         };
943                         hc = new HttpContextStub ("~/Foo/123", String.Empty);
944                         rd = r.GetRouteData (hc);
945                         Assert.IsNull (rd, "#2");
946                 }
947
948                 [Test (Description="Bug #651966")]
949                 public void GetRouteData47 ()
950                 {
951                         var r = new Route ("Foo/{id}", new StopRoutingHandler ()) {
952                                 Defaults = new RouteValueDictionary (new {
953                                         controller = "Foo",
954                                         action = "Retrieve"
955                                 }),
956                                 Constraints = new RouteValueDictionary (new {
957                                         id = @"\d{1,10}"
958                                 })
959                         };
960                         
961                         var hc = new HttpContextStub ("~/Foo/x123", String.Empty);
962                         var rd = r.GetRouteData (hc);
963
964                         Assert.IsNull (rd, "#1");
965                 }
966
967                 [Test]
968                 public void GetRouteDataWithCatchAll ()
969                 {
970                         var r = new Route ("{*path}", new StopRoutingHandler ()) {
971                                 Defaults = new RouteValueDictionary (new {
972                                         controller = "Error",
973                                         action = "NotFound"
974                                 })
975                         };
976
977                         var hc = new HttpContextStub ("~/", String.Empty);
978                         var rd = r.GetRouteData (hc);
979
980                         Assert.IsNotNull (rd, "#1");
981
982                         hc = new HttpContextStub ("~/Foo/x123", String.Empty);
983                         rd = r.GetRouteData (hc);
984
985                         Assert.IsNotNull (rd, "#2");
986                 }
987
988                 [Test]
989                 public void GetRouteDataWithCatchAll2 ()
990                 {
991                         var r = new Route ("something/{*path}", new StopRoutingHandler ()) {
992                                 Defaults = new RouteValueDictionary (new {
993                                         controller = "Error",
994                                         action = "NotFound"
995                                 })
996                         };
997
998                         var hc = new HttpContextStub ("~/", String.Empty);
999                         var rd = r.GetRouteData (hc);
1000
1001                         Assert.IsNull (rd, "#1");
1002
1003                         hc = new HttpContextStub ("~/something", String.Empty);
1004                         rd = r.GetRouteData (hc);
1005
1006                         Assert.IsNotNull (rd, "#2");
1007                         Assert.IsNull (rd.Values["path"], "#2.1");
1008
1009                         hc = new HttpContextStub ("~/something/", String.Empty);
1010                         rd = r.GetRouteData (hc);
1011
1012                         Assert.IsNotNull (rd, "#3");
1013                         Assert.IsNull (rd.Values["path"], "#3.1");
1014
1015                         hc = new HttpContextStub ("~/something/algo", String.Empty);
1016                         rd = r.GetRouteData (hc);
1017
1018                         Assert.IsNotNull (rd, "#4");
1019                         Assert.AreEqual ("algo", rd.Values["path"], "#4.1");
1020
1021                 }
1022
1023                 [Test]
1024                 [ExpectedException (typeof (ArgumentNullException))]
1025                 public void GetVirtualPathNullContext ()
1026                 {
1027                         try {
1028                                 var r = new Route (null, null);
1029                                 r.GetVirtualPath (null, new RouteValueDictionary ());
1030                         } catch (NullReferenceException) {
1031                                 // .NET lacks null arg check here. (No need to mimic silly behavior here.)
1032                                 throw new ArgumentNullException ();
1033                         }
1034                 }
1035
1036                 [Test]
1037                 public void GetVirtualPathNullValues ()
1038                 {
1039                         // null values is allowed.
1040                         var r = new Route (null, null);
1041                         var rd = new RouteData ();
1042                         var vp = r.GetVirtualPath (new RequestContext (new HttpContextStub (), rd), null);
1043                         Assert.AreEqual (String.Empty, vp.VirtualPath, "#1");
1044                         Assert.AreEqual (r, vp.Route, "#2");
1045                 }
1046
1047                 [Test]
1048                 public void GetVirtualPath ()
1049                 {
1050                         var r = new Route ("foo/bar", null);
1051                         var rd = new RouteData ();
1052                         var vp = r.GetVirtualPath (new RequestContext (new HttpContextStub ("~/foo/bar"), rd), null);
1053                         Assert.AreEqual ("foo/bar", vp.VirtualPath, "#1");
1054                         Assert.AreEqual (r, vp.Route, "#2");
1055
1056                         vp = r.GetVirtualPath (new RequestContext (new HttpContextStub ("~/foo/bar/baz"), rd), null);
1057                         Assert.AreEqual ("foo/bar", vp.VirtualPath, "#3");
1058                         Assert.AreEqual (r, vp.Route, "#4");
1059                 }
1060
1061                 [Test]
1062                 public void GetVirtualPath2 ()
1063                 {
1064                         var r = new Route ("{foo}/{bar}", null);
1065                         var hc = new HttpContextStub ("~/x/y", String.Empty);
1066                         var rd = r.GetRouteData (hc);
1067                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), null);
1068                         Assert.IsNotNull (vp, "#1");
1069                         Assert.AreEqual ("x/y", vp.VirtualPath, "#2");
1070                         Assert.AreEqual (r, vp.Route, "#3");
1071                         Assert.AreEqual (0, vp.DataTokens.Count, "#4");
1072                 }
1073
1074                 [Test]
1075                 public void GetVirtualPath3 ()
1076                 {
1077                         var r = new MyRoute ("{foo}/{bar}", new MyRouteHandler ());
1078                         var hc = new HttpContextStub2 ("~/x/y", String.Empty);
1079                         var rd = r.GetRouteData (hc);
1080                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), rd.Values);
1081
1082                         Assert.IsNotNull (vp, "#1");
1083                         Assert.AreEqual ("x/y", vp.VirtualPath, "#2");
1084                         Assert.AreEqual (r, vp.Route, "#3");
1085                         Assert.AreEqual (0, vp.DataTokens.Count, "#4");
1086                 }
1087
1088                 [Test]
1089                 public void GetVirtualPath4 ()
1090                 {
1091                         var r = new MyRoute ("{foo}/{bar}", new MyRouteHandler ());
1092                         var hc = new HttpContextStub2 ("~/x/y", String.Empty);
1093                         var rd = r.GetRouteData (hc);
1094
1095                         // override a value incompletely
1096                         var values = new RouteValueDictionary ();
1097                         values ["foo"] = "A";
1098
1099                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1100                         Assert.IsNull (vp);
1101                 }
1102
1103                 [Test]
1104                 public void GetVirtualPath4_2 ()
1105                 {
1106                         var r = new MyRoute("{foo}/{bar}", new MyRouteHandler());
1107                         var hc = new HttpContextStub2("~/x/y", String.Empty);
1108                         var rd = r.GetRouteData(hc);
1109
1110                         // override a value incompletely
1111                         var values = new RouteValueDictionary();
1112                         values["bar"] = "A";
1113
1114                         var vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1115                         Assert.IsNotNull(vp);
1116                         Assert.AreEqual("x/A", vp.VirtualPath);
1117                 }
1118
1119                 [Test]
1120                 public void GetVirtualPath4Bis ()
1121                 {
1122                         var r = new MyRoute("part/{foo}/{bar}", new MyRouteHandler());
1123                         var hc = new HttpContextStub2("~/part/x/y", String.Empty);
1124                         var rd = r.GetRouteData(hc);
1125
1126                         // override a value incompletely
1127                         var values = new RouteValueDictionary();
1128                         values["foo"] = "A";
1129
1130                         var vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1131                         Assert.IsNull(vp);
1132                 }
1133
1134                 [Test]
1135                 public void GetVirtualPath4_2Bis ()
1136                 {
1137                         var r = new MyRoute("part/{foo}/{bar}", new MyRouteHandler());
1138                         var hc = new HttpContextStub2("~/part/x/y", String.Empty);
1139                         var rd = r.GetRouteData(hc);
1140
1141                         // override a value incompletely
1142                         var values = new RouteValueDictionary();
1143                         values["bar"] = "A";
1144
1145                         var vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1146                         Assert.IsNotNull(vp);
1147                         Assert.AreEqual("part/x/A", vp.VirtualPath);
1148                 }
1149
1150                 [Test]
1151                 public void GetVirtualPath5 ()
1152                 {
1153                         var r = new MyRoute ("{foo}/{bar}", new MyRouteHandler ());
1154                         var hc = new HttpContextStub2 ("~/x/y", String.Empty);
1155                         var rd = r.GetRouteData (hc);
1156
1157                         // override values completely.
1158                         var values = new RouteValueDictionary ();
1159                         values ["foo"] = "A";
1160                         values ["bar"] = "B";
1161
1162                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1163
1164                         Assert.IsNotNull (vp, "#1");
1165                         Assert.AreEqual ("A/B", vp.VirtualPath, "#2");
1166                         Assert.AreEqual (r, vp.Route, "#3");
1167                         Assert.AreEqual (0, vp.DataTokens.Count, "#4");
1168                 }
1169
1170                 [Test]
1171                 public void GetVirtualPath6 ()
1172                 {
1173                         var r = new MyRoute ("summary/{action}-{type}/{page}", new MyRouteHandler ()) {
1174                                         Defaults = new RouteValueDictionary (new { action = "Index", page = 1 })
1175                                                 };
1176                         var hc = new HttpContextStub2 ("~/summary/Index-test/1", String.Empty);
1177                         var rd = r.GetRouteData (hc);
1178                         var values = new RouteValueDictionary (new { page = 2 });
1179
1180                         Assert.IsNotNull (rd, "#1");
1181                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1182
1183                         Assert.IsNotNull (vp, "#2");
1184                         Assert.AreEqual ("summary/Index-test/2", vp.VirtualPath, "#2-1");
1185                         Assert.AreEqual (r, vp.Route, "#2-2");
1186                         Assert.AreEqual (0, vp.DataTokens.Count, "#2-3");
1187
1188                         values = new RouteValueDictionary (new { page = 2, extra = "stuff" });
1189                         vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1190
1191                         Assert.IsNotNull (vp, "#3");
1192                         Assert.AreEqual ("summary/Index-test/2?extra=stuff", vp.VirtualPath, "#3-2");
1193                         Assert.AreEqual (0, vp.DataTokens.Count, "#3-3");
1194                 }
1195
1196                 [Test]
1197                 public void GetVirtualPath7 ()
1198                 {
1199                         var r = new MyRoute ("summary/{action}-{type}/{page}", new MyRouteHandler ()) {
1200                                         Defaults = new RouteValueDictionary (new { action = "Index", page = 1 })
1201                         };
1202                         var hc = new HttpContextStub2 ("~/summary/Index-test/1", String.Empty);
1203                         var rd = r.GetRouteData (hc);
1204                         var values = new RouteValueDictionary (new { page = 2 });
1205
1206                         Assert.IsNotNull (rd, "#1");
1207                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1208
1209                         Assert.IsNotNull (vp, "#2");
1210                         Assert.AreEqual ("summary/Index-test/2", vp.VirtualPath, "#2-1");
1211                         Assert.AreEqual (r, vp.Route, "#2-2");
1212                         Assert.AreEqual (0, vp.DataTokens.Count, "#2-3");
1213                 }
1214
1215                 [Test]
1216                 public void GetVirtualPath8 ()
1217                 {
1218                         var r = new MyRoute ("todo/{action}/{page}", new MyRouteHandler ()) {
1219                                         Defaults = new RouteValueDictionary (new { controller="todo", action="list", page=0 })
1220                         };
1221                         var hc = new HttpContextStub2 ("~/todo/list/2", String.Empty);
1222                         var rd = r.GetRouteData (hc);
1223
1224                         Assert.IsNotNull (rd, "#1");
1225                         
1226                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), new RouteValueDictionary (new { page = 3 }));
1227                         Assert.IsNotNull (vp, "#2");
1228                         Assert.AreEqual ("todo/list/3", vp.VirtualPath, "#2-1");
1229                 }
1230
1231                 [Test]
1232                 public void GetVirtualPath9 ()
1233                 {
1234                         var r = new MyRoute ("todo/{action}/{page}", new MyRouteHandler ()) {
1235                                         Defaults = new RouteValueDictionary {
1236                                                         {"controller", "todo"},
1237                                                         {"action", null},
1238                                                         {"page", null}
1239                                                 }
1240                                 };
1241                         
1242                         var hc = new HttpContextStub2 ("~/todo/list/2", String.Empty);
1243                         var rd = r.GetRouteData (hc);
1244
1245                         Assert.IsNotNull (rd, "#1");
1246                         
1247                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), new RouteValueDictionary (new { page = 3 }));
1248                         Assert.IsNotNull (vp, "#2");
1249                         Assert.AreEqual ("todo/list/3", vp.VirtualPath, "#2-1");
1250                 }
1251
1252                 [Test]
1253                 public void GetVirtualPath10 ()
1254                 {
1255                         var r = new MyRoute ("{foo}/{bar}", new MyRouteHandler ());
1256                         var hc = new HttpContextStub ("~/foo/bar", String.Empty);
1257                         var rd = r.GetRouteData (hc);
1258
1259                         Assert.IsNotNull (rd, "#1");
1260
1261                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), new RouteValueDictionary (new { page = 3 }));
1262                         Assert.IsNotNull (vp, "#2");
1263                         Assert.AreEqual ("foo/bar?page=3", vp.VirtualPath, "#2-1");
1264
1265                         vp = r.GetVirtualPath (new RequestContext (hc, rd), new RouteValueDictionary (new { page = 3, another = "stuff" }));
1266                         Assert.IsNotNull (vp, "#3");
1267                         Assert.AreEqual ("foo/bar?page=3&another=stuff", vp.VirtualPath, "#3-1");
1268
1269                         vp = r.GetVirtualPath (new RequestContext (hc, rd), new RouteValueDictionary (new { page = 3, another = "stuff", value = "with ; spaces & other chars" }));
1270                         Assert.IsNotNull (vp, "#4");
1271                         Assert.AreEqual ("foo/bar?page=3&another=stuff&value=with%20%3B%20spaces%20%26%20other%20chars", vp.VirtualPath, "#4-1");
1272                 }
1273
1274                 [Test]
1275                 public void GetVirtualPath11 ()
1276                 {
1277                         var r = new MyRoute ("summary/{action}/{page}", new MyRouteHandler ()) {
1278                                         Defaults = new RouteValueDictionary (new { action = "Index", page = 1 })
1279                                                 };
1280                         var hc = new HttpContextStub2 ("~/summary/test/1", String.Empty);
1281                         var rd = r.GetRouteData (hc);
1282                         var values = new RouteValueDictionary (new { page = 2 });
1283
1284                         Assert.IsNotNull (rd, "#1");
1285                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1286
1287                         Assert.IsNotNull (vp, "#2");
1288                         Assert.AreEqual ("summary/test/2", vp.VirtualPath, "#2-1");
1289                         Assert.AreEqual (r, vp.Route, "#2-2");
1290                         Assert.AreEqual (0, vp.DataTokens.Count, "#2-3");
1291
1292                         values = new RouteValueDictionary (new { page = 2, extra = "stuff" });
1293                         vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1294
1295                         Assert.IsNotNull (vp, "#3");
1296                         Assert.AreEqual ("summary/test/2?extra=stuff", vp.VirtualPath, "#3-2");
1297                         Assert.AreEqual (0, vp.DataTokens.Count, "#3-3");
1298                 }
1299
1300                 [Test]
1301                 public void GetVirtualPath12 ()
1302                 {
1303                         var r = new MyRoute ("{foo}/{bar}", new MyRouteHandler ()) {
1304                                         Defaults = new RouteValueDictionary (new { bar = "baz" })
1305                                                 };
1306                                                 
1307                         var hc = new HttpContextStub2 ("~/x/y", String.Empty);
1308                         var rd = r.GetRouteData (hc);
1309                         var values = new RouteValueDictionary ();
1310
1311                         // Partial override is possible if defaults are specified
1312                         values ["foo"] = "A";
1313                         values ["baz"] = "B";
1314                         
1315                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1316                         Assert.IsNotNull (vp, "#1");
1317                         Assert.AreEqual ("A?baz=B", vp.VirtualPath, "#1-1");
1318                 }
1319
1320                 [Test]
1321                 public void GetVirtualPath13 ()
1322                 {
1323                         var r = new MyRoute ("{foo}/{bar}", new MyRouteHandler ()) {
1324                                         Defaults = new RouteValueDictionary (new { baz = "baz" })
1325                                                 };
1326                         var hc = new HttpContextStub2 ("~/x/y", String.Empty);
1327                         var rd = r.GetRouteData (hc);
1328
1329                         // override a value incompletely
1330                         var values = new RouteValueDictionary ();
1331                         values ["foo"] = "A";
1332
1333                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1334                         Assert.IsNull (vp);
1335                 }
1336
1337                 [Test]
1338                 public void GetVirtualPath14 ()
1339                 {
1340                         var r = new MyRoute ("{table}/{action}.aspx", new MyRouteHandler ());
1341                         var hc = new HttpContextStub2 ("~/x/y.aspx", String.Empty);
1342                         var rd = r.GetRouteData (hc);
1343
1344                         // override a value incompletely
1345                         var values = new RouteValueDictionary (new {
1346                                 emptyValue = String.Empty,
1347                                 nullValue = (string)null,
1348                                 nonEmptyValue = "SomeValue"
1349                         });
1350
1351                         var vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1352                         Assert.IsNotNull (vp, "#A1");
1353                         Assert.AreEqual ("x/y.aspx?nonEmptyValue=SomeValue", vp.VirtualPath, "#A1-1");
1354
1355                         values["nonEmptyValue"] = "Some Value + encoding &";
1356                         vp = r.GetVirtualPath (new RequestContext (hc, rd), values);
1357                         Assert.IsNotNull (vp, "#B1");
1358                         Assert.AreEqual ("x/y.aspx?nonEmptyValue=Some%20Value%20%2B%20encoding%20%26", vp.VirtualPath, "#B1-1");
1359
1360                 }
1361                 
1362                 [Test (Description="Bug #671753")]
1363                 public void GetVirtualPath15 ()
1364                 {
1365                         var context = new HttpContextWrapper (
1366                                 new HttpContext (new HttpRequest ("filename", "http://localhost/filename", String.Empty),
1367                                                  new HttpResponse (new StringWriter())
1368                                 )
1369                         );
1370                         var rc = new RequestContext (context, new RouteData ());
1371
1372                         Assert.IsNotNull (RouteTable.Routes, "#A1");
1373                         RouteTable.Routes.MapPageRoute ("TestRoute", "{language}/testroute", "~/TestRoute.aspx", true, null,
1374                                                         new RouteValueDictionary {{"language", "(ru|en)"}});
1375
1376                         Assert.IsNotNull(RouteTable.Routes.GetVirtualPath (rc, "TestRoute", new RouteValueDictionary {{"language", "en"}}), "#A2");
1377
1378                         rc.RouteData.Values["language"] = "ru";
1379                         Assert.IsNotNull (RouteTable.Routes.GetVirtualPath (rc, "TestRoute", new RouteValueDictionary ()), "#A3");
1380                         Assert.IsNotNull (RouteTable.Routes.GetVirtualPath (rc, "TestRoute", null), "#A4");
1381                 }
1382
1383                 [Test (Description="Xamarin Bug #9116")]
1384                 public void GetVirtualPath16 ()
1385                 {
1386                         var context = new HttpContextWrapper (
1387                                 new HttpContext (new HttpRequest ("filename", "http://localhost/filename", String.Empty),
1388                                                  new HttpResponse (new StringWriter())
1389                                 )
1390                         );
1391                         var rc = new RequestContext (context, new RouteData ());
1392
1393                         var route = new Route ("Hello", new MyRouteHandler ()) {
1394                                         Defaults = new RouteValueDictionary (new {controller = "Home", action = "Hello", page = 1})
1395                         };
1396
1397                         var routeValues = new RouteValueDictionary
1398                         {
1399                                 {"controller", "Home"},
1400                                 {"action", "Hello"},
1401                                 {"page", 1}
1402                         };
1403
1404                         var result = route.GetVirtualPath(rc, routeValues);
1405                         Assert.IsNotNull(result, "#A1");
1406                         Assert.AreEqual("Hello", result.VirtualPath, "#A2");
1407                 }
1408
1409                 [Test (Description="Xamarin Bug #9116")]
1410                 public void GetVirtualPath17 () 
1411                 {
1412                         var context = new HttpContextWrapper (
1413                                 new HttpContext (new HttpRequest ("filename", "http://localhost/filename", String.Empty),
1414                                                  new HttpResponse (new StringWriter())
1415                                 )
1416                         );
1417                         var rc = new RequestContext (context, new RouteData ());
1418
1419                         RouteTable.Routes.Add("FirstPage", new Route ("Hello/FirstPage", new MyRouteHandler ()) {
1420                                         Defaults = new RouteValueDictionary (new {controller = "Home", action = "Hello", page = 1})
1421                         });
1422                         RouteTable.Routes.Add("OtherPages", new Route ("Hello/Page-{page}", new MyRouteHandler ()) {
1423                                         Defaults = new RouteValueDictionary (new {controller = "Home", action = "Hello"})
1424                         });
1425
1426                         var firstPageRouteValues = new RouteValueDictionary
1427                         {
1428                                 {"controller", "Home"},
1429                                 {"action", "Hello"},
1430                                 {"page", 1}
1431                         };
1432                         var secondPageRouteValues = new RouteValueDictionary
1433                         {
1434                                 {"controller", "Home"},
1435                                 {"action", "Hello"},
1436                                 {"page", 2}
1437                         };
1438
1439                         var firstPageResult = RouteTable.Routes.GetVirtualPath (rc, firstPageRouteValues);
1440                         var secondPageResult = RouteTable.Routes.GetVirtualPath (rc, secondPageRouteValues);
1441
1442                         Assert.AreEqual ("/Hello/FirstPage", firstPageResult.VirtualPath, "#A1");
1443                         Assert.AreEqual ("/Hello/Page-2", secondPageResult.VirtualPath, "#A2");
1444                 }
1445
1446                 [Test (Description="Xamarin Bug #9116")]
1447                 public void GetVirtualPath18 () 
1448                 {
1449                         var context = new HttpContextWrapper (
1450                                 new HttpContext (new HttpRequest ("filename", "http://localhost/filename", String.Empty),
1451                                                  new HttpResponse (new StringWriter())
1452                                 )
1453                         );
1454                         var rc = new RequestContext (context, new RouteData ());
1455
1456                         RouteTable.Routes.Add("Published", new Route ("Posts/Published", new MyRouteHandler ()) {
1457                                         Defaults = new RouteValueDictionary (new {controller = "Home", action = "Posts", published = true})
1458                         });
1459                         RouteTable.Routes.Add("Unpublished", new Route ("Posts/Unpublished", new MyRouteHandler ()) {
1460                                         Defaults = new RouteValueDictionary (new {controller = "Home", action = "Posts", published = false})
1461                         });
1462
1463                         var publishedRouteValues = new RouteValueDictionary
1464                         {
1465                                 {"controller", "Home"},
1466                                 {"action", "Posts"},
1467                                 {"published", true}
1468                         };
1469                         var unpublishedRouteValues = new RouteValueDictionary
1470                         {
1471                                 {"controller", "Home"},
1472                                 {"action", "Posts"},
1473                                 {"published", false}
1474                         };
1475
1476                         var publishedResult = RouteTable.Routes.GetVirtualPath (rc, publishedRouteValues);
1477                         var unpublishedResult = RouteTable.Routes.GetVirtualPath (rc, unpublishedRouteValues);
1478
1479                         Assert.AreEqual ("/Posts/Published", publishedResult.VirtualPath, "#A1");
1480                         Assert.AreEqual ("/Posts/Unpublished", unpublishedResult.VirtualPath, "#A2");
1481                 }
1482
1483                 [Test (Description="Routes should be case insensitive - Xamarin bug #9133")]
1484                 public void GetVirtualPath19 ()
1485                 {
1486                         var context = new HttpContextWrapper (
1487                                 new HttpContext (new HttpRequest ("filename", "http://localhost/filename", String.Empty),
1488                                                  new HttpResponse (new StringWriter())
1489                                 )
1490                         );
1491                         var rc = new RequestContext (context, new RouteData ());
1492
1493                         var route = new Route ("HelloWorld", new MyRouteHandler ()) {
1494                                         Defaults = new RouteValueDictionary (new {controller = "Home", action = "HelloWorld"})
1495                         };
1496
1497                         var lowercase = route.GetVirtualPath (rc, new RouteValueDictionary
1498                         {
1499                                 {"controller", "home"},
1500                                 {"action", "helloworld"}
1501                         });
1502                         var standardCase = route.GetVirtualPath (rc, new RouteValueDictionary
1503                         {
1504                                 {"controller", "Home"},
1505                                 {"action", "HelloWorld"}
1506                         });
1507                         var uppercase = route.GetVirtualPath (rc, new RouteValueDictionary
1508                         {
1509                                 {"controller", "HOME"},
1510                                 {"action", "HELLOWORLD"}
1511                         });
1512
1513                         Assert.IsNotNull(lowercase, "#A1");
1514                         Assert.AreEqual ("HelloWorld", lowercase.VirtualPath, "#A2");
1515
1516                         Assert.IsNotNull(standardCase, "#A3");
1517                         Assert.AreEqual ("HelloWorld", standardCase.VirtualPath, "#A4");
1518
1519                         Assert.IsNotNull(uppercase, "#A5");
1520                         Assert.AreEqual ("HelloWorld", uppercase.VirtualPath, "#A6");
1521                 }
1522
1523                 [Test]
1524                 public void GetVirtualPath20 ()
1525                 {
1526                         var r = new MyRoute("summary/{controller}/{id}/{action}", new MyRouteHandler())
1527                         {
1528                                 Defaults = new RouteValueDictionary(new { action = "Index" })
1529                         };
1530                         var hc = new HttpContextStub2("~/summary/kind/1/test", String.Empty);
1531                         var rd = r.GetRouteData(hc);
1532                         Assert.IsNotNull(rd, "#1");
1533
1534                         var values = new RouteValueDictionary(new { id = "2", action = "save" });
1535                         var vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1536
1537                         Assert.IsNotNull(vp, "#2");
1538                         Assert.AreEqual("summary/kind/2/save", vp.VirtualPath, "#2-1");
1539                         Assert.AreEqual(r, vp.Route, "#2-2");
1540                         Assert.AreEqual(0, vp.DataTokens.Count, "#2-3");
1541
1542                         values = new RouteValueDictionary(new { id = "3", action = "save", extra = "stuff" });
1543                         vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1544
1545                         Assert.IsNotNull(vp, "#3");
1546                         Assert.AreEqual("summary/kind/3/save?extra=stuff", vp.VirtualPath, "#3-2");
1547                         Assert.AreEqual(0, vp.DataTokens.Count, "#3-3");
1548                 }
1549
1550                 [Test]
1551                 public void GetVirtualPath21 ()
1552                 {
1553                         var r = new MyRoute("summary/{controller}/{id}/{action}", new MyRouteHandler())
1554                         {
1555                                 Defaults = new RouteValueDictionary(new { action = "Index" })
1556                         };
1557                         var hc = new HttpContextStub2("~/summary/kind/1/test", String.Empty);
1558                         var rd = r.GetRouteData(hc);
1559                         Assert.IsNotNull(rd, "#1");
1560                         Assert.AreEqual("1", rd.Values["id"]);
1561
1562                         var values = new RouteValueDictionary(new { action = "save" });
1563                         var vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1564
1565                         Assert.IsNotNull(vp, "#2");
1566                         Assert.AreEqual("summary/kind/1/save", vp.VirtualPath, "#2-1");
1567                         Assert.AreEqual(r, vp.Route, "#2-2");
1568                         Assert.AreEqual(0, vp.DataTokens.Count, "#2-3");
1569
1570                         values = new RouteValueDictionary(new { action = "save", extra = "stuff" });
1571                         vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1572
1573                         Assert.IsNotNull(vp, "#3");
1574                         Assert.AreEqual("summary/kind/1/save?extra=stuff", vp.VirtualPath, "#3-2");
1575                         Assert.AreEqual(0, vp.DataTokens.Count, "#3-3");
1576                 }
1577
1578                 [Test]
1579                 public void GetVirtualPath22 ()
1580                 {
1581                         var r = new MyRoute("summary/{controller}/{id}/{action}", new MyRouteHandler())
1582                         {
1583                                 Defaults = new RouteValueDictionary(new { action = "Index" })
1584                         };
1585                         var hc = new HttpContextStub2("~/summary/kind/90941a4f-daf3-4c89-a6dc-83e8de4e3db5/test", String.Empty);
1586                         var rd = r.GetRouteData(hc);
1587                         Assert.IsNotNull(rd, "#0");
1588                         Assert.AreEqual("90941a4f-daf3-4c89-a6dc-83e8de4e3db5", rd.Values["id"]);
1589
1590                         var values = new RouteValueDictionary(new { action = "Index" });
1591                         var vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1592
1593                         Assert.IsNotNull(vp, "#1");
1594                         Assert.AreEqual("summary/kind/90941a4f-daf3-4c89-a6dc-83e8de4e3db5", vp.VirtualPath, "#1-1");
1595                         Assert.AreEqual(r, vp.Route, "#1-2");
1596                         Assert.AreEqual(0, vp.DataTokens.Count, "#1-3");
1597
1598                         values = new RouteValueDictionary(new { action = "save" });
1599                         vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1600
1601                         Assert.IsNotNull(vp, "#2");
1602                         Assert.AreEqual("summary/kind/90941a4f-daf3-4c89-a6dc-83e8de4e3db5/save", vp.VirtualPath, "#2-1");
1603                         Assert.AreEqual(r, vp.Route, "#2-2");
1604                         Assert.AreEqual(0, vp.DataTokens.Count, "#2-3");
1605
1606                         values = new RouteValueDictionary(new { action = "save", extra = "stuff" });
1607                         vp = r.GetVirtualPath(new RequestContext(hc, rd), values);
1608
1609                         Assert.IsNotNull(vp, "#3");
1610                         Assert.AreEqual("summary/kind/90941a4f-daf3-4c89-a6dc-83e8de4e3db5/save?extra=stuff", vp.VirtualPath, "#3-2");
1611                         Assert.AreEqual(0, vp.DataTokens.Count, "#3-3");
1612                 }
1613
1614                 [Test]
1615                 public void GetVirtualPath23 ()
1616                 {
1617                         var r0 = new MyRoute ("summary/{id}", new MyRouteHandler());
1618                         var r1 = new MyRoute ("summary/{controller}/{id}/{action}", new MyRouteHandler())
1619                         {
1620                                 Defaults = new RouteValueDictionary (new { action = "Index" })
1621                         };
1622                         var hc = new HttpContextStub2 ("~/summary/90941a4f-daf3-4c89-a6dc-83e8de4e3db5", String.Empty);
1623                         var rd = r0.GetRouteData (hc);
1624                         Assert.IsNotNull (rd, "#0");
1625                         Assert.AreEqual ("90941a4f-daf3-4c89-a6dc-83e8de4e3db5", rd.Values["id"]);
1626
1627                         var values = new RouteValueDictionary ()
1628                         {
1629                                 { "controller", "SomeThing" },
1630                                 { "action", "Index" }
1631                         };
1632                         var vp = r1.GetVirtualPath (new RequestContext (hc, rd), values);
1633
1634                         Assert.IsNotNull (vp, "#1");
1635                         Assert.AreEqual ("summary/SomeThing/90941a4f-daf3-4c89-a6dc-83e8de4e3db5", vp.VirtualPath, "#1-1");
1636                         Assert.AreEqual (r1, vp.Route, "#1-2");
1637                         Assert.AreEqual (0, vp.DataTokens.Count, "#1-3");
1638                 }
1639
1640                 [Test]
1641                 public void GetVirtualPath24 ()
1642                 {
1643                         var r = new MyRoute ("{controller}/{country}-{locale}/{action}", new MyRouteHandler())
1644                         {
1645                                 Defaults = new RouteValueDictionary (new { action = "Index", country = "us", locale = "en" })
1646                         };
1647                         var hc = new HttpContextStub2 ("~/login", String.Empty);
1648                         var rd = r.GetRouteData (hc);
1649                         Assert.IsNull (rd, "#0");
1650
1651                         var values = new RouteValueDictionary ()
1652                         {
1653                                 { "controller", "SomeThing" },
1654                                 { "action", "Index" },
1655                                 { "country", "es" }
1656                         };
1657                         var vp = r.GetVirtualPath (new RequestContext (hc, new RouteData()), values);
1658
1659                         Assert.IsNotNull (vp, "#1");
1660                         Assert.AreEqual ("SomeThing/es-en", vp.VirtualPath, "#1-1");
1661                         Assert.AreEqual (r, vp.Route, "#1-2");
1662                         Assert.AreEqual (0, vp.DataTokens.Count, "#1-3");
1663
1664                         // Case #2: pass no country, but locale as user value.
1665                         values.Remove("country");
1666                         values.Add("locale", "xx");
1667                         vp = r.GetVirtualPath(new RequestContext(hc, new RouteData()), values);
1668
1669                         Assert.IsNotNull(vp, "#2");
1670                         Assert.AreEqual("SomeThing/us-xx", vp.VirtualPath, "#2-1");
1671                         Assert.AreEqual(r, vp.Route, "#2-2");
1672                         Assert.AreEqual(0, vp.DataTokens.Count, "#2-3");
1673
1674                         // Case #3: make contry required.
1675                         r = new MyRoute("{controller}/{country}-{locale}/{action}", new MyRouteHandler())
1676                         {
1677                                 Defaults = new RouteValueDictionary(new { action = "Index", locale = "en" })
1678                         };
1679                         vp = r.GetVirtualPath(new RequestContext(hc, new RouteData()), values);
1680
1681                         Assert.IsNull(vp, "#3");
1682                 }
1683
1684                 [Test (Description="Xamarin Bug #13708")]
1685                 public void GetVirtualPath25()
1686                 {
1687                         var r = new MyRoute("{year}/{month}/{slug}", new MyRouteHandler())
1688                         {
1689                                 Defaults = new RouteValueDictionary(new { controller = "Blog", action = "View" }),
1690                                 Constraints = new RouteValueDictionary(new { year = @"\d{4}", month = @"\d{2}" }),
1691                         };
1692                         var hc = new HttpContextStub2("~/", String.Empty);
1693                         var values = new RouteValueDictionary()
1694                         {
1695                                 { "area", string.Empty },
1696                                 { "controller", "Blog" },
1697                                 { "action", "View" },
1698                                 { "year", 2013 }, // Year as an int, not a string
1699                                 { "month", "08" },
1700                                 { "slug", "hello-world" },
1701                         };
1702                         var vp = r.GetVirtualPath(new RequestContext(hc, new RouteData()), values);
1703
1704                         Assert.IsNotNull(vp, "#1");
1705                         Assert.AreEqual("2013/08/hello-world", vp.VirtualPath, "#2");
1706                 }
1707
1708                 [Test (Description = "Xamarin Bug #17960")]
1709                 public void GetVirtualPathWithCatchall1()
1710                 {
1711                         var r = new MyRoute("HelloWorld/{*path}", new MyRouteHandler());
1712                         var hc = new HttpContextStub2("~/", String.Empty);
1713                         var values = new RouteValueDictionary()
1714                         {
1715                                 { "path", "foobar" },
1716                         };
1717                         var vp = r.GetVirtualPath(new RequestContext(hc, new RouteData()), values);
1718
1719                         Assert.IsNotNull(vp, "#1");
1720                         Assert.AreEqual("HelloWorld/foobar", vp.VirtualPath, "#2");
1721                 }
1722
1723                 [Test (Description = "Xamarin Bug #17960")]
1724                 public void GetVirtualPathWithCatchall2()
1725                 {
1726                         var r = new MyRoute("HelloWorld/{*path}", new MyRouteHandler());
1727                         var hc = new HttpContextStub2("~/", String.Empty);
1728                         var values = new RouteValueDictionary()
1729                         {
1730                                 { "path", "foo/bar/baz" },
1731                         };
1732                         var vp = r.GetVirtualPath(new RequestContext(hc, new RouteData()), values);
1733
1734                         Assert.IsNotNull(vp, "#1");
1735                         Assert.AreEqual("HelloWorld/foo/bar/baz", vp.VirtualPath, "#2");
1736                 }
1737
1738                 // Bug #500739
1739                 [Test]
1740                 public void RouteGetRequiredStringWithDefaults ()
1741                 {
1742                         var routes = new RouteValueDictionary ();
1743                         var route = new Route ("Hello/{name}", new MyRouteHandler ()) {
1744                                         Defaults = new RouteValueDictionary (new {controller = "Home", action = "Hello"})
1745                         };
1746                         
1747                         routes.Add ("Name", route);
1748
1749                         var hc = new HttpContextStub2 ("~/Hello/World", String.Empty);
1750                         var rd = route.GetRouteData (hc);
1751
1752                         Assert.IsNotNull (rd, "#A1");
1753                         Assert.AreEqual ("Home", rd.GetRequiredString ("controller"), "#A2");
1754                         Assert.AreEqual ("Hello", rd.GetRequiredString ("action"), "#A3");
1755                         Assert.AreEqual ("World", rd.Values ["name"], "#A4");
1756                 }
1757
1758                 [Test]
1759                 public void ProcessConstraint ()
1760                 {
1761                         var route = new MyRoute ("hello/{name}", new MyRouteHandler ());
1762
1763                         Assert.IsFalse (route.DoProcessConstraint (null, "regex", "parameter", new RouteValueDictionary (), RouteDirection.IncomingRequest), "#1");
1764
1765                         // constraint is null
1766                         AssertExtensions.Throws <InvalidOperationException> (
1767                                 () => route.DoProcessConstraint (null, null, "parameter", new RouteValueDictionary (), RouteDirection.IncomingRequest),
1768                                 "#2"
1769                         );
1770
1771                         // constraint is neither a string or an IRouteConstraint instance
1772                         AssertExtensions.Throws <InvalidOperationException> (
1773                                 () => route.DoProcessConstraint (null, 1, "parameter", new RouteValueDictionary (), RouteDirection.IncomingRequest),
1774                                 "#3"
1775                         );
1776
1777                         AssertExtensions.Throws <ArgumentNullException> (
1778                                 () => route.DoProcessConstraint (null, "regex", null, new RouteValueDictionary (), RouteDirection.IncomingRequest),
1779                                 "#4"
1780                         );
1781
1782                         Assert.IsFalse (route.DoProcessConstraint (null, "regex", String.Empty, new RouteValueDictionary (), RouteDirection.IncomingRequest), "#5");
1783                         
1784                         // This is a .NET programming error, so not sure if we should test for this...
1785                         AssertExtensions.Throws <NullReferenceException> (
1786                                 () => route.DoProcessConstraint (null, "regex", "parameter", null, RouteDirection.IncomingRequest),
1787                                 "#6"
1788                         );
1789                 }
1790         }
1791 }