1 changed files with 477 additions and 409 deletions
@ -1,410 +1,478 @@
|
||||
package require tcltest |
||||
tcltest::configure {*}$::argv |
||||
|
||||
|
||||
package require punk::lib |
||||
package require punk::path |
||||
|
||||
namespace eval ::testspace { |
||||
namespace import ::tcltest::* |
||||
|
||||
variable common { |
||||
set result "" |
||||
} |
||||
|
||||
variable subfolders_tree { |
||||
set sub_prevdir [pwd] |
||||
set sub_newbase [punk::lib::tempdir_newfolder -prefix punk_path_subfolders] |
||||
cd $sub_newbase |
||||
set sub_tree_tail __punk_path_subfolders_test__ |
||||
set sub_tree_root [file join $sub_newbase $sub_tree_tail] |
||||
file mkdir [file join $sub_tree_root keep] |
||||
file mkdir [file join $sub_tree_root src vfs deep] |
||||
file mkdir [file join $sub_tree_root aside child grandchild] |
||||
} |
||||
|
||||
variable subfolders_cleanup { |
||||
cd $sub_prevdir |
||||
file delete -force $sub_newbase |
||||
} |
||||
|
||||
variable repeated_subfolders_tree { |
||||
set rep_prevdir [pwd] |
||||
set rep_newbase [punk::lib::tempdir_newfolder -prefix punk_path_repeated_subfolders] |
||||
cd $rep_newbase |
||||
set rep_tree_tail __punk_path_repeated_subfolders_test__ |
||||
set rep_tree_root [file join $rep_newbase $rep_tree_tail] |
||||
file mkdir [file join $rep_tree_root alpha a a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a x a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a xx a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a x y a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a x y z a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a x y z keep] |
||||
file mkdir [file join $rep_tree_root alpha a q aa leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha aa x a leaf deeper] |
||||
} |
||||
|
||||
variable repeated_subfolders_cleanup { |
||||
cd $rep_prevdir |
||||
file delete -force $rep_newbase |
||||
} |
||||
|
||||
variable treefilenames_tree { |
||||
set tf_prevdir [pwd] |
||||
set tf_newbase [punk::lib::tempdir_newfolder -prefix punk_path_treefilenames] |
||||
cd $tf_newbase |
||||
set tf_tree_tail __punk_path_treefilenames_test__ |
||||
set tf_tree_root [file join $tf_newbase $tf_tree_tail] |
||||
file mkdir [file join $tf_tree_root keep] |
||||
file mkdir [file join $tf_tree_root src vfs deep] |
||||
file mkdir [file join $tf_tree_root aside child grandchild] |
||||
foreach relpath { |
||||
keep/keep.txt |
||||
src/srcroot.txt |
||||
src/vfs/vfs.txt |
||||
src/vfs/deep/deep.txt |
||||
aside/aside.txt |
||||
aside/child/child.txt |
||||
aside/child/grandchild/grandchild.txt |
||||
b/other/other.txt |
||||
} { |
||||
set filepath [file join $tf_tree_root $relpath] |
||||
file mkdir [file dirname $filepath] |
||||
set channel [open $filepath w] |
||||
puts $channel $relpath |
||||
close $channel |
||||
} |
||||
} |
||||
|
||||
variable treefilenames_cleanup { |
||||
cd $tf_prevdir |
||||
file delete -force $tf_newbase |
||||
} |
||||
|
||||
test globmatchpath_basic {Test single star between slashes pathglob argument will match exactly a single level} \ |
||||
-setup $common -body { |
||||
set result [list \ |
||||
[punk::path::globmatchpath /etc/*/*.doc /etc/A/test.doc] \ |
||||
[punk::path::globmatchpath /etc/*/*.doc /etc/A/B/test.doc] \ |
||||
[punk::path::globmatchpath /etc/*/*.doc /etc/test.doc] \ |
||||
] |
||||
} \ |
||||
-cleanup { |
||||
} \ |
||||
-result {1 0 0} |
||||
|
||||
test subfolders_exclude_trailing_doublestar {Trailing /** prunes descendants but keeps the matching base directory} \ |
||||
-setup $subfolders_tree -body { |
||||
set result [lsort [punk::path::subfolders -recursive -exclude-paths {**/src/**} .]] |
||||
set expected [lsort [list \ |
||||
[file join . $sub_tree_tail] \ |
||||
[file join . $sub_tree_tail aside] \ |
||||
[file join . $sub_tree_tail aside child] \ |
||||
[file join . $sub_tree_tail aside child grandchild] \ |
||||
[file join . $sub_tree_tail keep] \ |
||||
[file join . $sub_tree_tail src] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_exclude_single_segment {Single-level excludes omit the node but still recurse into it} \ |
||||
-setup $subfolders_tree -body { |
||||
set result [lsort [punk::path::subfolders -recursive -exclude-paths {**/aside/*} .]] |
||||
set expected [lsort [list \ |
||||
[file join . $sub_tree_tail] \ |
||||
[file join . $sub_tree_tail aside] \ |
||||
[file join . $sub_tree_tail aside child grandchild] \ |
||||
[file join . $sub_tree_tail keep] \ |
||||
[file join . $sub_tree_tail src] \ |
||||
[file join . $sub_tree_tail src vfs] \ |
||||
[file join . $sub_tree_tail src vfs deep] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_exclude_exact_segment {Exact segment excludes omit the node but still traverse below it} \ |
||||
-setup $subfolders_tree -body { |
||||
set result [lsort [punk::path::subfolders -recursive -exclude-paths {**/aside} .]] |
||||
set expected [lsort [list \ |
||||
[file join . $sub_tree_tail] \ |
||||
[file join . $sub_tree_tail aside child] \ |
||||
[file join . $sub_tree_tail aside child grandchild] \ |
||||
[file join . $sub_tree_tail keep] \ |
||||
[file join . $sub_tree_tail src] \ |
||||
[file join . $sub_tree_tail src vfs] \ |
||||
[file join . $sub_tree_tail src vfs deep] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_exclude_combined_patterns {Subtree and exact excludes compose correctly in recursive traversal} \ |
||||
-setup $subfolders_tree -body { |
||||
set result [lsort [punk::path::subfolders -recursive -exclude-paths {**/src/** **/aside} .]] |
||||
set expected [lsort [list \ |
||||
[file join . $sub_tree_tail] \ |
||||
[file join . $sub_tree_tail aside child] \ |
||||
[file join . $sub_tree_tail aside child grandchild] \ |
||||
[file join . $sub_tree_tail keep] \ |
||||
[file join . $sub_tree_tail src] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_single_star {Repeated segment exclude with one wildcard segment prunes only that shape} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf deeper] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z keep] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_two_single_stars {Repeated segment exclude with two wildcard segments prunes only that shape} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x y a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf deeper] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_middle_doublestar {Repeated segment exclude with middle doublestar prunes repeated a descendants at multiple depths} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/**/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a leaf] ni $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_nonmatching_pattern {Repeated path segments are retained when pattern literals do not match} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/b/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_exact_boundary {Exact repeated segment excludes boundary node but still traverses below it} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/a} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_adjacent_literals {Adjacent repeated literals match only adjacent path segments} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_question_segment {Question mark wildcard matches exactly one character within one segment} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/?/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a xx a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_similar_names {Similar segment names do not match repeated literal a patterns accidentally} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a q aa leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha aa x a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_similar_name_patterns {Similar literal aa patterns match only their own segment shapes} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/aa/** **/aa/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a q aa] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a q aa leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha aa x a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha aa x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_overlapping_patterns {Overlapping repeated segment excludes prune each matching shape independently} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/a/** **/a/*/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z keep] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_recurse_nested_positive_glob {Positive glob traversal reaches nested matches below unmatched ancestors} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory . -include-paths {**/src/**} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join . $tf_tree_tail src vfs deep deep.txt] \ |
||||
[file join . $tf_tree_tail src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_nonexistent_glob_path_returns_empty {Non-matching glob_paths subtree should return no files} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [punk::path::treefilenames -sort none -directory . -include-paths {**/nonexistantfolder/**} *] |
||||
expr {$result eq [list]} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_newbase_returns_tree_tail {Tailbase can trim returned filenames to the tree folder} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_newbase *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join $tf_tree_tail aside aside.txt] \ |
||||
[file join $tf_tree_tail aside child child.txt] \ |
||||
[file join $tf_tree_tail aside child grandchild grandchild.txt] \ |
||||
[file join $tf_tree_tail b other other.txt] \ |
||||
[file join $tf_tree_tail keep keep.txt] \ |
||||
[file join $tf_tree_tail src srcroot.txt] \ |
||||
[file join $tf_tree_tail src vfs deep deep.txt] \ |
||||
[file join $tf_tree_tail src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_tree_root_returns_tree_relative {Tailbase can trim returned filenames to paths below the search root} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join aside aside.txt] \ |
||||
[file join aside child child.txt] \ |
||||
[file join aside child grandchild grandchild.txt] \ |
||||
[file join b other other.txt] \ |
||||
[file join keep keep.txt] \ |
||||
[file join src srcroot.txt] \ |
||||
[file join src vfs deep deep.txt] \ |
||||
[file join src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_exclude_paths_match_returned_paths {Exclude paths match tailbase-relative returned paths} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root -exclude-paths {aside aside/** src/vfs/**} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join b other other.txt] \ |
||||
[file join keep keep.txt] \ |
||||
[file join src srcroot.txt] \ |
||||
[file join src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_include_paths_match_tree_root_relative_paths {Include paths match tailbase-relative paths below the tree root} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root -include-paths {src/**} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join src vfs deep deep.txt] \ |
||||
[file join src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_include_paths_match_newbase_relative_paths {Include paths include the tree folder when tailbase is above the search root} \ |
||||
-setup $treefilenames_tree -body { |
||||
set include_path [file join $tf_tree_tail src **] |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_newbase -include-paths [list $include_path] *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join $tf_tree_tail src vfs deep deep.txt] \ |
||||
[file join $tf_tree_tail src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_include_and_exclude_paths_share_relative_base {Include and exclude paths use the same tailbase-relative base} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root -include-paths {src/**} -exclude-paths {src/vfs/**} *.txt]] |
||||
set expected [list [file join src vfs vfs.txt]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_rejects_internal_call_flags {Internal recursion state flags are not public API} \ |
||||
-setup $treefilenames_tree -body { |
||||
set results [list] |
||||
foreach arglist { |
||||
{-call-depth-internal 1 -directory . *} |
||||
{-call-subvector {a b} -directory . *} |
||||
{-call-allbelow 1 -directory . *} |
||||
} { |
||||
lappend results [catch {punk::path::treefilenames {*}$arglist}] |
||||
} |
||||
expr {$results eq {1 1 1}} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
} |
||||
|
||||
package require tcltest |
||||
tcltest::configure {*}$::argv |
||||
|
||||
|
||||
package require punk::lib |
||||
package require punk::path |
||||
|
||||
namespace eval ::testspace { |
||||
namespace import ::tcltest::* |
||||
|
||||
variable common { |
||||
set result "" |
||||
} |
||||
|
||||
variable subfolders_tree { |
||||
set sub_prevdir [pwd] |
||||
set sub_newbase [punk::lib::tempdir_newfolder -prefix punk_path_subfolders] |
||||
cd $sub_newbase |
||||
set sub_tree_tail __punk_path_subfolders_test__ |
||||
set sub_tree_root [file join $sub_newbase $sub_tree_tail] |
||||
file mkdir [file join $sub_tree_root keep] |
||||
file mkdir [file join $sub_tree_root src vfs deep] |
||||
file mkdir [file join $sub_tree_root aside child grandchild] |
||||
} |
||||
|
||||
variable subfolders_cleanup { |
||||
cd $sub_prevdir |
||||
file delete -force $sub_newbase |
||||
} |
||||
|
||||
variable repeated_subfolders_tree { |
||||
set rep_prevdir [pwd] |
||||
set rep_newbase [punk::lib::tempdir_newfolder -prefix punk_path_repeated_subfolders] |
||||
cd $rep_newbase |
||||
set rep_tree_tail __punk_path_repeated_subfolders_test__ |
||||
set rep_tree_root [file join $rep_newbase $rep_tree_tail] |
||||
file mkdir [file join $rep_tree_root alpha a a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a x a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a xx a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a x y a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a x y z a leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha a x y z keep] |
||||
file mkdir [file join $rep_tree_root alpha a q aa leaf deeper] |
||||
file mkdir [file join $rep_tree_root alpha aa x a leaf deeper] |
||||
} |
||||
|
||||
variable repeated_subfolders_cleanup { |
||||
cd $rep_prevdir |
||||
file delete -force $rep_newbase |
||||
} |
||||
|
||||
variable treefilenames_tree { |
||||
set tf_prevdir [pwd] |
||||
set tf_newbase [punk::lib::tempdir_newfolder -prefix punk_path_treefilenames] |
||||
cd $tf_newbase |
||||
set tf_tree_tail __punk_path_treefilenames_test__ |
||||
set tf_tree_root [file join $tf_newbase $tf_tree_tail] |
||||
file mkdir [file join $tf_tree_root keep] |
||||
file mkdir [file join $tf_tree_root src vfs deep] |
||||
file mkdir [file join $tf_tree_root aside child grandchild] |
||||
foreach relpath { |
||||
keep/keep.txt |
||||
src/srcroot.txt |
||||
src/vfs/vfs.txt |
||||
src/vfs/deep/deep.txt |
||||
aside/aside.txt |
||||
aside/child/child.txt |
||||
aside/child/grandchild/grandchild.txt |
||||
b/other/other.txt |
||||
alpha/subdir/direct.txt |
||||
alpha/subdir/deep/deep.txt |
||||
} { |
||||
set filepath [file join $tf_tree_root $relpath] |
||||
file mkdir [file dirname $filepath] |
||||
set channel [open $filepath w] |
||||
puts $channel $relpath |
||||
close $channel |
||||
} |
||||
} |
||||
|
||||
variable treefilenames_cleanup { |
||||
cd $tf_prevdir |
||||
file delete -force $tf_newbase |
||||
} |
||||
|
||||
test globmatchpath_basic {Test single star between slashes pathglob argument will match exactly a single level} \ |
||||
-setup $common -body { |
||||
set result [list \ |
||||
[punk::path::globmatchpath /etc/*/*.doc /etc/A/test.doc] \ |
||||
[punk::path::globmatchpath /etc/*/*.doc /etc/A/B/test.doc] \ |
||||
[punk::path::globmatchpath /etc/*/*.doc /etc/test.doc] \ |
||||
] |
||||
} \ |
||||
-cleanup { |
||||
} \ |
||||
-result {1 0 0} |
||||
|
||||
test subfolders_exclude_trailing_doublestar {Trailing /** prunes descendants but keeps the matching base directory} \ |
||||
-setup $subfolders_tree -body { |
||||
set result [lsort [punk::path::subfolders -recursive -exclude-paths {**/src/**} .]] |
||||
set expected [lsort [list \ |
||||
[file join . $sub_tree_tail] \ |
||||
[file join . $sub_tree_tail aside] \ |
||||
[file join . $sub_tree_tail aside child] \ |
||||
[file join . $sub_tree_tail aside child grandchild] \ |
||||
[file join . $sub_tree_tail keep] \ |
||||
[file join . $sub_tree_tail src] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_exclude_single_segment {Single-level excludes omit the node but still recurse into it} \ |
||||
-setup $subfolders_tree -body { |
||||
set result [lsort [punk::path::subfolders -recursive -exclude-paths {**/aside/*} .]] |
||||
set expected [lsort [list \ |
||||
[file join . $sub_tree_tail] \ |
||||
[file join . $sub_tree_tail aside] \ |
||||
[file join . $sub_tree_tail aside child grandchild] \ |
||||
[file join . $sub_tree_tail keep] \ |
||||
[file join . $sub_tree_tail src] \ |
||||
[file join . $sub_tree_tail src vfs] \ |
||||
[file join . $sub_tree_tail src vfs deep] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_exclude_exact_segment {Exact segment excludes omit the node but still traverse below it} \ |
||||
-setup $subfolders_tree -body { |
||||
set result [lsort [punk::path::subfolders -recursive -exclude-paths {**/aside} .]] |
||||
set expected [lsort [list \ |
||||
[file join . $sub_tree_tail] \ |
||||
[file join . $sub_tree_tail aside child] \ |
||||
[file join . $sub_tree_tail aside child grandchild] \ |
||||
[file join . $sub_tree_tail keep] \ |
||||
[file join . $sub_tree_tail src] \ |
||||
[file join . $sub_tree_tail src vfs] \ |
||||
[file join . $sub_tree_tail src vfs deep] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_exclude_combined_patterns {Subtree and exact excludes compose correctly in recursive traversal} \ |
||||
-setup $subfolders_tree -body { |
||||
set result [lsort [punk::path::subfolders -recursive -exclude-paths {**/src/** **/aside} .]] |
||||
set expected [lsort [list \ |
||||
[file join . $sub_tree_tail] \ |
||||
[file join . $sub_tree_tail aside child] \ |
||||
[file join . $sub_tree_tail aside child grandchild] \ |
||||
[file join . $sub_tree_tail keep] \ |
||||
[file join . $sub_tree_tail src] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_single_star {Repeated segment exclude with one wildcard segment prunes only that shape} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf deeper] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z keep] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_two_single_stars {Repeated segment exclude with two wildcard segments prunes only that shape} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x y a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf deeper] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_middle_doublestar {Repeated segment exclude with middle doublestar prunes repeated a descendants at multiple depths} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/**/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a leaf] ni $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_nonmatching_pattern {Repeated path segments are retained when pattern literals do not match} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/b/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_exact_boundary {Exact repeated segment excludes boundary node but still traverses below it} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/a} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_adjacent_literals {Adjacent repeated literals match only adjacent path segments} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_question_segment {Question mark wildcard matches exactly one character within one segment} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/?/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a xx a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_similar_names {Similar segment names do not match repeated literal a patterns accidentally} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a q aa leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha aa x a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_similar_name_patterns {Similar literal aa patterns match only their own segment shapes} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/aa/** **/aa/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a q aa] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a q aa leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha aa x a] in $result \ |
||||
&& [file join . $rep_tree_tail alpha aa x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x a leaf] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test subfolders_repeated_segments_overlapping_patterns {Overlapping repeated segment excludes prune each matching shape independently} \ |
||||
-setup $repeated_subfolders_tree -body { |
||||
set result [punk::path::subfolders -recursive -exclude-paths {**/a/*/a/** **/a/*/*/a/**} .] |
||||
expr { \ |
||||
[file join . $rep_tree_tail alpha a x a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y a leaf] ni $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z a leaf] in $result \ |
||||
&& [file join . $rep_tree_tail alpha a x y z keep] in $result \ |
||||
} |
||||
} \ |
||||
-cleanup $repeated_subfolders_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_recurse_nested_positive_glob {Positive glob traversal reaches nested matches below unmatched ancestors} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory . -include-paths {**/src/**} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join . $tf_tree_tail src vfs deep deep.txt] \ |
||||
[file join . $tf_tree_tail src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_nonexistent_glob_path_returns_empty {Non-matching glob_paths subtree should return no files} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [punk::path::treefilenames -sort none -directory . -include-paths {**/nonexistantfolder/**} *] |
||||
expr {$result eq [list]} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_include_paths_subdir_boundary_before_exact {Include paths include internal and trailing subdir matches when subtree pattern appears first} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory . -include-paths {**/subdir/** **/subdir} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join . $tf_tree_tail alpha subdir deep deep.txt] \ |
||||
[file join . $tf_tree_tail alpha subdir direct.txt] \ |
||||
]] |
||||
if {$result ne $expected} { |
||||
error "result mismatch\nexpected: $expected\nactual: $result" |
||||
} |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_include_paths_subdir_exact_before_boundary {Include paths include internal and trailing subdir matches when exact pattern appears first} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory . -include-paths {**/subdir **/subdir/**} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join . $tf_tree_tail alpha subdir deep deep.txt] \ |
||||
[file join . $tf_tree_tail alpha subdir direct.txt] \ |
||||
]] |
||||
if {$result ne $expected} { |
||||
error "result mismatch\nexpected: $expected\nactual: $result" |
||||
} |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_newbase_returns_tree_tail {Tailbase can trim returned filenames to the tree folder} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_newbase *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join $tf_tree_tail alpha subdir deep deep.txt] \ |
||||
[file join $tf_tree_tail alpha subdir direct.txt] \ |
||||
[file join $tf_tree_tail aside aside.txt] \ |
||||
[file join $tf_tree_tail aside child child.txt] \ |
||||
[file join $tf_tree_tail aside child grandchild grandchild.txt] \ |
||||
[file join $tf_tree_tail b other other.txt] \ |
||||
[file join $tf_tree_tail keep keep.txt] \ |
||||
[file join $tf_tree_tail src srcroot.txt] \ |
||||
[file join $tf_tree_tail src vfs deep deep.txt] \ |
||||
[file join $tf_tree_tail src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_tree_root_returns_tree_relative {Tailbase can trim returned filenames to paths below the search root} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join alpha subdir deep deep.txt] \ |
||||
[file join alpha subdir direct.txt] \ |
||||
[file join aside aside.txt] \ |
||||
[file join aside child child.txt] \ |
||||
[file join aside child grandchild grandchild.txt] \ |
||||
[file join b other other.txt] \ |
||||
[file join keep keep.txt] \ |
||||
[file join src srcroot.txt] \ |
||||
[file join src vfs deep deep.txt] \ |
||||
[file join src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_exclude_paths_match_returned_paths {Exclude paths match tailbase-relative returned paths} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root -exclude-paths {aside aside/** src/vfs/**} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join alpha subdir deep deep.txt] \ |
||||
[file join alpha subdir direct.txt] \ |
||||
[file join b other other.txt] \ |
||||
[file join keep keep.txt] \ |
||||
[file join src srcroot.txt] \ |
||||
[file join src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_include_paths_match_tree_root_relative_paths {Include paths match tailbase-relative paths below the tree root} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root -include-paths {src/**} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join src vfs deep deep.txt] \ |
||||
[file join src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_include_paths_subdir_boundary_before_exact {Tailbase include paths include internal and trailing subdir matches when subtree pattern appears first} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root -include-paths {**/subdir/** **/subdir} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join alpha subdir deep deep.txt] \ |
||||
[file join alpha subdir direct.txt] \ |
||||
]] |
||||
if {$result ne $expected} { |
||||
error "result mismatch\nexpected: $expected\nactual: $result" |
||||
} |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_include_paths_subdir_exact_before_boundary {Tailbase include paths include internal and trailing subdir matches when exact pattern appears first} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root -include-paths {**/subdir **/subdir/**} *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join alpha subdir deep deep.txt] \ |
||||
[file join alpha subdir direct.txt] \ |
||||
]] |
||||
if {$result ne $expected} { |
||||
error "result mismatch\nexpected: $expected\nactual: $result" |
||||
} |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_include_paths_match_newbase_relative_paths {Include paths include the tree folder when tailbase is above the search root} \ |
||||
-setup $treefilenames_tree -body { |
||||
set include_path [file join $tf_tree_tail src **] |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_newbase -include-paths [list $include_path] *.txt]] |
||||
set expected [lsort [list \ |
||||
[file join $tf_tree_tail src vfs deep deep.txt] \ |
||||
[file join $tf_tree_tail src vfs vfs.txt] \ |
||||
]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_tailbase_include_and_exclude_paths_share_relative_base {Include and exclude paths use the same tailbase-relative base} \ |
||||
-setup $treefilenames_tree -body { |
||||
set result [lsort [punk::path::treefilenames -sort none -directory $tf_tree_root -tailbase $tf_tree_root -include-paths {src/**} -exclude-paths {src/vfs/**} *.txt]] |
||||
set expected [list [file join src vfs vfs.txt]] |
||||
expr {$result eq $expected} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
|
||||
test treefilenames_rejects_internal_call_flags {Internal recursion state flags are not public API} \ |
||||
-setup $treefilenames_tree -body { |
||||
set results [list] |
||||
foreach arglist { |
||||
{-call-depth-internal 1 -directory . *} |
||||
{-call-subvector {a b} -directory . *} |
||||
{-call-allbelow 1 -directory . *} |
||||
} { |
||||
lappend results [catch {punk::path::treefilenames {*}$arglist}] |
||||
} |
||||
expr {$results eq {1 1 1}} |
||||
} \ |
||||
-cleanup $treefilenames_cleanup \ |
||||
-result 1 |
||||
} |
||||
|
||||
tcltest::cleanupTests ;#needed to produce test summary. |
||||
Loading…
Reference in new issue