3 # This file contains a collection of tests for safe Tcl, packages loading, and
4 # using safe interpreters. Sourcing this file into tcl runs the tests and
5 # generates output for errors. No output means no errors were found.
7 # The package http 1.0 is convenient for testing package loading, but will soon
9 # - Tests that use http are replaced here with tests that use example packages
10 # provided in subdirectory auto0 of the tests directory, which are independent
11 # of any changes made to the packages provided with Tcl itself.
12 # - These are tests 7.1 7.2 7.4 9.11 9.13
13 # - Tests 5.* test the example packages themselves before they
14 # are used to test Safe Base interpreters.
15 # - Alternative tests using stock packages of Tcl 8.6 are in file
18 # Copyright (c) 1995-1996 Sun Microsystems, Inc.
19 # Copyright (c) 1998-1999 by Scriptics Corporation.
21 # See the file "license.terms" for information on usage and redistribution of
22 # this file, and for a DISCLAIMER OF ALL WARRANTIES.
24 if {"::tcltest" ni [namespace children]} {
25 package require tcltest 2.5
26 namespace import -force ::tcltest::*
29 foreach i [interp children] {
33 set SaveAutoPath $::auto_path
34 set ::auto_path [info library]
35 set TestsDir [file normalize [file dirname [info script]]]
36 set PathMapp [list $tcl_library TCLLIB $TestsDir TESTSDIR]
38 proc mapList {map listIn} {
40 foreach element $listIn {
41 lappend listOut [string map $map $element]
45 proc mapAndSortList {map listIn} {
47 foreach element $listIn {
48 lappend listOut [string map $map $element]
53 # Force actual loading of the safe package because we use un-exported (and
54 # thus un-autoindexed) APIs in this test result arguments:
55 catch {safe::interpConfigure}
57 # testing that nested and statics do what is advertised (we use a static
58 # package - Tcltest - but it might be absent if we're in standard tclsh)
60 testConstraint TcltestPackage [expr {![catch {package require Tcltest}]}]
62 test safe-1.1 {safe::interpConfigure syntax} -returnCodes error -body {
64 } -result {no value given for parameter "slave" (use -help for full usage) :
65 slave name () name of the slave}
66 test safe-1.2 {safe::interpCreate syntax} -returnCodes error -body {
67 safe::interpCreate -help
68 } -result {Usage information:
69 Var/FlagName Type Value Help
70 ------------ ---- ----- ----
71 (-help gives this help)
72 ?slave? name () name of the slave (optional)
73 -accessPath list () access path for the slave
74 -noStatics boolflag (false) prevent loading of statically linked pkgs
75 -statics boolean (true) loading of statically linked pkgs
76 -nestedLoadOk boolflag (false) allow nested loading
77 -nested boolean (false) nested loading
78 -deleteHook script () delete hook}
79 test safe-1.3 {safe::interpInit syntax} -returnCodes error -body {
80 safe::interpInit -noStatics
81 } -result {bad value "-noStatics" for parameter
82 slave name () name of the slave}
84 test safe-2.1 {creating interpreters, should have no aliases} emptyTest {
85 # Disabled this test. It tests nothing sensible. [Bug 999612]
88 test safe-2.2 {creating interpreters, should have no aliases} -setup {
89 catch {safe::interpDelete a}
95 # This (ab)use of safe::interpDelete to delete non-Safe-Base interpreters
96 # is regrettable and should be removed at the next major revision.
98 test safe-2.3 {creating safe interpreters, should have no unexpected aliases} -setup {
99 catch {safe::interpDelete a}
101 interp create a -safe
105 } -result {::tcl::mathfunc::max ::tcl::mathfunc::min clock}
107 test safe-3.1 {calling safe::interpInit is safe} -setup {
108 catch {safe::interpDelete a}
109 interp create a -safe
112 interp eval a exec ls
113 } -returnCodes error -cleanup {
115 } -result {invalid command name "exec"}
116 test safe-3.2 {calling safe::interpCreate on trusted interp} -setup {
117 catch {safe::interpDelete a}
123 } -result {::tcl::file::atime ::tcl::file::attributes ::tcl::file::copy ::tcl::file::delete ::tcl::file::dirname ::tcl::file::executable ::tcl::file::exists ::tcl::file::extension ::tcl::file::isdirectory ::tcl::file::isfile ::tcl::file::link ::tcl::file::lstat ::tcl::file::mkdir ::tcl::file::mtime ::tcl::file::nativename ::tcl::file::normalize ::tcl::file::owned ::tcl::file::readable ::tcl::file::readlink ::tcl::file::rename ::tcl::file::rootname ::tcl::file::size ::tcl::file::stat ::tcl::file::tail ::tcl::file::tempfile ::tcl::file::type ::tcl::file::volumes ::tcl::file::writable ::tcl::info::nameofexecutable clock encoding exit glob load source}
124 test safe-3.3 {calling safe::interpCreate on trusted interp} -setup {
125 catch {safe::interpDelete a}
128 interp eval a {source [file join $tcl_library init.tcl]}
132 test safe-3.4 {calling safe::interpCreate on trusted interp} -setup {
133 catch {safe::interpDelete a}
136 interp eval a {source [file join $tcl_library init.tcl]}
141 test safe-4.1 {safe::interpDelete} -setup {
142 catch {safe::interpDelete a}
146 # This (ab)use of safe::interpDelete to delete non-Safe-Base interpreters
147 # is regrettable and should be removed at the next major revision.
149 test safe-4.2 {safe::interpDelete, indirectly} -setup {
150 catch {safe::interpDelete a}
153 a alias exit safe::interpDelete a
155 # This (ab)use of safe::interpDelete to delete non-Safe-Base interpreters
156 # is regrettable and should be removed at the next major revision.
158 test safe-4.5 {safe::interpDelete} -setup {
159 catch {safe::interpDelete a}
163 } -returnCodes error -cleanup {
165 } -result {interpreter named "a" already exists, cannot create}
166 test safe-4.6 {safe::interpDelete, indirectly} -setup {
167 catch {safe::interpDelete a}
173 # The old test "safe-5.1" has been moved to "safe-stock-9.8".
174 # A replacement test using example files is "safe-9.8".
175 # Tests 5.* test the example files before using them to test safe interpreters.
177 unset -nocomplain path
179 test safe-5.1 {example tclIndex commands, test in parent interpreter} -setup {
180 set tmpAutoPath $::auto_path
181 lappend ::auto_path [file join $TestsDir auto0 auto1] [file join $TestsDir auto0 auto2]
183 # Try to load the commands.
184 set code3 [catch report1 msg3]
185 set code4 [catch report2 msg4]
186 list $code3 $msg3 $code4 $msg4
188 catch {rename report1 {}}
189 catch {rename report2 {}}
190 set ::auto_path $tmpAutoPath
192 } -match glob -result {0 ok1 0 ok2}
193 test safe-5.2 {example tclIndex commands, negative test in parent interpreter} -setup {
194 set tmpAutoPath $::auto_path
195 lappend ::auto_path [file join $TestsDir auto0]
197 # Try to load the commands.
198 set code3 [catch report1 msg3]
199 set code4 [catch report2 msg4]
200 list $code3 $msg3 $code4 $msg4
202 catch {rename report1 {}}
203 catch {rename report2 {}}
204 set ::auto_path $tmpAutoPath
206 } -match glob -result {1 {invalid command name "report1"} 1 {invalid command name "report2"}}
207 test safe-5.3 {example pkgIndex.tcl packages, test in parent interpreter, child directories} -setup {
208 set tmpAutoPath $::auto_path
209 lappend ::auto_path [file join $TestsDir auto0]
211 # Try to load the packages and run a command from each one.
212 set code3 [catch {package require SafeTestPackage1} msg3]
213 set code4 [catch {package require SafeTestPackage2} msg4]
214 set code5 [catch HeresPackage1 msg5]
215 set code6 [catch HeresPackage2 msg6]
216 list $code3 $msg3 $code4 $msg4 $code5 $msg5 $code6 $msg6
218 set ::auto_path $tmpAutoPath
219 catch {package forget SafeTestPackage1}
220 catch {package forget SafeTestPackage2}
221 catch {rename HeresPackage1 {}}
222 catch {rename HeresPackage2 {}}
223 } -match glob -result {0 1.2.3 0 2.3.4 0 OK1 0 OK2}
224 test safe-5.4 {example pkgIndex.tcl packages, test in parent interpreter, main directories} -setup {
225 set tmpAutoPath $::auto_path
226 lappend ::auto_path [file join $TestsDir auto0 auto1] \
227 [file join $TestsDir auto0 auto2]
229 # Try to load the packages and run a command from each one.
230 set code3 [catch {package require SafeTestPackage1} msg3]
231 set code4 [catch {package require SafeTestPackage2} msg4]
232 set code5 [catch HeresPackage1 msg5]
233 set code6 [catch HeresPackage2 msg6]
234 list $code3 $msg3 $code4 $msg4 $code5 $msg5 $code6 $msg6
236 set ::auto_path $tmpAutoPath
237 catch {package forget SafeTestPackage1}
238 catch {package forget SafeTestPackage2}
239 catch {rename HeresPackage1 {}}
240 catch {rename HeresPackage2 {}}
241 } -match glob -result {0 1.2.3 0 2.3.4 0 OK1 0 OK2}
242 test safe-5.5 {example modules packages, test in parent interpreter, replace path} -setup {
243 set oldTm [tcl::tm::path list]
244 foreach path $oldTm {
245 tcl::tm::path remove $path
247 tcl::tm::path add [file join $TestsDir auto0 modules]
249 # Try to load the modules and run a command from each one.
250 set code0 [catch {package require test0} msg0]
251 set code1 [catch {package require mod1::test1} msg1]
252 set code2 [catch {package require mod2::test2} msg2]
253 set out0 [test0::try0]
254 set out1 [mod1::test1::try1]
255 set out2 [mod2::test2::try2]
256 list $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $out0 $out1 $out2
258 tcl::tm::path remove [file join $TestsDir auto0 modules]
259 foreach path [lreverse $oldTm] {
260 tcl::tm::path add $path
262 catch {package forget test0}
263 catch {package forget mod1::test1}
264 catch {package forget mod2::test2}
265 catch {namespace delete ::test0}
266 catch {namespace delete ::mod1}
267 } -match glob -result {0 0.5 0 1.0 0 2.0 -- res0 res1 res2}
268 test safe-5.6 {example modules packages, test in parent interpreter, append to path} -setup {
269 tcl::tm::path add [file join $TestsDir auto0 modules]
271 # Try to load the modules and run a command from each one.
272 set code0 [catch {package require test0} msg0]
273 set code1 [catch {package require mod1::test1} msg1]
274 set code2 [catch {package require mod2::test2} msg2]
275 set out0 [test0::try0]
276 set out1 [mod1::test1::try1]
277 set out2 [mod2::test2::try2]
278 list $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $out0 $out1 $out2
280 tcl::tm::path remove [file join $TestsDir auto0 modules]
281 catch {package forget test0}
282 catch {package forget mod1::test1}
283 catch {package forget mod2::test2}
284 catch {namespace delete ::test0}
285 catch {namespace delete ::mod1}
286 } -match glob -result {0 0.5 0 1.0 0 2.0 -- res0 res1 res2}
288 # test safe interps 'information leak'
289 proc SafeEval {script} {
290 # Helper procedure that ensures the safe interp is cleaned up even if
291 # there is a failure in the script.
292 set SafeInterp [interp create -safe]
293 catch {$SafeInterp eval $script} msg opts
294 interp delete $SafeInterp
295 return -options $opts $msg
298 test safe-6.1 {test safe interpreters knowledge of the world} {
299 lsort [SafeEval {info globals}]
300 } {tcl_interactive tcl_patchLevel tcl_platform tcl_version}
301 test safe-6.2 {test safe interpreters knowledge of the world} {
302 SafeEval {info script}
304 test safe-6.3 {test safe interpreters knowledge of the world} {
305 set r [SafeEval {array names tcl_platform}]
306 # If running a windows-debug shell, remove the "debug" element from r.
307 if {[testConstraint win]} {
308 set r [lsearch -all -inline -not -exact $r "debug"]
310 set r [lsearch -all -inline -not -exact $r "threaded"]
312 } {byteOrder engine pathSeparator platform pointerSize wordSize}
315 # More test should be added to check that hostname, nameofexecutable, aren't
316 # leaking infos, but they still do...
318 # high level general test
319 # Use example packages not http1.0 etc
320 test safe-7.1 {tests that everything works at high level} -setup {
321 set tmpAutoPath $::auto_path
322 lappend ::auto_path [file join $TestsDir auto0]
323 set i [safe::interpCreate]
324 set ::auto_path $tmpAutoPath
326 # no error shall occur:
327 # (because the default access_path shall include 1st level sub dirs so
328 # package require in a child works like in the parent)
329 set v [interp eval $i {package require SafeTestPackage1}]
330 # no error shall occur:
331 interp eval $i {HeresPackage1}
334 safe::interpDelete $i
335 } -match glob -result 1.2.3
336 test safe-7.2 {tests specific path and interpFind/AddToAccessPath} -setup {
338 set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
339 # should not add anything (p0)
340 set token1 [safe::interpAddToAccessPath $i [info library]]
341 # should add as p* (not p1 if parent has a module path)
342 set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
343 # should add as p* (not p2 if parent has a module path)
344 set token3 [safe::interpAddToAccessPath $i [file join $TestsDir auto0]]
345 set confA [safe::interpConfigure $i]
346 set mappA [mapList $PathMapp [dict get $confA -accessPath]]
347 # an error shall occur (SafeTestPackage1 is not anymore in the secure 0-level
348 # provided deep path)
349 list $token1 $token2 $token3 -- \
350 [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg -- \
351 $mappA -- [safe::interpDelete $i]
353 } -match glob -result {{$p(:0:)} {$p(:*:)} {$p(:*:)} --\
354 1 {can't find package SafeTestPackage1} --\
355 {TCLLIB */dummy/unixlike/test/path TESTSDIR/auto0} -- {}}
356 test safe-7.3 {check that safe subinterpreters work} {
357 set g [interp children]
359 append g { -- residue of an earlier test}
361 set h [info vars ::safe::S*]
363 append h { -- residue of an earlier test}
365 set i [safe::interpCreate]
366 set j [safe::interpCreate [list $i x]]
367 list $g $h [interp eval $j {join {o k} ""}] [safe::interpDelete $i] \
368 [interp exists $j] [info vars ::safe::S*]
370 test safe-7.3.1 {check that safe subinterpreters work with namespace names} -setup {
372 set g [interp children]
374 append g { -- residue of an earlier test}
376 set h [info vars ::safe::S*]
378 append h { -- residue of an earlier test}
380 set i [safe::interpCreate foo::bar]
381 set j [safe::interpCreate [list $i hello::world]]
382 list $g $h [interp eval $j {join {o k} ""}] \
383 [foo::bar eval {hello::world eval {join {o k} ""}}] \
384 [safe::interpDelete $i] \
385 [interp exists $j] [info vars ::safe::S*]
386 } -match glob -result {{} {} ok ok {} 0 {}}
387 test safe-7.4 {tests specific path and positive search} -setup {
389 set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
390 # should not add anything (p0)
391 set token1 [safe::interpAddToAccessPath $i [info library]]
392 # should add as p* (not p1 if parent has a module path)
393 set token2 [safe::interpAddToAccessPath $i [file join $TestsDir auto0 auto1]]
394 set confA [safe::interpConfigure $i]
395 set mappA [mapList $PathMapp [dict get $confA -accessPath]]
396 # this time, unlike test safe-7.2, SafeTestPackage1 should be found
397 list $token1 $token2 -- \
398 [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg -- \
399 $mappA -- [safe::interpDelete $i]
400 # Note that the glob match elides directories (those from the module path)
401 # other than the first and last in the access path.
403 } -match glob -result {{$p(:0:)} {$p(:*:)} -- 0 1.2.3 --\
404 {TCLLIB * TESTSDIR/auto0/auto1} -- {}}
406 # test source control on file name
407 test safe-8.1 {safe source control on file} -setup {
409 catch {safe::interpDelete $i}
411 safe::interpCreate $i
413 } -returnCodes error -cleanup {
414 safe::interpDelete $i
416 } -result {wrong # args: should be "source ?-encoding E? fileName"}
417 test safe-8.2 {safe source control on file} -setup {
419 catch {safe::interpDelete $i}
421 safe::interpCreate $i
422 $i eval {source a b c d e}
423 } -returnCodes error -cleanup {
424 safe::interpDelete $i
426 } -result {wrong # args: should be "source ?-encoding E? fileName"}
427 test safe-8.3 {safe source control on file} -setup {
429 catch {safe::interpDelete $i}
431 proc safe-test-log {str} {lappend ::log $str}
432 set prevlog [safe::setLogCmd]
434 safe::interpCreate $i
435 safe::setLogCmd safe-test-log
436 list [catch {$i eval {source .}} msg] $msg $log
438 safe::setLogCmd $prevlog
439 safe::interpDelete $i
440 rename safe-test-log {}
442 } -result {1 {permission denied} {{ERROR for slave a : ".": is a directory}}}
443 test safe-8.4 {safe source control on file} -setup {
445 catch {safe::interpDelete $i}
447 proc safe-test-log {str} {global log; lappend log $str}
448 set prevlog [safe::setLogCmd]
450 safe::interpCreate $i
451 safe::setLogCmd safe-test-log
452 list [catch {$i eval {source /abc/def}} msg] $msg $log
454 safe::setLogCmd $prevlog
455 safe::interpDelete $i
456 rename safe-test-log {}
458 } -result {1 {permission denied} {{ERROR for slave a : "/abc/def": not in access_path}}}
459 test safe-8.5 {safe source control on file} -setup {
461 catch {safe::interpDelete $i}
463 proc safe-test-log {str} {global log; lappend log $str}
464 set prevlog [safe::setLogCmd]
466 # This tested filename == *.tcl or tclIndex, but that restriction was
467 # removed in 8.4a4 - hobbs
468 safe::interpCreate $i
469 safe::setLogCmd safe-test-log
471 $i eval {source [file join [info lib] blah]}
474 safe::setLogCmd $prevlog
475 safe::interpDelete $i
476 rename safe-test-log {}
478 } -result [list 1 {no such file or directory} [list "ERROR for slave a : [file join [info library] blah]:no such file or directory"]]
479 test safe-8.6 {safe source control on file} -setup {
481 catch {safe::interpDelete $i}
483 proc safe-test-log {str} {global log; lappend log $str}
484 set prevlog [safe::setLogCmd]
486 safe::interpCreate $i
487 safe::setLogCmd safe-test-log
489 $i eval {source [file join [info lib] blah.tcl]}
492 safe::setLogCmd $prevlog
493 safe::interpDelete $i
494 rename safe-test-log {}
496 } -result [list 1 {no such file or directory} [list "ERROR for slave a : [file join [info library] blah.tcl]:no such file or directory"]]
497 test safe-8.7 {safe source control on file} -setup {
499 catch {safe::interpDelete $i}
501 proc safe-test-log {str} {global log; lappend log $str}
502 set prevlog [safe::setLogCmd]
504 safe::interpCreate $i
505 # This tested length of filename, but that restriction was removed in
507 safe::setLogCmd safe-test-log
509 $i eval {source [file join [info lib] xxxxxxxxxxx.tcl]}
512 safe::setLogCmd $prevlog
513 safe::interpDelete $i
514 rename safe-test-log {}
516 } -result [list 1 {no such file or directory} [list "ERROR for slave a : [file join [info library] xxxxxxxxxxx.tcl]:no such file or directory"]]
517 test safe-8.8 {safe source forbids -rsrc} emptyTest {
518 # Disabled this test. It was only useful for long unsupported
519 # Mac OS 9 systems. [Bug 860a9f1945]
521 test safe-8.9 {safe source and return} -setup {
523 set returnScript [makeFile {return "ok"} return.tcl]
524 catch {safe::interpDelete $i}
526 safe::interpCreate $i
527 set token [safe::interpAddToAccessPath $i [file dirname $returnScript]]
528 $i eval [list source $token/[file tail $returnScript]]
530 catch {safe::interpDelete $i}
531 removeFile $returnScript
534 test safe-8.10 {safe source and return} -setup {
536 set returnScript [makeFile {return -level 2 "ok"} return.tcl]
537 catch {safe::interpDelete $i}
539 safe::interpCreate $i
540 set token [safe::interpAddToAccessPath $i [file dirname $returnScript]]
541 $i eval [list apply {filename {
544 }} $token/[file tail $returnScript]]
546 catch {safe::interpDelete $i}
547 removeFile $returnScript
551 test safe-9.1 {safe interps' deleteHook} -setup {
553 catch {safe::interpDelete $i}
556 proc testDelHook {args} {
558 # the interp still exists at that point
559 interp eval a {set delete 1}
560 # mark that we've been here (successfully)
563 safe::interpCreate $i -deleteHook "testDelHook arg1 arg2"
564 list [interp eval $i exit] $res
566 catch {rename testDelHook {}}
568 } -result {{} {arg1 arg2 a}}
569 test safe-9.2 {safe interps' error in deleteHook} -setup {
571 catch {safe::interpDelete $i}
574 proc safe-test-log {str} {lappend ::log $str}
575 set prevlog [safe::setLogCmd]
577 proc testDelHook {args} {
579 # the interp still exists at that point
580 interp eval a {set delete 1}
581 # mark that we've been here (successfully)
583 # create an exception
584 error "being catched"
586 safe::interpCreate $i -deleteHook "testDelHook arg1 arg2"
587 safe::setLogCmd safe-test-log
588 list [safe::interpDelete $i] $res $log
590 safe::setLogCmd $prevlog
591 catch {rename testDelHook {}}
592 rename safe-test-log {}
594 } -result {{} {arg1 arg2 a} {{NOTICE for slave a : About to delete} {ERROR for slave a : Delete hook error (being catched)} {NOTICE for slave a : Deleted}}}
595 test safe-9.3 {dual specification of statics} -returnCodes error -body {
596 safe::interpCreate -stat true -nostat
597 } -result {conflicting values given for -statics and -noStatics}
598 test safe-9.4 {dual specification of statics} {
599 # no error shall occur
600 safe::interpDelete [safe::interpCreate -stat false -nostat]
602 test safe-9.5 {dual specification of nested} -returnCodes error -body {
603 safe::interpCreate -nested 0 -nestedload
604 } -result {conflicting values given for -nested and -nestedLoadOk}
605 test safe-9.6 {interpConfigure widget like behaviour} -body {
606 # this test shall work, don't try to "fix it" unless you *really* know what
607 # you are doing (ie you are me :p) -- dl
608 list [set i [safe::interpCreate \
611 -deleteHook {foo bar}]
612 safe::interpConfigure $i -accessPath /foo/bar
613 safe::interpConfigure $i]\
614 [safe::interpConfigure $i -aCCess]\
615 [safe::interpConfigure $i -nested]\
616 [safe::interpConfigure $i -statics]\
617 [safe::interpConfigure $i -DEL]\
618 [safe::interpConfigure $i -accessPath /blah -statics 1
619 safe::interpConfigure $i]\
620 [safe::interpConfigure $i -deleteHook toto -nosta -nested 0
621 safe::interpConfigure $i]
623 safe::interpDelete $i
624 } -match glob -result {{-accessPath * -statics 0 -nested 1 -deleteHook {foo bar}}\
625 {-accessPath *} {-nested 1} {-statics 0} {-deleteHook {foo bar}}\
626 {-accessPath * -statics 1 -nested 1 -deleteHook {foo bar}}\
627 {-accessPath * -statics 0 -nested 0 -deleteHook toto}}
628 test safe-9.7 {interpConfigure widget like behaviour (demystified)} -body {
629 # this test shall work, believed equivalent to 9.6
630 set i [safe::interpCreate \
633 -deleteHook {foo bar}]
634 safe::interpConfigure $i -accessPath /foo/bar
635 set a [safe::interpConfigure $i]
636 set b [safe::interpConfigure $i -aCCess]
637 set c [safe::interpConfigure $i -nested]
638 set d [safe::interpConfigure $i -statics]
639 set e [safe::interpConfigure $i -DEL]
640 safe::interpConfigure $i -accessPath /blah -statics 1
641 set f [safe::interpConfigure $i]
642 safe::interpConfigure $i -deleteHook toto -nosta -nested 0
643 set g [safe::interpConfigure $i]
645 list $a $b $c $d $e $f $g
647 safe::interpDelete $i
648 unset -nocomplain a b c d e f g i
649 } -match glob -result {{-accessPath * -statics 0 -nested 1 -deleteHook {foo bar}}\
650 {-accessPath *} {-nested 1} {-statics 0} {-deleteHook {foo bar}}\
651 {-accessPath * -statics 1 -nested 1 -deleteHook {foo bar}}\
652 {-accessPath * -statics 0 -nested 0 -deleteHook toto}}
653 test safe-9.8 {test autoloading commands indexed in tclIndex files} -setup {
655 set i [safe::interpCreate -accessPath [list $tcl_library \
656 [file join $TestsDir auto0 auto1] \
657 [file join $TestsDir auto0 auto2]]]
659 set confA [safe::interpConfigure $i]
660 set mappA [mapList $PathMapp [dict get $confA -accessPath]]
661 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
662 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
664 # Load and run the commands.
665 set code1 [catch {interp eval $i {report1}} msg1]
666 set code2 [catch {interp eval $i {report2}} msg2]
668 list $path1 $path2 -- $code1 $msg1 $code2 $msg2 -- $mappA
670 safe::interpDelete $i
671 } -match glob -result {{$p(:1:)} {$p(:2:)} -- 0 ok1 0 ok2 --\
672 {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*}}
673 test safe-9.9 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (dummy test of doreset)} -setup {
675 set i [safe::interpCreate -accessPath [list $tcl_library \
676 [file join $TestsDir auto0 auto1] \
677 [file join $TestsDir auto0 auto2]]]
679 set confA [safe::interpConfigure $i]
680 set mappA [mapList $PathMapp [dict get $confA -accessPath]]
681 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
682 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
684 # Load auto_load data.
685 interp eval $i {catch nonExistentCommand}
687 # Load and run the commands.
688 # This guarantees the test will pass even if the tokens are swapped.
689 set code1 [catch {interp eval $i {report1}} msg1]
690 set code2 [catch {interp eval $i {report2}} msg2]
692 # Rearrange access path. Swap tokens {$p(:1:)} and {$p(:2:)}.
693 safe::interpConfigure $i -accessPath [list $tcl_library \
694 [file join $TestsDir auto0 auto2] \
695 [file join $TestsDir auto0 auto1]]
697 set confB [safe::interpConfigure $i]
698 set mappB [mapList $PathMapp [dict get $confB -accessPath]]
699 set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
700 set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
703 set code3 [catch {interp eval $i {report1}} msg3]
704 set code4 [catch {interp eval $i {report2}} msg4]
706 list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- $mappA -- $mappB
708 safe::interpDelete $i
709 } -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} -- 0 ok1 0 ok2 --\
710 {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
711 {TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*}}
712 test safe-9.10 {interpConfigure change the access path; tclIndex commands unaffected by token rearrangement (actual test of doreset)} -setup {
714 set i [safe::interpCreate -accessPath [list $tcl_library \
715 [file join $TestsDir auto0 auto1] \
716 [file join $TestsDir auto0 auto2]]]
718 set confA [safe::interpConfigure $i]
719 set mappA [mapList $PathMapp [dict get $confA -accessPath]]
720 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
721 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
723 # Load auto_load data.
724 interp eval $i {catch nonExistentCommand}
726 # Do not load the commands. With the tokens swapped, the test
727 # will pass only if the Safe Base has called auto_reset.
729 # Rearrange access path. Swap tokens {$p(:1:)} and {$p(:2:)}.
730 safe::interpConfigure $i -accessPath [list $tcl_library \
731 [file join $TestsDir auto0 auto2] \
732 [file join $TestsDir auto0 auto1]]
734 set confB [safe::interpConfigure $i]
735 set mappB [mapList $PathMapp [dict get $confB -accessPath]]
736 set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
737 set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
739 # Load and run the commands.
740 set code3 [catch {interp eval $i {report1}} msg3]
741 set code4 [catch {interp eval $i {report2}} msg4]
743 list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- $mappA -- $mappB
745 safe::interpDelete $i
746 } -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} --\
748 {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
749 {TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*}}
750 test safe-9.11 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement} -setup {
752 # For complete correspondence to safe-9.10opt, include auto0 in access path.
753 set i [safe::interpCreate -accessPath [list $tcl_library \
754 [file join $TestsDir auto0] \
755 [file join $TestsDir auto0 auto1] \
756 [file join $TestsDir auto0 auto2]]]
758 set confA [safe::interpConfigure $i]
759 set mappA [mapList $PathMapp [dict get $confA -accessPath]]
760 set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0]]
761 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
762 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
764 # Load pkgIndex.tcl data.
765 catch {interp eval $i {package require NOEXIST}}
767 # Rearrange access path. Swap tokens {$p(:2:)} and {$p(:3:)}.
768 # This would have no effect because the records in Pkg of these directories
769 # were from access as children of {$p(:1:)}.
770 safe::interpConfigure $i -accessPath [list $tcl_library \
771 [file join $TestsDir auto0] \
772 [file join $TestsDir auto0 auto2] \
773 [file join $TestsDir auto0 auto1]]
775 set confB [safe::interpConfigure $i]
776 set mappB [mapList $PathMapp [dict get $confB -accessPath]]
777 set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
778 set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
780 # Try to load the packages and run a command from each one.
781 set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
782 set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
783 set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
784 set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]
786 list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
787 $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
789 safe::interpDelete $i
790 } -match glob -result {{$p(:2:)} {$p(:3:)} -- {$p(:3:)} {$p(:2:)} -- 0 1.2.3 0 2.3.4 --\
791 {TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
792 {TCLLIB TESTSDIR/auto0 TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
794 test safe-9.12 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement, 9.10 without path auto0} -setup {
796 set i [safe::interpCreate -accessPath [list $tcl_library \
797 [file join $TestsDir auto0 auto1] \
798 [file join $TestsDir auto0 auto2]]]
800 set confA [safe::interpConfigure $i]
801 set mappA [mapList $PathMapp [dict get $confA -accessPath]]
802 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
803 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
805 # Load pkgIndex.tcl data.
806 catch {interp eval $i {package require NOEXIST}}
808 # Rearrange access path. Swap tokens {$p(:1:)} and {$p(:2:)}.
809 safe::interpConfigure $i -accessPath [list $tcl_library \
810 [file join $TestsDir auto0 auto2] \
811 [file join $TestsDir auto0 auto1]]
813 set confB [safe::interpConfigure $i]
814 set mappB [mapList $PathMapp [dict get $confB -accessPath]]
815 set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
816 set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
818 # Try to load the packages and run a command from each one.
819 set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3 opts3]
820 set code4 [catch {interp eval $i {package require SafeTestPackage2}} msg4 opts4]
821 set code5 [catch {interp eval $i {HeresPackage1}} msg5 opts5]
822 set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]
824 list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
825 $mappA -- $mappB -- \
826 $code5 $msg5 $code6 $msg6
828 safe::interpDelete $i
829 } -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} --\
831 {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} --\
832 {TCLLIB TESTSDIR/auto0/auto2 TESTSDIR/auto0/auto1*} --\
834 test safe-9.13 {interpConfigure change the access path; pkgIndex.tcl packages fail if directory de-listed} -setup {
836 set i [safe::interpCreate -accessPath [list $tcl_library \
837 [file join $TestsDir auto0 auto1] \
838 [file join $TestsDir auto0 auto2]]]
840 set confA [safe::interpConfigure $i]
841 set mappA [mapList $PathMapp [dict get $confA -accessPath]]
842 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]]
843 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]]
845 # Load pkgIndex.tcl data.
846 catch {interp eval $i {package require NOEXIST}}
848 # Limit access path. Remove tokens {$p(:1:)} and {$p(:2:)}.
849 safe::interpConfigure $i -accessPath [list $tcl_library]
852 set confB [safe::interpConfigure $i]
853 set mappB [mapList $PathMapp [dict get $confB -accessPath]]
854 set code4 [catch {::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto1]} path4]
855 set code5 [catch {::safe::interpFindInAccessPath $i [file join $TestsDir auto0 auto2]} path5]
857 # Try to load the packages.
858 set code3 [catch {interp eval $i {package require SafeTestPackage1}} msg3]
859 set code6 [catch {interp eval $i {package require SafeTestPackage2}} msg6]
861 list $path1 $path2 -- $code4 $path4 -- $code5 $path5 -- $code3 $code6 -- \
864 safe::interpDelete $i
865 } -match glob -result {{$p(:1:)} {$p(:2:)} -- 1 {* not found in access path} --\
866 1 {* not found in access path} -- 1 1 --\
867 {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2*} -- {TCLLIB*}}
868 test safe-9.20 {check module loading} -setup {
869 set oldTm [tcl::tm::path list]
870 foreach path $oldTm {
871 tcl::tm::path remove $path
873 tcl::tm::path add [file join $TestsDir auto0 modules]
875 set i [safe::interpCreate -accessPath [list $tcl_library]]
878 set confA [safe::interpConfigure $i]
879 set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
880 set modsA [interp eval $i {tcl::tm::path list}]
881 set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
882 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
883 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
885 # Try to load the packages and run a command from each one.
886 set code0 [catch {interp eval $i {package require test0}} msg0]
887 set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
888 set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
889 set out0 [interp eval $i {test0::try0}]
890 set out1 [interp eval $i {mod1::test1::try1}]
891 set out2 [interp eval $i {mod2::test2::try2}]
893 list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
894 $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $out0 $out1 $out2
896 tcl::tm::path remove [file join $TestsDir auto0 modules]
897 foreach path [lreverse $oldTm] {
898 tcl::tm::path add $path
900 safe::interpDelete $i
901 } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
902 0 0.5 0 1.0 0 2.0 --\
903 {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
904 TESTSDIR/auto0/modules/mod2} -- res0 res1 res2}
905 # - The command safe::InterpSetConfig adds the parent's [tcl::tm::list] in
906 # tokenized form to the child's access path, and then adds all the
907 # descendants, discovered recursively by using glob.
908 # - The order of the directories in the list returned by glob is system-dependent,
909 # and therefore this is true also for (a) the order of token assignment to
910 # descendants of the [tcl::tm::list] roots; and (b) the order of those same
911 # directories in the access path. Both those things must be sorted before
912 # comparing with expected results. The test is therefore not totally strict,
913 # but will notice missing or surplus directories.
914 test safe-9.21 {interpConfigure change the access path; check module loading; stale data case 1} -setup {
915 set oldTm [tcl::tm::path list]
916 foreach path $oldTm {
917 tcl::tm::path remove $path
919 tcl::tm::path add [file join $TestsDir auto0 modules]
921 set i [safe::interpCreate -accessPath [list $tcl_library]]
924 set confA [safe::interpConfigure $i]
925 set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
926 set modsA [interp eval $i {tcl::tm::path list}]
927 set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
928 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
929 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
931 # Add to access path.
932 # This injects more tokens, pushing modules to higher token numbers.
933 safe::interpConfigure $i -accessPath [list $tcl_library \
934 [file join $TestsDir auto0 auto1] \
935 [file join $TestsDir auto0 auto2]]
937 set confB [safe::interpConfigure $i]
938 set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
939 set modsB [interp eval $i {tcl::tm::path list}]
940 set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
941 set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
942 set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
945 catch {interp eval $i {package require NOEXIST}}
946 catch {interp eval $i {package require mod1::NOEXIST}}
947 catch {interp eval $i {package require mod2::NOEXIST}}
949 # Try to load the packages and run a command from each one.
950 set code0 [catch {interp eval $i {package require test0}} msg0]
951 set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
952 set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
953 set out0 [interp eval $i {test0::try0}]
954 set out1 [interp eval $i {mod1::test1::try1}]
955 set out2 [interp eval $i {mod2::test2::try2}]
957 list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
958 [lsort [list $path3 $path4 $path5]] -- $modsB -- \
959 $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
962 tcl::tm::path remove [file join $TestsDir auto0 modules]
963 foreach path [lreverse $oldTm] {
964 tcl::tm::path add $path
966 safe::interpDelete $i
967 } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
968 {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
969 0 0.5 0 1.0 0 2.0 --\
970 {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
971 TESTSDIR/auto0/modules/mod2} --\
972 {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
973 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
975 # See comments on lsort after test safe-9.20.
976 test safe-9.22 {interpConfigure change the access path; check module loading; stale data case 0} -setup {
977 set oldTm [tcl::tm::path list]
978 foreach path $oldTm {
979 tcl::tm::path remove $path
981 tcl::tm::path add [file join $TestsDir auto0 modules]
983 set i [safe::interpCreate -accessPath [list $tcl_library]]
986 set confA [safe::interpConfigure $i]
987 set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
988 set modsA [interp eval $i {tcl::tm::path list}]
989 set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
990 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
991 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
993 # Add to access path.
994 # This injects more tokens, pushing modules to higher token numbers.
995 safe::interpConfigure $i -accessPath [list $tcl_library \
996 [file join $TestsDir auto0 auto1] \
997 [file join $TestsDir auto0 auto2]]
999 set confB [safe::interpConfigure $i]
1000 set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
1001 set modsB [interp eval $i {tcl::tm::path list}]
1002 set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
1003 set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
1004 set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
1006 # Try to load the packages and run a command from each one.
1007 set code0 [catch {interp eval $i {package require test0}} msg0]
1008 set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
1009 set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
1010 set out0 [interp eval $i {test0::try0}]
1011 set out1 [interp eval $i {mod1::test1::try1}]
1012 set out2 [interp eval $i {mod2::test2::try2}]
1014 list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
1015 [lsort [list $path3 $path4 $path5]] -- $modsB -- \
1016 $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
1019 tcl::tm::path remove [file join $TestsDir auto0 modules]
1020 foreach path [lreverse $oldTm] {
1021 tcl::tm::path add $path
1023 safe::interpDelete $i
1024 } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
1025 {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
1026 0 0.5 0 1.0 0 2.0 --\
1027 {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
1028 TESTSDIR/auto0/modules/mod2} --\
1029 {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
1030 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
1032 # See comments on lsort after test safe-9.20.
1033 test safe-9.23 {interpConfigure change the access path; check module loading; stale data case 3} -setup {
1034 set oldTm [tcl::tm::path list]
1035 foreach path $oldTm {
1036 tcl::tm::path remove $path
1038 tcl::tm::path add [file join $TestsDir auto0 modules]
1040 set i [safe::interpCreate -accessPath [list $tcl_library]]
1043 set confA [safe::interpConfigure $i]
1044 set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
1045 set modsA [interp eval $i {tcl::tm::path list}]
1046 set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
1047 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
1048 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
1050 # Force the interpreter to acquire pkg data which will soon become stale.
1051 catch {interp eval $i {package require NOEXIST}}
1052 catch {interp eval $i {package require mod1::NOEXIST}}
1053 catch {interp eval $i {package require mod2::NOEXIST}}
1055 # Add to access path.
1056 # This injects more tokens, pushing modules to higher token numbers.
1057 safe::interpConfigure $i -accessPath [list $tcl_library \
1058 [file join $TestsDir auto0 auto1] \
1059 [file join $TestsDir auto0 auto2]]
1061 set confB [safe::interpConfigure $i]
1062 set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
1063 set modsB [interp eval $i {tcl::tm::path list}]
1064 set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
1065 set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
1066 set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
1068 # Refresh stale pkg data.
1069 catch {interp eval $i {package require NOEXIST}}
1070 catch {interp eval $i {package require mod1::NOEXIST}}
1071 catch {interp eval $i {package require mod2::NOEXIST}}
1073 # Try to load the packages and run a command from each one.
1074 set code0 [catch {interp eval $i {package require test0}} msg0]
1075 set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
1076 set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
1077 set out0 [interp eval $i {test0::try0}]
1078 set out1 [interp eval $i {mod1::test1::try1}]
1079 set out2 [interp eval $i {mod2::test2::try2}]
1081 list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
1082 [lsort [list $path3 $path4 $path5]] -- $modsB -- \
1083 $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
1086 tcl::tm::path remove [file join $TestsDir auto0 modules]
1087 foreach path [lreverse $oldTm] {
1088 tcl::tm::path add $path
1090 safe::interpDelete $i
1091 } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
1092 {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
1093 0 0.5 0 1.0 0 2.0 --\
1094 {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
1095 TESTSDIR/auto0/modules/mod2} --\
1096 {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
1097 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
1099 # See comments on lsort after test safe-9.20.
1100 test safe-9.24 {interpConfigure change the access path; check module loading; stale data case 2 (worst case)} -setup {
1101 set oldTm [tcl::tm::path list]
1102 foreach path $oldTm {
1103 tcl::tm::path remove $path
1105 tcl::tm::path add [file join $TestsDir auto0 modules]
1107 set i [safe::interpCreate -accessPath [list $tcl_library]]
1110 set confA [safe::interpConfigure $i]
1111 set sortA [mapAndSortList $PathMapp [dict get $confA -accessPath]]
1112 set modsA [interp eval $i {tcl::tm::path list}]
1113 set path0 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
1114 set path1 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
1115 set path2 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
1117 # Force the interpreter to acquire pkg data which will soon become stale.
1118 catch {interp eval $i {package require NOEXIST}}
1119 catch {interp eval $i {package require mod1::NOEXIST}}
1120 catch {interp eval $i {package require mod2::NOEXIST}}
1122 # Add to access path.
1123 # This injects more tokens, pushing modules to higher token numbers.
1124 safe::interpConfigure $i -accessPath [list $tcl_library \
1125 [file join $TestsDir auto0 auto1] \
1126 [file join $TestsDir auto0 auto2]]
1128 set confB [safe::interpConfigure $i]
1129 set sortB [mapAndSortList $PathMapp [dict get $confB -accessPath]]
1130 set modsB [interp eval $i {tcl::tm::path list}]
1131 set path3 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules]]
1132 set path4 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod1]]
1133 set path5 [::safe::interpFindInAccessPath $i [file join $TestsDir auto0 modules mod2]]
1135 # Try to load the packages and run a command from each one.
1136 set code0 [catch {interp eval $i {package require test0}} msg0]
1137 set code1 [catch {interp eval $i {package require mod1::test1}} msg1]
1138 set code2 [catch {interp eval $i {package require mod2::test2}} msg2]
1139 set out0 [interp eval $i {test0::try0}]
1140 set out1 [interp eval $i {mod1::test1::try1}]
1141 set out2 [interp eval $i {mod2::test2::try2}]
1143 list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
1144 [lsort [list $path3 $path4 $path5]] -- $modsB -- \
1145 $code0 $msg0 $code1 $msg1 $code2 $msg2 -- $sortA -- $sortB -- \
1148 tcl::tm::path remove [file join $TestsDir auto0 modules]
1149 foreach path [lreverse $oldTm] {
1150 tcl::tm::path add $path
1152 safe::interpDelete $i
1153 } -match glob -result {{{$p(:1:)} {$p(:2:)} {$p(:3:)}} -- {{$p(:1:)}} --\
1154 {{$p(:3:)} {$p(:4:)} {$p(:5:)}} -- {{$p(:3:)}} --\
1155 0 0.5 0 1.0 0 2.0 --\
1156 {TCLLIB TESTSDIR/auto0/modules TESTSDIR/auto0/modules/mod1\
1157 TESTSDIR/auto0/modules/mod2} --\
1158 {TCLLIB TESTSDIR/auto0/auto1 TESTSDIR/auto0/auto2 TESTSDIR/auto0/modules\
1159 TESTSDIR/auto0/modules/mod1 TESTSDIR/auto0/modules/mod2} --\
1161 # See comments on lsort after test safe-9.20.
1163 catch {teststaticpkg Safepkg1 0 0}
1164 test safe-10.1 {testing statics loading} -constraints TcltestPackage -setup {
1165 set i [safe::interpCreate]
1167 interp eval $i {load {} Safepkg1}
1168 } -returnCodes error -cleanup {
1169 safe::interpDelete $i
1170 } -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure}
1171 test safe-10.1.1 {testing statics loading} -constraints TcltestPackage -setup {
1172 set i [safe::interpCreate]
1174 catch {interp eval $i {load {} Safepkg1}} m o
1175 dict get $o -errorinfo
1176 } -returnCodes ok -cleanup {
1177 unset -nocomplain m o
1178 safe::interpDelete $i
1179 } -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure
1183 "interp eval $i {load {} Safepkg1}"}
1184 test safe-10.2 {testing statics loading / -nostatics} -constraints TcltestPackage -body {
1185 set i [safe::interpCreate -nostatics]
1186 interp eval $i {load {} Safepkg1}
1187 } -returnCodes error -cleanup {
1188 safe::interpDelete $i
1189 } -result {permission denied (static package)}
1190 test safe-10.3 {testing nested statics loading / no nested by default} -setup {
1191 set i [safe::interpCreate]
1192 } -constraints TcltestPackage -body {
1193 interp eval $i {interp create x; load {} Safepkg1 x}
1194 } -returnCodes error -cleanup {
1195 safe::interpDelete $i
1196 } -result {permission denied (nested load)}
1197 test safe-10.4 {testing nested statics loading / -nestedloadok} -constraints TcltestPackage -body {
1198 set i [safe::interpCreate -nestedloadok]
1199 interp eval $i {interp create x; load {} Safepkg1 x}
1200 } -returnCodes error -cleanup {
1201 safe::interpDelete $i
1202 } -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure}
1203 test safe-10.4.1 {testing nested statics loading / -nestedloadok} -constraints TcltestPackage -body {
1204 set i [safe::interpCreate -nestedloadok]
1205 catch {interp eval $i {interp create x; load {} Safepkg1 x}} m o
1206 dict get $o -errorinfo
1207 } -returnCodes ok -cleanup {
1208 unset -nocomplain m o
1209 safe::interpDelete $i
1210 } -result {load of binary library for package Safepkg1 failed: can't use package in a safe interpreter: no Safepkg1_SafeInit procedure
1212 "load {} Safepkg1 x"
1214 "interp eval $i {interp create x; load {} Safepkg1 x}"}
1216 test safe-11.1 {testing safe encoding} -setup {
1217 set i [safe::interpCreate]
1219 interp eval $i encoding
1220 } -returnCodes error -cleanup {
1221 safe::interpDelete $i
1222 } -result {wrong # args: should be "encoding option ?arg ...?"}
1223 test safe-11.1a {testing safe encoding} -setup {
1224 set i [safe::interpCreate]
1226 interp eval $i encoding foobar
1227 } -returnCodes error -cleanup {
1228 safe::interpDelete $i
1229 } -match glob -result {bad option "foobar": must be *}
1230 test safe-11.2 {testing safe encoding} -setup {
1231 set i [safe::interpCreate]
1233 interp eval $i encoding system cp775
1234 } -returnCodes error -cleanup {
1235 safe::interpDelete $i
1236 } -result {wrong # args: should be "encoding system"}
1237 test safe-11.3 {testing safe encoding} -setup {
1238 set i [safe::interpCreate]
1240 interp eval $i encoding system
1242 safe::interpDelete $i
1243 } -result [encoding system]
1244 test safe-11.4 {testing safe encoding} -setup {
1245 set i [safe::interpCreate]
1247 interp eval $i encoding names
1249 safe::interpDelete $i
1250 } -result [encoding names]
1251 test safe-11.5 {testing safe encoding} -setup {
1252 set i [safe::interpCreate]
1254 interp eval $i encoding convertfrom cp1258 foobar
1256 safe::interpDelete $i
1258 test safe-11.6 {testing safe encoding} -setup {
1259 set i [safe::interpCreate]
1261 interp eval $i encoding convertto cp1258 foobar
1263 safe::interpDelete $i
1265 test safe-11.7 {testing safe encoding} -setup {
1266 set i [safe::interpCreate]
1268 interp eval $i encoding convertfrom
1269 } -returnCodes error -cleanup {
1270 safe::interpDelete $i
1271 } -result {wrong # args: should be "encoding convertfrom ?encoding? data"}
1272 test safe-11.7.1 {testing safe encoding} -setup {
1273 set i [safe::interpCreate]
1275 catch {interp eval $i encoding convertfrom} m o
1276 dict get $o -errorinfo
1277 } -returnCodes ok -match glob -cleanup {
1278 unset -nocomplain m o
1279 safe::interpDelete $i
1280 } -result {wrong # args: should be "encoding convertfrom ?encoding? data"
1282 "encoding convertfrom"
1284 "::interp invokehidden interp* encoding convertfrom"
1286 "encoding convertfrom"
1288 "interp eval $i encoding convertfrom"}
1289 test safe-11.8 {testing safe encoding} -setup {
1290 set i [safe::interpCreate]
1292 interp eval $i encoding convertto
1293 } -returnCodes error -cleanup {
1294 safe::interpDelete $i
1295 } -result {wrong # args: should be "encoding convertto ?encoding? data"}
1296 test safe-11.8.1 {testing safe encoding} -setup {
1297 set i [safe::interpCreate]
1299 catch {interp eval $i encoding convertto} m o
1300 dict get $o -errorinfo
1301 } -returnCodes ok -match glob -cleanup {
1302 unset -nocomplain m o
1303 safe::interpDelete $i
1304 } -result {wrong # args: should be "encoding convertto ?encoding? data"
1306 "encoding convertto"
1308 "::interp invokehidden interp* encoding convertto"
1310 "encoding convertto"
1312 "interp eval $i encoding convertto"}
1314 test safe-12.1 {glob is restricted [Bug 2906841]} -setup {
1315 set i [safe::interpCreate]
1318 } -returnCodes error -cleanup {
1319 safe::interpDelete $i
1320 } -result "permission denied"
1321 test safe-12.2 {glob is restricted [Bug 2906841]} -setup {
1322 set i [safe::interpCreate]
1324 $i eval glob -directory .. *
1325 } -returnCodes error -cleanup {
1326 safe::interpDelete $i
1327 } -result "permission denied"
1328 test safe-12.3 {glob is restricted [Bug 2906841]} -setup {
1329 set i [safe::interpCreate]
1331 $i eval glob -join .. *
1332 } -returnCodes error -cleanup {
1333 safe::interpDelete $i
1334 } -result "permission denied"
1335 test safe-12.4 {glob is restricted [Bug 2906841]} -setup {
1336 set i [safe::interpCreate]
1338 $i eval glob -nocomplain ../*
1340 safe::interpDelete $i
1342 test safe-12.5 {glob is restricted [Bug 2906841]} -setup {
1343 set i [safe::interpCreate]
1345 $i eval glob -directory .. -nocomplain *
1347 safe::interpDelete $i
1349 test safe-12.6 {glob is restricted [Bug 2906841]} -setup {
1350 set i [safe::interpCreate]
1352 $i eval glob -nocomplain -join .. *
1354 safe::interpDelete $i
1356 test safe-12.7 {glob is restricted} -setup {
1357 set i [safe::interpCreate]
1360 } -returnCodes error -cleanup {
1361 safe::interpDelete $i
1362 } -result {permission denied}
1364 proc buildEnvironment {filename} {
1365 upvar 1 testdir testdir testdir2 testdir2 testfile testfile
1366 set testdir [makeDirectory deletethisdir]
1367 set testdir2 [makeDirectory deletemetoo $testdir]
1368 set testfile [makeFile {} $filename $testdir2]
1370 proc buildEnvironment2 {filename} {
1371 upvar 1 testdir testdir testdir2 testdir2 testfile testfile
1372 upvar 1 testdir3 testdir3 testfile2 testfile2
1373 set testdir [makeDirectory deletethisdir]
1374 set testdir2 [makeDirectory deletemetoo $testdir]
1375 set testfile [makeFile {} $filename $testdir2]
1376 set testdir3 [makeDirectory deleteme $testdir]
1377 set testfile2 [makeFile {} $filename $testdir3]
1379 #### New tests for Safe base glob, with patches @ Bug 2964715
1380 test safe-13.1 {glob is restricted [Bug 2964715]} -setup {
1381 set i [safe::interpCreate]
1384 } -returnCodes error -cleanup {
1385 safe::interpDelete $i
1386 } -result {permission denied}
1387 test safe-13.2 {mimic the valid glob call by ::tcl::tm::UnknownHandler [Bug 2964715]} -setup {
1388 set i [safe::interpCreate]
1389 buildEnvironment deleteme.tm
1391 ::safe::interpAddToAccessPath $i $testdir2
1392 set result [$i eval glob -nocomplain -directory $testdir2 *.tm]
1393 if {$result eq [list $testfile]} {
1396 return "no match: $result"
1399 safe::interpDelete $i
1400 removeDirectory $testdir
1401 } -result {glob match}
1402 test safe-13.3 {cf 13.2 but test glob failure when -directory is outside access path [Bug 2964715]} -setup {
1403 set i [safe::interpCreate]
1404 buildEnvironment deleteme.tm
1406 $i eval glob -directory $testdir2 *.tm
1407 } -returnCodes error -cleanup {
1408 safe::interpDelete $i
1409 removeDirectory $testdir
1410 } -result {permission denied}
1411 test safe-13.4 {another valid glob call [Bug 2964715]} -setup {
1412 set i [safe::interpCreate]
1413 buildEnvironment deleteme.tm
1415 ::safe::interpAddToAccessPath $i $testdir
1416 ::safe::interpAddToAccessPath $i $testdir2
1417 set result [$i eval \
1418 glob -nocomplain -directory $testdir [file join deletemetoo *.tm]]
1419 if {$result eq [list $testfile]} {
1422 return "no match: $result"
1425 safe::interpDelete $i
1426 removeDirectory $testdir
1427 } -result {glob match}
1428 test safe-13.5 {as 13.4 but test glob failure when -directory is outside access path [Bug 2964715]} -setup {
1429 set i [safe::interpCreate]
1430 buildEnvironment deleteme.tm
1432 ::safe::interpAddToAccessPath $i $testdir2
1434 glob -directory $testdir [file join deletemetoo *.tm]
1435 } -returnCodes error -cleanup {
1436 safe::interpDelete $i
1437 removeDirectory $testdir
1438 } -result {permission denied}
1439 test safe-13.6 {as 13.4 but test silent failure when result is outside access_path [Bug 2964715]} -setup {
1440 set i [safe::interpCreate]
1441 buildEnvironment deleteme.tm
1443 ::safe::interpAddToAccessPath $i $testdir
1445 glob -nocomplain -directory $testdir [file join deletemetoo *.tm]
1447 safe::interpDelete $i
1448 removeDirectory $testdir
1450 test safe-13.7 {mimic the glob call by tclPkgUnknown in a safe interpreter [Bug 2964715]} -setup {
1451 set i [safe::interpCreate]
1452 buildEnvironment pkgIndex.tcl
1454 set safeTD [::safe::interpAddToAccessPath $i $testdir]
1455 ::safe::interpAddToAccessPath $i $testdir2
1456 mapList [list $safeTD EXPECTED] [$i eval [list \
1457 glob -directory $safeTD -join * pkgIndex.tcl]]
1459 safe::interpDelete $i
1460 removeDirectory $testdir
1461 } -result {EXPECTED/deletemetoo/pkgIndex.tcl}
1462 test safe-13.7.1 {mimic the glob call by tclPkgUnknown in a safe interpreter with multiple subdirectories} -setup {
1463 set i [safe::interpCreate]
1464 buildEnvironment2 pkgIndex.tcl
1466 set safeTD [::safe::interpAddToAccessPath $i $testdir]
1467 ::safe::interpAddToAccessPath $i $testdir2
1468 ::safe::interpAddToAccessPath $i $testdir3
1469 mapAndSortList [list $safeTD EXPECTED] [$i eval [list \
1470 glob -directory $safeTD -join * pkgIndex.tcl]]
1472 safe::interpDelete $i
1473 removeDirectory $testdir
1474 } -result {EXPECTED/deleteme/pkgIndex.tcl EXPECTED/deletemetoo/pkgIndex.tcl}
1475 # See comments on lsort after test safe-9.20.
1476 test safe-13.8 {mimic the glob call by tclPkgUnknown without the special treatment that is specific to pkgIndex.tcl [Bug 2964715]} -setup {
1477 set i [safe::interpCreate]
1478 buildEnvironment notIndex.tcl
1480 set safeTD [::safe::interpAddToAccessPath $i $testdir]
1481 ::safe::interpAddToAccessPath $i $testdir2
1482 $i eval [list glob -directory $safeTD -join -nocomplain * notIndex.tcl]
1484 safe::interpDelete $i
1485 removeDirectory $testdir
1487 test safe-13.9 {as 13.8 but test glob failure when -directory is outside access path [Bug 2964715]} -setup {
1488 set i [safe::interpCreate]
1489 buildEnvironment notIndex.tcl
1491 ::safe::interpAddToAccessPath $i $testdir2
1492 set result [$i eval \
1493 glob -directory $testdir -join -nocomplain * notIndex.tcl]
1494 if {$result eq [list $testfile]} {
1497 return "no match: $result"
1500 safe::interpDelete $i
1501 removeDirectory $testdir
1502 } -result {no match: }
1503 test safe-13.10 {as 13.8 but test silent failure when result is outside access_path [Bug 2964715]} -setup {
1504 set i [safe::interpCreate]
1505 buildEnvironment notIndex.tcl
1507 ::safe::interpAddToAccessPath $i $testdir
1508 $i eval glob -directory $testdir -join -nocomplain * notIndex.tcl
1510 safe::interpDelete $i
1511 removeDirectory $testdir
1513 rename buildEnvironment {}
1514 rename buildEnvironment2 {}
1516 #### Test for the module path
1517 test safe-14.1 {Check that module path is the same as in the parent interpreter [Bug 2964715]} -setup {
1518 set i [safe::interpCreate]
1521 foreach token [$i eval ::tcl::tm::path list] {
1522 lappend tm [dict get [set ::safe::S${i}(access_path,map)] $token]
1526 safe::interpDelete $i
1527 } -result [::tcl::tm::path list]
1529 test safe-15.1 {safe file ensemble does not surprise code} -setup {
1530 set i [interp create -safe]
1532 set result [expr {"file" in [interp hidden $i]}]
1533 lappend result [interp eval $i {tcl::file::split a/b/c}]
1534 lappend result [catch {interp eval $i {tcl::file::isdirectory .}}]
1535 lappend result [interp invokehidden $i file split a/b/c]
1536 lappend result [catch {interp eval $i {file split a/b/c}} msg] $msg
1537 lappend result [catch {interp invokehidden $i file isdirectory .}]
1538 interp expose $i file
1539 lappend result [catch {interp eval $i {file split a/b/c}} msg] $msg
1540 lappend result [catch {interp eval $i {file isdirectory .}} msg] $msg
1542 unset -nocomplain msg
1544 } -result {1 {a b c} 1 {a b c} 1 {invalid command name "file"} 1 0 {a b c} 1 {not allowed to invoke subcommand isdirectory of file}}
1545 test safe-15.2 {safe file ensemble does not surprise code} -setup {
1546 set i [interp create -safe]
1548 set result [expr {"file" in [interp hidden $i]}]
1549 lappend result [interp eval $i {tcl::file::split a/b/c}]
1550 lappend result [catch {interp eval $i {tcl::file::isdirectory .}}]
1551 lappend result [interp invokehidden $i file split a/b/c]
1552 lappend result [catch {interp eval $i {file split a/b/c}} msg] $msg
1553 lappend result [catch {interp invokehidden $i file isdirectory .}]
1554 interp expose $i file
1555 lappend result [catch {interp eval $i {file split a/b/c}} msg] $msg
1556 lappend result [catch {interp eval $i {file isdirectory .}} msg o] [dict get $o -errorinfo]
1558 unset -nocomplain msg o
1560 } -result {1 {a b c} 1 {a b c} 1 {invalid command name "file"} 1 0 {a b c} 1 {not allowed to invoke subcommand isdirectory of file
1562 "file isdirectory ."
1564 "interp eval $i {file isdirectory .}"}}
1566 ### ~ should have no special meaning in paths in safe interpreters
1567 test safe-16.1 {Bug 3529949: defang ~ in paths} -setup {
1568 set savedHOME $env(HOME)
1569 set env(HOME) /foo/bar
1570 set i [safe::interpCreate]
1573 set d [format %c 126]
1574 list [file join [file dirname $d] [file tail $d]]
1577 safe::interpDelete $i
1578 set env(HOME) $savedHOME
1581 test safe-16.2 {Bug 3529949: defang ~user in paths} -setup {
1582 set i [safe::interpCreate]
1583 set user $tcl_platform(user)
1585 string map [list $user USER] [$i eval \
1586 "file join \[file dirname ~$user\] \[file tail ~$user\]"]
1588 safe::interpDelete $i
1591 test safe-16.3 {Bug 3529949: defang ~ in globs} -setup {
1592 set syntheticHOME [makeDirectory foo]
1593 makeFile {} bar $syntheticHOME
1594 set savedHOME $env(HOME)
1595 set env(HOME) $syntheticHOME
1596 set i [safe::interpCreate]
1598 ::safe::interpAddToAccessPath $i $syntheticHOME
1599 $i eval {glob -nocomplain ~/*}
1601 safe::interpDelete $i
1602 set env(HOME) $savedHOME
1603 removeDirectory $syntheticHOME
1604 unset savedHOME syntheticHOME
1606 test safe-16.4 {Bug 3529949: defang ~user in globs} -setup {
1607 set i [safe::interpCreate]
1609 ::safe::interpAddToAccessPath $i $~$tcl_platform(user)
1610 $i eval [list glob -nocomplain ~$tcl_platform(user)/*]
1612 safe::interpDelete $i
1614 test safe-16.5 {Bug 3529949: defang ~ in paths used by AliasGlob (1)} -setup {
1615 set savedHOME $env(HOME)
1616 set env(HOME) /foo/bar
1617 set i [safe::interpCreate]
1620 set d [format %c 126]
1621 file join {$p(:0:)} $d
1624 safe::interpDelete $i
1625 set env(HOME) $savedHOME
1628 test safe-16.6 {Bug 3529949: defang ~ in paths used by AliasGlob (2)} -setup {
1629 set savedHOME $env(HOME)
1630 set env(HOME) /foo/bar
1631 set i [safe::interpCreate]
1634 set d [format %c 126]
1635 file join {$p(:0:)/foo/bar} $d
1638 safe::interpDelete $i
1639 set env(HOME) $savedHOME
1642 test safe-16.7 {Bug 3529949: defang ~user in paths used by AliasGlob (1)} -setup {
1643 set i [safe::interpCreate]
1644 set user $tcl_platform(user)
1646 string map [list $user USER] [$i eval [list file join {$p(:0:)} ~$user]]
1648 safe::interpDelete $i
1651 test safe-16.8 {Bug 3529949: defang ~user in paths used by AliasGlob (2)} -setup {
1652 set i [safe::interpCreate]
1653 set user $tcl_platform(user)
1655 string map [list $user USER] [$i eval [list file join {$p(:0:)/foo/bar} ~$user]]
1657 safe::interpDelete $i
1662 set ::auto_path $SaveAutoPath
1663 unset SaveAutoPath TestsDir PathMapp
1664 unset -nocomplain path
1666 rename mapAndSortList {}
1667 ::tcltest::cleanupTests