1#!perl -T
2
3use strict;
4use warnings;
5
6use Test::Most;
7
8plan qw/no_plan/;
9
10use Path::Abstract qw/path --no_0_093_warning/;
11
12{
13    my $path;
14
15    $path = path [qw/a b c d ef g h/];
16    is($path, "a/b/c/d/ef/g/h");
17    $path = $path->child([qw/.. ij k lm/]);
18    is($path, "a/b/c/d/ef/g/h/../ij/k/lm");
19
20    $path = path "/a/b/c/d";
21    is($path, "/a/b/c/d");
22    $path->pop(8);
23    is($path, "/");
24
25    {
26        my $path;
27        $path = path 'a.html.tar.gz';
28        $path->pop;
29        is($path, '');
30
31        $path = path '/a.html.tar.gz';
32        $path->pop;
33        is($path, '/');
34
35        $path = path 'a.html.tar.gz';
36        $path->up;
37        is($path, '');
38
39        $path = path '/a.html.tar.gz';
40        $path->up;
41        is($path, '/');
42    }
43
44    {
45        cmp_deeply([ path( 'a/b/c' )->list ], [qw/ a b c /]);
46        cmp_deeply([ path( '/a/b/c' )->list ], [qw/ a b c /]);
47        cmp_deeply([ path( '/a/b/c/' )->list ], [qw/ a b c /]);
48        cmp_deeply([ path( 'a/b/c/' )->list ], [qw/ a b c /]);
49
50        cmp_deeply([ path( 'a/b/c' )->split ], [qw( a b c )]);
51        cmp_deeply([ path( '/a/b/c' )->split ], [qw( /a b c )]);
52        cmp_deeply([ path( '/a/b/c/' )->split ], [qw( /a b c/ )]);
53        cmp_deeply([ path( 'a/b/c/' )->split ], [qw( a b c/ )]);
54    }
55
56    {
57        my $path;
58        # .append
59        $path = path();
60
61        $path->append("c/d");
62        is("c/d", $path.'');
63        is("d", $path->last());
64
65        $path->append("ef");
66        is("c/def", $path.'');
67        is("def", $path->last());
68
69        $path->append("", "g/");
70        is("c/def/g/", $path.'');
71        is("g", $path->last());
72    }
73
74    {
75        my $path;
76        # .extension
77        $path = path("a.tar.gz.html");
78
79        is(".html", $path->extension());
80        is(".gz.html", $path->extension({ match => 2 }));
81        is(".tar.gz.html", $path->extension({ match => 3 }));
82        is(".tar.gz.html", $path->extension({ match => 4 }));
83        is("a", $path->clone()->extension("", { match => 4 }));
84
85        is("a.tar.gz.txt", $path->clone()->extension(".txt").'');
86        is("a.tar.txt", $path->clone()->extension(".txt", 2).'');
87        is("a.txt", $path->clone()->extension(".txt", 3).'');
88        is("a.tar", $path->clone()->extension(".txt", 3)->extension(".tar").'');
89        is("a", $path->clone()->extension(".txt", 3)->extension("").'');
90
91        $path->set("");
92        is("", $path->extension());
93        is(".html", $path->clone()->extension("html").'');
94        is(".html", $path->clone()->extension(".html").'');
95        is("", $path->clone()->extension("").'');
96
97        $path->set("/");
98        is("", $path->extension());
99        is("/.html.gz", $path->clone()->extension("html.gz").'');
100        is("/.html.gz", $path->clone()->extension(".html.gz").'');
101        is("/", $path->clone()->extension("").'');
102
103        is(".html", path( "a/b/c.html" )->extension());
104        is("", path( "a/b/c" )->extension());
105        is(".gz", path( "a/b/c.tar.gz" )->extension());
106        is(".tar.gz", path( "a/b/c.tar.gz" )->extension({ match => "*" }));
107        is("a/b/c.txt", path( "a/b/c.html" )->extension( ".txt" ));
108        is("a/b/c.zip", path( "a/b/c.html" )->extension( "zip" ));
109        is("a/b/c", path( "a/b/c.html" )->extension( "" ));
110        is("a/b/c.", path( "a/b/c.html" )->extension( "." ));
111
112        $path = path("a/b/c");
113        is("a/b/c.html", $path->extension(".html").'');
114        is("a/b/c.html", $path->extension(".html").'');
115    }
116
117    {
118        # non-greedy
119        my $path = path;
120
121        $path->set('a/');
122        is($path->pop, 'a');
123        is($path->get, '');
124        is($path->pop, '');
125        is($path->get, '');
126
127        $path->set('/a/');
128        is($path->pop, 'a');
129        is($path->get, '/');
130        is($path->pop, '');
131        is($path->get, '/');
132
133        $path->set('/a');
134        is($path->pop, 'a');
135        is($path->get, '/');
136        is($path->pop, '');
137        is($path->get, '/');
138
139        $path->set('/a/b/c/');
140        is($path->pop, 'c');
141        is($path->get, '/a/b');
142        is($path->pop, 'b');
143        is($path->get, '/a');
144        is($path->pop, 'a');
145        is($path->get, '/');
146
147        $path->set('a/');
148        $path->up;
149        is($path->get, '');
150        $path->up;
151        is($path->get, '');
152
153        $path->set('/a/');
154        $path->up;
155        is($path->get, '/');
156        $path->up;
157        is($path->get, '/');
158
159        $path->set('/a');
160        $path->up;
161        is($path->get, '/');
162        $path->up;
163        is($path->get, '/');
164
165        $path->set('/a/b/c/');
166        $path->up;
167        is($path->get, '/a/b');
168        $path->up;
169        is($path->get, '/a');
170        $path->up;
171        is($path->get, '/');
172    }
173
174
175    {
176        # greedy ^
177        my $path = path;
178
179        $path->set('a/');
180        is($path->pop('^'), 'a');
181        is($path->get, '');
182        is($path->pop('^'), '');
183        is($path->get, '');
184
185        $path->set('/a/');
186        is($path->pop('^'), '/a');
187        is($path->get, '');
188        is($path->pop('^'), '');
189        is($path->get, '');
190
191        $path->set('/a');
192        is($path->pop('^'), '/a');
193        is($path->get, '');
194        is($path->pop('^'), '');
195        is($path->get, '');
196
197        $path->set('/a/b/c/');
198        is($path->pop('^'), 'c');
199        is($path->get, '/a/b');
200        is($path->pop('^'), 'b');
201        is($path->get, '/a');
202        is($path->pop('^'), '/a');
203        is($path->get, '');
204
205        $path->set('a/');
206        $path->up('^');
207        is($path->get, '');
208        $path->up('^');
209        is($path->get, '');
210
211        $path->set('/a/');
212        $path->up('^');
213        is($path->get, '');
214        $path->up('^');
215        is($path->get, '');
216
217        $path->set('/a');
218        $path->up('^');
219        is($path->get, '');
220        $path->up('^');
221        is($path->get, '');
222
223        $path->set('/a/b/c/');
224        $path->up('^');
225        is($path->get, '/a/b');
226        $path->up('^');
227        is($path->get, '/a');
228        $path->up('^');
229        is($path->get, '');
230    }
231
232    {
233        # greedy *
234        my $path = path;
235
236        $path->set('a/');
237        is($path->pop('*'), 'a/');
238        is($path->get, '');
239        is($path->pop('*'), '');
240        is($path->get, '');
241
242        $path->set('/a/');
243        is($path->pop('*'), '/a/');
244        is($path->get, '');
245        is($path->pop('*'), '');
246        is($path->get, '');
247
248        $path->set('/a');
249        is($path->pop('*'), '/a');
250        is($path->get, '');
251        is($path->pop('*'), '');
252        is($path->get, '');
253
254        $path->set('/a/b/c/');
255        is($path->pop('*'), 'c/');
256        is($path->get, '/a/b');
257        is($path->pop('*'), 'b');
258        is($path->get, '/a');
259        is($path->pop('*'), '/a');
260        is($path->get, '');
261
262        $path->set('a/');
263        $path->up('*');
264        is($path->get, '');
265        $path->up('*');
266        is($path->get, '');
267
268        $path->set('/a/');
269        $path->up('*');
270        is($path->get, '');
271        $path->up('*');
272        is($path->get, '');
273
274        $path->set('/a');
275        $path->up('*');
276        is($path->get, '');
277        $path->up('*');
278        is($path->get, '');
279
280        $path->set('/a/b/c/');
281        $path->up('*');
282        is($path->get, '/a/b');
283        $path->up('*');
284        is($path->get, '/a');
285        $path->up('*');
286        is($path->get, '');
287    }
288
289    {
290        my $path;
291
292        # non-greedy
293        is(($path = path('a/b/c'))->pop('4'), 'a/b/c');
294        is($path->get, '');
295
296        is(($path = path('a/b/c'))->pop('3'), 'a/b/c');
297        is($path->get, '');
298
299        is(($path = path('a/b/c'))->pop('2'), 'b/c');
300        is($path->get, 'a');
301
302        is(($path = path('a/b/c'))->pop('1'), 'c');
303        is($path->get, 'a/b');
304
305        is(($path = path('a/b/c'))->pop('0'), '');
306        is($path->get, 'a/b/c');
307
308        # greedy-^
309        is(($path = path('a/b/c'))->pop('4^'), 'a/b/c');
310        is($path->get, '');
311
312        is(($path = path('a/b/c'))->pop('3^'), 'a/b/c');
313        is($path->get, '');
314
315        is(($path = path('a/b/c'))->pop('2^'), 'b/c');
316        is($path->get, 'a');
317
318        is(($path = path('a/b/c'))->pop('1^'), 'c');
319        is($path->get, 'a/b');
320
321        is(($path = path('a/b/c'))->pop('0^'), '');
322        is($path->get, 'a/b/c');
323
324        # greedy-$
325        is(($path = path('a/b/c'))->pop('4$'), 'a/b/c');
326        is($path->get, '');
327
328        is(($path = path('a/b/c'))->pop('3$'), 'a/b/c');
329        is($path->get, '');
330
331        is(($path = path('a/b/c'))->pop('2$'), 'b/c');
332        is($path->get, 'a');
333
334        is(($path = path('a/b/c'))->pop('1$'), 'c');
335        is($path->get, 'a/b');
336
337        is(($path = path('a/b/c'))->pop('0$'), '');
338        is($path->get, 'a/b/c');
339
340        # greedy-*
341        is(($path = path('a/b/c'))->pop('4*'), 'a/b/c');
342        is($path->get, '');
343
344        is(($path = path('a/b/c'))->pop('3*'), 'a/b/c');
345        is($path->get, '');
346
347        is(($path = path('a/b/c'))->pop('2*'), 'b/c');
348        is($path->get, 'a');
349
350        is(($path = path('a/b/c'))->pop('1*'), 'c');
351        is($path->get, 'a/b');
352
353        is(($path = path('a/b/c'))->pop('0*'), '');
354        is($path->get, 'a/b/c');
355
356        # non-greedy /.
357        is(($path = path('/a/b/c'))->pop('4'), 'a/b/c');
358        is($path->get, '/');
359
360        is(($path = path('/a/b/c'))->pop('3'), 'a/b/c');
361        is($path->get, '/');
362
363        is(($path = path('/a/b/c'))->pop('2'), 'b/c');
364        is($path->get, '/a');
365
366        is(($path = path('/a/b/c'))->pop('1'), 'c');
367        is($path->get, '/a/b');
368
369        is(($path = path('/a/b/c'))->pop('0'), '');
370        is($path->get, '/a/b/c');
371
372        # greedy-^ /.
373        is(($path = path('/a/b/c'))->pop('4^'), '/a/b/c');
374        is($path->get, '');
375
376        is(($path = path('/a/b/c'))->pop('3^'), '/a/b/c');
377        is($path->get, '');
378
379        is(($path = path('/a/b/c'))->pop('2^'), 'b/c');
380        is($path->get, '/a');
381
382        is(($path = path('/a/b/c'))->pop('1^'), 'c');
383        is($path->get, '/a/b');
384
385        is(($path = path('/a/b/c'))->pop('0^'), '');
386        is($path->get, '/a/b/c');
387
388        # greedy-$ /.
389        is(($path = path('/a/b/c'))->pop('4$'), 'a/b/c');
390        is($path->get, '/');
391
392        is(($path = path('/a/b/c'))->pop('3$'), 'a/b/c');
393        is($path->get, '/');
394
395        is(($path = path('/a/b/c'))->pop('2$'), 'b/c');
396        is($path->get, '/a');
397
398        is(($path = path('/a/b/c'))->pop('1$'), 'c');
399        is($path->get, '/a/b');
400
401        is(($path = path('/a/b/c'))->pop('0$'), '');
402        is($path->get, '/a/b/c');
403
404        # greedy-* /.
405        is(($path = path('/a/b/c'))->pop('4*'), '/a/b/c');
406        is($path->get, '');
407
408        is(($path = path('/a/b/c'))->pop('3*'), '/a/b/c');
409        is($path->get, '');
410
411        is(($path = path('/a/b/c'))->pop('2*'), 'b/c');
412        is($path->get, '/a');
413
414        is(($path = path('/a/b/c'))->pop('1*'), 'c');
415        is($path->get, '/a/b');
416
417        is(($path = path('/a/b/c'))->pop('0*'), '');
418        is($path->get, '/a/b/c');
419
420        # non-greedy /./
421        is(($path = path('/a/b/c/'))->pop('4'), 'a/b/c');
422        is($path->get, '/');
423
424        is(($path = path('/a/b/c/'))->pop('3'), 'a/b/c');
425        is($path->get, '/');
426
427        is(($path = path('/a/b/c/'))->pop('2'), 'b/c');
428        is($path->get, '/a');
429
430        is(($path = path('/a/b/c/'))->pop('1'), 'c');
431        is($path->get, '/a/b');
432
433        is(($path = path('/a/b/c/'))->pop('0'), '');
434        is($path->get, '/a/b/c/');
435
436        # greedy-^ /./
437        is(($path = path('/a/b/c/'))->pop('4^'), '/a/b/c');
438        is($path->get, '');
439
440        is(($path = path('/a/b/c/'))->pop('3^'), '/a/b/c');
441        is($path->get, '');
442
443        is(($path = path('/a/b/c/'))->pop('2^'), 'b/c');
444        is($path->get, '/a');
445
446        is(($path = path('/a/b/c/'))->pop('1^'), 'c');
447        is($path->get, '/a/b');
448
449        is(($path = path('/a/b/c/'))->pop('0^'), '');
450        is($path->get, '/a/b/c/');
451
452        # greedy-$ /./
453        is(($path = path('/a/b/c/'))->pop('4$'), 'a/b/c/');
454        is($path->get, '/');
455
456        is(($path = path('/a/b/c/'))->pop('3$'), 'a/b/c/');
457        is($path->get, '/');
458
459        is(($path = path('/a/b/c/'))->pop('2$'), 'b/c/');
460        is($path->get, '/a');
461
462        is(($path = path('/a/b/c/'))->pop('1$'), 'c/');
463        is($path->get, '/a/b');
464
465        is(($path = path('/a/b/c/'))->pop('0$'), '');
466        is($path->get, '/a/b/c/');
467
468        # greedy-* /./
469        is(($path = path('/a/b/c/'))->pop('4*'), '/a/b/c/');
470        is($path->get, '');
471
472        is(($path = path('/a/b/c/'))->pop('3*'), '/a/b/c/');
473        is($path->get, '');
474
475        is(($path = path('/a/b/c/'))->pop('2*'), 'b/c/');
476        is($path->get, '/a');
477
478        is(($path = path('/a/b/c/'))->pop('1*'), 'c/');
479        is($path->get, '/a/b');
480
481        is(($path = path('/a/b/c/'))->pop('0*'), '');
482        is($path->get, '/a/b/c/');
483
484        # non-greedy ./
485        is(($path = path('a/b/c/'))->pop('4'), 'a/b/c');
486        is($path->get, '');
487
488        is(($path = path('a/b/c/'))->pop('3'), 'a/b/c');
489        is($path->get, '');
490
491        is(($path = path('a/b/c/'))->pop('2'), 'b/c');
492        is($path->get, 'a');
493
494        is(($path = path('a/b/c/'))->pop('1'), 'c');
495        is($path->get, 'a/b');
496
497        is(($path = path('a/b/c/'))->pop('0'), '');
498        is($path->get, 'a/b/c/');
499
500        # greedy-^ ./
501        is(($path = path('a/b/c/'))->pop('4^'), 'a/b/c');
502        is($path->get, '');
503
504        is(($path = path('a/b/c/'))->pop('3^'), 'a/b/c');
505        is($path->get, '');
506
507        is(($path = path('a/b/c/'))->pop('2^'), 'b/c');
508        is($path->get, 'a');
509
510        is(($path = path('a/b/c/'))->pop('1^'), 'c');
511        is($path->get, 'a/b');
512
513        is(($path = path('a/b/c/'))->pop('0^'), '');
514        is($path->get, 'a/b/c/');
515
516        # greedy-$ ./
517        is(($path = path('a/b/c/'))->pop('4$'), 'a/b/c/');
518        is($path->get, '');
519
520        is(($path = path('a/b/c/'))->pop('3$'), 'a/b/c/');
521        is($path->get, '');
522
523        is(($path = path('a/b/c/'))->pop('2$'), 'b/c/');
524        is($path->get, 'a');
525
526        is(($path = path('a/b/c/'))->pop('1$'), 'c/');
527        is($path->get, 'a/b');
528
529        is(($path = path('a/b/c/'))->pop('0$'), '');
530        is($path->get, 'a/b/c/');
531
532        # greedy-* ./
533        is(($path = path('a/b/c/'))->pop('4*'), 'a/b/c/');
534        is($path->get, '');
535
536        is(($path = path('a/b/c/'))->pop('3*'), 'a/b/c/');
537        is($path->get, '');
538
539        is(($path = path('a/b/c/'))->pop('2*'), 'b/c/');
540        is($path->get, 'a');
541
542        is(($path = path('a/b/c/'))->pop('1*'), 'c/');
543        is($path->get, 'a/b');
544
545        is(($path = path('a/b/c/'))->pop('0*'), '');
546        is($path->get, 'a/b/c/');
547    }
548
549    {
550        my $path = path;
551
552        # .get
553        $path = path("a/b", "c/d", "e");
554        is("a/b/c/d/e", $path->get());
555
556        # .set
557        $path->set("");
558        is("", $path->get());
559
560        $path->set("/");
561        is("/", $path->get());
562
563        $path->set("a", "b/c//");
564        is("a/b/c/", $path->get());
565
566        $path->set("a/b/c/d/e");
567        is("a/b/c/d/e", $path->get());
568
569        # .pop
570        $path->pop();
571        is("a/b/c/d", $path->get());
572
573        $path->pop(2);
574        is("a/b", $path->get());
575
576        $path->pop(3);
577        is("", $path->get());
578
579        $path = path("/a/b/c");
580        $path->pop(10);
581        is("/", $path->get());
582
583        $path->set("/");
584        $path->pop();
585        is("/", $path->get());
586
587        # .push
588        $path->push("a");
589        is("/a", $path->get());
590
591        $path->push("a", "b/c//");
592        is("/a/a/b/c/", $path->get());
593
594        $path->push($path.'');
595        is("/a/a/b/c/a/a/b/c/", $path->get());
596
597        is("/a/a/b/c/a/a/b/c/", $path->get());
598
599        # .up .down
600        $path->set("a");
601        $path->up();
602        is("", path.'');
603
604        $path->down("a/b/c")->up();
605        is("a/b", $path.'');
606
607        $path->down("/h/i/j//")->up()->up()->up();
608        is("a/b", $path.'');
609
610        $path->down("/h/i/j//")->up(3);
611        is("a/b", $path.'');
612
613        $path->set("/");
614        $path->up();
615        is("/", $path.'');
616
617        $path->down("a");
618        is("/a", $path.'');
619
620        $path->down(1);
621        is("/a/1", $path.'');
622    }
623
624    {
625        my $path;
626        $path = path();
627        is("", $path . "");
628        is("", $path->get());
629        is("", $path->at(0));
630        is("", $path->at(-1));
631        is("", $path->at(1));
632        is("", $path->first());
633        is("", $path->last());
634        is("", $path->beginning());
635        is("", $path->ending());
636        ok($path->is_empty());
637        ok(!$path->is_root());
638        ok(!$path->is_tree());
639        ok($path->is_branch());
640        cmp_deeply([], [ $path->list ]);
641
642        $path = path("/");
643        is("/", $path . "");
644        is("/", $path->get());
645        is("", $path->at(0));
646        is("", $path->at(-1));
647        is("", $path->at(1));
648        is("", $path->first());
649        is("", $path->last());
650        is("/", $path->beginning());
651        is("/", $path->ending());
652        cmp_deeply([], [ $path->list ]);
653        ok(!$path->is_empty());
654        ok($path->is_root());
655        ok($path->is_tree());
656        ok(!$path->is_branch());
657
658        $path = path("a");
659        is("a", $path . "");
660        is("a", $path->get());
661        is("a", $path->at(0));
662        is("a", $path->at(-1));
663        is("", $path->at(1));
664        is("a", $path->first());
665        is("a", $path->last());
666        is("a", $path->beginning());
667        is("a", $path->ending());
668        cmp_deeply([ 'a' ], [ $path->list ]);
669        ok(!$path->is_empty());
670        ok(!$path->is_root());
671        ok(!$path->is_tree());
672        ok($path->is_branch());
673
674        $path = path("/a");
675        is("/a", $path . "");
676        is("/a", $path->get());
677        is("a", $path->at(0));
678        is("a", $path->at(-1));
679        is("", $path->at(1));
680        is("a", $path->first());
681        is("a", $path->last());
682        is("/a", $path->beginning());
683        is("a", $path->ending());
684        cmp_deeply([qw/ a /], [ $path->list ]);
685        ok(!$path->is_empty());
686        ok(!$path->is_root());
687        ok($path->is_tree());
688        ok(!$path->is_branch());
689
690        $path = path("/a/b");
691        is("/a/b", $path . "");
692        is("/a/b", $path->get());
693        is("a", $path->at(0));
694        is("b", $path->at(-1));
695        is("b", $path->at(1));
696        is("a", $path->first());
697        is("b", $path->last());
698        is("/a", $path->beginning());
699        is("b", $path->ending());
700        cmp_deeply([qw/ a b /], [ $path->list ]);
701        ok(!$path->is_empty());
702        ok(!$path->is_root());
703        ok($path->is_tree());
704        ok(!$path->is_branch());
705
706        $path = path("/a/b/");
707        is("/a/b/", $path . "");
708        is("/a/b/", $path->get());
709        is("a", $path->at(0));
710        is("b", $path->at(-1));
711        is("b", $path->at(1));
712        is("a", $path->first());
713        is("b", $path->last());
714        is("/a", $path->beginning());
715        is("b/", $path->ending());
716        cmp_deeply([qw/ a b /], [ $path->list ]);
717        ok(!$path->is_empty());
718        ok(!$path->is_root());
719        ok($path->is_tree());
720        ok(!$path->is_branch());
721
722        $path = path("/a/b/c");
723        is("/a/b/c", $path . "");
724        is("/a/b/c", $path->get());
725        is("a", $path->at(0));
726        is("c", $path->at(-1));
727        is("b", $path->at(1));
728        is("a", $path->first());
729        is("c", $path->last());
730        is("/a", $path->beginning());
731        is("c", $path->ending());
732        cmp_deeply([qw/ a b c /], [ $path->list ]);
733        ok(!$path->is_empty());
734        ok(!$path->is_empty());
735        ok(!$path->is_root());
736        ok($path->is_tree());
737        ok(!$path->is_branch());
738
739        $path = path("a/b/c");
740        is("a/b/c", $path . "");
741        is("a/b/c", $path->get());
742        is("a", $path->at(0));
743        is("c", $path->at(-1));
744        is("b", $path->at(1));
745        is("a", $path->first());
746        is("c", $path->last());
747        is("a", $path->beginning());
748        is("c", $path->ending());
749        cmp_deeply([qw/ a b c /], [ $path->list ]);
750        ok(!$path->is_empty());
751        ok(!$path->is_empty());
752        ok(!$path->is_root());
753        ok(!$path->is_tree());
754        ok($path->is_branch());
755    }
756}
757
758
759__END__
760
761    {
762        # greedy +
763        my $path = path;
764
765        $path->set('a/');
766        is($path->pop('+'), 'a');
767        is($path->get, '');
768        is($path->pop('+'), '');
769        is($path->get, '');
770
771        $path->set('/a/');
772        is($path->pop('+'), '/a');
773        is($path->get, '');
774        is($path->pop('+'), '');
775        is($path->get, '');
776
777        $path->set('/a');
778        is($path->pop('+'), '/a');
779        is($path->get, '');
780        is($path->pop('+'), '');
781        is($path->get, '');
782
783        $path->set('/a/b/c/');
784        is($path->pop('+'), 'c');
785        is($path->get, '/a/b');
786        is($path->pop('+'), 'b');
787        is($path->get, '/a');
788        is($path->pop('+'), '/a');
789        is($path->get, '');
790
791        $path->set('a/');
792        $path->up('+');
793        is($path->get, '');
794        $path->up('+');
795        is($path->get, '');
796
797        $path->set('/a/');
798        $path->up('+');
799        is($path->get, '');
800        $path->up('+');
801        is($path->get, '');
802
803        $path->set('/a');
804        $path->up('+');
805        is($path->get, '');
806        $path->up('+');
807        is($path->get, '');
808
809        $path->set('/a/b/c/');
810        $path->up('+');
811        is($path->get, '/a/b');
812        $path->up('+');
813        is($path->get, '/a');
814        $path->up('+');
815        is($path->get, '');
816    }
817
818    {
819        # greedy *
820        my $path = path;
821
822        $path->set('a/');
823        is($path->pop('*'), 'a/');
824        is($path->get, '');
825        is($path->pop('*'), '');
826        is($path->get, '');
827
828        $path->set('/a/');
829        is($path->pop('*'), '/a/');
830        is($path->get, '');
831        is($path->pop('*'), '');
832        is($path->get, '');
833
834        $path->set('/a');
835        is($path->pop('*'), '/a');
836        is($path->get, '');
837        is($path->pop('*'), '');
838        is($path->get, '');
839
840        $path->set('/a/b/c/');
841        is($path->pop('*'), 'c/');
842        is($path->get, '/a/b');
843        is($path->pop('*'), 'b');
844        is($path->get, '/a');
845        is($path->pop('*'), '/a');
846        is($path->get, '');
847
848        $path->set('a/');
849        $path->up('*');
850        is($path->get, '');
851        $path->up('*');
852        is($path->get, '');
853
854        $path->set('/a/');
855        $path->up('*');
856        is($path->get, '');
857        $path->up('*');
858        is($path->get, '');
859
860        $path->set('/a');
861        $path->up('*');
862        is($path->get, '');
863        $path->up('*');
864        is($path->get, '');
865
866        $path->set('/a/b/c/');
867        $path->up('*');
868        is($path->get, '/a/b');
869        $path->up('*');
870        is($path->get, '/a');
871        $path->up('*');
872        is($path->get, '');
873    }
874
875    {
876        my $path;
877
878        # non-greedy
879        is(($path = path('a/b/c'))->pop('4'), 'a/b/c');
880        is($path->get, '');
881
882        is(($path = path('a/b/c'))->pop('3'), 'a/b/c');
883        is($path->get, '');
884
885        is(($path = path('a/b/c'))->pop('2'), 'b/c');
886        is($path->get, 'a');
887
888        is(($path = path('a/b/c'))->pop('1'), 'c');
889        is($path->get, 'a/b');
890
891        is(($path = path('a/b/c'))->pop('0'), '');
892        is($path->get, 'a/b/c');
893
894        # greedy-+
895        is(($path = path('a/b/c'))->pop('4+'), 'a/b/c');
896        is($path->get, '');
897
898        is(($path = path('a/b/c'))->pop('3+'), 'a/b/c');
899        is($path->get, '');
900
901        is(($path = path('a/b/c'))->pop('2+'), 'b/c');
902        is($path->get, 'a');
903
904        is(($path = path('a/b/c'))->pop('1+'), 'c');
905        is($path->get, 'a/b');
906
907        is(($path = path('a/b/c'))->pop('0+'), '');
908        is($path->get, 'a/b/c');
909
910        # greedy-*
911        is(($path = path('a/b/c'))->pop('4*'), 'a/b/c');
912        is($path->get, '');
913
914        is(($path = path('a/b/c'))->pop('3*'), 'a/b/c');
915        is($path->get, '');
916
917        is(($path = path('a/b/c'))->pop('2*'), 'b/c');
918        is($path->get, 'a');
919
920        is(($path = path('a/b/c'))->pop('1*'), 'c');
921        is($path->get, 'a/b');
922
923        is(($path = path('a/b/c'))->pop('0*'), '');
924        is($path->get, 'a/b/c');
925
926        # non-greedy /.
927        is(($path = path('/a/b/c'))->pop('4'), 'a/b/c');
928        is($path->get, '/');
929
930        is(($path = path('/a/b/c'))->pop('3'), 'a/b/c');
931        is($path->get, '/');
932
933        is(($path = path('/a/b/c'))->pop('2'), 'b/c');
934        is($path->get, '/a');
935
936        is(($path = path('/a/b/c'))->pop('1'), 'c');
937        is($path->get, '/a/b');
938
939        is(($path = path('/a/b/c'))->pop('0'), '');
940        is($path->get, '/a/b/c');
941
942        # greedy-+ /.
943        is(($path = path('/a/b/c'))->pop('4+'), '/a/b/c');
944        is($path->get, '');
945
946        is(($path = path('/a/b/c'))->pop('3+'), '/a/b/c');
947        is($path->get, '');
948
949        is(($path = path('/a/b/c'))->pop('2+'), 'b/c');
950        is($path->get, '/a');
951
952        is(($path = path('/a/b/c'))->pop('1+'), 'c');
953        is($path->get, '/a/b');
954
955        is(($path = path('/a/b/c'))->pop('0+'), '');
956        is($path->get, '/a/b/c');
957
958        # greedy-* /.
959        is(($path = path('/a/b/c'))->pop('4*'), '/a/b/c');
960        is($path->get, '');
961
962        is(($path = path('/a/b/c'))->pop('3*'), '/a/b/c');
963        is($path->get, '');
964
965        is(($path = path('/a/b/c'))->pop('2*'), 'b/c');
966        is($path->get, '/a');
967
968        is(($path = path('/a/b/c'))->pop('1*'), 'c');
969        is($path->get, '/a/b');
970
971        is(($path = path('/a/b/c'))->pop('0*'), '');
972        is($path->get, '/a/b/c');
973
974        # non-greedy /./
975        is(($path = path('/a/b/c/'))->pop('4'), 'a/b/c');
976        is($path->get, '/');
977
978        is(($path = path('/a/b/c/'))->pop('3'), 'a/b/c');
979        is($path->get, '/');
980
981        is(($path = path('/a/b/c/'))->pop('2'), 'b/c');
982        is($path->get, '/a');
983
984        is(($path = path('/a/b/c/'))->pop('1'), 'c');
985        is($path->get, '/a/b');
986
987        is(($path = path('/a/b/c/'))->pop('0'), '');
988        is($path->get, '/a/b/c/');
989
990        # greedy-+ /./
991        is(($path = path('/a/b/c/'))->pop('4+'), '/a/b/c');
992        is($path->get, '');
993
994        is(($path = path('/a/b/c/'))->pop('3+'), '/a/b/c');
995        is($path->get, '');
996
997        is(($path = path('/a/b/c/'))->pop('2+'), 'b/c');
998        is($path->get, '/a');
999
1000        is(($path = path('/a/b/c/'))->pop('1+'), 'c');
1001        is($path->get, '/a/b');
1002
1003        is(($path = path('/a/b/c/'))->pop('0+'), '');
1004        is($path->get, '/a/b/c/');
1005
1006        # greedy-* /./
1007        is(($path = path('/a/b/c/'))->pop('4*'), '/a/b/c/');
1008        is($path->get, '');
1009
1010        is(($path = path('/a/b/c/'))->pop('3*'), '/a/b/c/');
1011        is($path->get, '');
1012
1013        is(($path = path('/a/b/c/'))->pop('2*'), 'b/c/');
1014        is($path->get, '/a');
1015
1016        is(($path = path('/a/b/c/'))->pop('1*'), 'c/');
1017        is($path->get, '/a/b');
1018
1019        is(($path = path('/a/b/c/'))->pop('0*'), '');
1020        is($path->get, '/a/b/c/');
1021    }
1022