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