summaryrefslogtreecommitdiffstats
path: root/tests/safe-stock.test
blob: d23d86ef127e37d9b63fc555df09d829d5f789b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# safe-stock.test --
#
# This file contains tests for safe Tcl that were previously in the file
# safe.test, and use files and packages of stock Tcl 8.7 to perform the tests.
# These files may be changed or disappear in future revisions of Tcl, for
# example package opt will eventually be removed.
#
# The tests are replaced in safe.tcl with tests that use files provided in the
# tests directory.  Test numbering is for comparison with similar tests in
# safe.test.
#
# Sourcing this file into tcl runs the tests and generates output for errors.
# No output means no errors were found.
#
# The defunct package http 1.0 was convenient for testing package loading.
# - This file, safe-stock.test, uses packages opt and (from cookiejar)
#   tcl::idna to provide alternative tests based on stock Tcl packages.
#   - These are tests 7.1 7.2 7.4 9.11 9.13
#   - Tests 7.[124], 9.1[13] use "package require opt".
#   - Tests 9.1[13] also use "package require tcl::idna".
# - The corresponding tests in safe.test use example packages provided in
#   subdirectory auto0 of the tests directory, which are independent of any
#   changes made to the packages provided with Tcl.
#
# Copyright © 1995-1996 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::*
}

foreach i [interp children] {
    interp delete $i
}

# When using package opt for testing positive/negative package search:
# - The directory location and the error message depend on whether
#   and how the package is installed.

# Error message for test 7.2 for "package require opt".
if {[string match *zipfs:/* [info library]]} {
    # pkgIndex.tcl is in [info library]
    # file to be sourced is in [info library]/opt*
    set pkgOptErrMsg {permission denied}
} else {
    # pkgIndex.tcl and file to be sourced are
    # both in [info library]/opt*
    set pkgOptErrMsg {can't find package opt}
}

# Directory of opt for tests 7.4, 9.10, 9.12 for "package require opt".
if {[file exists [file join [info library] opt0.4]]} {
    # Installed files in lib8.7/opt0.4
    set pkgOptDir opt0.4
} elseif {[file exists [file join [info library] opt]]} {
    # Installed files in zipfs, or source files used by "make test"
    set pkgOptDir opt
} else {
    error {cannot find opt library}
}

# Directory of cookiejar for tests 9.10, 9.12 for "package require tcl::idna".
if {[file exists [file join [info library] cookiejar0.2]]} {
    # Installed files in lib8.7/cookiejar0.2
    set pkgJarDir cookiejar0.2
} elseif {[file exists [file join [info library] cookiejar]]} {
    # Installed files in zipfs, or source files used by "make test"
    set pkgJarDir cookiejar
} else {
    error {cannot find cookiejar library}
}

set SaveAutoPath $::auto_path
set ::auto_path [info library]
set TestsDir [file normalize [file dirname [info script]]]
set PathMapp {}
lappend PathMapp [file join [info library] $pkgOptDir] TCLLIB/OPTDIR
lappend PathMapp [file join [info library] $pkgJarDir] TCLLIB/JARDIR
lappend PathMapp $tcl_library TCLLIB $TestsDir TESTSDIR

proc mapList {map listIn} {
    set listOut {}
    foreach element $listIn {
        lappend listOut [string map $map $element]
    }
    return $listOut
}
proc mapAndSortList {map listIn} {
    set listOut {}
    foreach element $listIn {
        lappend listOut [string map $map $element]
    }
    lsort $listOut
}

# Force actual loading of the safe package because we use un-exported (and
# thus un-autoindexed) APIs in this test result arguments:
catch {safe::interpConfigure}

testConstraint AutoSyncDefined 1

# high level general test
test safe-stock-7.1 {tests that everything works at high level with conventional AutoPathSync, use pkg opt} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 1
    }
    set i [safe::interpCreate]
} -body {
    # no error shall occur:
    # (because the default access_path shall include 1st level sub dirs so
    #  package require in a child works like in the parent)
    set v [interp eval $i {package require opt}]
    # no error shall occur:
    interp eval $i {::tcl::Lempty {a list}}
    set v
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
        safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result 0.4.*
test safe-stock-7.2 {tests specific path and interpFind/AddToAccessPath with conventional AutoPathSync, use pkg opt} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 1
    } else {
        set SyncVal_TMP 1
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
    # an error shall occur (opt is not anymore in the secure 0-level
    # provided deep path)
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    list $token1 $token2 -- \
	    [catch {interp eval $i {package require opt}} msg] $msg -- \
	    $mappA -- [safe::interpDelete $i]
} -cleanup {
    if {$SyncExists} {
        safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result "{\$p(:0:)} {\$p(:*:)} -- 1 {$pkgOptErrMsg} --\
        {TCLLIB */dummy/unixlike/test/path} -- {}"
test safe-stock-7.4 {tests specific path and positive search with conventional AutoPathSync, use pkg opt} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 1
    } else {
        set SyncVal_TMP 1
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i [file join [info library] $pkgOptDir]]
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    # this time, unlike test safe-stock-7.2, opt should be found
    list $token1 $token2 -- \
            [catch {interp eval $i {package require opt}} msg] $msg -- \
            $mappA -- [safe::interpDelete $i]
    # Note that the glob match elides directories (those from the module path)
    # other than the first and last in the access path.
} -cleanup {
    if {$SyncExists} {
        safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:0:)} {$p(:*:)} -- 0 0.4.* --\
        {TCLLIB * TCLLIB/OPTDIR} -- {}}
