mirror of
https://github.com/tcltk/tcl.git
synced 2026-05-29 00:27:49 +08:00
2016 lines
64 KiB
Plaintext
2016 lines
64 KiB
Plaintext
# This file tests the tclWinFCmd.c file.
|
|
#
|
|
# This file contains a collection of tests for one or more of the Tcl
|
|
# built-in commands. Sourcing this file into Tcl runs the tests and
|
|
# generates output for errors. No output means no errors were found.
|
|
#
|
|
# Copyright © 1996-1997 Sun Microsystems, Inc.
|
|
# Copyright © 1998-1999 Scriptics Corporation.
|
|
#
|
|
# See the file "license.terms" for information on usage and redistribution
|
|
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
|
|
if {"::tcltest" ni [namespace children]} {
|
|
package require tcltest 2.5
|
|
namespace import -force ::tcltest::*
|
|
}
|
|
|
|
::tcltest::loadTestedCommands
|
|
catch [list package require -exact tcl::test [info patchlevel]]
|
|
|
|
# Initialise the test constraints
|
|
|
|
testConstraint testvolumetype [llength [info commands testvolumetype]]
|
|
testConstraint testfile [llength [info commands testfile]]
|
|
testConstraint testchmod [llength [info commands testchmod]]
|
|
testConstraint cdrom 0
|
|
testConstraint exdev 0
|
|
testConstraint longFileNames 0
|
|
# Some things fail under all Continuous Integration systems for subtle reasons
|
|
# such as CI often running with elevated privileges in a container.
|
|
testConstraint notInCIenv [expr {![info exists ::env(CI)]}]
|
|
testConstraint knownMsvcBug [expr {[tcl::build-info msvc] eq 0}]
|
|
|
|
# Long path support (not to be confused with long name support!) depends on
|
|
# the system being recent enough AND configured for long paths in the registry.
|
|
testConstraint longPathAware 0
|
|
if {![catch {exec {*}[auto_execok cmd.exe] /c ver} winVer]} {
|
|
if {[regexp {(\d+)\.\d+\.(\d+)\.\d+} $winVer -> winMajor winBuild]} {
|
|
# Must be Win 10
|
|
if {$winMajor > 10 || ($winMajor == 10 && $winBuild >= 14393)} {
|
|
if {[llength [info commands testlongpathsetting]]} {
|
|
testConstraint longPathAware [testlongpathsetting]
|
|
} else {
|
|
catch {
|
|
package require registry
|
|
testConstraint longPathAware [registry get "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\FileSystem" LongPathsEnabled]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
unset -nocomplain winMajor winBuild winVer
|
|
|
|
proc createfile {file {string a}} {
|
|
set f [open $file w]
|
|
puts -nonewline $f $string
|
|
close $f
|
|
return $string
|
|
}
|
|
|
|
proc contents {file} {
|
|
set f [open $file r]
|
|
set r [read $f]
|
|
close $f
|
|
set r
|
|
}
|
|
|
|
proc cleanupRecurse {args} {
|
|
# Assumes no loops via links!
|
|
# Need to change permissions BEFORE deletion
|
|
catch {testchmod 0o777 {*}$args}
|
|
foreach victim $args {
|
|
if {[file isdirectory $victim]} {
|
|
cleanupRecurse {*}[glob -nocomplain -directory $victim td* tf* Test*]
|
|
}
|
|
file delete -force $victim
|
|
}
|
|
}
|
|
proc cleanup {args} {
|
|
foreach p [list [pwd] {*}$args] {
|
|
cleanupRecurse {*}[glob -nocomplain -directory $p tf* td*]
|
|
}
|
|
}
|
|
|
|
# find a CD-ROM so we can test read-only filesystems.
|
|
|
|
proc findfile {dir} {
|
|
foreach p [glob -nocomplain -type f -directory $dir *] {
|
|
return $p
|
|
}
|
|
foreach p [glob -nocomplain -type d -directory $dir *] {
|
|
set f [findfile $p]
|
|
if {$f ne ""} {
|
|
return $f
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
if {[testConstraint testvolumetype]} {
|
|
foreach p {d e f g h i j k l m n o p q r s t u v w x y z} {
|
|
if {![catch {testvolumetype ${p}:} result] && $result in {CDFS UDF}} {
|
|
set cdrom ${p}:
|
|
set cdfile [findfile $cdrom]
|
|
testConstraint cdrom 1
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
# NB: filename is chosen to be short but unlikely to clash with other apps
|
|
if {[file exists c:/] && [file exists d:/]} {
|
|
catch {file delete d:/TclTmpF.1}
|
|
catch {file delete d:/TclTmpD.1}
|
|
catch {file delete c:/TclTmpC.1}
|
|
if {![catch {createfile d:/TclTmpF.1 {}}] && [file isfile d:/TclTmpF.1]
|
|
&& ![catch {file mkdir d:/TclTmpD.1}] && [file isdirectory d:/TclTmpD.1]
|
|
&& ![catch {file mkdir c:/TclTmpC.1}] && [file isdirectory c:/TclTmpC.1]
|
|
} {
|
|
file delete d:/TclTmpF.1 d:/TclTmpD.1 c:/TclTmpC.1
|
|
testConstraint exdev 1
|
|
}
|
|
}
|
|
|
|
file delete -force -- td1
|
|
if {![catch {open td1 w} testfile]} {
|
|
close $testfile
|
|
testConstraint longFileNames 1
|
|
file delete -force -- td1
|
|
}
|
|
|
|
# A really long file name
|
|
# length of longname is 1216 chars, which should be greater than any static
|
|
# buffer or allowable filename.
|
|
|
|
set longname "abcdefghihjllmnopqrstuvwxyz01234567890"
|
|
append longname $longname
|
|
append longname $longname
|
|
append longname $longname
|
|
append longname $longname
|
|
append longname $longname
|
|
|
|
# Uses the "testfile" command instead of the "file" command. The "file"
|
|
# command provides several layers of sanity checks on the arguments and
|
|
# it can be difficult to actually forward "insane" arguments to the
|
|
# low-level Posix emulation layer.
|
|
|
|
test winFCmd-1.1 {TclpRenameFile: errno: EACCES} -body {
|
|
testfile mv $cdfile $cdrom/dummy~~.fil
|
|
} -constraints {win cdrom testfile} -returnCodes error -result EACCES
|
|
test winFCmd-1.2 {TclpRenameFile: errno: EEXIST} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
file mkdir td1/td2/td3
|
|
file mkdir td2
|
|
testfile mv td2 td1/td2
|
|
} -returnCodes error -result EEXIST
|
|
test winFCmd-1.3 {TclpRenameFile: errno: EINVAL} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
testfile mv / td1
|
|
} -returnCodes error -result EINVAL
|
|
test winFCmd-1.4 {TclpRenameFile: errno: EINVAL} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
file mkdir td1
|
|
testfile mv td1 td1/td2
|
|
} -returnCodes error -result EINVAL
|
|
test winFCmd-1.5 {TclpRenameFile: errno: EISDIR} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
file mkdir td1
|
|
createfile tf1
|
|
testfile mv tf1 td1
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-1.6 {TclpRenameFile: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile mv tf1 tf2
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-1.7 {TclpRenameFile: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile mv "" tf2
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-1.8 {TclpRenameFile: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
testfile mv tf1 ""
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-1.9 {TclpRenameFile: errno: ENOTDIR} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile tf1
|
|
testfile mv td1 tf1
|
|
} -returnCodes error -result ENOTDIR
|
|
test winFCmd-1.10 {TclpRenameFile: errno: EXDEV} -setup {
|
|
file delete -force d:/TclTmpD.1
|
|
} -constraints {win exdev testfile} -body {
|
|
file mkdir c:/TclTmpC.1
|
|
testfile mv c:/TclTmpC.1 d:/TclTmpD.1
|
|
} -cleanup {
|
|
file delete -force c:/TclTmpC.1
|
|
} -returnCodes error -result EXDEV
|
|
test winFCmd-1.11 {TclpRenameFile: errno: EACCES} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
set fd [open tf1 w]
|
|
testfile mv tf1 tf2
|
|
} -cleanup {
|
|
catch {close $fd}
|
|
} -returnCodes error -result EACCES
|
|
test winFCmd-1.12 {TclpRenameFile: errno: EACCES} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
set fd [open tf2 w]
|
|
testfile mv tf1 tf2
|
|
} -cleanup {
|
|
catch {close $fd}
|
|
} -returnCodes error -result EACCES
|
|
test winFCmd-1.15 {TclpRenameFile: errno: EEXIST} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
testfile mv tf1 nul
|
|
} -returnCodes error -result {^(ENODEV|EEXIST)$} -match regexp
|
|
test winFCmd-1.16 {TclpRenameFile: MoveFile() != FALSE} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1 tf1
|
|
testfile mv tf1 tf2
|
|
list [file exists tf1] [contents tf2]
|
|
} -result {0 tf1}
|
|
test winFCmd-1.17 {TclpRenameFile: MoveFile() == FALSE} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile mv tf1 tf2
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-1.18 {TclpRenameFile: srcAttr == -1} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile mv tf1 tf2
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-1.20 {TclpRenameFile: src is dir} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file delete /tf1
|
|
testfile mv [pwd] /tf1
|
|
} -returnCodes error -result EACCES
|
|
test winFCmd-1.21 {TclpRenameFile: long src} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile mv $longname tf1
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-1.22 {TclpRenameFile: long dst} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
testfile mv tf1 $longname
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-1.23 {TclpRenameFile: move dir into self} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
file mkdir td1
|
|
testfile mv [pwd]/td1 td1/td2
|
|
} -returnCodes error -result EINVAL
|
|
test winFCmd-1.24 {TclpRenameFile: move a root dir} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
# Error code depends on Windows/WINE version
|
|
testfile mv / c:/
|
|
} -returnCodes error -result {^(EINVAL|ENOENT|EEXIST)$} -match regexp
|
|
test winFCmd-1.25 {TclpRenameFile: cross file systems} -setup {
|
|
cleanup
|
|
} -constraints {win cdrom testfile} -body {
|
|
file mkdir td1
|
|
testfile mv td1 $cdrom/td1
|
|
} -returnCodes error -result EXDEV
|
|
test winFCmd-1.26 {TclpRenameFile: readonly fs} -setup {
|
|
cleanup
|
|
} -constraints {win cdrom testfile} -body {
|
|
testfile mv $cdfile $cdrom/dummy~~.fil
|
|
} -returnCodes error -result EACCES
|
|
test winFCmd-1.27 {TclpRenameFile: open file} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
set fd [open tf1 w]
|
|
testfile mv tf1 tf2
|
|
} -cleanup {
|
|
catch {close $fd}
|
|
} -returnCodes error -result EACCES
|
|
test winFCmd-1.28 {TclpRenameFile: errno == EEXIST} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
createfile tf2
|
|
testfile mv tf1 tf2
|
|
list [file exists tf1] [file exists tf2]
|
|
} -result {0 1}
|
|
test winFCmd-1.29 {TclpRenameFile: src is dir} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile tf1
|
|
testfile mv td1 tf1
|
|
} -returnCodes error -result ENOTDIR
|
|
test winFCmd-1.30 {TclpRenameFile: dst is dir} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
file mkdir td1
|
|
file mkdir td2/td2
|
|
testfile mv td1 td2
|
|
} -returnCodes error -result EEXIST
|
|
test winFCmd-1.31 {TclpRenameFile: TclpRemoveDirectory fails} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
file mkdir td1
|
|
file mkdir td2/td2
|
|
testfile mv td1 td2
|
|
} -returnCodes error -result EEXIST
|
|
test winFCmd-1.32 {TclpRenameFile: TclpRemoveDirectory succeeds} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
file mkdir td1/td2
|
|
file mkdir td2
|
|
testfile mv td1 td2
|
|
list [file exists td1] [file exists td2] [file exists td2/td2]
|
|
} -result {0 1 1}
|
|
test winFCmd-1.33 {TclpRenameFile: After removing dst dir, MoveFile fails} \
|
|
-constraints {win exdev testfile testchmod} -body {
|
|
file mkdir d:/TclTmpD.1
|
|
testchmod 0 d:/TclTmpD.1
|
|
file mkdir c:/TclTmpC.1
|
|
catch {testfile mv c:/TclTmpC.1 d:/TclTmpD.1} msg
|
|
list $msg [file writable d:/TclTmpD.1]
|
|
} -cleanup {
|
|
catch {testchmod 0o666 d:/TclTmpD.1}
|
|
file delete d:/TclTmpD.1
|
|
file delete -force c:/TclTmpC.1
|
|
} -result {EXDEV 0}
|
|
test winFCmd-1.34 {TclpRenameFile: src is dir, dst is not} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile tf1
|
|
testfile mv td1 tf1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result ENOTDIR
|
|
test winFCmd-1.35 {TclpRenameFile: src is not dir, dst is} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
file mkdir td1
|
|
createfile tf1
|
|
testfile mv tf1 td1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-1.36 {TclpRenameFile: src and dst not dir} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1 tf1
|
|
createfile tf2 tf2
|
|
testfile mv tf1 tf2
|
|
contents tf2
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {tf1}
|
|
test winFCmd-1.37 {TclpRenameFile: need to restore temp file} {win emptyTest} {
|
|
# Can't figure out how to cause this.
|
|
# Need a file that can't be copied.
|
|
} {}
|
|
|
|
# If the native filesystem produces 0 for inodes numbers there is no point
|
|
# doing the following test.
|
|
testConstraint winNonZeroInodes [eval {
|
|
file stat [info nameofexecutable] statExe
|
|
expr {$statExe(ino) != 0}
|
|
}]
|
|
|
|
proc MakeFiles {dirname} {
|
|
set inodes {}
|
|
set ndx -1
|
|
while {1} {
|
|
# upped to 50K for 64bit Server 2008
|
|
if {$ndx > 50000} {
|
|
tcltest::Skip "limit-reached:no-collistion"
|
|
}
|
|
set filename [file join $dirname Test[incr ndx]]
|
|
set f [open $filename w]
|
|
close $f
|
|
file stat $filename stat
|
|
if {[set n [lsearch -exact -integer $inodes $stat(ino)]] >= 0} {
|
|
return [list [file join $dirname Test$n] $filename]
|
|
}
|
|
lappend inodes $stat(ino)
|
|
unset stat
|
|
}
|
|
}
|
|
|
|
test winFCmd-1.38 {TclpRenameFile: check rename of conflicting inodes} -setup {
|
|
cleanup
|
|
} -constraints {win winNonZeroInodes knownMsvcBug notInCIenv extensive} -body {
|
|
file mkdir td1
|
|
lassign [MakeFiles td1] a b
|
|
file rename -force $a $b
|
|
file exists $a
|
|
} -cleanup {
|
|
cleanup
|
|
} -result 0
|
|
|
|
|
|
test winFCmd-2.1 {TclpCopyFile: errno: EACCES} -setup {
|
|
cleanup
|
|
} -constraints {win cdrom testfile} -body {
|
|
testfile cp $cdfile $cdrom/dummy~~.fil
|
|
} -returnCodes error -result EACCES
|
|
test winFCmd-2.2 {TclpCopyFile: errno: EISDIR} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile cp td1 tf1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-2.3 {TclpCopyFile: errno: EISDIR} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
file mkdir td1
|
|
testfile cp tf1 td1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-2.4 {TclpCopyFile: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile cp tf1 tf2
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-2.5 {TclpCopyFile: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile cp "" tf2
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-2.6 {TclpCopyFile: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
testfile cp tf1 ""
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-2.10 {TclpCopyFile: CopyFile succeeds} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1 tf1
|
|
testfile cp tf1 tf2
|
|
list [contents tf1] [contents tf2]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {tf1 tf1}
|
|
test winFCmd-2.11 {TclpCopyFile: CopyFile succeeds} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1 tf1
|
|
createfile tf2 tf2
|
|
testfile cp tf1 tf2
|
|
list [contents tf1] [contents tf2]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {tf1 tf1}
|
|
test winFCmd-2.12 {TclpCopyFile: CopyFile succeeds} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod} -body {
|
|
createfile tf1 tf1
|
|
file attribute tf1 -readonly 1
|
|
testfile cp tf1 tf2
|
|
list [contents tf2] [file writable tf2]
|
|
} -cleanup {
|
|
testchmod 0o660 tf1
|
|
cleanup
|
|
} -result {tf1 0}
|
|
test winFCmd-2.13 {TclpCopyFile: CopyFile fails} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
file mkdir td1
|
|
testfile cp tf1 td1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-2.14 {TclpCopyFile: errno == EACCES} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile cp td1 tf1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-2.15 {TclpCopyFile: src is directory} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile cp td1 tf1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-2.16 {TclpCopyFile: dst is directory} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
file mkdir td1
|
|
testfile cp tf1 td1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-2.17 {TclpCopyFile: dst is readonly} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod} -body {
|
|
createfile tf1 tf1
|
|
createfile tf2 tf2
|
|
file attribute tf2 -readonly 1
|
|
testfile cp tf1 tf2
|
|
list [file writable tf2] [contents tf2]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {1 tf1}
|
|
|
|
test winFCmd-3.1 {TclpDeleteFile: errno: EACCES} -body {
|
|
testfile rm $cdfile $cdrom/dummy~~.fil
|
|
} -constraints {win cdrom testfile} -returnCodes error -result EACCES
|
|
test winFCmd-3.2 {TclpDeleteFile: errno: EISDIR} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile rm td1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-3.3 {TclpDeleteFile: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile rm tf1
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-3.4 {TclpDeleteFile: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile rm ""
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-3.5 {TclpDeleteFile: errno: EACCES} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
set fd [open tf1 w]
|
|
testfile rm tf1
|
|
} -cleanup {
|
|
close $fd
|
|
cleanup
|
|
} -returnCodes error -result EACCES
|
|
test winFCmd-3.6 {TclpDeleteFile: errno: EACCES} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile rm nul
|
|
} -returnCodes error -result EACCES
|
|
test winFCmd-3.7 {TclpDeleteFile: DeleteFile succeeds} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
testfile rm tf1
|
|
file exists tf1
|
|
} -result {0}
|
|
test winFCmd-3.8 {TclpDeleteFile: DeleteFile fails} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile rm td1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EISDIR
|
|
test winFCmd-3.9 {TclpDeleteFile: errno == EACCES} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
set fd [open tf1 w]
|
|
testfile rm tf1
|
|
} -cleanup {
|
|
close $fd
|
|
} -returnCodes error -result EACCES
|
|
test winFCmd-3.10 {TclpDeleteFile: path is readonly} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod} -body {
|
|
createfile tf1
|
|
testchmod 0 tf1
|
|
testfile rm tf1
|
|
file exists tf1
|
|
} -result {0}
|
|
test winFCmd-3.11 {TclpDeleteFile: still can't remove path} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod} -body {
|
|
set fd [open tf1 w]
|
|
testchmod 0 tf1
|
|
testfile rm tf1
|
|
} -cleanup {
|
|
close $fd
|
|
cleanup
|
|
} -returnCodes error -result EACCES
|
|
|
|
test winFCmd-4.1 {TclpCreateDirectory: errno: EACCES} -body {
|
|
testfile mkdir $cdrom/dummy~~.dir
|
|
} -constraints {win cdrom testfile} -returnCodes error -result EACCES
|
|
test winFCmd-4.3 {TclpCreateDirectory: errno: EEXIST} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile mkdir td1
|
|
} -cleanup {
|
|
cleanup
|
|
} -returnCodes error -result EEXIST
|
|
test winFCmd-4.4 {TclpCreateDirectory: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile mkdir td1/td2
|
|
} -returnCodes error -result ENOENT
|
|
test winFCmd-4.5 {TclpCreateDirectory: CreateDirectory succeeds} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile mkdir td1
|
|
file type td1
|
|
} -cleanup cleanup -result directory
|
|
|
|
test winFCmd-5.1 {TclpCopyDirectory: calls TraverseWinTree} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile cpdir td1 td2
|
|
list [file type td1] [file type td2]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {directory directory}
|
|
|
|
test winFCmd-6.1 {TclpRemoveDirectory: errno: EACCES} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod notInCIenv} -body {
|
|
# Parent's FILE_DELETE_CHILD setting permits deletion of subdir
|
|
# even when subdir DELETE mask is clear. So we need an intermediate
|
|
# parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
|
|
file mkdir td0/td1
|
|
testchmod 0o777 td0
|
|
testchmod 0 td0/td1
|
|
testfile rmdir td0/td1
|
|
file exists td0/td1
|
|
} -returnCodes error -cleanup {
|
|
cleanup
|
|
} -result {td0/td1 EACCES}
|
|
# This next test has a very hokey way of matching...
|
|
test winFCmd-6.2 {TclpRemoveDirectory: errno: EEXIST} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1/td2
|
|
list [catch {testfile rmdir td1} msg] [file tail $msg]
|
|
} -result {1 {td1 EEXIST}}
|
|
test winFCmd-6.3 {TclpRemoveDirectory: errno: EACCES} {win emptyTest trashSystem} {
|
|
# can't test this w/o removing everything on your hard disk first!
|
|
# testfile rmdir /
|
|
} {}
|
|
# This next test has a very hokey way of matching...
|
|
test winFCmd-6.4 {TclpRemoveDirectory: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
list [catch {testfile rmdir td1} msg] [file tail $msg]
|
|
} -result {1 {td1 ENOENT}}
|
|
test winFCmd-6.5 {TclpRemoveDirectory: errno: ENOENT} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile rmdir ""
|
|
} -returnCodes error -result ENOENT
|
|
# This next test has a very hokey way of matching...
|
|
test winFCmd-6.6 {TclpRemoveDirectory: errno: ENOTDIR} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
list [catch {testfile rmdir tf1} msg] [file tail $msg]
|
|
} -result {1 {tf1 ENOTDIR}}
|
|
test winFCmd-6.7 {TclpRemoveDirectory: RemoveDirectory succeeds} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile rmdir td1
|
|
file exists td1
|
|
} -result {0}
|
|
# This next test has a very hokey way of matching...
|
|
test winFCmd-6.8 {TclpRemoveDirectory: RemoveDirectory fails} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
list [catch {testfile rmdir tf1} msg] [file tail $msg]
|
|
} -result {1 {tf1 ENOTDIR}}
|
|
# winFCmd-6.9 removed - was exact dup of winFCmd-6.1
|
|
test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} -setup {
|
|
cleanup
|
|
} -constraints {win testfile notInCIenv} -body {
|
|
testfile rmdir /
|
|
# WinXP returns EEXIST, WinNT seems to return EACCES, WINE returns
|
|
# ENODEV. No policy decision has been made as to which is correct.
|
|
} -returnCodes error -match regexp -result {^/ E(ACCES|EXIST|NODEV)$}
|
|
test winFCmd-6.13 {TclpRemoveDirectory: write-protected} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod notInCIenv} -body {
|
|
# Parent's FILE_DELETE_CHILD setting permits deletion of subdir
|
|
# even when subdir DELETE mask is clear. So we need an intermediate
|
|
# parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
|
|
file mkdir td0/td1
|
|
testchmod 0o770 td0
|
|
testchmod 0o444 td0/td1
|
|
testfile rmdir td0/td1
|
|
file exists td0/td1
|
|
} -cleanup {
|
|
testchmod 0o770 td0/td1
|
|
cleanup
|
|
} -returnCodes error -result {td0/td1 EACCES}
|
|
# This next test has a very hokey way of matching...
|
|
test winFCmd-6.15 {TclpRemoveDirectory: !recursive} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1/td2
|
|
list [catch {testfile rmdir td1} msg] [file tail $msg]
|
|
} -result {1 {td1 EEXIST}}
|
|
test winFCmd-6.16 {TclpRemoveDirectory: recursive, but errno != EEXIST} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
createfile tf1
|
|
testfile rmdir -force tf1
|
|
} -returnCodes error -result {tf1 ENOTDIR}
|
|
test winFCmd-6.17 {TclpRemoveDirectory: calls TraverseWinTree} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1/td2
|
|
testfile rmdir -force td1
|
|
file exists td1
|
|
} -result {0}
|
|
|
|
test winFCmd-7.1 {TraverseWinTree: targetPtr == NULL} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1/td2/td3
|
|
testfile rmdir -force td1
|
|
file exists td1
|
|
} -result {0}
|
|
test winFCmd-7.2 {TraverseWinTree: targetPtr != NULL} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1/td2/td3
|
|
testfile cpdir td1 td2
|
|
list [file exists td1] [file exists td2]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {1 1}
|
|
test winFCmd-7.3 {TraverseWinTree: sourceAttr == -1} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile cpdir td1 td2
|
|
} -returnCodes error -result {td1 ENOENT}
|
|
test winFCmd-7.4 {TraverseWinTree: source isn't directory} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1 tf1
|
|
testfile cpdir td1 td2
|
|
contents td2/tf1
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {tf1}
|
|
test winFCmd-7.5 {TraverseWinTree: call TraversalCopy: DOTREE_F} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1 tf1
|
|
testfile cpdir td1 td2
|
|
contents td2/tf1
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {tf1}
|
|
test winFCmd-7.6 {TraverseWinTree: call TraversalDelete: DOTREE_F} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1 tf1
|
|
testfile rmdir -force td1
|
|
file exists td1
|
|
} -result {0}
|
|
test winFCmd-7.7 {TraverseWinTree: append \ to source if necessary} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1 tf1
|
|
testfile cpdir td1 td2
|
|
contents td2/tf1
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {tf1}
|
|
test winFCmd-7.9 {TraverseWinTree: append \ to source if necessary} -body {
|
|
testfile rmdir $cdrom/
|
|
} -constraints {win cdrom testfile} -returnCodes error -match glob \
|
|
-result {* EACCES}
|
|
test winFCmd-7.10 {TraverseWinTree: can't read directory: handle == INVALID} \
|
|
{win emptyTest} {
|
|
# can't make it happen
|
|
} {}
|
|
test winFCmd-7.11 {TraverseWinTree: call TraversalCopy: DOTREE_PRED} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1 tf1
|
|
testchmod 0o770 td1/tf1; # Else tf2 will have no ACL after td1 testchmod
|
|
testchmod 0o400 td1
|
|
testfile cpdir td1 td2
|
|
list [file exists td2] [file writable td2]
|
|
} -cleanup {
|
|
testchmod 0o660 td1
|
|
cleanup
|
|
} -result {1 1}
|
|
test winFCmd-7.12 {TraverseWinTree: call TraversalDelete: DOTREE_PRED} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1 tf1
|
|
testfile rmdir -force td1
|
|
file exists td1
|
|
} -result {0}
|
|
test winFCmd-7.13 {TraverseWinTree: append \ to target if necessary} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1 tf1
|
|
testfile cpdir td1 td2
|
|
contents td2/tf1
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {tf1}
|
|
test winFCmd-7.15 {TraverseWinTree: append \ to target if necessary} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile cpdir td1 /
|
|
} -cleanup {
|
|
cleanup
|
|
# Windows7 returns EEXIST, XP returns EACCES
|
|
} -returnCodes error -match regexp -result {^/ E(ACCES|EXIST)$}
|
|
test winFCmd-7.16 {TraverseWinTree: recurse on files: no files} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile cpdir td1 td2
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {}
|
|
test winFCmd-7.17 {TraverseWinTree: recurse on files: one file} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/td2
|
|
testfile cpdir td1 td2
|
|
glob td2/*
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {td2/td2}
|
|
test winFCmd-7.18 {TraverseWinTree: recurse on files: several files and dir} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1
|
|
createfile td1/tf2
|
|
file mkdir td1/td2/td3
|
|
createfile td1/tf3
|
|
createfile td1/tf4
|
|
testfile cpdir td1 td2
|
|
lsort [glob td2/*]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {td2/td2 td2/tf1 td2/tf2 td2/tf3 td2/tf4}
|
|
test winFCmd-7.19 {TraverseWinTree: call TraversalCopy: DOTREE_POSTD} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1 tf1
|
|
testchmod 0o770 td1/tf1; # Else tf2 will have no ACL after td1 testchmod
|
|
testchmod 0o400 td1
|
|
testfile cpdir td1 td2
|
|
list [file exists td2] [file writable td2]
|
|
} -cleanup {
|
|
testchmod 0o660 td1
|
|
cleanup
|
|
} -result {1 1}
|
|
test winFCmd-7.20 {TraverseWinTree: call TraversalDelete: DOTREE_POSTD} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1 tf1
|
|
testfile rmdir -force td1
|
|
file exists td1
|
|
} -result {0}
|
|
test winFCmd-7.21 {TraverseWinTree: fill errorPtr} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
testfile cpdir td1 td2
|
|
} -returnCodes error -result {td1 ENOENT}
|
|
|
|
test winFCmd-8.1 {TraversalCopy: DOTREE_F} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile cpdir td1 td1
|
|
} -returnCodes error -result {td1 EEXIST}
|
|
test winFCmd-8.2 {TraversalCopy: DOTREE_PRED} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod} -body {
|
|
file mkdir td1/td2
|
|
testchmod 0o770 td1/td2; # Else td2 will have no ACL after td1 testchmod
|
|
testchmod 0o400 td1
|
|
testfile cpdir td1 td2
|
|
list [file writable td1] [file writable td1/td2]
|
|
} -cleanup {
|
|
testchmod 0o660 td1
|
|
cleanup
|
|
} -result {0 1}
|
|
test winFCmd-8.3 {TraversalCopy: DOTREE_POSTD} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
testfile cpdir td1 td2
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {}
|
|
|
|
test winFCmd-9.1 {TraversalDelete: DOTREE_F} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1
|
|
createfile td1/tf1
|
|
testfile rmdir -force td1
|
|
} -result {}
|
|
test winFCmd-9.3 {TraversalDelete: DOTREE_PRED} -setup {
|
|
cleanup
|
|
} -constraints {win testfile testchmod notInCIenv} -body {
|
|
# Parent's FILE_DELETE_CHILD setting permits deletion of subdir
|
|
# even when subdir DELETE mask is clear. So we need an intermediate
|
|
# parent td0 with FILE_DELETE_CHILD turned off while allowing R/W.
|
|
file mkdir td0/td1/td2
|
|
testchmod 0o770 td0
|
|
testchmod 0o400 td0/td1
|
|
testfile rmdir -force td0/td1
|
|
file exists td1
|
|
} -cleanup {
|
|
testchmod 0o770 td0/td1
|
|
cleanup
|
|
} -returnCodes error -result {td0/td1 EACCES}
|
|
test winFCmd-9.4 {TraversalDelete: DOTREE_POSTD} -setup {
|
|
cleanup
|
|
} -constraints {win testfile} -body {
|
|
file mkdir td1/td1/td3/td4/td5
|
|
testfile rmdir -force td1
|
|
} -result {}
|
|
|
|
test winFCmd-10.1 {AttributesPosixError - get} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
file attributes td1 -archive
|
|
} -returnCodes error -result {could not read "td1": no such file or directory}
|
|
test winFCmd-10.2 {AttributesPosixError - set} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
file attributes td1 -archive 0
|
|
} -returnCodes error -result {could not read "td1": no such file or directory}
|
|
|
|
test winFCmd-11.1 {GetWinFileAttributes} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
file attributes td1 -archive
|
|
} -cleanup {
|
|
cleanup
|
|
} -result 1
|
|
test winFCmd-11.2 {GetWinFileAttributes} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
file attributes td1 -readonly
|
|
} -cleanup {
|
|
cleanup
|
|
} -result 0
|
|
test winFCmd-11.3 {GetWinFileAttributes} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
file attributes td1 -hidden
|
|
} -cleanup {
|
|
cleanup
|
|
} -result 0
|
|
test winFCmd-11.4 {GetWinFileAttributes} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
file attributes td1 -system
|
|
} -cleanup {
|
|
cleanup
|
|
} -result 0
|
|
test winFCmd-11.5 {GetWinFileAttributes} -constraints {win} -setup {
|
|
set old [pwd]
|
|
} -body {
|
|
# Attr of relative paths that resolve to root was failing don't care about
|
|
# answer, just that test runs.
|
|
cd c:/
|
|
file attr c:
|
|
file attr c:.
|
|
file attr .
|
|
} -cleanup {
|
|
cd $old
|
|
} -match glob -result *
|
|
test winFCmd-11.6 {GetWinFileAttributes} -constraints {win} -body {
|
|
file attr c:/ -hidden
|
|
} -result {0}
|
|
|
|
test winFCmd-12.1 {ConvertFileNameFormat} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
string tolower [file attributes td1 -longname]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {td1}
|
|
test winFCmd-12.2 {ConvertFileNameFormat} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
file mkdir td1
|
|
createfile td1/td1 {}
|
|
string tolower [file attributes td1/td1 -longname]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {td1/td1}
|
|
test winFCmd-12.3 {ConvertFileNameFormat} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
file mkdir td1
|
|
file mkdir td1/td2
|
|
createfile td1/td3 {}
|
|
string tolower [file attributes td1/td2/../td3 -longname]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {td1/td2/../td3}
|
|
test winFCmd-12.4 {ConvertFileNameFormat} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
string tolower [file attributes ./td1 -longname]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {./td1}
|
|
test winFCmd-12.5 {ConvertFileNameFormat: absolute path} -body {
|
|
list [file attributes / -longname] [file attributes \\ -longname]
|
|
} -constraints {win} -result {/ /}
|
|
test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive (in temp folder)} -setup {
|
|
catch {file delete -force -- $::env(TEMP)/td1}
|
|
} -constraints {win} -body {
|
|
createfile $::env(TEMP)/td1 {}
|
|
string equal [string tolower [file attributes $::env(TEMP)/td1 -longname]] \
|
|
[string tolower [file normalize $::env(TEMP)]/td1]
|
|
} -cleanup {
|
|
file delete -force -- $::env(TEMP)/td1
|
|
} -result 1
|
|
test winFCmd-12.7 {ConvertFileNameFormat} -body {
|
|
string tolower [file attributes //bisque/tcl/ws -longname]
|
|
} -constraints {nonPortable win} -result {//bisque/tcl/ws}
|
|
test winFCmd-12.8 {ConvertFileNameFormat} -setup {
|
|
cleanup
|
|
} -constraints {win longFileNames} -body {
|
|
createfile td1 {}
|
|
string tolower [file attributes td1 -longname]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {td1}
|
|
test winFCmd-12.10 {ConvertFileNameFormat} -setup {
|
|
cleanup
|
|
} -constraints {longFileNames win} -body {
|
|
createfile td1td1td1 {}
|
|
file attributes td1td1td1 -shortname
|
|
} -cleanup {
|
|
cleanup
|
|
} -match glob -result *
|
|
test winFCmd-12.11 {ConvertFileNameFormat} -setup {
|
|
cleanup
|
|
} -constraints {longFileNames win} -body {
|
|
createfile td1 {}
|
|
string tolower [file attributes td1 -shortname]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {td1}
|
|
|
|
test winFCmd-13.1 {GetWinFileLongName} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
string tolower [file attributes td1 -longname]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result td1
|
|
|
|
test winFCmd-14.1 {GetWinFileShortName} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
string tolower [file attributes td1 -shortname]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result td1
|
|
|
|
test winFCmd-15.1 {SetWinFileAttributes} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
file attributes td1 -archive 0
|
|
} -returnCodes error -result {could not read "td1": no such file or directory}
|
|
test winFCmd-15.2 {SetWinFileAttributes - archive} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
list [file attributes td1 -archive 1] [file attributes td1 -archive]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {{} 1}
|
|
test winFCmd-15.3 {SetWinFileAttributes - archive} -constraints {win notInCIenv} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
list [file attributes td1 -archive 0] [file attributes td1 -archive]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {{} 0}
|
|
test winFCmd-15.4 {SetWinFileAttributes - hidden} -constraints {win notInCIenv} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
list [file attributes td1 -hidden 1] [file attributes td1 -hidden] \
|
|
[file attributes td1 -hidden 0]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {{} 1 {}}
|
|
test winFCmd-15.5 {SetWinFileAttributes - hidden} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
list [file attributes td1 -hidden 0] [file attributes td1 -hidden]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {{} 0}
|
|
test winFCmd-15.6 {SetWinFileAttributes - readonly} -setup {
|
|
cleanup
|
|
} -constraints {win} -body {
|
|
createfile td1 {}
|
|
list [file attributes td1 -readonly 1] [file attributes td1 -readonly]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {{} 1}
|
|
test winFCmd-15.7 {SetWinFileAttributes - readonly} -setup {
|
|
cleanup
|
|
} -constraints {win} -body {
|
|
createfile td1 {}
|
|
list [file attributes td1 -readonly 0] [file attributes td1 -readonly]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {{} 0}
|
|
test winFCmd-15.8 {SetWinFileAttributes - system} -constraints {win notInCIenv} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
list [file attributes td1 -system 1] [file attributes td1 -system]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {{} 1}
|
|
test winFCmd-15.9 {SetWinFileAttributes - system} -constraints {win} -setup {
|
|
cleanup
|
|
} -body {
|
|
createfile td1 {}
|
|
list [file attributes td1 -system 0] [file attributes td1 -system]
|
|
} -cleanup {
|
|
cleanup
|
|
} -result {{} 0}
|
|
test winFCmd-15.10 {SetWinFileAttributes - failing} -setup {
|
|
cleanup
|
|
} -constraints {win cdrom} -body {
|
|
file attributes $cdfile -archive 1
|
|
} -returnCodes error -match glob -result *
|
|
|
|
test winFCmd-16.1 {Windows file normalization} -constraints {win} -body {
|
|
list [file normalize c:/] [file normalize C:/]
|
|
} -result {C:/ C:/}
|
|
test winFCmd-16.2 {Windows file normalization} -constraints {win} -body {
|
|
createfile td1... {}
|
|
file tail [file normalize td1]
|
|
} -cleanup {
|
|
file delete td1...
|
|
} -result {td1}
|
|
set pwd [pwd]
|
|
set d [string index $pwd 0]
|
|
test winFCmd-16.3 {Windows file normalization} -constraints {win} -body {
|
|
file norm ${d}:foo
|
|
} -result [file join $pwd foo]
|
|
test winFCmd-16.4 {Windows file normalization} -constraints {win} -body {
|
|
file norm [string tolower ${d}]:foo
|
|
} -result [file join $pwd foo]
|
|
test winFCmd-16.5 {Windows file normalization} -constraints {win} -body {
|
|
file norm ${d}:foo/bar
|
|
} -result [file join $pwd foo/bar]
|
|
test winFCmd-16.6 {Windows file normalization} -constraints {win} -body {
|
|
file norm ${d}:foo\\bar
|
|
} -result [file join $pwd foo/bar]
|
|
test winFCmd-16.7 {Windows file normalization} -constraints {win} -body {
|
|
file norm /bar
|
|
} -result "${d}:/bar"
|
|
test winFCmd-16.8 {Windows file normalization} -constraints {win} -body {
|
|
file norm ///bar
|
|
} -result "${d}:/bar"
|
|
test winFCmd-16.9 {Windows file normalization} -constraints {win} -body {
|
|
file norm /bar/foo
|
|
} -result "${d}:/bar/foo"
|
|
if {$d eq "C"} { set dd "D" } else { set dd "C" }
|
|
test winFCmd-16.10 {Windows file normalization} -constraints {
|
|
win notInCIenv
|
|
} -setup {
|
|
cd ${dd}:
|
|
} -cleanup {
|
|
cd $pwd
|
|
} -body {
|
|
file norm ${d}:foo
|
|
} -result [file join $pwd foo]
|
|
test winFCmd-16.11 {Windows file normalization} -body {
|
|
cd ${d}:
|
|
cd $cdrom
|
|
cd ${d}:
|
|
cd $cdrom
|
|
# Must not crash
|
|
set result "no crash"
|
|
} -constraints {win cdrom} -cleanup {
|
|
cd $pwd
|
|
} -result {no crash}
|
|
test winFCmd-16.12 {Windows file normalization - no crash} \
|
|
-constraints win -setup {
|
|
set oldhome ""
|
|
catch {set oldhome $::env(HOME)}
|
|
} -body {
|
|
set expectedResult [file normalize ${d}:]
|
|
set ::env(HOME) ${d}:
|
|
cd
|
|
# At one point this led to an infinite recursion in Tcl
|
|
set result [pwd]; # <- Must not crash
|
|
set result "no crash"
|
|
} -cleanup {
|
|
set ::env(HOME) $oldhome
|
|
cd $pwd
|
|
} -result {no crash}
|
|
test winFCmd-16.13 {Windows file normalization - absolute HOME} -setup {
|
|
set oldhome ""
|
|
catch {set oldhome $::env(HOME)}
|
|
} -constraints win -body {
|
|
# Test 'cd' normalization when HOME is absolute
|
|
set ::env(HOME) ${d}:/
|
|
cd
|
|
pwd
|
|
} -cleanup {
|
|
set ::env(HOME) $oldhome
|
|
cd $pwd
|
|
} -result [file normalize ${d}:/]
|
|
test winFCmd-16.14 {Windows file normalization - relative HOME} -setup {
|
|
set oldhome ""
|
|
catch {set oldhome $::env(HOME)}
|
|
} -constraints win -body {
|
|
# Test 'cd' normalization when HOME is relative
|
|
set ::env(HOME) ${d}:
|
|
cd
|
|
pwd
|
|
} -cleanup {
|
|
set ::env(HOME) $oldhome
|
|
cd $pwd
|
|
} -result $pwd
|
|
test winFCmd-16.15 {Windows file normalization - invalid drive} -setup {
|
|
set volumes [file volumes]
|
|
foreach baddrive [split ABCDEFGHIJKLMNOPQRSTUVWXYZ ""] {
|
|
if {"$baddrive:/" ni $volumes} break
|
|
}
|
|
} -cleanup {
|
|
unset volumes
|
|
} -constraints win -body {
|
|
string equal [file norm ${baddrive}:foo] ${baddrive}:/foo
|
|
} -result 1
|
|
|
|
test winFCmd-17.1 {Windows bad permissions cd} -constraints win -body {
|
|
set d {}
|
|
foreach dd {c:/ d:/ e:/} {
|
|
eval lappend d [glob -nocomplain \
|
|
-types hidden -dir $dd "System Volume Information"]
|
|
}
|
|
# Old versions of Tcl gave a misleading error that the
|
|
# directory in question didn't exist.
|
|
if {[llength $d] && [catch {cd [lindex $d 0]} err]} {
|
|
regsub ".*: " $err "" err
|
|
set err
|
|
} else {
|
|
set err "permission denied"
|
|
}
|
|
} -cleanup {
|
|
cd $pwd
|
|
} -result "permission denied"
|
|
|
|
cd $pwd
|
|
unset d dd pwd
|
|
|
|
test winFCmd-18.1 {Windows reserved path names} -constraints win -body {
|
|
file pathtype com1
|
|
} -result "absolute"
|
|
test winFCmd-18.1.2 {Windows reserved path names} -constraints win -body {
|
|
file pathtype com4
|
|
} -result "absolute"
|
|
test winFCmd-18.1.3 {Windows reserved path names} -constraints win -body {
|
|
file pathtype com9
|
|
} -result "absolute"
|
|
test winFCmd-18.1.4 {Windows reserved path names} -constraints win -body {
|
|
file pathtype lpt3
|
|
} -result "absolute"
|
|
test winFCmd-18.1.5 {Windows reserved path names} -constraints win -body {
|
|
file pathtype lpt9
|
|
} -result "absolute"
|
|
test winFCmd-18.1.6 {Windows reserved path names} -constraints win -body {
|
|
file pathtype nul
|
|
} -result "absolute"
|
|
test winFCmd-18.1.7 {Windows reserved path names} -constraints win -body {
|
|
file pathtype null
|
|
} -result "relative"
|
|
test winFCmd-18.2 {Windows reserved path names} -constraints win -body {
|
|
file pathtype com1:
|
|
} -result "absolute"
|
|
test winFCmd-18.3 {Windows reserved path names} -constraints win -body {
|
|
file pathtype COM1
|
|
} -result "absolute"
|
|
test winFCmd-18.4 {Windows reserved path names} -constraints win -body {
|
|
file pathtype CoM1:
|
|
} -result "absolute"
|
|
test winFCmd-18.5 {Windows reserved path names} -constraints win -body {
|
|
file normalize com1:
|
|
} -result COM1
|
|
test winFCmd-18.6 {Windows reserved path names} -constraints win -body {
|
|
file normalize COM1:
|
|
} -result COM1
|
|
test winFCmd-18.7 {Windows reserved path names} -constraints win -body {
|
|
file normalize cOm1
|
|
} -result COM1
|
|
test winFCmd-18.8 {Windows reserved path names} -constraints win -body {
|
|
file normalize cOm1:
|
|
} -result COM1
|
|
|
|
test winFCmd-19.1 {Windows extended path names} -constraints win -body {
|
|
file normalize //?/c:/windows/win.ini
|
|
} -result //?/c:/windows/win.ini
|
|
test winFCmd-19.2 {Windows extended path names} -constraints win -body {
|
|
file normalize //?/c:/windows/../windows/win.ini
|
|
} -result //?/c:/windows/win.ini
|
|
test winFCmd-19.3 {Windows extended path names} -constraints win -setup {
|
|
set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
|
|
set tmpfile [file normalize $tmpfile]
|
|
} -body {
|
|
list [catch {
|
|
set f [open $tmpfile [list WRONLY CREAT]]
|
|
close $f
|
|
} res] $res
|
|
} -cleanup {
|
|
catch {file delete $tmpfile}
|
|
} -result [list 0 {}]
|
|
test winFCmd-19.4 {Windows extended path names} -constraints win -setup {
|
|
set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
|
|
set tmpfile //?/[file normalize $tmpfile]
|
|
} -body {
|
|
list [catch {
|
|
set f [open $tmpfile [list WRONLY CREAT]]
|
|
close $f
|
|
} res] $res
|
|
} -cleanup {
|
|
catch {file delete $tmpfile}
|
|
} -result [list 0 {}]
|
|
test winFCmd-19.5 {Windows extended path names} -constraints win -setup {
|
|
set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
|
|
set tmpfile [file normalize $tmpfile]
|
|
} -body {
|
|
list [catch {
|
|
set f [open $tmpfile [list WRONLY CREAT]]
|
|
close $f
|
|
} res] $res
|
|
} -cleanup {
|
|
catch {file delete $tmpfile}
|
|
} -result [list 0 {}]
|
|
test winFCmd-19.6 {Windows extended path names} -constraints win -setup {
|
|
set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
|
|
set tmpfile //?/[file normalize $tmpfile]
|
|
} -body {
|
|
list [catch {
|
|
set f [open $tmpfile [list WRONLY CREAT]]
|
|
close $f
|
|
} res] $res
|
|
} -cleanup {
|
|
catch {file delete $tmpfile}
|
|
} -result [list 0 {}]
|
|
test winFCmd-19.7 {Windows extended path names} -constraints win -setup {
|
|
set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
|
|
set tmpfile [file normalize $tmpfile]
|
|
} -body {
|
|
list [catch {
|
|
set f [open $tmpfile [list WRONLY CREAT]]
|
|
close $f
|
|
} res] $res [glob -directory $::env(TEMP) -tails tcl[pid].*]
|
|
} -cleanup {
|
|
catch {file delete $tmpfile}
|
|
} -result [list 0 {} [list tcl[pid].tmp]]
|
|
test winFCmd-19.8 {Windows extended path names} -constraints win -setup {
|
|
set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
|
|
set tmpfile //?/[file normalize $tmpfile]
|
|
} -body {
|
|
list [catch {
|
|
set f [open $tmpfile [list WRONLY CREAT]]
|
|
close $f
|
|
} res] $res [glob -directory $::env(TEMP) -tails tcl[pid].*]
|
|
} -cleanup {
|
|
catch {file delete $tmpfile}
|
|
} -result [list 0 {} [list "tcl[pid].tmp "]]
|
|
|
|
test winFCmd-19.9 {Windows devices path names} -constraints win -body {
|
|
file normalize //./com1
|
|
} -result //./com1
|
|
|
|
# To reliably exercise bug b0682c3c24, we need a second drive.
|
|
# Can't do this in -setup because have to initialize constraint
|
|
testConstraint haveTwoDrives 0
|
|
if {$::tcl_platform(platform) eq "windows"} {
|
|
set drive [string toupper [lindex [file split [pwd]] 0]]
|
|
foreach otherDrive [file volumes] {
|
|
if {$otherDrive ne $drive
|
|
&& [lindex [file system $otherDrive] 0] eq "native"} {
|
|
testConstraint haveTwoDrives 1
|
|
# Do not use file join here. We need a string literal
|
|
# for the bug, not one with an internal file system rep
|
|
set pathInOther [string cat \
|
|
${otherDrive} \
|
|
[lindex [glob -directory $otherDrive -tails *] 0]]
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
test winFCmd-20.1 {
|
|
Bug b0682c3c24 - relative paths in pattern
|
|
} -constraints haveTwoDrives -body {
|
|
glob $pathInOther/$pathInOther
|
|
} -result {}
|
|
|
|
test winFCmd-20.2 {
|
|
Bug b0682c3c24 - absolute paths in pattern (-directory)
|
|
} -constraints haveTwoDrives -body {
|
|
puts $pathInOther
|
|
glob -directory $pathInOther $pathInOther
|
|
} -result {}
|
|
|
|
|
|
unset -nocomplain drive otherDrive pathInOther
|
|
|
|
################################################################
|
|
# Tests for long path support. On systems that support long paths, verify
|
|
# various commands work. On systems that don't, verify commands return
|
|
# appropriate errors (in particular, do not crash!). Commands are tested with
|
|
# the usual "file" command as well as the testsuite "testfile" command which
|
|
# tests the C API without the sanity checks of the "file" command.
|
|
|
|
namespace eval testlongpaths {
|
|
# A long path should not have any individual component longer than MAX_PATH
|
|
# Use string operations with FORWARD slash to generate paths, not [file
|
|
# join] since [file join] itself is under test.
|
|
|
|
variable pathTail Y\u6587
|
|
variable longPathComponent [string repeat X\u4e2d 120]
|
|
variable longPathRoot "[tcltest::configure -tmpdir]/longpathtest"
|
|
variable longPathComponents [lrepeat 4 $longPathComponent]
|
|
variable longPathDir [join [list $longPathRoot \
|
|
{*}$longPathComponents] /]
|
|
variable longPathFile [string cat $longPathDir / $pathTail]
|
|
variable deepPathComponent [string repeat X\u4e2d 4]
|
|
variable deepPathComponents [lrepeat 128 $deepPathComponent]
|
|
variable deepPathDir [join [list $longPathRoot \
|
|
{*}$deepPathComponents] /]
|
|
variable deepPathFile [string cat $deepPathDir / $pathTail]
|
|
|
|
# Generator that only depends on parsing path syntax, not actual file system ops
|
|
proc testlongpathsyntax {id comment body args} {
|
|
uplevel [list test $id $comment -body $body -constraints win {*}$args]
|
|
}
|
|
|
|
# Generator that requires actual file system ops
|
|
proc testlongpath {id comment body args} {
|
|
uplevel [list test $id $comment -body $body \
|
|
-constraints {win longPathAware} \
|
|
-setup [list if {[file exists $longPathRoot]} {error "Precondition failed: $longPathRoot exists"}] \
|
|
-cleanup {file delete -force $longPathRoot} \
|
|
{*}$args]
|
|
}
|
|
|
|
proc julian {seconds} {
|
|
clock format $seconds -format %J
|
|
}
|
|
# Assumes all tests will run within the same day to sanity check times
|
|
variable today [julian now]
|
|
|
|
#
|
|
# Path operations - file cmdname ...
|
|
testlongpathsyntax file-dirname-longpath-0 "long path file dirname" {
|
|
file dirname $longPathDir
|
|
} -result [join [lrange [split $longPathDir /] 0 end-1] /]
|
|
|
|
testlongpathsyntax file-extension-longpath-0 "long path file extension" {
|
|
file extension $longPathFile.ext
|
|
} -result .ext
|
|
|
|
testlongpathsyntax file-join-longpath-0 "deep path file join" {
|
|
file join $longPathRoot {*}$deepPathComponents $pathTail
|
|
} -result $deepPathFile
|
|
|
|
testlongpath file-join-longpath-1 "long path file join - native name" {
|
|
file join $longPathRoot [join $longPathComponents \\] $pathTail
|
|
} -result $longPathFile
|
|
|
|
testlongpath file-join-longpath-0 "deep path file join - relative" {
|
|
file join {*}$deepPathComponents
|
|
} -result [join $deepPathComponents /]
|
|
|
|
testlongpathsyntax file-nativename-longpath-0 "long path nativename" {
|
|
file nativename $longPathDir
|
|
} -result [string map [list / \\] $longPathDir]
|
|
|
|
testlongpathsyntax file-normalize-longpath-0 "long path normalize" {
|
|
file normalize $longPathDir
|
|
} -constraints win -result $longPathDir
|
|
|
|
testlongpathsyntax file-normalize-longpath-1 "long path normalize - dotdot" {
|
|
file normalize $longPathDir/../../$longPathComponent/$pathTail
|
|
} -result [join [list $longPathRoot {*}[lrange $longPathComponents 0 end-1] $pathTail] /]
|
|
|
|
testlongpathsyntax file-normalize-longpath-2 "long path normalize - dot, native" {
|
|
file normalize [string map [list / \\] $longPathDir/././$pathTail]
|
|
} -result $longPathFile
|
|
|
|
testlongpath file-normalize-longpath-3 "Long path normalize - pwd-relative name" {
|
|
set origDir [pwd]
|
|
file mkdir $longPathDir
|
|
cd $longPathDir
|
|
set path [file normalize foo]
|
|
cd $origDir
|
|
set path
|
|
} -result $longPathDir/foo
|
|
|
|
testlongpathsyntax file-rootname-longpath-0 "long path file rootname" {
|
|
file rootname $longPathFile.ext
|
|
} -result $longPathFile
|
|
|
|
testlongpathsyntax file-split-longpath-0 "long path file split" {
|
|
file split $longPathFile
|
|
} -result [list {*}[file split $longPathRoot] {*}$longPathComponents $pathTail]
|
|
|
|
testlongpathsyntax file-split-longpath-1 "deep path file split - native" {
|
|
file split [string map [list / \\] $deepPathFile]
|
|
} -result [list {*}[file split $longPathRoot] {*}$deepPathComponents $pathTail]
|
|
|
|
testlongpathsyntax file-tail-longpath-0 "long path file tail" {
|
|
file tail $longPathFile.ext
|
|
} -result $pathTail.ext
|
|
|
|
testlongpathsyntax file-pathtype-longpath-0 "long path type" {
|
|
file pathtype $longPathDir
|
|
} -result absolute
|
|
|
|
testlongpathsyntax file-pathtype-longpath-1 "long path type - relative" {
|
|
file pathtype [join $longPathComponents /]
|
|
} -result relative
|
|
|
|
testlongpathsyntax file-pathtype-longpath-2 "long path type - volumerelative" {
|
|
file pathtype C:[join $longPathComponents /]
|
|
} -result volumerelative
|
|
|
|
testlongpathsyntax file-separator-longpath-0 "long path separator" {
|
|
file separator $longPathDir
|
|
} -result \\
|
|
|
|
testlongpathsyntax file-system-longpath-0 "long path system" {
|
|
lindex [file system $longPathDir] 0
|
|
} -result native
|
|
|
|
testlongpathsyntax file-tildeexpand-longpath-0 "long path tildeexpand" {
|
|
file tildeexpand ~/[join $longPathComponents /]
|
|
} -result [join [list [file home] {*}$longPathComponents] /]
|
|
|
|
#
|
|
# File and directory operations
|
|
proc ops {path type} {
|
|
set cpath $path-copy
|
|
set rpath $path-renamed
|
|
if {$type eq "dir"} {
|
|
lappend result [file mkdir $path]
|
|
} else {
|
|
file mkdir [file dirname $path]
|
|
lappend result [writeFile $path abc]
|
|
lappend result [readFile $path]
|
|
}
|
|
# Note. For file owned, we only check no errors are generated since
|
|
# ownership semantics in NTFS are quirky depending on whether files
|
|
# created in admin mode etc.
|
|
lappend result \
|
|
[file exists $path] \
|
|
[file exists $path/..] \
|
|
[file readable $path] \
|
|
[file writable $path] \
|
|
[file executable $path] \
|
|
[catch {file owned $path}] \
|
|
[file isdirectory $path] \
|
|
[file isfile $path] \
|
|
[file size $path] \
|
|
[file type $path] \
|
|
[dict get [file stat $path] type] \
|
|
[julian [file atime $path]] \
|
|
[julian [file mtime $path]] \
|
|
[file rename $path $rpath] \
|
|
[file exists $path] \
|
|
[file copy $rpath $cpath] \
|
|
[file exists $cpath] \
|
|
[file delete $rpath] \
|
|
[file exists $rpath]
|
|
}
|
|
variable dirOpsResult [list {} 1 1 1 1 1 0 1 0 0 directory directory $today $today {} 0 {} 1 {} 0]
|
|
variable fileOpsResult [list {} abc 1 1 1 1 0 0 0 1 3 file file $today $today {} 0 {} 1 {} 0]
|
|
|
|
proc getAttrs {path} {
|
|
set attrs [file attributes $path]
|
|
# We do not test -shortname because Windows is unpredictable in how
|
|
# it is constructed and whether it is constructed at all
|
|
return [list \
|
|
[dict get $attrs -archive] \
|
|
[dict get $attrs -hidden] \
|
|
[dict get $attrs -readonly] \
|
|
[dict get $attrs -system] \
|
|
[dict get $attrs -longname]]
|
|
}
|
|
|
|
variable testsDir [file normalize [file dirname [info script]]]
|
|
variable zipTestDir [file join $testsDir zipfiles]
|
|
|
|
#
|
|
# Test directory ops
|
|
|
|
testlongpath dirops-longpath-0 "Long path directory operations" {
|
|
ops $longPathDir dir
|
|
} -result $dirOpsResult
|
|
|
|
testlongpath dirops-longpath-1 "Long path directory operations - native paths" {
|
|
ops [file nativename $longPathDir] dir
|
|
} -result $dirOpsResult
|
|
|
|
testlongpath dirops-longpath-2 "Long path directory operations - deep nesting" {
|
|
ops $deepPathDir dir
|
|
} -result $dirOpsResult
|
|
|
|
testlongpath dirops-longpath-2 "Long path directory operations - dot, dotdot" {
|
|
ops $longPathDir/.././$longPathComponent dir
|
|
} -result $dirOpsResult
|
|
|
|
testlongpath cd-longpath-0 "Long path directory - cd, pwd" {
|
|
set origDir [pwd]
|
|
file mkdir $longPathDir
|
|
cd $longPathDir
|
|
set newDir [pwd]
|
|
cd $origDir
|
|
set newDir
|
|
} -result $longPathDir
|
|
|
|
testlongpath dir-attributes-longpath-0 "Long path directory attributes" {
|
|
file mkdir $deepPathDir
|
|
getAttrs $deepPathDir
|
|
} -result [list 0 0 0 0 $deepPathDir]
|
|
|
|
testlongpath dir-attributes-longpath-1 "Long path directory attributes - set" {
|
|
file mkdir $longPathDir
|
|
file attributes $longPathDir -archive 1 -hidden 1 -system 1 -readonly 1
|
|
getAttrs $longPathDir
|
|
} -result [list 1 1 1 1 $longPathDir]
|
|
|
|
testlongpath dir-glob-longpath-0 "Long path glob" {
|
|
file mkdir $deepPathDir
|
|
writeFile $deepPathFile ""
|
|
writeFile $deepPathFile-2 ""
|
|
lsort [glob $deepPathDir/*]
|
|
} -result [list $deepPathFile $deepPathFile-2]
|
|
|
|
testlongpath dir-glob-longpath-1 "Long path glob -directory" {
|
|
file mkdir $deepPathDir
|
|
writeFile $deepPathFile ""
|
|
writeFile $deepPathFile-2 ""
|
|
lsort [glob -directory $deepPathDir *2]
|
|
} -result [list $deepPathFile-2]
|
|
|
|
testlongpath dir-glob-longpath-2 "Long path glob -path" {
|
|
file mkdir $deepPathDir
|
|
writeFile $deepPathFile ""
|
|
writeFile $deepPathFile-2 ""
|
|
lsort [glob -path $deepPathDir/[string index $pathTail 0] *[string range $pathTail 1 end]]
|
|
} -result [list $deepPathFile]
|
|
|
|
#
|
|
# Test file ops
|
|
|
|
testlongpath fileops-longpath-0 "Long path file operations" {
|
|
ops $longPathFile file
|
|
} -result $fileOpsResult
|
|
|
|
testlongpath fileops-longpath-1 "Long path file operations - native paths" {
|
|
ops [file nativename $longPathFile] file
|
|
} -result $fileOpsResult
|
|
|
|
testlongpath fileops-longpath-2 "Long path file operations - deep nesting" {
|
|
ops $deepPathFile file
|
|
} -result $fileOpsResult
|
|
|
|
testlongpath fileops-longpath-2 "Long path file operations - dot, dotdot" {
|
|
ops $longPathDir/.././$longPathComponent/$pathTail file
|
|
} -result $fileOpsResult
|
|
|
|
testlongpath file-attributes-longpath-0 "Long path file attributes" {
|
|
file mkdir [file dirname $deepPathFile]
|
|
close [open $deepPathFile w]
|
|
getAttrs $deepPathFile
|
|
} -result [list 1 0 0 0 $deepPathFile]
|
|
|
|
testlongpath file-attributes-longpath-1 "Long path file attributes - set" {
|
|
file mkdir $longPathDir
|
|
close [open $longPathFile w]
|
|
file attributes $longPathFile -archive 0 -hidden 1 -system 1 -readonly 1
|
|
getAttrs $longPathFile
|
|
} -result [list 0 1 1 1 $longPathFile]
|
|
|
|
#
|
|
# zipfs mounts
|
|
testlongpath zipfs-mount-longpath-0 "Long path archive" {
|
|
file mkdir $longPathDir
|
|
set mt //zipfs:/longpathtest
|
|
set archive [file join $longPathDir test.zip]
|
|
file copy [file join $zipTestDir test.zip] $archive
|
|
zipfs mount $archive $mt
|
|
set text [readFile $mt/test]
|
|
zipfs unmount $mt
|
|
set text
|
|
} -result "test\n"
|
|
|
|
#
|
|
# file link
|
|
testlongpath file-link-dir-longpath-0 "Link to a long path directory" {
|
|
file mkdir $deepPathDir
|
|
writeFile $deepPathFile abc
|
|
set link [file join [temporaryDirectory] dirlink]
|
|
file link $link $deepPathDir
|
|
set result [list [file link $link] [readFile $link/[file tail $deepPathFile]]]
|
|
file delete $link
|
|
set result
|
|
} -result [list [file nativename $deepPathDir] abc]
|
|
|
|
testlongpath file-link-dir-longpath-1 "Long path Link to a directory" {
|
|
set target [file join [temporaryDirectory] dirtarget]
|
|
file mkdir $target
|
|
writeFile $target/file.txt abc
|
|
file mkdir $deepPathDir
|
|
set link [file join $deepPathDir dirlink]
|
|
file link $link $target
|
|
set result [list [file link $link] [readFile $link/file.txt]]
|
|
file delete -force $target
|
|
set result
|
|
} -result [list [file nativename [file join [temporaryDirectory] dirtarget]] abc]
|
|
|
|
testlongpath file-link-file-longpath-0 "Test link to a long path file" {
|
|
file mkdir $longPathDir
|
|
writeFile $longPathFile abc
|
|
set link [file join [temporaryDirectory] filelink]
|
|
file link $link $longPathFile
|
|
set result [readFile $link]
|
|
file delete $link
|
|
set result
|
|
} -result abc
|
|
|
|
testlongpath file-link-file-longpath-1 "Test long path link to a file" {
|
|
set target [file join [temporaryDirectory] filetarget]
|
|
writeFile $target abc
|
|
file mkdir $deepPathDir
|
|
set link [file join $deepPathDir filelink]
|
|
file link $link $target
|
|
set result [readFile $link]
|
|
file delete -force $target
|
|
set result
|
|
} -result abc
|
|
|
|
#
|
|
# file lstat
|
|
testlongpath file-lstat-dir-longpath-0 "Lstat link to a long path directory" {
|
|
file mkdir $deepPathDir
|
|
set link [file join [temporaryDirectory] dirlink]
|
|
file link $link $deepPathDir
|
|
set result [list [dict get [file lstat $link] type] [dict get [file stat $link] type]]
|
|
file delete $link
|
|
set result
|
|
} -result {link directory}
|
|
|
|
testlongpath file-lstat-dir-longpath-1 "lstat long path Link to a directory" {
|
|
set target [file join [temporaryDirectory] dirtarget]
|
|
file mkdir $target
|
|
file mkdir $deepPathDir
|
|
set link [file join $deepPathDir dirlink]
|
|
file link $link $target
|
|
set result [list [dict get [file lstat $link] type] [dict get [file stat $link] type]]
|
|
file delete -force $target
|
|
set result
|
|
} -result {link directory}
|
|
|
|
testlongpath file-lstat-file-longpath-0 "lstat link to a long path file" {
|
|
file mkdir $longPathDir
|
|
writeFile $longPathFile abc
|
|
set link [file join [temporaryDirectory] filelink]
|
|
file link $link $longPathFile
|
|
set result [list [dict get [file lstat $link] type] [dict get [file stat $link] type]]
|
|
file delete $link
|
|
# Result is {file file} because file links are symbolic?
|
|
set result
|
|
} -result {file file}
|
|
|
|
testlongpath file-lstat-file-longpath-1 "lstat long path link to a file" {
|
|
set target [file join [temporaryDirectory] filetarget]
|
|
writeFile $target abc
|
|
file mkdir $deepPathDir
|
|
set link [file join $deepPathDir filelink]
|
|
file link $link $target
|
|
set result [list [dict get [file lstat $link] type] [dict get [file stat $link] type]]
|
|
file delete -force $target
|
|
set result
|
|
} -result {file file}
|
|
|
|
#
|
|
# exec and running Tcl from a deep install
|
|
if {0} {
|
|
# CreateProcessW is not long path aware. Have to wait for Microsoft
|
|
# to make it so.
|
|
variable srcBinDir [file dirname [info nameofexecutable]]
|
|
variable installDir $deepPathDir
|
|
set deepExe [file join $installDir bin [file tail [info nameofexecutable]]]
|
|
testlongpath exec-longpath-0 "Long path Tcl installation" {
|
|
file mkdir $installDir/bin
|
|
file mkdir $installDir/lib
|
|
# Copy executables and library
|
|
set srcdir [file dirname [info nameofexecutable]]
|
|
file copy -force [info nameofexecutable] $deepExe
|
|
foreach f [glob [file join $srcBinDir *.dll]] {
|
|
file copy -force $f [file join $installDir bin]
|
|
}
|
|
file copy -force [file join $testsDir .. library] [file join $installDir lib/tcl[info tclversion]]
|
|
set script [file join $installDir x.tcl]
|
|
writeFile $script {puts [info nameofexecutable],[info library]}
|
|
catch {set oldenv $env(TCL_LIBRARY)}
|
|
set env(TCL_LIBRARY) [file join $installDir lib]
|
|
set olddir [pwd]
|
|
cd $installDir/bin
|
|
set code [catch {exec $deepExe $script} output]
|
|
cd $olddir
|
|
if {[info exists oldenv]} {
|
|
set env(TCL_LIBRARY) $oldenv
|
|
}
|
|
list $code $output
|
|
} -result [list 0 $deepExe,[file join $deepPathDir lib]]
|
|
}
|
|
}
|
|
namespace delete testlongpaths
|
|
|
|
#
|
|
# Tests for C error interfaces
|
|
testConstraint testwinerror [llength [info commands testwinerror]]
|
|
namespace eval testwinerror {
|
|
if {[testConstraint testwinerror]} {
|
|
catch {
|
|
variable regOut [exec {*}[auto_execok reg] query {HKCU\Control Panel\International} /v LocaleName]
|
|
if {[regexp -nocase {en-US} $regOut]} {
|
|
testConstraint englishLocale 1
|
|
}
|
|
}
|
|
}
|
|
variable pdhErrorCode 0x800007D0
|
|
proc test args {
|
|
uplevel 1 [list ::tcltest::test {*}$args -constraints [list win englishLocale testwinerror]]
|
|
}
|
|
test winerror-appendmessage-0 "Get Windows error message" -body {
|
|
testwinerror appendmessage 4
|
|
} -result [list 1 {The system cannot open the file.}]
|
|
|
|
test winerror-appendmessage-1 "Get Windows error message with a header" -body {
|
|
testwinerror appendmessage 4 "System error:"
|
|
} -result [list 1 {System error: The system cannot open the file.}]
|
|
|
|
test winerror-appendmessage-2 {
|
|
Get Windows error message with a header having trailing space
|
|
} -body {
|
|
testwinerror appendmessage 4 "System error: "
|
|
} -result [list 1 {System error: The system cannot open the file.}]
|
|
|
|
test winerror-appendmessage-3 {
|
|
Get Windows message for non-system message id
|
|
} -body {
|
|
testwinerror appendmessage $pdhErrorCode
|
|
} -result [list 0 {unknown error: 0x800007d0}]
|
|
|
|
test winerror-appendmessage-4 {
|
|
Get Windows message for non-system message id with header
|
|
} -body {
|
|
testwinerror appendmessage $pdhErrorCode "Non-system error:"
|
|
} -result [list 0 {Non-system error: unknown error: 0x800007d0}]
|
|
|
|
test winerror-appendmessage-5 {
|
|
Get Windows message for non-system message id - no default message
|
|
} -body {
|
|
testwinerror appendmessage $pdhErrorCode "" 0
|
|
} -result [list 0 {}]
|
|
|
|
test winerror-appendmessage-6 {
|
|
Get message for non-system message id
|
|
} -body {
|
|
testwinerror appendmessage $pdhErrorCode "" 0 pdh.dll
|
|
} -result [list 1 {Unable to connect to the specified computer or the computer is offline.}]
|
|
|
|
test winerror-appendmessage-7 {
|
|
Get non-existent message for non-system message id
|
|
} -body {
|
|
testwinerror appendmessage 0x123 "" 1 pdh.dll
|
|
} -result [list 0 {unknown error: 0x123}]
|
|
|
|
test winerror-raiseerror-0 {
|
|
Raise a Windows error
|
|
} -body {
|
|
list [catch {testwinerror raiseerror 4} m d] $m [dict get $d -errorcode]
|
|
} -result [list 1 {The system cannot open the file.} {WINDOWS 0x4 {The system cannot open the file.}}]
|
|
|
|
test winerror-raiseerror-1 {
|
|
Raise a Windows error with prefix
|
|
} -body {
|
|
list [catch {testwinerror raiseerror 4 "System error:"} m d] $m [dict get $d -errorcode]
|
|
} -result [list 1 {System error: The system cannot open the file.} {WINDOWS 0x4 {System error: The system cannot open the file.}}]
|
|
|
|
test winerror-raiseerror-2 {
|
|
Raise a Windows error with prefix with trailing space
|
|
} -body {
|
|
list [catch {testwinerror raiseerror 4 "System error: "} m d] $m [dict get $d -errorcode]
|
|
} -result [list 1 {System error: The system cannot open the file.} {WINDOWS 0x4 {System error: The system cannot open the file.}}]
|
|
|
|
test winerror-raiseerror-3 {
|
|
Raise a Windows error with bad error code
|
|
} -body {
|
|
list [catch {testwinerror raiseerror $pdhErrorCode} m d] $m [dict get $d -errorcode]
|
|
} -result [list 1 {unknown error: 0x800007d0} {WINDOWS 0x800007d0 {unknown error: 0x800007d0}}]
|
|
|
|
test winerror-raiseerror-4 {
|
|
Raise a Windows error with non-system error code
|
|
} -body {
|
|
list [catch {testwinerror raiseerror $pdhErrorCode "" pdh.dll} m d] $m [dict get $d -errorcode]
|
|
} -result [list 1 {Unable to connect to the specified computer or the computer is offline.} {WINDOWS 0x800007d0 {Unable to connect to the specified computer or the computer is offline.}}]
|
|
|
|
}
|
|
namespace delete testwinerror
|
|
|
|
|
|
################################################################
|
|
|
|
# This block of code used to occur after the "return" call, so I'm
|
|
# commenting it out and assuming that this code is still under construction.
|
|
#foreach source {tef ted tnf tnd "" nul com1} {
|
|
# foreach chmodsrc {000 755} {
|
|
# foreach dest "tfn tfe tdn tdempty tdfull td1/td2 $p $p/td1 {} nul" {
|
|
# foreach chmoddst {000 755} {
|
|
# puts hi
|
|
# cleanup
|
|
# file delete -force ted tef
|
|
# file mkdir ted
|
|
# createfile tef
|
|
# createfile tfe
|
|
# file mkdir tdempty
|
|
# file mkdir tdfull/td1/td2
|
|
#
|
|
# catch {testchmod $chmodsrc $source}
|
|
# catch {testchmod $chmoddst $dest}
|
|
#
|
|
# if [catch {file rename $source $dest} msg] {
|
|
# puts "file rename $source ($chmodsrc) $dest ($chmoddst)"
|
|
# puts $msg
|
|
# }
|
|
# }
|
|
# }
|
|
# }
|
|
#}
|
|
|
|
cleanup
|
|
::tcltest::cleanupTests
|
|
return
|
|
|
|
# Local Variables:
|
|
# mode: tcl
|
|
# End:
|