Fix regression for counter case to 6005f0a7.
[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 BindByNameManySlashes ()
233                 {
234                         var t = new UriTemplate ("////{foo}/{bar}/");
235                         var n = new NameValueCollection ();
236                         n.Add ("Bar", "value1"); // case insensitive
237                         n.Add ("FOO", "value2"); // case insensitive
238                         var u = t.BindByName (new Uri ("http://localhost/"), n);
239                         Assert.AreEqual ("http://localhost////value2/value1/", u.ToString ());
240                 }
241
242                 [Test]
243                 public void BindByNameManySlashes2 ()
244                 {
245                         var t = new UriTemplate ("////{foo}/{bar}/");
246                         var n = new NameValueCollection ();
247                         n.Add ("Bar", "value1"); // case insensitive
248                         n.Add ("FOO", "value2"); // case insensitive
249                         var u = t.BindByName (new Uri ("http://localhost//"), n);
250                         Assert.AreEqual ("http://localhost/////value2/value1/", u.ToString ());
251                 }
252                 
253                 [Test]
254                 public void BindByNameWithDefaults ()
255                 {
256                         var d = new Dictionary<string,string> ();
257                         d.Add ("Bar", "value1"); // case insensitive
258                         d.Add ("FOO", "value2"); // case insensitive
259                         var t = new UriTemplate ("/{foo}/{bar}/", d);
260                         var u = t.BindByName (new Uri ("http://localhost/"), new NameValueCollection ());
261                         Assert.AreEqual ("http://localhost/value2/value1/", u.ToString ());
262                 }
263
264                 [Test]
265                 [ExpectedException (typeof (ArgumentException))]
266                 public void BindByNameWithDefaults2 ()
267                 {
268                         var d = new Dictionary<string,string> ();
269                         d.Add ("Bar", "value1"); // case insensitive
270                         d.Add ("FOO", "value2"); // case insensitive
271                         var t = new UriTemplate ("/{foo}/{bar}/{baz}", d);
272                         t.BindByName (new Uri ("http://localhost/"), new NameValueCollection ()); // missing baz
273                 }
274
275                 [Test]
276                 [ExpectedException (typeof (ArgumentNullException))]
277                 public void BindByPositionNullBaseAddress ()
278                 {
279                         var t = new UriTemplate ("http://localhost:8080/");
280                         t.BindByPosition (null);
281                 }
282
283                 [Test]
284                 [ExpectedException (typeof (ArgumentException))]
285                 public void BindByPositionRelativeBaseAddress ()
286                 {
287                         var t = new UriTemplate ("http://localhost:8080/");
288                         t.BindByPosition (new Uri ("", UriKind.Relative));
289                 }
290
291                 [Test]
292                 [Category ("NotWorking")] // not worthy
293                 public void BindByPositionFileUriBaseAddress ()
294                 {
295                         var t = new UriTemplate ("http://localhost:8080/");
296                         Assert.AreEqual (new Uri ("file:///http://localhost:8080/"), t.BindByPosition (new Uri ("file:///")));
297                 }
298
299                 [Test] // it is NOT allowed (unlike BindByName)
300                 [ExpectedException (typeof (FormatException))]
301                 public void BindByPositionFileExtraValues ()
302                 {
303                         var t = new UriTemplate ("http://localhost:8080/");
304                         t.BindByPosition (new Uri ("http://localhost/"), "value");
305                 }
306
307                 [Test]
308                 [ExpectedException (typeof (FormatException))]
309                 public void BindByPositionFileMissingValues ()
310                 {
311                         var t = new UriTemplate ("/{foo}/");
312                         t.BindByPosition (new Uri ("http://localhost/"));
313                 }
314
315                 [Test]
316                 public void BindByPosition ()
317                 {
318                         var t = new UriTemplate ("/{foo}/{bar}/");
319                         var u = t.BindByPosition (new Uri ("http://localhost/"), "value1", "value2");
320                         Assert.AreEqual ("http://localhost/value1/value2/", u.ToString ());
321                 }
322
323                 [Test]
324                 [ExpectedException (typeof (FormatException))] // it does not allow default values
325                 public void BindByPositionWithDefaults ()
326                 {
327                         var d = new Dictionary<string,string> ();
328                         d ["baz"] = "value3";
329                         var t = new UriTemplate ("/{foo}/{bar}/{baz}", d);
330                         t.BindByPosition (new Uri ("http://localhost/"), "value1", "value2");
331                 }
332
333                 [Test]
334                 [ExpectedException (typeof (ArgumentNullException))]
335                 public void MatchNullArgument1 ()
336                 {
337                         var t = new UriTemplate ("/hooray");
338                         t.Match (null, new Uri ("http://localhost/"));
339                 }
340
341                 [Test]
342                 [ExpectedException (typeof (ArgumentNullException))]
343                 public void MatchNullArgument2 ()
344                 {
345                         var t = new UriTemplate ("/hooray");
346                         t.Match (new Uri ("http://localhost/"), null);
347                 }
348
349                 [Test]
350                 public void MatchNoTemplateItem ()
351                 {
352                         var t = new UriTemplate ("/hooray");
353                         var n = new NameValueCollection ();
354                         Assert.IsNotNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hooray")), "#1");
355                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/foobar")), "#2");
356                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hooray/foobar")), "#3");
357                 }
358
359                 [Test]
360                 public void MatchWrongTemplate ()
361                 {
362                         var t = new UriTemplate ("/hoo{foo}");
363                         var n = new NameValueCollection ();
364                         var m = t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hooray"));
365                         Assert.AreEqual ("ray", m.BoundVariables ["foo"], "#1");
366                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/foobar")), "#2");
367                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hooray/foobar")), "#3");
368                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hoo/ray")), "#4");
369                         Assert.IsNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hoo")), "#5");
370                         // this matches (as if there were no template).
371                         Assert.IsNotNull (t.Match (new Uri ("http://localhost/"), new Uri ("http://localhost/hoo{foo}")), "#6");
372                 }
373
374                 [Test]
375                 public void Match ()
376                 {
377                         var t = new UriTemplate ("/{foo}/{bar}");
378                         var n = new NameValueCollection ();
379                         Uri baseUri = new Uri ("http://localhost/");
380                         Assert.IsNull (t.Match (baseUri, new Uri ("http://localhost/hooray")), "#1");
381                         Assert.IsNull (t.Match (baseUri, new Uri ("http://localhost/v1/v2/extra")), "#2");
382                         Assert.IsNull (t.Match (baseUri, new Uri ("http://localhost/1/2/")), "#3");
383                         UriTemplateMatch m = t.Match (baseUri, new Uri ("http://localhost/foooo/baaar"));
384                         Assert.IsNotNull (m, "#4");
385                         Assert.AreEqual ("foooo", m.BoundVariables ["foo"], "#5");
386                         Assert.AreEqual ("baaar", m.BoundVariables ["bar"], "#6");
387                 }
388
389                 [Test]
390                 public void Match2 ()
391                 {
392                         var t = new UriTemplate ("/{foo}/{bar}?p1={baz}");
393                         var n = new NameValueCollection ();
394                         Uri baseUri = new Uri ("http://localhost/");
395                         Assert.IsNotNull (t.Match (baseUri, new Uri ("http://localhost/X/Y")), "#1");
396                         UriTemplateMatch m = t.Match (baseUri, new Uri ("http://localhost/X/Y?p2=v&p1=vv"));
397                         Assert.IsNotNull (m, "#2");
398                         // QueryParameters must contain non-template query parameters.
399                         Assert.AreEqual (2, m.QueryParameters.Count, "#3");
400                         Assert.AreEqual ("v", m.QueryParameters ["p2"], "#4");
401                         Assert.AreEqual ("vv", m.QueryParameters ["p1"], "#5");
402                 }
403
404                 [Test]
405                 public void MatchWildcard ()
406                 {
407                         var t = new UriTemplate ("/hoge/*?p1={foo}");
408                         var m = t.Match (new Uri ("http://localhost"), new Uri ("http://localhost/hoge/ppp/qqq?p1=v1"));
409                         Assert.IsNotNull (m, "#0");
410                         Assert.IsNotNull (m.QueryParameters, "#1.0");
411                         Assert.AreEqual ("v1", m.QueryParameters ["p1"], "#1");
412                         Assert.IsNotNull (m.WildcardPathSegments, "#2.0");
413                         Assert.AreEqual (2, m.WildcardPathSegments.Count, "#2");
414                         Assert.AreEqual ("ppp", m.WildcardPathSegments [0], "#3");
415                         Assert.AreEqual ("qqq", m.WildcardPathSegments [1], "#4");
416                 }
417
418                 [Test]
419                 public void IgnoreTrailingSlash ()
420                 {
421                         var t = new UriTemplate ("/{foo}/{bar}", true);
422                         var n = new NameValueCollection ();
423                         Uri baseUri = new Uri ("http://localhost/");
424                         Assert.IsNotNull (t.Match (baseUri, new Uri ("http://localhost/v1/v2/")), "#1");
425
426                         t = new UriTemplate ("/{foo}/{bar}", false);
427                         Assert.IsNull (t.Match (baseUri, new Uri ("http://localhost/v1/v2/")), "#2");
428                 }
429
430                 [Test]
431                 public void SimpleWebGet () {
432                         UriTemplate t = new UriTemplate ("GetBlog");
433                         Assert.IsNotNull(t.Match(new Uri("http://localhost:8000/BlogService"),
434                                 new Uri("http://localhost:8000/BlogService/GetBlog")), "Matches simple WebGet method");
435                         Assert.IsNull(t.Match (new Uri ("http://localhost:8000/BlogService"),
436                                 new Uri ("http://localhost:8000/BlogService/GetData")), "Doesn't match wrong WebGet method");
437                 }
438
439                 [Test]
440                 [ExpectedException (typeof (ArgumentException))]
441                 public void DictContainsNullValue ()
442                 {
443                         var t = new UriTemplate ("/id-{foo}/{bar}");
444                         var dic = new Dictionary<string,string> ();
445                         dic ["foo"] = null;
446                         dic ["bar"] = "bbb";
447                         t.BindByName (new Uri ("http://localhost:8080"), dic);
448                 }
449
450                 [Test]
451                 public void DictContainsCaseInsensitiveKey ()
452                 {
453                         var t = new UriTemplate ("/id-{foo}/{bar}");
454                         var dic = new Dictionary<string,string> ();
455                         dic ["foo"] = "aaa";
456                         dic ["Bar"] = "bbb";
457                         var uri = t.BindByName (new Uri ("http://localhost:8080"), dic);
458                         Assert.AreEqual ("http://localhost:8080/id-aaa/bbb", uri.ToString ());
459                 }
460
461         }
462 }