test safe-stock-7.5 {tests positive and negative module loading with conventional AutoPathSync} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 1
    }
    set i [safe::interpCreate]
    interp eval $i {
        package forget platform::shell
        package forget platform
        catch {namespace delete ::platform}
    }
} -body {
    # Should raise an error (module ancestor directory issue)
    set code1 [catch {interp eval $i {package require shell}} msg1]
    # Should not raise an error
    set code2 [catch {interp eval $i {package require platform::shell}} msg2]
    return [list $code1 $msg1 $code2]
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
        safe::setSyncMode $SyncVal_TMP
    }
} -result {1 {can't find package shell} 0}

# The following test checks whether the definition of tcl_endOfWord can be
# obtained from auto_loading.  It was previously test "safe-5.1".
test safe-stock-9.8 {test auto-loading in safe interpreters, was safe-5.1} -setup {
    catch {safe::interpDelete a}
    safe::interpCreate a
} -body {
    interp eval a {tcl_endOfWord "" 0}
} -cleanup {
    safe::interpDelete a
} -result -1
test safe-stock-9.11 {interpConfigure change the access path; pkgIndex.tcl packages unaffected by token rearrangement with conventional AutoPathSync, uses pkg opt and tcl::idna} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 1
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $tcl_library $pkgOptDir] \
                                            [file join $tcl_library $pkgJarDir]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgOptDir]]
    set path2 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgJarDir]]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Rearrange access path.  Swap tokens {$p(:1:)} and {$p(:2:)}.
    # This has no effect because the records in Pkg of these directories were from access as children of {$p(:0:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library \
                                           [file join $tcl_library $pkgJarDir] \
                                           [file join $tcl_library $pkgOptDir]]
    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set path3 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgOptDir]]
    set path4 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgJarDir]]

    # Try to load the packages and run a command from each one.
    set code3 [catch {interp eval $i {package require tcl::idna}} msg3]
    set code4 [catch {interp eval $i {package require opt}} msg4]
    set code5 [catch {interp eval $i {::tcl::Lempty {a list}}} msg5]
    set code6 [catch {interp eval $i {::tcl::idna::IDNAencode example.com}} msg6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
         $mappA -- $mappB -- $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
        safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- {$p(:2:)} {$p(:1:)} -- 0 1.* 0 0.4.* --\
        {TCLLIB TCLLIB/OPTDIR TCLLIB/JARDIR*} --\
        {TCLLIB TCLLIB/JARDIR TCLLIB/OPTDIR*} --\
        0 0 0 example.com}
test safe-stock-9.13 {interpConfigure change the access path; pkgIndex.tcl packages fail if directory de-listed with conventional AutoPathSync, uses pkg opt and tcl::idna} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 1
    }
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $tcl_library $pkgOptDir] \
                                            [file join $tcl_library $pkgJarDir]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
    set path1 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgOptDir]]
    set path2 [::safe::interpFindInAccessPath $i [file join $tcl_library $pkgJarDir]]

    # Load pkgIndex.tcl data.
    catch {interp eval $i {package require NOEXIST}}

    # Limit access path.  Remove tokens {$p(:1:)} and {$p(:2:)}.
    safe::interpConfigure $i -accessPath [list $tcl_library]

    # Inspect.
    set confB [safe::interpConfigure $i]
    set mappB [mapList $PathMapp [dict get $confB -accessPath]]
    set code4 [catch {::safe::interpFindInAccessPath $i [file join $tcl_library $pkgOptDir]} path4]
    set code5 [catch {::safe::interpFindInAccessPath $i [file join $tcl_library $pkgJarDir]} path5]

    # Try to load the packages.
    set code3 [catch {interp eval $i {package require opt}} msg3]
    set code6 [catch {interp eval $i {package require tcl::idna}} msg6]

    list $path1 $path2 -- $code4 $path4 -- $code5 $path5 -- $code3 $code6 -- \
            $mappA -- $mappB
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
        safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result {{$p(:1:)} {$p(:2:)} -- 1 {* not found in access path} --\
        1 {* not found in access path} -- 1 1 --\
        {TCLLIB TCLLIB/OPTDIR TCLLIB/JARDIR*} -- {TCLLIB*}}

