Skip to content

Commit 7570fda

Browse files
committed
testutils.tcl [testutils]: new command that handles importing/forgetting of utility procs and associated variables, and performs auto-(re)initialization of upvar'ed namespace variables previously unset by cleanup in the test file.
1 parent 84b1e81 commit 7570fda

File tree

11 files changed

+163
-40
lines changed

11 files changed

+163
-40
lines changed

tests/choosedir.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ eval tcltest::configure $argv
1111
tcltest::loadTestedCommands
1212

1313
# Import utility procs for specific functional areas
14-
namespace import -force ::tk::test::dialog::*
14+
testutils import -novars dialog
1515
setDialogType choosedir
1616

1717
#----------------------------------------------------------------------
@@ -143,6 +143,6 @@ test choosedir-5.1 {tk_chooseDirectory, handles {} entry text} -constraints {
143143

144144
removeDirectory choosedirTest
145145
setDialogType none
146-
namespace forget ::tk::test::dialog::*
146+
testutils forget dialog
147147
cleanupTests
148148
return

tests/clrpick.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ tcltest::loadTestedCommands
1111
namespace import -force tcltest::test
1212

1313
# Import utility procs for specific functional areas
14-
namespace import -force ::tk::test::dialog::*
14+
testutils import -novars dialog
1515
setDialogType clrpick
1616

1717
if {[testConstraint defaultPseudocolor8]} {
@@ -173,6 +173,6 @@ test clrpick-4.1 {tk_chooseColor: screen is inherited from parent} -constraints
173173
#
174174

175175
setDialogType none
176-
namespace forget ::tk::test::dialog::*
176+
testutils forget dialog
177177
cleanupTests
178178
return

tests/dialog.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ tcltest::loadTestedCommands
77
namespace import -force tcltest::test
88

99
# Import utility procs for specific functional areas
10-
namespace import -force ::tk::test::dialog::*
10+
testutils import -novars dialog
1111

1212
test dialog-1.1 {tk_dialog command} -body {
1313
tk_dialog
@@ -64,6 +64,6 @@ test dialog-2.3 {tk_dialog operation} -body {
6464
# CLEANUP
6565
#
6666

67-
namespace forget ::tk::test::dialog::*
67+
testutils forget dialog
6868
cleanupTests
6969
return

tests/filebox.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ eval tcltest::configure $argv
1111
tcltest::loadTestedCommands
1212

1313
# Import utility procs for specific functional areas
14-
namespace import -force ::tk::test::dialog::*
14+
testutils import -novars dialog
1515
setDialogType filebox
1616

1717
test fileDialog-0.1 {GetFileName: file types: MakeFilter() fails} {
@@ -446,6 +446,6 @@ foreach mode $modes {
446446
set tk_strictMotif $tk_strictMotif_old
447447
removeFile filebox.tmp
448448
setDialogType none
449-
namespace forget ::tk::test::dialog::*
449+
testutils forget dialog
450450
cleanupTests
451451
return

tests/fontchooser.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ eval tcltest::configure $argv
77
tcltest::loadTestedCommands
88

99
# Import utility procs for specific functional areas
10-
namespace import -force ::tk::test::dialog::*
11-
upvar #0 ::tk::test::dialog::testDialog testDialog
10+
testutils import dialog
11+
1212
set applyFontCmd [list testDialogFont set]
1313

1414
# -------------------------------------------------------------------------
@@ -165,7 +165,7 @@ test fontchooser-5.1 {fontchooser multiple configure} -constraints {scriptImpl}
165165
#
166166

167167
unset applyFontCmd
168-
namespace forget ::tk::test::dialog::*
168+
testutils forget dialog
169169
cleanupTests
170170
return
171171

tests/msgbox.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ tcltest::loadTestedCommands
1111
namespace import -force tcltest::test
1212

1313
# Import utility procs for specific functional areas
14-
namespace import -force ::tk::test::dialog::*
14+
testutils import -novars dialog
1515
setDialogType msgbox
1616

1717
test msgbox-1.1.1 {tk_messageBox command} -constraints notAqua -body {
@@ -423,6 +423,6 @@ test msgbox-3.2 {tk_messageBox handles iconified parent} -constraints {
423423
# CLEANUP
424424
#
425425

426-
namespace forget ::tk::test::dialog::*
426+
testutils forget dialog
427427
cleanupTests
428428
return

tests/testutils.tcl

Lines changed: 142 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@
2929
namespace eval tk {
3030
namespace eval test {
3131

32+
# auto_ns_vars --
33+
#
34+
# Each new namespace automatically holds several variables upvar'ed
35+
# from the global namespace. Notably:
36+
#
37+
# argc argv argv0 auto_index auto_path env tcl_interactive tcl_library \
38+
# tcl_patchLevel tcl_pkgPath tcl_platform tcl_rcFileName tcl_version
39+
#
40+
# proc testutils (see below) needs to know about them to keep track of
41+
# newly created variables.
42+
#
43+
variable auto_ns_vars [namespace eval tmp {info vars}]
44+
namespace delete tmp
45+
3246
proc assert {expr} {
3347
if {! [uplevel 1 [list expr $expr]]} {
3448
return -code error "assertion failed: \"[uplevel 1 [list subst -nocommands $expr]]\""
@@ -192,6 +206,86 @@ namespace eval tk {
192206
unset _pause($num)
193207
}
194208

209+
# testutils --
210+
#
211+
# Takes care of importing/forgetting utility procs with any associated
212+
# variables from a specific test domain (functional area). It hides
213+
# details/peculiarities from the test writer.
214+
#
215+
# The "import" subcmd invokes any proc "init" defined in the doamin-
216+
# specific namespace. See also the explanation of this mehanism below
217+
# the header for the section "DEFINITIONS OF UTILITY PROCS PER
218+
# FUNCTIONAL AREA" in this file.
219+
#
220+
# Arguments:
221+
# subCmd : "import" or "forget"
222+
# args : a sequence of domains that need to be imported/forgotten,
223+
# optionally preceded by the option -nocommands or -novars.
224+
#
225+
proc testutils {subCmd args} {
226+
variable importedVars
227+
228+
set usage "[lindex [info level 0] 0] import|forget ?-nocommands|-novars? domain ?domain domain ...?"
229+
set argc [llength $args]
230+
if {$argc < 1} {
231+
return -code error $usage
232+
}
233+
234+
set option [lindex $args 0]
235+
if {$option ni "-nocommands -novars"} {
236+
set option {}
237+
}
238+
if {($subCmd ni "import forget") || (($option ne "") && ($argc < 2))} {
239+
return -code error $usage
240+
}
241+
if {($subCmd eq "forget") && ($option ne "")} {
242+
return -code error "options \"-nocommands\" and \"-novars\" are not valid with subCmd \"forget\""
243+
}
244+
245+
set domains [expr {$option eq ""?$args:[lrange $args 1 end]}]
246+
foreach domain $domains {
247+
if {! [namespace exists ::tk::test::$domain]} {
248+
return -code error "Tk test domain \"$domain\" doesn't exist"
249+
}
250+
switch -- $subCmd {
251+
import {
252+
if {$domain ni [array names importedVars]} {
253+
if {$option ne "-nocommands"} {
254+
uplevel 1 [list namespace import -force ::tk::test::${domain}::*]
255+
set importedVars($domain) [list]
256+
}
257+
if {$option ne "-novars"} {
258+
variable auto_ns_vars
259+
if {[namespace inscope ::tk::test::$domain {info procs init}] eq "init"} {
260+
::tk::test::${domain}::init
261+
}
262+
foreach varName [namespace inscope ::tk::test::$domain {info vars}] {
263+
if {$varName ni $auto_ns_vars} {
264+
uplevel 1 [list upvar #0 ::tk::test::${domain}::$varName $varName]
265+
lappend importedVars($domain) $varName
266+
}
267+
}
268+
}
269+
} else {
270+
if {[namespace inscope ::tk::test::$domain {info procs init}] eq "init"} {
271+
::tk::test::${domain}::init
272+
}
273+
}
274+
}
275+
forget {
276+
if {! [info exists importedVars($domain)]} {
277+
return -code error "domain \"$domain\" was not imported"
278+
}
279+
uplevel 1 [list namespace forget ::tk::test::${domain}::*]
280+
foreach varName $importedVars($domain) {
281+
uplevel 1 unset -nocomplain $varName
282+
}
283+
unset importedVars($domain)
284+
}
285+
}
286+
}
287+
}
288+
195289
namespace export *
196290
}
197291
}
@@ -203,6 +297,40 @@ namespace import -force tk::test::*
203297
# DEFINITIONS OF UTILITY PROCS PER FUNCTIONAL AREA
204298
#
205299

300+
#
301+
# INIT PROCS, IMPORTING UTILITY PROCS AND ASSOCIATED NAMESPACE VARIABLES,
302+
# AND AUTO-INITIALIZATION
303+
#
304+
# Some utility procs from specific functional areas store state in a namespace
305+
# variable that is also accessed from the namespace in which the tests are
306+
# executed (the "executing namespace"). Some tests require such variables
307+
# to be initialized.
308+
#
309+
# When such variables are imported into the "executing namespace" through
310+
# an "upvar" command, and the test file unsets these variables as part of a
311+
# cleanup operation, this results in the deletion of the target variable
312+
# inside the specific domain namespace. This, in turn, poses a problem for
313+
# the next test file, which presumes that the variable is initialized.
314+
#
315+
# The proc "testutils" deals with this upvar issue as follows:
316+
#
317+
# If a namespace for a specific functional area holds a proc "init", the
318+
# "testutils import xxx" will invoke it to carry out the initialization of
319+
# such namespace variables and subsequently imports them into the executing
320+
# namespace using "upvar" (import with auto-initialization).
321+
# Upon test file cleanup "testutils forget xxx" will remove the imported
322+
# utility procs with the associated namespace variables, and unset the upvar'ed
323+
# variable in both the source and target namespace, including their link. The
324+
# link and initialization will be recreated for the next namespace upon
325+
# "testutils import yyy".
326+
#
327+
# Test writers that create a new utility procs that use a namespace variable
328+
# that is also accessed by a test file, need to add the initialization
329+
# statements to the init proc. Just placing them inside the "namespace eval"
330+
# scope for the specific domain (outside the init proc) isn't enough because
331+
# that foregoes the importing of the namespace variables and their automatic
332+
# re-initialization.
333+
#
206334
namespace eval ::tk::test::button {
207335
proc bogusTrace args {
208336
error "trace aborted"
@@ -388,6 +516,11 @@ namespace eval ::tk::test::colors {
388516

389517
namespace eval ::tk::test::dialog {
390518

519+
proc init {} {
520+
variable dialogType none
521+
variable testDialog
522+
}
523+
391524
proc Click {button} {
392525
variable testDialog
393526
if {$button ni "ok cancel apply"} {
@@ -456,7 +589,6 @@ namespace eval ::tk::test::dialog {
456589
}
457590
}
458591

459-
variable dialogType none
460592
proc setDialogType {type} {
461593
variable dialogType $type
462594
}
@@ -534,7 +666,8 @@ namespace eval ::tk::test::dialog {
534666

535667
::tk::test::createStdAccessProc testDialogFont
536668

537-
namespace export *
669+
namespace export Click PressButton SendButtonPress setDialogType testDialog \
670+
testDialogFont ToPressButton
538671
}
539672

540673

@@ -599,7 +732,6 @@ namespace eval ::tk::test::geometry {
599732
}
600733

601734
namespace eval ::tk::test::image {
602-
variable ImageNames
603735

604736
proc imageCleanup {} {
605737
variable ImageNames
@@ -774,10 +906,12 @@ namespace eval ::tk::test::select {
774906
}
775907

776908
namespace eval ::tk::test::text {
777-
variable fixedFont {Courier -12}
778-
variable fixedWidth [font measure $fixedFont m]
779-
variable fixedHeight [font metrics $fixedFont -linespace]
780-
variable fixedAscent [font metrics $fixedFont -ascent]
909+
proc init {} {
910+
variable fixedFont {Courier -12}
911+
variable fixedWidth [font measure $fixedFont m]
912+
variable fixedHeight [font metrics $fixedFont -linespace]
913+
variable fixedAscent [font metrics $fixedFont -ascent]
914+
}
781915

782916
# full border size of the text widget, i.e. first x or y coordinate inside the text widget
783917
# warning: -padx is supposed to be the same as -pady (same border size horizontally and
@@ -803,7 +937,7 @@ namespace eval ::tk::test::text {
803937
return [expr {[bo $w] + ($l - 1) * $fixedHeight}]
804938
}
805939

806-
namespace export *
940+
namespace export bo xchar xw yline
807941
}
808942

809943
# EOF

tests/textDisp.test

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ tcltest::loadTestedCommands
1212
namespace import -force tcltest::test
1313

1414
# Import utility procs for specific functional areas
15-
namespace import -force ::tk::test::text::*
16-
upvar 0 ::tk::test::text::fixedFont fixedFont \
17-
::tk::test::text::fixedWidth fixedWidth \
18-
::tk::test::text::fixedHeight fixedHeight \
19-
::tk::test::text::fixedAscent fixedAscent
15+
testutils import text
2016

2117
namespace import -force ::tk::test::scroll::*
2218

@@ -4908,7 +4904,7 @@ test textDisp-36.1 {Display bug with 'yview insert'} -constraints {knownBug} -se
49084904

49094905
unset scrollCmdPrefix
49104906
namespace forget ::tk::test::scroll::*
4911-
namespace forget ::tk::test::text::*
4907+
testutils forget text
49124908
deleteWindows
49134909
option clear
49144910
cleanupTests

tests/textIndex.test

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ package require tcltest 2.2
1010
eval tcltest::configure $argv
1111
tcltest::loadTestedCommands
1212
namespace import -force tcltest::test
13-
14-
upvar 0 ::tk::test::text::fixedFont fixedFont \
15-
::tk::test::text::fixedWidth fixedWidth \
16-
::tk::test::text::fixedHeight fixedHeight
13+
testutils import -nocommands text
1714

1815
catch {destroy .t}
1916
text .t -font {Courier -12} -width 20 -height 10
@@ -1027,5 +1024,6 @@ test textIndex-26.2 {GetIndex errors out if mark, image, window, or tag is outsi
10271024
# cleanup
10281025
rename textimage {}
10291026
catch {destroy .t}
1027+
testutils forget text
10301028
cleanupTests
10311029
return

tests/textWind.test

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ tcltest::configure {*}$argv
1212
tcltest::loadTestedCommands
1313

1414
# Import utility procs for specific functional areas
15-
namespace import -force ::tk::test::text::*
16-
upvar 0 ::tk::test::text::fixedFont fixedFont \
17-
::tk::test::text::fixedWidth fixedWidth \
18-
::tk::test::text::fixedHeight fixedHeight \
19-
::tk::test::text::fixedAscent fixedAscent
15+
testutils import text
2016

2117
deleteWindows
2218

@@ -1653,6 +1649,6 @@ test textWind-18.3 {embedded window destruction in cascade} -setup {
16531649
#
16541650

16551651
option clear
1656-
namespace forget ::tk::test::text::*
1652+
testutils forget text
16571653
cleanupTests
16581654
return

0 commit comments

Comments
 (0)