1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.rest.util;
18
19 import static org.apache.juneau.TestUtils.*;
20 import static org.apache.juneau.rest.util.UrlPathMatcher.*;
21 import static org.junit.jupiter.api.Assertions.*;
22
23 import java.util.*;
24
25 import org.apache.juneau.*;
26 import org.apache.juneau.json.*;
27 import org.junit.jupiter.api.*;
28
29 class UrlPathMatcher_Test extends TestBase {
30
31 private void check(UrlPathMatcher p, String path, String expected) {
32 assertString(expected, p.match(UrlPath.of(path)));
33 }
34
35 private void shouldNotMatch(UrlPathMatcher p, String...paths) {
36 for (String path : paths)
37 assertNull(p.match(UrlPath.of(path)));
38 }
39
40
41
42
43
44 @Test void a01_comparision() {
45 var l = new LinkedList<UrlPathMatcher>();
46
47 l.add(of(""));
48 l.add(of("*"));
49 l.add(of("/"));
50 l.add(of("/*"));
51 l.add(of("/foo"));
52 l.add(of("/foo/*"));
53 l.add(of("/foo/bar"));
54 l.add(of("/foo/bar/*"));
55 l.add(of("/foo/{id}"));
56 l.add(of("/foo/{id}/*"));
57 l.add(of("/foo/{id}/bar"));
58 l.add(of("/foo/{id}/bar/*"));
59 l.add(of("foo.txt"));
60 l.add(of("*.txt"));
61 l.add(of("foo.*"));
62
63 Collections.sort(l);
64 assertEquals("['foo.txt','foo.*','*.txt','/foo/bar','/foo/bar/*','/foo/{id}/bar','/foo/{id}/bar/*','/foo/{id}','/foo/{id}/*','/foo','/foo/*','/','/*','','*']", Json5Serializer.DEFAULT.toString(l));
65 }
66
67 @Test void a02_comparision() {
68 var l = new LinkedList<UrlPathMatcher>();
69
70 l.add(of("foo.txt"));
71 l.add(of("*.txt"));
72 l.add(of("foo.*"));
73 l.add(of("/foo/{id}/bar/*"));
74 l.add(of("/foo/{id}/bar"));
75 l.add(of("/foo/{id}/*"));
76 l.add(of("/foo/{id}"));
77 l.add(of("/foo/bar/*"));
78 l.add(of("/foo/bar"));
79 l.add(of("/foo/*"));
80 l.add(of("/foo"));
81 l.add(of("/*"));
82 l.add(of("/"));
83 l.add(of("*"));
84 l.add(of(""));
85
86 Collections.sort(l);
87 assertEquals("['foo.txt','foo.*','*.txt','/foo/bar','/foo/bar/*','/foo/{id}/bar','/foo/{id}/bar/*','/foo/{id}','/foo/{id}/*','/foo','/foo/*','/','/*','','*']", Json5Serializer.DEFAULT.toString(l));
88 }
89
90 @Test void a03_comparision() {
91 var l = new LinkedList<UrlPathMatcher>();
92
93 l.add(of("/foo"));
94 l.add(of("/foo"));
95
96 Collections.sort(l);
97 assertEquals("['/foo','/foo']", Json5Serializer.DEFAULT.toString(l));
98 }
99
100
101
102
103
104 @Test void b01_simple_match() {
105 var p = of("/foo");
106 check(p, "/foo", "{}");
107 check(p, "/foo/", "{r:''}");
108 }
109
110 @Test void b02_simple_noMatch() {
111 var p = of("/foo");
112 shouldNotMatch(p, "/fooo", "/fo", "/fooo/", "/", "/foo/bar");
113 }
114
115 @Test void b03_simple_match_2parts() {
116 var p = of("/foo/bar");
117 check(p, "/foo/bar", "{}");
118 check(p, "/foo/bar/", "{r:''}");
119 }
120
121 @Test void b04_simple_noMatch_2parts() {
122 var p = of("/foo/bar");
123 shouldNotMatch(p, "/foo", "/foo/baz", "/foo/barr", "/foo/bar/baz");
124 }
125
126 @Test void b05_simple_match_0parts() {
127 var p = of("/");
128 check(p, "/", "{r:''}");
129 }
130
131 @Test void b06_simple_noMatch_0parts() {
132 var p = of("/");
133 shouldNotMatch(p, "/foo", "/foo/bar");
134 }
135
136 @Test void b07_simple_match_blank() {
137 var p = of("");
138 check(p, "/", "{r:''}");
139 }
140
141 @Test void b08_simple_noMatch_blank() {
142 var p = of("");
143 shouldNotMatch(p, "/foo", "/foo/bar");
144 }
145
146
147
148
149
150 @Test void c01_simple_withRemainder_match() {
151 var p = of("/foo/*");
152 check(p, "/foo", "{}");
153 check(p, "/foo/", "{r:''}");
154 check(p, "/foo/bar", "{r:'bar'}");
155 check(p, "/foo/bar/", "{r:'bar/'}");
156 check(p, "/foo/bar/baz", "{r:'bar/baz'}");
157 }
158
159 @Test void c02_simple_withRemainder_noMatch() {
160 var p = of("/foo/*");
161 shouldNotMatch(p, "/fooo", "/fo", "/fooo/", "/", "/fooo/bar");
162 }
163
164 @Test void c03_simple_withRemainder_match_2parts() {
165 var p = of("/foo/bar/*");
166 check(p, "/foo/bar", "{}");
167 check(p, "/foo/bar/baz", "{r:'baz'}");
168 check(p, "/foo/bar/baz/", "{r:'baz/'}");
169 }
170
171 @Test void c04_simple_withRemainder_noMatch_2parts() {
172 var p = of("/foo/bar/*");
173 shouldNotMatch(p, "/", "/foo", "/foo/baz", "/foo/barr", "/foo/barr/");
174 }
175
176 @Test void c05_simple_withRemainder_match_0parts() {
177 var p = of("/*");
178 check(p, "/", "{r:''}");
179 check(p, "/foo", "{r:'foo'}");
180 check(p, "/foo/bar", "{r:'foo/bar'}");
181 }
182
183 @Test void c06_simple_withRemainder_match_blank() {
184 var p = of("*");
185 check(p, "/", "{r:''}");
186 check(p, "/foo", "{r:'foo'}");
187 check(p, "/foo/bar", "{r:'foo/bar'}");
188 }
189
190
191
192
193
194 @Test void d01_1part1vars_match() {
195 var p = of("/{foo}");
196 check(p, "/bar", "{v:{foo:'bar'}}");
197 check(p, "/bar/", "{v:{foo:'bar'},r:''}");
198 }
199
200 @Test void d02_1part1var_noMatch() {
201 var p = of("/{foo}");
202 shouldNotMatch(p, "/foo/bar", "/");
203 }
204
205 @Test void d03_2parts1var_match() {
206 var p = of("/foo/{bar}");
207 check(p, "/foo/baz", "{v:{bar:'baz'}}");
208 check(p, "/foo/baz/", "{v:{bar:'baz'},r:''}");
209 }
210
211 @Test void d04_2parts1var_noMatch() {
212 var p = of("/foo/{bar}");
213 shouldNotMatch(p, "/fooo/baz", "/fo/baz", "/foo", "/");
214 }
215
216 @Test void d05_3vars_match() {
217 var p = of("/{a}/{b}/{c}");
218 check(p, "/A/B/C", "{v:{a:'A',b:'B',c:'C'}}");
219 check(p, "/A/B/C/", "{v:{a:'A',b:'B',c:'C'},r:''}");
220 }
221
222 @Test void d06_3vars_noMatch() {
223 var p = of("/{a}/{b}/{c}");
224 shouldNotMatch(p, "/A/B", "/A/B/C/D", "/");
225 }
226
227 @Test void d07_7parts3vars_match() {
228 var p = of("/a/{a}/b/{b}/c/{c}/d");
229 check(p, "/a/A/b/B/c/C/d", "{v:{a:'A',b:'B',c:'C'}}");
230 check(p, "/a/A/b/B/c/C/d/", "{v:{a:'A',b:'B',c:'C'},r:''}");
231 }
232
233 @Test void d08_6parts3vars_noMatch() {
234 var p = of("/a/{a}/b/{b}/c/{c}/d");
235 shouldNotMatch(p, "/a/A/a/B/c/C/d", "/a/A/b/B/c/C/dd", "/a/b/c/d");
236 }
237
238
239
240
241
242 @Test void e01_1part1vars_withRemainder_match() {
243 var p = of("/{foo}/*");
244 check(p, "/bar", "{v:{foo:'bar'}}");
245 check(p, "/bar/", "{v:{foo:'bar'},r:''}");
246 check(p, "/bar/baz", "{v:{foo:'bar'},r:'baz'}");
247 check(p, "/bar/baz/qux", "{v:{foo:'bar'},r:'baz/qux'}");
248 }
249
250 @Test void e02_1part1var_withRemainder_noMatch() {
251 var p = of("/{foo}/*");
252 shouldNotMatch(p, "/");
253 }
254
255 @Test void e03_2parts1var_withRemainder_match() {
256 var p = of("/foo/{bar}/*");
257 check(p, "/foo/baz", "{v:{bar:'baz'}}");
258 check(p, "/foo/baz/", "{v:{bar:'baz'},r:''}");
259 check(p, "/foo/baz/qux/", "{v:{bar:'baz'},r:'qux/'}");
260 }
261
262 @Test void e04_2parts1var_withRemainder_noMatch() {
263 var p = of("/foo/{bar}/*");
264 shouldNotMatch(p, "/fooo/baz", "/fo/baz", "/foo", "/");
265 }
266
267
268
269
270
271 @Test void f01_innerMeta_withRemainder_match() {
272 var p = of("/*/*");
273 check(p, "/bar", "{}");
274 check(p, "/bar/", "{r:''}");
275 check(p, "/bar/baz", "{r:'baz'}");
276 check(p, "/bar/baz/qux", "{r:'baz/qux'}");
277 }
278
279 @Test void f02_innerMeta_withRemainder_noMatch() {
280 var p = of("/*/*");
281 shouldNotMatch(p, "/");
282 }
283
284 @Test void f03_innerMeta_withRemainder_match() {
285 var p = of("/foo/*/bar/*");
286 check(p, "/foo/baz/bar", "{}");
287 check(p, "/foo/baz/bar/", "{r:''}");
288 check(p, "/foo/baz/bar/qux/", "{r:'qux/'}");
289 }
290
291 @Test void f04_innerMeta_withRemainder_noMatch() {
292 var p = of("/foo/*/bar/*");
293 shouldNotMatch(p, "/fooo/baz/bar", "/fo/baz/bar", "/foo/bar", "/");
294 }
295
296
297
298
299
300 @Test void g01_encodedVars() {
301 var p = of("/foo/{bar}/*");
302 check(p, "/foo/baz%2Fqux", "{v:{bar:'baz/qux'}}");
303 check(p, "/foo/baz+qux", "{v:{bar:'baz qux'}}");
304 check(p, "/foo/baz%2Fqux/quux%2Fquuux", "{v:{bar:'baz/qux'},r:'quux%2Fquuux'}");
305 check(p, "/foo/baz+qux/quux+quuux", "{v:{bar:'baz qux'},r:'quux+quuux'}");
306 }
307
308
309
310
311
312 @Test void h01_notVars() {
313 var p = of("/foo/{bar/*");
314 check(p, "/foo/{bar", "{}");
315 check(p, "/foo/{bar/{baz", "{r:'{baz'}");
316 }
317
318 @Test void h02_notVars() {
319 var p = of("/foo/bar}/*");
320 check(p, "/foo/bar}", "{}");
321 check(p, "/foo/bar}/baz}", "{r:'baz}'}");
322 }
323
324 @Test void h03_notVars() {
325 var p = of("/foo/x{bar}x/*");
326 check(p, "/foo/x{bar}x", "{}");
327 check(p, "/foo/x{bar}x/x{baz}x", "{r:'x{baz}x'}");
328 }
329
330
331
332
333
334 @Test void i01_filenameMatcher() {
335 var p = of("foo.bar");
336 check(p, "/foo.bar", "{}");
337 check(p, "/foo/foo.bar", "{}");
338 shouldNotMatch(p, "/foo.baz", "/foo", "/foo.barx", "/foo", "/foo.*", "/*.bar", "/*.*", "/*", null);
339
340 p = of("*.bar");
341 check(p, "/foo.bar", "{}");
342 check(p, "/foo/foo.bar", "{}");
343 check(p, "/*.bar", "{}");
344 shouldNotMatch(p, "/foo.baz", "/foo", "/foo", "/foo.*", "/*.*", "/*", null);
345
346 p = of("foo.*");
347 check(p, "/foo.bar", "{}");
348 check(p, "/foo/foo.bar", "{}");
349 check(p, "/foo.*", "{}");
350 shouldNotMatch(p, "/foo", "/foo", "/*.*", "/*", null);
351
352 p = of("*.*");
353 check(p, "/foo.bar", "{}");
354 check(p, "/foo/foo.bar", "{}");
355 check(p, "/foo.*", "{}");
356 check(p, "/*.bar", "{}");
357 check(p, "/*.*", "{}");
358 shouldNotMatch(p, "/foo", "/foo", "/*", null);
359 }
360 }