test safe-stock-18.1 {cf. safe-stock-7.1opt - tests that everything works at high level without conventional AutoPathSync, use pkg opt} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 0
    } else {
        error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    # Without AutoPathSync, we need a more complete auto_path,
    # because the child will use the same value.
    set lib1        [info library]
    set lib2        [file dirname $lib1]
    set ::auto_TMP  $::auto_path
    set ::auto_path [list $lib1 $lib2]

    set i [safe::interpCreate]
    set ::auto_path $::auto_TMP
} -body {
    # no error shall occur:
    # (because the default access_path shall include 1st level sub dirs so
    #  package require in a child works like in the parent)
    set v [interp eval $i {package require opt}]
    # no error shall occur:
    interp eval $i {::tcl::Lempty {a list}}
    set v
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
        safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result 0.4.*
test safe-stock-18.2 {cf. safe-stock-7.2opt - tests specific path and interpFind/AddToAccessPath without conventional AutoPathSync, use pkg opt} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 0
    } else {
        error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]
    set auto1 [interp eval $i {set ::auto_path}]
    # This will differ from the value -autoPath {}
    interp eval $i {set ::auto_path [list {$p(:0:)}]}
    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]
    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i "/dummy/unixlike/test/path"]
    # an error shall occur (opt is not anymore in the secure 0-level
    # provided deep path)
    list $auto1 $token1 $token2 \
	    [catch {interp eval $i {package require opt}} msg] $msg \
	    [safe::interpConfigure $i]\
	    [safe::interpDelete $i]
} -cleanup {
    if {$SyncExists} {
        safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result "{} {\$p(:0:)} {\$p(:*:)} 1 {$pkgOptErrMsg}\
        {-accessPath {[list $tcl_library */dummy/unixlike/test/path]}\
        -statics 0 -nested 1 -deleteHook {} -autoPath {}} {}"
test safe-stock-18.4 {cf. safe-stock-7.4opt - tests specific path and positive search and auto_path without conventional AutoPathSync, use pkg opt} -constraints AutoSyncDefined -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 0
    } else {
        error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
} -body {
    set i [safe::interpCreate -nostat -nested 1 -accessPath [list [info library]]]

    # should not have been set by Safe Base:
    set auto1 [interp eval $i {set ::auto_path}]

    # This will differ from the value -autoPath {}
    interp eval $i {set ::auto_path [list {$p(:0:)}]}

    # should not add anything (p0)
    set token1 [safe::interpAddToAccessPath $i [info library]]

    # should add as p* (not p1 if parent has a module path)
    set token2 [safe::interpAddToAccessPath $i [file join [info library] $pkgOptDir]]

    # should not have been changed by Safe Base:
    set auto2 [interp eval $i {set ::auto_path}]

    # This time, unlike test safe-stock-18.2opt and the try above, opt should be found:
    list $auto1 $auto2 $token1 $token2 \
	    [catch {interp eval $i {package require opt}} msg] $msg \
	    [safe::interpConfigure $i]\
	    [safe::interpDelete $i]
} -cleanup {
    if {$SyncExists} {
	safe::setSyncMode $SyncVal_TMP
    }
} -match glob -result "{} {{\$p(:0:)}} {\$p(:0:)} {\$p(:*:)} 0 0.4.*\
        {-accessPath {[list $tcl_library *$tcl_library/$pkgOptDir]}\
        -statics 0 -nested 1 -deleteHook {} -autoPath {}} {}"
test safe-stock-18.5 {cf. safe-stock-7.5 - tests positive and negative module loading without conventional AutoPathSync} -setup {
    set SyncExists [expr {[info commands ::safe::setSyncMode] ne {}}]
    if {$SyncExists} {
        set SyncVal_TMP [safe::setSyncMode]
        safe::setSyncMode 0
    } else {
        error {This test is meaningful only if the command ::safe::setSyncMode is defined}
    }
    set i [safe::interpCreate]
    interp eval $i {
        package forget platform::shell
        package forget platform
        catch {namespace delete ::platform}
    }
} -body {
    # Should raise an error (tests module ancestor directory rule)
    set code1 [catch {interp eval $i {package require shell}} msg1]
    # Should not raise an error
    set code2 [catch {interp eval $i {package require platform::shell}} msg2]
    return [list $code1 $msg1 $code2]
} -cleanup {
    safe::interpDelete $i
    if {$SyncExists} {
        safe::setSyncMode $SyncVal_TMP
    }
} -result {1 {can't find package shell} 0}

set ::auto_path $SaveAutoPath
unset pkgOptErrMsg pkgOptDir pkgJarDir SaveAutoPath TestsDir PathMapp
rename mapList {}
rename mapAndSortList {}
# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End: