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