Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mcs / class / System.ServiceModel.Web / Test / System / UriTemplateTest.cs
1 //
2 // UriTemplate.cs
3 //
4 // Author:
5 //      Atsushi Enomoto  <atsushi@ximian.com>
6 //
7 // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
8 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 using System;
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.Collections.Specialized;
33 using NUnit.Framework;
34
35 namespace MonoTests.System
36 {
37         [TestFixture]
38         public class UriTemplateTest
39         {
40                 [Test]
41                 [ExpectedException (typeof (ArgumentNullException))]
42                 public void ConstructorNull ()
43                 {
44                         new UriTemplate (null);
45                 }
46
47                 [Test]
48                 public void ConstructorEmpty ()
49                 {
50                         // it does not raise an error at this state.
51                         new UriTemplate (String.Empty);
52                 }
53
54                 [Test]
55                 public void ConstructorNullDictionary ()
56                 {
57                         new UriTemplate (String.Empty, null);
58                 }
59
60                 [Test]
61                 public void IgnoreTrailingSlashDefault ()
62                 {
63                         Assert.IsFalse (new UriTemplate (String.Empty).IgnoreTrailingSlash);
64                 }
65
66                 [Test]
67                 [ExpectedException (typeof (FormatException))]
68                 public void ConstructorBrokenTemplate ()
69                 {
70                         // it used to be allowed but now it isn't in 3.5 SP1.
71                         new UriTemplate ("{");
72                 }
73
74                 [Test]
75                 [ExpectedException (typeof (FormatException))]
76                 public void ConstructorBrokenTemplate2 ()
77                 {
78                         new UriTemplate ("http://localhost:8080/{foo}/{");
79                 }
80
81                 [Test]
82                 [ExpectedException (typeof (FormatException))]
83                 public void ConstructorBrokenTemplate3 ()
84                 {
85                         new UriTemplate ("http://localhost:8080/{foo}/*/baz");
86                 }
87
88                 [Test]
89                 public void ToString ()
90                 {
91                         Assert.AreEqual ("urn:foo", new UriTemplate ("urn:foo").ToString (), "#1");
92                         // It used to be allowed but now it isn't in 3.5 SP1.
93                         //Assert.AreEqual ("{", new UriTemplate ("{").ToString (), "#2");
94                 }
95
96                 [Test]
97                 public void Variables ()
98                 {
99                         var t = new UriTemplate ("urn:foo");
100                         Assert.AreEqual (0, t.PathSegmentVariableNames.Count, "#1a");
101                         Assert.AreEqual (0, t.QueryValueVariableNames.Count, "#1b");
102
103                         t = new UriTemplate ("http://localhost:8080/");
104                         Assert.AreEqual (0, t.PathSegmentVariableNames.Count, "#2a");
105                         Assert.AreEqual (0, t.QueryValueVariableNames.Count, "#2b");
106
107                         t = new UriTemplate ("http://localhost:8080/foo/");
108                         Assert.AreEqual (0, t.PathSegmentVariableNames.Count, "#3a");
109                         Assert.AreEqual (0, t.QueryValueVariableNames.Count, "#3b");
110
111                         t = new UriTemplate ("http://localhost:8080/{foo}");
112                         Assert.AreEqual (1, t.PathSegmentVariableNames.Count, "#4a");
113                         Assert.AreEqual ("FOO", t.PathSegmentVariableNames [0], "#4b");
114                         Assert.AreEqual (0, t.QueryValueVariableNames.Count, "#4c");
115
116                         // This became invalid in 3.5 SP1
117                         //t = new UriTemplate ("http://localhost:8080/{foo}/{");
118                         //Assert.AreEqual (1, t.PathSegmentVariableNames.Count, "#5a");
119                         //Assert.AreEqual ("FOO", t.PathSegmentVariableNames [0], "#5b");
120                         //Assert.AreEqual (0, t.QueryValueVariableNames.Count, "#5c");
121
122                         t = new UriTemplate ("http://localhost:8080/hoge?test={foo}&test2={bar}");
123                         Assert.AreEqual (0, t.PathSegmentVariableNames.Count, "#6a");
124                         Assert.AreEqual (2, t.QueryValueVariableNames.Count, "#6b");
125                         Assert.AreEqual ("FOO", t.QueryValueVariableNames [0], "#6c");
126                         Assert.AreEqual ("BAR", t.QueryValueVariableNames [1], "#6d");
127                 }
128
129                 [Test]
130                 [ExpectedException (typeof (ArgumentException))]
131                 public void VariablesInSameSegment ()
132                 {
133                         new UriTemplate ("http://localhost:8080/{foo}{bar}");
134                 }
135
136                 [Test]
137                 [Category ("NotDotNet")] //.NET 3.5 SP1 incorrectly matches the port part
138                 public void VariablesInNonPathQuery ()
139                 {
140                         var t = new UriTemplate ("http://localhost:{foo}/");
141                         Assert.AreEqual (0, t.PathSegmentVariableNames.Count, "#8a");
142                         Assert.AreEqual (0, t.QueryValueVariableNames.Count, "#8b");
143                 }
144
145                 [Test]
146                 [ExpectedException (typeof (InvalidOperationException))]
147                 public void DuplicateNameInTemplate ()
148                 {
149                         // one name to two places to match
150                         new UriTemplate ("http://localhost:8080/hoge?test={foo}&test2={foo}");
151                 }
152
153                 [Test]
154                 [ExpectedException (typeof (InvalidOperationException))]
155                 public void DuplicateNameInTemplate2 ()
156                 {
157                         // one name to two places to match
158                         new UriTemplate ("http://localhost:8080/hoge/{foo}?test={foo}");
159                 }
160
161                 [Test]
162                 [ExpectedException (typeof (ArgumentNullException))]
163                 public void BindByNameNullBaseAddress ()
164                 {
165                         var t = new UriTemplate ("http://localhost:8080/");
166                         t.BindByName (null, new NameValueCollection ());
167                 }
168
169                 [Test]
170                 [ExpectedException (typeof (ArgumentException))]
171                 public void BindByNameRelativeBaseAddress ()
172                 {
173                         var t = new UriTemplate ("http://localhost:8080/");
174                         t.BindByName (new Uri ("", UriKind.Relative), new NameValueCollection ());
175                 }
176
177                 [Test]
178                 [Category ("NotWorking")] // not worthy
179                 public void BindByNameFileUriBaseAddress ()
180                 {
181                         var t = new UriTemplate ("http://localhost:8080/");
182                         var u = t.BindByName (new Uri ("file:///"), new NameValueCollection ());
183                         Assert.AreEqual ("file:///http://localhost:8080/", u.ToString ());
184                 }
185
186                 [Test] // it is allowed.
187                 public void BindByNameFileExtraNames ()
188                 {
189                         var t = new UriTemplate ("http://localhost:8080/");
190                         var n = new NameValueCollection ();
191                         n.Add ("name", "value");
192                         t.BindByName (new Uri ("http://localhost/"), n);
193                 }
194
195                 [Test]
196                 [ExpectedException (typeof (ArgumentException))]
197                 public void BindByNameFileMissingName ()
198                 {
199                         var t = new UriTemplate ("/{foo}/");
200                         t.BindByName (new Uri ("http://localhost/"), new NameValueCollection ());
201                 }
202
203                 [Test]
204                 [ExpectedException (typeof (ArgumentException))]
205                 public void BindInSameSegment ()
206                 {
207                         new UriTemplate ("/hoo/{foo}{bar}");
208                 }
209
210                 [Test]
211                 public void BindByName ()
212                 {
213                         var t = new UriTemplate ("/{foo}/{bar}/");
214                         var n = new NameValueCollection ();
215                         n.Add ("Bar", "value1"); // case insensitive
216                         n.Add ("FOO", "value2"); // case insensitive
217                         var u = t.BindByName (new Uri ("http://localhost/"), n);
218                         Assert.AreEqual ("http://localhost/value2/value1/", u.ToString ());
219                 }
220
221                 [Test]
222                 public void BindByName2 ()
223                 {
224                         var t = new UriTemplate ("{foo}/{bar}");
225                         var n = new NameValueCollection ();
226                         n.Add ("Bar", "value1"); // case insensitive
227                         n.Add ("FOO", "value2"); // case insensitive
228                         var u = t.BindByName (new Uri ("http://localhost/x"), n);
229                         Assert.AreEqual ("http://localhost/x/value2/value1", u.ToString ());
230                 }
231
232                 [Test]
233                 public void BindByName3 ()
234                 {
235                         var t = new UriTemplate ("Login?clientLoginData={clientLoginData}&credentials={credentials}");
236                         var n = new NameValueCollection ();
237                         var u = t.BindByName (new Uri ("http://localhost"), n);
238                         Assert.AreEqual ("http://localhost/Login", u.ToString (), "#1");
239                 }
240
241                 [Test]
242                 public void BindByNameManySlashes ()
243                 {
244                         var t = new UriTemplate ("////{foo}/{bar}/");
245                         var n = new NameValueCollection ();
246                         n.Add ("Bar", "value1"); // case insensitive
247                         n.Add ("FOO", "value2"); // case insensitive
248                         var u = t.BindByName (new Uri ("http://localhost/"), n);
249                         Assert.AreEqual ("http://localhost////value2/value1/", u.ToString ());
250                 }
251
252                 [Test]
253                 public void BindByNameManySlashes2 ()
254                 {
255                         var t = new UriTemplate ("////{foo}/{bar}/");
256                         var n = new NameValueCollection ();
257                         n.Add ("Bar", "value1"); // case insensitive
258                         n.Add ("FOO", "value2"); // case insensitive
259                         var u = t.BindByName (new Uri ("http://localhost//"), n);
260                         Assert.AreEqual ("http://localhost/////value2/value1/", u.ToString ());
261                 }
262                 
263                 [Test]
264                 public void BindByNameWithDefaults ()
265                 {
266                         var d = new Dictionary<string,string> ();
267                         d.Add ("Bar", "value1"); // case insensitive
268                         d.Add ("FOO", "value2"); // case insensitive
269                         var t = new UriTemplate ("/{foo}/{bar}/", d);
270                         var u = t.BindByName (new Uri ("http://localhost/"), new NameValueCollection ());
271                         Assert.AreEqual ("http://localhost/value2/value1/", u.ToString ());
272                 }
273
274                 [Test]
275                 [ExpectedException (typeof (ArgumentException))]
276                 public void BindByNameWithDefaults2 ()
277                 {
278                         var d = new Dictionary<string,string> ();
279                         d.Add ("Bar", "value1"); // case insensitive
280                         d.Add ("FOO", "value2"); // case insensitive
281                         var t = new UriTemplate ("/{foo}/{bar}/{baz}", d);
282                         t.BindByName (new Uri ("http://localhost/"), new NameValueCollection ()); // missing baz
283                 }
284
285                 [Test]
286                 [ExpectedException (typeof (ArgumentNullException))]
287                 public void BindByPositionNullBaseAddress ()
288                 {
289                         var t = new UriTemplate ("http://localhost:8080/");
290                         t.BindByPosition (null);
291                 }
292
293                 [Test]
294                 [ExpectedException (typeof (ArgumentException))]
295                 public void BindByPositionRelativeBaseAddress ()
296                 {
297                         var t = new UriTemplate ("http://localhost:8080/");
298                         t.BindByPosition (new Uri ("", UriKind.Relative));
299                 }
300
301                 [Test]
302                 [Category ("NotWorking")] // not worthy
303                 public void BindByPositionFileUriBaseAddress ()
304                 {
305                         var t = new UriTemplate ("http://localhost:8080/");
306                         Assert.AreEqual (new Uri ("file:///http://localhost:8080/"), t.BindByPosition (new Uri ("file:///")));
307                 }
308
309                 [Test] // it is NOT allowed (unlike BindByName)
310                 [ExpectedException (typeof (FormatException))]
311                 public void BindByPositionFileExtraValues ()
312                 {
313                         var t = new UriTemplate ("http://localhost:8080/");
314                         t.BindByPosition (new Uri ("http://localhost/"), "value");
315                 }
316
317                 [Test]
318                 [ExpectedException (typeof (FormatException))]
319                 public void BindByPositionFileMissingValues ()
320                 {
321                         var t = new UriTemplate ("/{foo}/");
322                         t.BindByPosition (new Uri ("http://localhost/"));
323                 }
324
325                 [Test]
326                 public void BindByPosition ()
327                 {
328                         var t = new UriTemplate ("/{foo}/{bar}/");
329                         var u = t.BindByPosition (new Uri ("http://localhost/"), "value1", "value2");
330                         Assert.AreEqual ("http://localhost/value1/value2/", u.ToString ());
331                 }
332
333                 [Test]
334                 [ExpectedException (typeof (FormatException))] // it does not allow default values
335                 public void BindByPositionWithDefaults ()
336                 {
337                         var d = new Dictionary<string,string> ();
338                         d ["baz"] = "value3";
339                         var t = new UriTemplate ("/{foo}/{bar}/{baz}", d);
340                         t.BindByPosition (new Uri ("http://localhost/"), "value1", "value2");
341                 }
342
343                 [Test]
344                 [ExpectedException (typeof (ArgumentNullException))]
345                 public void MatchNullArgument1 ()
346                 {
347                         var t = new UriTemplate ("/hooray");
348                         t.Match (null, new Uri ("http://localhost/"));
349                 }
350
351                 [Test]
352                 [ExpectedException (typeof (ArgumentNullException))]
353                 public void MatchNullArgument2 ()
354                 {
355                         var t = new UriTemplate ("/hooray");
356                         t.Match (new Uri ("http://localhost/"), null);
357                 }
358
359                 [Test]
360                 public void MatchNoTemplateItem ()
361                 {
362                         var t = new UriTemplate ("/hooray");
363                         var n = new NameValueCollection ();
364                         Assert.IsNotNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hooray")), "#1");
365                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/foobar")), "#2");
366                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hooray/foobar")), "#3");
367                 }
368
369                 [Test]
370                 public void MatchWrongTemplate ()
371                 {
372                         var t = new UriTemplate ("/hoo{foo}");
373                         var n = new NameValueCollection ();
374                         var m = t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hooray"));
375                         Assert.AreEqual ("ray", m.BoundVariables ["foo"], "#1");
376                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/foobar")), "#2");
377                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hooray/foobar")), "#3");
378                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hoo/ray")), "#4");
379                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hoo")), "#5");
380                         // this matches (as if there were no template).
381                         Assert.IsNotNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hoo{foo}")), "#6");
382                 }
383
384                 [Test]
385                 public void Match ()
386                 {
387                         var t = new UriTemplate ("/{foo}/{bar}");
388                         var n = new NameValueCollection ();
389                         Uri baseUri = new Uri ("http://localhost/");
390                         Assert.IsNull (t.Match (baseUri, new Uri ("http://localhost/hooray")), "#1");
391                         Assert.IsNull (t.Match (baseUri, new Uri ("http://localhost/v1/v2/extra")), "#2");
392                         Assert.IsNull (t.Match (baseUri, new Uri ("http://localhost/1/2/")), "#3");
393                         UriTemplateMatch m = t.Match (baseUri, new Uri ("http://localhost/foooo/baaar"));
394                         Assert.IsNotNull (m, "#4");
395                         Assert.AreEqual ("foooo", m.BoundVariables ["foo"], "#5");
396                         Assert.AreEqual ("baaar", m.BoundVariables ["bar"], "#6");
397                 }
398
399                 [Test]
400                 public void Match2 ()
401                 {
402                         var t = new UriTemplate ("/{foo}/{bar}?p1={baz}");
403                         var n = new NameValueCollection ();
404                         Uri baseUri = new Uri ("http://localhost/");
405                         Assert.IsNotNull (t.Match (baseUri, new Uri ("http://localhost/X/Y")), "#1");
406                         UriTemplateMatch m = t.Match (baseUri, new Uri ("http://localhost/X/Y?p2=v&p1=vv"));
407                         Assert.IsNotNull (m, "#2");
408                         // QueryParameters must contain non-template query parameters.
409                         Assert.AreEqual (2, m.QueryParameters.Count, "#3");
410                         Assert.AreEqual ("v", m.QueryParameters ["p2"], "#4");
411                         Assert.AreEqual ("vv", m.QueryParameters ["p1"], "#5");
412                 }
413
414                 [Test]
415                 public void Match3 ()
416                 {
417                         var template = new UriTemplate ("test");
418                         var match1 = template.Match (new Uri ("http://something"), new Uri ("http://something/test"));
419                         var match2 = template.Match (new Uri ("http://something/something2"), new Uri ("http://something/something2/test"));
420                         Assert.IsNotNull (match1, "#1");
421                         Assert.IsNotNull (match2, "#2");
422                 }
423                 
424                 [Test]
425                 public void MatchWildcard ()
426                 {
427                         var t = new UriTemplate ("/hoge/*?p1={foo}");
428                         var m = t.Match (new Uri ("http://localhost"), new Uri ("http://localhost/hoge/ppp/qqq?p1=v1"));
429                         Assert.IsNotNull (m, "#0");
430                         Assert.IsNotNull (m.QueryParameters, "#1.0");
431                         Assert.AreEqual ("v1", m.QueryParameters ["p1"], "#1");
432                         Assert.IsNotNull (m.WildcardPathSegments, "#2.0");
433                         Assert.AreEqual (2, m.WildcardPathSegments.Count, "#2");
434                         Assert.AreEqual ("ppp", m.WildcardPathSegments [0], "#3");
435                         Assert.AreEqual ("qqq", m.WildcardPathSegments [1], "#4");
436                 }
437
438                 [Test]
439                 public void MatchWildcard2 ()
440                 {
441                         var t = new UriTemplate ("*");
442                         var m = t.Match (new Uri ("http://localhost"), new Uri ("http://localhost/hoge/ppp"));
443                         Assert.IsNotNull (m, "#0");
444                         Assert.IsEmpty (m.QueryParameters, "#1.0");
445                         Assert.AreEqual ("hoge", m.WildcardPathSegments [0], "#2");
446                         Assert.AreEqual ("ppp", m.WildcardPathSegments [1], "#3");
447                 }
448
449                 [Test]
450                 public void MatchWildcard3 ()
451                 {
452                         var t = new UriTemplate ("*?p1={foo}");
453                         var m = t.Match (new Uri ("http://localhost"), new Uri ("http://localhost/hoge/ppp/qqq?p1=v1"));
454                         Assert.IsNotNull (m, "#0");
455                         Assert.IsNotNull (m.QueryParameters, "#1.0");
456                         Assert.AreEqual ("v1", m.QueryParameters ["p1"], "#1");
457                         Assert.IsNotNull (m.WildcardPathSegments, "#2.0");
458                         Assert.AreEqual (3, m.WildcardPathSegments.Count, "#2");
459                         Assert.AreEqual ("hoge", m.WildcardPathSegments [0], "#3");
460                         Assert.AreEqual ("ppp", m.WildcardPathSegments [1], "#4");
461                         Assert.AreEqual ("qqq", m.WildcardPathSegments [2], "#5");
462                 }
463
464                 [Test]
465                 public void IgnoreTrailingSlash ()
466                 {
467                         var t = new UriTemplate ("/{foo}/{bar}", true);
468                         var n = new NameValueCollection ();
469                         Uri baseUri = new Uri ("http://localhost/");
470                         Assert.IsNotNull (t.Match (baseUri, new Uri ("http://localhost/v1/v2/")), "#1");
471
472                         t = new UriTemplate ("/{foo}/{bar}", false);
473                         Assert.IsNull (t.Match (baseUri, new Uri ("http://localhost/v1/v2/")), "#2");
474                 }
475
476                 [Test]
477                 [Category ("NotWorking")]
478                 public void SimpleWebGet () {
479                         UriTemplate t = new UriTemplate ("GetBlog");
480                         Assert.IsNotNull(t.Match(new Uri("http://localhost:8000/BlogService"),
481                                 new Uri("http://localhost:8000/BlogService/GetBlog")), "Matches simple WebGet method");
482                         Assert.IsNull(t.Match (new Uri ("http://localhost:8000/BlogService"),
483                                 new Uri ("http://localhost:8000/BlogService/GetData")), "Doesn't match wrong WebGet method");
484                 }
485
486                 [Test]
487                 [ExpectedException (typeof (ArgumentException))]
488                 public void DictContainsNullValue ()
489                 {
490                         var t = new UriTemplate ("/id-{foo}/{bar}");
491                         var dic = new Dictionary<string,string> ();
492                         dic ["foo"] = null;
493                         dic ["bar"] = "bbb";
494                         t.BindByName (new Uri ("http://localhost:8080"), dic);
495                 }
496
497                 [Test]
498                 public void DictContainsCaseInsensitiveKey ()
499                 {
500                         var t = new UriTemplate ("/id-{foo}/{bar}");
501                         var dic = new Dictionary<string,string> ();
502                         dic ["foo"] = "aaa";
503                         dic ["Bar"] = "bbb";
504                         var uri = t.BindByName (new Uri ("http://localhost:8080"), dic);
505                         Assert.AreEqual ("http://localhost:8080/id-aaa/bbb", uri.ToString ());
506                 }
507
508                 [Test]
509                 public void NamedWildcard ()
510                 {
511                         UriTemplate template = new UriTemplate ("{*path}");
512                         UriTemplateMatch match = template.Match (new Uri ("http://localhost"), new Uri ("http://localhost/something"));
513                         Assert.IsNotNull (match, "#1");
514                         Assert.AreEqual ("something", match.BoundVariables ["path"], "#2");
515                 }
516
517         [Test]
518         [Category ("NotWorking")]
519         public void EscapedUriCandidate ()
520         {
521             var candidateUri = new Uri (@"https://somehost:12345/path1/path2/path3/endprefix/tpath1/guid1/tpath2/~|~~|~%3F~|~Path{guid2}~|~/tpath3");
522             var matchUri = new Uri (candidateUri.Scheme + "://" + candidateUri.Host + ":" + candidateUri.Port + @"/path1/path2/path3/endprefix");
523             
524             var template = new UriTemplate (@"tpath1/{guid}/tpath2/{encodedGuidString}/tpath3");
525             var match = template.Match (matchUri, candidateUri);
526
527             Assert.IsNotNull (match);
528             Assert.That (match.BoundVariables ["GUID"] == "guid1");
529             Assert.That (match.BoundVariables ["ENCODEDGUIDSTRING"] == "~|~~|~?~|~Path{guid2}~|~");
530         }
531         }
532 }