| [25] | 1 | # Commands covered:  auto_mkindex auto_import | 
|---|
 | 2 | # | 
|---|
 | 3 | # This file contains tests related to autoloading and generating | 
|---|
 | 4 | # the autoloading index. | 
|---|
 | 5 | # | 
|---|
 | 6 | # Copyright (c) 1998  Lucent Technologies, Inc. | 
|---|
 | 7 | # Copyright (c) 1998-1999 by Scriptics Corporation. | 
|---|
 | 8 | # | 
|---|
 | 9 | # See the file "license.terms" for information on usage and redistribution | 
|---|
 | 10 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. | 
|---|
 | 11 | # | 
|---|
 | 12 | # RCS: @(#) $Id: autoMkindex.test,v 1.15 2004/05/25 17:44:29 dgp Exp $ | 
|---|
 | 13 |  | 
|---|
 | 14 | if {[lsearch [namespace children] ::tcltest] == -1} { | 
|---|
 | 15 |     package require tcltest 2 | 
|---|
 | 16 |     namespace import -force ::tcltest::* | 
|---|
 | 17 | } | 
|---|
 | 18 |  | 
|---|
 | 19 | makeFile {# Test file for: | 
|---|
 | 20 | #   auto_mkindex | 
|---|
 | 21 | # | 
|---|
 | 22 | # This file provides example cases for testing the Tcl autoloading | 
|---|
 | 23 | # facility.  Things are much more complicated with namespaces and classes. | 
|---|
 | 24 | # The "auto_mkindex" facility can no longer be built on top of a simple | 
|---|
 | 25 | # regular expression parser.  It must recognize constructs like this: | 
|---|
 | 26 | # | 
|---|
 | 27 | #   namespace eval foo { | 
|---|
 | 28 | #       proc test {x y} { ... } | 
|---|
 | 29 | #       namespace eval bar { | 
|---|
 | 30 | #           proc another {args} { ... } | 
|---|
 | 31 | #       } | 
|---|
 | 32 | #   } | 
|---|
 | 33 | # | 
|---|
 | 34 | # Note that procedures and itcl class definitions can be nested inside | 
|---|
 | 35 | # of namespaces. | 
|---|
 | 36 | # | 
|---|
 | 37 | # Copyright (c) 1993-1998  Lucent Technologies, Inc. | 
|---|
 | 38 |  | 
|---|
 | 39 | # This shouldn't cause any problems | 
|---|
 | 40 | namespace import -force blt::* | 
|---|
 | 41 |  | 
|---|
 | 42 | # Should be able to handle "proc" definitions, even if they are | 
|---|
 | 43 | # preceded by white space. | 
|---|
 | 44 |  | 
|---|
 | 45 | proc normal {x y} {return [expr $x+$y]} | 
|---|
 | 46 |   proc indented {x y} {return [expr $x+$y]} | 
|---|
 | 47 |  | 
|---|
 | 48 | # | 
|---|
 | 49 | # Should be able to handle proc declarations within namespaces, | 
|---|
 | 50 | # even if they have explicit namespace paths. | 
|---|
 | 51 | # | 
|---|
 | 52 | namespace eval buried { | 
|---|
 | 53 |     proc inside {args} {return "inside: $args"} | 
|---|
 | 54 |  | 
|---|
 | 55 |     namespace export pub_* | 
|---|
 | 56 |     proc pub_one {args} {return "one: $args"} | 
|---|
 | 57 |     proc pub_two {args} {return "two: $args"} | 
|---|
 | 58 | } | 
|---|
 | 59 | proc buried::within {args} {return "within: $args"} | 
|---|
 | 60 |  | 
|---|
 | 61 | namespace eval buried { | 
|---|
 | 62 |     namespace eval under { | 
|---|
 | 63 |         proc neath {args} {return "neath: $args"} | 
|---|
 | 64 |     } | 
|---|
 | 65 |     namespace eval ::buried { | 
|---|
 | 66 |         proc relative {args} {return "relative: $args"} | 
|---|
 | 67 |         proc ::top {args} {return "top: $args"} | 
|---|
 | 68 |         proc ::buried::explicit {args} {return "explicit: $args"} | 
|---|
 | 69 |     } | 
|---|
 | 70 | } | 
|---|
 | 71 |  | 
|---|
 | 72 | # With proper hooks, we should be able to support other commands | 
|---|
 | 73 | # that create procedures | 
|---|
 | 74 |  | 
|---|
 | 75 | proc buried::myproc {name body args} { | 
|---|
 | 76 |     ::proc $name $body $args | 
|---|
 | 77 | } | 
|---|
 | 78 | namespace eval ::buried { | 
|---|
 | 79 |     proc mycmd1 args {return "mycmd"} | 
|---|
 | 80 |     myproc mycmd2 args {return "mycmd"} | 
|---|
 | 81 | } | 
|---|
 | 82 | ::buried::myproc mycmd3 args {return "another"} | 
|---|
 | 83 |  | 
|---|
 | 84 | proc {buried::my proc} {name body args} { | 
|---|
 | 85 |     ::proc $name $body $args | 
|---|
 | 86 | } | 
|---|
 | 87 | namespace eval ::buried { | 
|---|
 | 88 |     proc mycmd4 args {return "mycmd"} | 
|---|
 | 89 |     {my proc} mycmd5 args {return "mycmd"} | 
|---|
 | 90 | } | 
|---|
 | 91 | {::buried::my proc} mycmd6 args {return "another"} | 
|---|
 | 92 |  | 
|---|
 | 93 | # A correctly functioning [auto_import] won't choke when a child | 
|---|
 | 94 | # namespace [namespace import]s from its parent. | 
|---|
 | 95 | # | 
|---|
 | 96 | namespace eval ::parent::child { | 
|---|
 | 97 |     namespace import ::parent::* | 
|---|
 | 98 | } | 
|---|
 | 99 | proc ::parent::child::test {} {} | 
|---|
 | 100 |  | 
|---|
 | 101 | } autoMkindex.tcl | 
|---|
 | 102 |  | 
|---|
 | 103 |  | 
|---|
 | 104 | # Save initial state of auto_mkindex_parser | 
|---|
 | 105 |  | 
|---|
 | 106 | auto_load auto_mkindex | 
|---|
 | 107 | if {[info exists auto_mkindex_parser::initCommands]} { | 
|---|
 | 108 |     set saveCommands $auto_mkindex_parser::initCommands | 
|---|
 | 109 | } | 
|---|
 | 110 | proc AutoMkindexTestReset {} { | 
|---|
 | 111 |     global saveCommands | 
|---|
 | 112 |     if {[info exists saveCommands]} { | 
|---|
 | 113 |         set auto_mkindex_parser::initCommands $saveCommands | 
|---|
 | 114 |     } elseif {[info exists auto_mkindex_parser::initCommands]} { | 
|---|
 | 115 |         unset auto_mkindex_parser::initCommands | 
|---|
 | 116 |     } | 
|---|
 | 117 | } | 
|---|
 | 118 |  | 
|---|
 | 119 | set result "" | 
|---|
 | 120 |  | 
|---|
 | 121 | set origDir [pwd] | 
|---|
 | 122 | cd $::tcltest::temporaryDirectory | 
|---|
 | 123 |  | 
|---|
 | 124 | test autoMkindex-1.1 {remove any existing tclIndex file} { | 
|---|
 | 125 |     file delete tclIndex | 
|---|
 | 126 |     file exists tclIndex | 
|---|
 | 127 | } {0} | 
|---|
 | 128 |  | 
|---|
 | 129 | test autoMkindex-1.2 {build tclIndex based on a test file} { | 
|---|
 | 130 |     auto_mkindex . autoMkindex.tcl | 
|---|
 | 131 |     file exists tclIndex | 
|---|
 | 132 | } {1} | 
|---|
 | 133 |  | 
|---|
 | 134 | set element "{source [file join . autoMkindex.tcl]}" | 
|---|
 | 135 |  | 
|---|
 | 136 | test autoMkindex-1.3 {examine tclIndex} { | 
|---|
 | 137 |     file delete tclIndex | 
|---|
 | 138 |     auto_mkindex . autoMkindex.tcl | 
|---|
 | 139 |     namespace eval tcl_autoMkindex_tmp { | 
|---|
 | 140 |         set dir "." | 
|---|
 | 141 |         variable auto_index | 
|---|
 | 142 |         source tclIndex | 
|---|
 | 143 |         set ::result "" | 
|---|
 | 144 |         foreach elem [lsort [array names auto_index]] { | 
|---|
 | 145 |             lappend ::result [list $elem $auto_index($elem)] | 
|---|
 | 146 |         } | 
|---|
 | 147 |     } | 
|---|
 | 148 |     namespace delete tcl_autoMkindex_tmp | 
|---|
 | 149 |     set ::result | 
|---|
 | 150 | } "{::buried::explicit $element} {::buried::inside $element} {{::buried::my proc} $element} {::buried::mycmd1 $element} {::buried::mycmd4 $element} {::buried::myproc $element} {::buried::pub_one $element} {::buried::pub_two $element} {::buried::relative $element} {::buried::under::neath $element} {::buried::within $element} {::parent::child::test $element} {indented $element} {normal $element} {top $element}" | 
|---|
 | 151 |  | 
|---|
 | 152 |  | 
|---|
 | 153 | test autoMkindex-2.1 {commands on the autoload path can be imported} { | 
|---|
 | 154 |     file delete tclIndex | 
|---|
 | 155 |     auto_mkindex . autoMkindex.tcl | 
|---|
 | 156 |     set interp [interp create] | 
|---|
 | 157 |     set final [$interp eval { | 
|---|
 | 158 |         namespace eval blt {} | 
|---|
 | 159 |         set auto_path [linsert $auto_path 0 .] | 
|---|
 | 160 |         set info [list [catch {namespace import buried::*} result] $result] | 
|---|
 | 161 |         foreach name [lsort [info commands pub_*]] { | 
|---|
 | 162 |             lappend info $name [namespace origin $name] | 
|---|
 | 163 |         } | 
|---|
 | 164 |         set info | 
|---|
 | 165 |     }] | 
|---|
 | 166 |     interp delete $interp | 
|---|
 | 167 |     set final | 
|---|
 | 168 | } "0 {} pub_one ::buried::pub_one pub_two ::buried::pub_two" | 
|---|
 | 169 |  | 
|---|
 | 170 | # Test auto_mkindex hooks | 
|---|
 | 171 |  | 
|---|
 | 172 | # Slave hook executes interesting code in the interp used to watch code. | 
|---|
 | 173 |  | 
|---|
 | 174 | test autoMkindex-3.1 {slaveHook} { | 
|---|
 | 175 |     auto_mkindex_parser::slavehook { | 
|---|
 | 176 |         _%@namespace eval ::blt { | 
|---|
 | 177 |             proc foo {} {} | 
|---|
 | 178 |             _%@namespace export foo | 
|---|
 | 179 |         } | 
|---|
 | 180 |     } | 
|---|
 | 181 |     auto_mkindex_parser::slavehook { _%@namespace import -force ::blt::* } | 
|---|
 | 182 |     file delete tclIndex | 
|---|
 | 183 |     auto_mkindex . autoMkindex.tcl | 
|---|
 | 184 |       | 
|---|
 | 185 |     # Reset initCommands to avoid trashing other tests | 
|---|
 | 186 |  | 
|---|
 | 187 |     AutoMkindexTestReset | 
|---|
 | 188 |     file exists tclIndex | 
|---|
 | 189 | } 1  | 
|---|
 | 190 |  | 
|---|
 | 191 | # The auto_mkindex_parser::command is used to register commands | 
|---|
 | 192 | # that create new commands. | 
|---|
 | 193 |  | 
|---|
 | 194 | test autoMkindex-3.2 {auto_mkindex_parser::command} { | 
|---|
 | 195 |     auto_mkindex_parser::command buried::myproc {name args} { | 
|---|
 | 196 |         variable index | 
|---|
 | 197 |         variable scriptFile | 
|---|
 | 198 |         append index [list set auto_index([fullname $name])] \ | 
|---|
 | 199 |                 " \[list source \[file join \$dir [list $scriptFile]\]\]\n" | 
|---|
 | 200 |     } | 
|---|
 | 201 |     file delete tclIndex | 
|---|
 | 202 |     auto_mkindex . autoMkindex.tcl | 
|---|
 | 203 |     namespace eval tcl_autoMkindex_tmp { | 
|---|
 | 204 |         set dir "." | 
|---|
 | 205 |         variable auto_index | 
|---|
 | 206 |         source tclIndex | 
|---|
 | 207 |         set ::result "" | 
|---|
 | 208 |         foreach elem [lsort [array names auto_index]] { | 
|---|
 | 209 |             lappend ::result [list $elem $auto_index($elem)] | 
|---|
 | 210 |         } | 
|---|
 | 211 |     } | 
|---|
 | 212 |     namespace delete tcl_autoMkindex_tmp | 
|---|
 | 213 |  | 
|---|
 | 214 |     # Reset initCommands to avoid trashing other tests | 
|---|
 | 215 |  | 
|---|
 | 216 |     AutoMkindexTestReset | 
|---|
 | 217 |     set ::result | 
|---|
 | 218 | } "{::buried::explicit $element} {::buried::inside $element} {{::buried::my proc} $element} {::buried::mycmd1 $element} {::buried::mycmd2 $element} {::buried::mycmd4 $element} {::buried::myproc $element} {::buried::pub_one $element} {::buried::pub_two $element} {::buried::relative $element} {::buried::under::neath $element} {::buried::within $element} {::parent::child::test $element} {indented $element} {mycmd3 $element} {normal $element} {top $element}" | 
|---|
 | 219 |  | 
|---|
 | 220 |  | 
|---|
 | 221 | test autoMkindex-3.3 {auto_mkindex_parser::command} {knownBug} { | 
|---|
 | 222 |     auto_mkindex_parser::command {buried::my proc} {name args} { | 
|---|
 | 223 |         variable index | 
|---|
 | 224 |         variable scriptFile | 
|---|
 | 225 |         puts "my proc $name" | 
|---|
 | 226 |         append index [list set auto_index([fullname $name])] \ | 
|---|
 | 227 |                 " \[list source \[file join \$dir [list $scriptFile]\]\]\n" | 
|---|
 | 228 |     } | 
|---|
 | 229 |     file delete tclIndex | 
|---|
 | 230 |     auto_mkindex . autoMkindex.tcl | 
|---|
 | 231 |     namespace eval tcl_autoMkindex_tmp { | 
|---|
 | 232 |         set dir "." | 
|---|
 | 233 |         variable auto_index | 
|---|
 | 234 |         source tclIndex | 
|---|
 | 235 |         set ::result "" | 
|---|
 | 236 |         foreach elem [lsort [array names auto_index]] { | 
|---|
 | 237 |             lappend ::result [list $elem $auto_index($elem)] | 
|---|
 | 238 |         } | 
|---|
 | 239 |     } | 
|---|
 | 240 |     namespace delete tcl_autoMkindex_tmp | 
|---|
 | 241 |  | 
|---|
 | 242 |     # Reset initCommands to avoid trashing other tests | 
|---|
 | 243 |  | 
|---|
 | 244 |     AutoMkindexTestReset | 
|---|
 | 245 |     proc lvalue {list pattern} { | 
|---|
 | 246 |         set ix [lsearch $list $pattern] | 
|---|
 | 247 |         if {$ix >= 0} { | 
|---|
 | 248 |             return [lindex $list $ix] | 
|---|
 | 249 |         } else { | 
|---|
 | 250 |             return {} | 
|---|
 | 251 |         } | 
|---|
 | 252 |     } | 
|---|
 | 253 |     list [lvalue $::result *mycmd4*] [lvalue $::result *mycmd5*] [lvalue $::result *mycmd6*] | 
|---|
 | 254 | } "{::buried::mycmd4 $element} {::buried::mycmd5 $element} {mycmd6 $element}" | 
|---|
 | 255 |  | 
|---|
 | 256 |  | 
|---|
 | 257 | makeDirectory pkg | 
|---|
 | 258 | makeFile { | 
|---|
 | 259 | package provide football 1.0 | 
|---|
 | 260 |      | 
|---|
 | 261 | namespace eval ::pro:: { | 
|---|
 | 262 |     # | 
|---|
 | 263 |     # export only public functions. | 
|---|
 | 264 |     # | 
|---|
 | 265 |     namespace export {[a-z]*} | 
|---|
 | 266 | } | 
|---|
 | 267 | namespace eval ::college:: { | 
|---|
 | 268 |     # | 
|---|
 | 269 |     # export only public functions. | 
|---|
 | 270 |     # | 
|---|
 | 271 |     namespace export {[a-z]*} | 
|---|
 | 272 | } | 
|---|
 | 273 |  | 
|---|
 | 274 | proc ::pro::team {} { | 
|---|
 | 275 |     puts "go packers!" | 
|---|
 | 276 |     return true | 
|---|
 | 277 | } | 
|---|
 | 278 |  | 
|---|
 | 279 | proc ::college::team {} { | 
|---|
 | 280 |     puts "go badgers!" | 
|---|
 | 281 |     return true | 
|---|
 | 282 | } | 
|---|
 | 283 |  | 
|---|
 | 284 | } [file join pkg samename.tcl] | 
|---|
 | 285 |  | 
|---|
 | 286 |  | 
|---|
 | 287 | test autoMkindex-4.1 {platform indenpendant source commands} { | 
|---|
 | 288 |     file delete tclIndex | 
|---|
 | 289 |     auto_mkindex . pkg/samename.tcl | 
|---|
 | 290 |     set f [open tclIndex r] | 
|---|
 | 291 |     set dat [split [string trim [read $f]] "\n"] | 
|---|
 | 292 |     set len [llength $dat] | 
|---|
 | 293 |     set result [lsort [lrange $dat [expr {$len-2}] [expr {$len-1}]]] | 
|---|
 | 294 |     close $f | 
|---|
 | 295 |     set result | 
|---|
 | 296 | } {{set auto_index(::college::team) [list source [file join $dir pkg samename.tcl]]} {set auto_index(::pro::team) [list source [file join $dir pkg samename.tcl]]}} | 
|---|
 | 297 |  | 
|---|
 | 298 | removeFile [file join pkg samename.tcl] | 
|---|
 | 299 |  | 
|---|
 | 300 | makeFile { | 
|---|
 | 301 | set dollar1 "this string contains an unescaped dollar sign -> \\$foo" | 
|---|
 | 302 | set dollar2 "this string contains an escaped dollar sign -> \$foo \\\$foo" | 
|---|
 | 303 | set bracket1 "this contains an unescaped bracket [NoSuchProc]" | 
|---|
 | 304 | set bracket2 "this contains an escaped bracket \[NoSuchProc\]" | 
|---|
 | 305 | set bracket3 "this contains nested unescaped brackets [[NoSuchProc]]" | 
|---|
 | 306 | proc testProc {} {} | 
|---|
 | 307 | } [file join pkg magicchar.tcl] | 
|---|
 | 308 |  | 
|---|
 | 309 | test autoMkindex-5.1 {escape magic tcl chars in general code} { | 
|---|
 | 310 |     file delete tclIndex | 
|---|
 | 311 |     set result {} | 
|---|
 | 312 |     if { ![catch {auto_mkindex . pkg/magicchar.tcl}] } { | 
|---|
 | 313 |         set f [open tclIndex r] | 
|---|
 | 314 |         set dat [split [string trim [read $f]] "\n"] | 
|---|
 | 315 |         set result [lindex $dat end] | 
|---|
 | 316 |         close $f | 
|---|
 | 317 |     } | 
|---|
 | 318 |     set result | 
|---|
 | 319 | } {set auto_index(testProc) [list source [file join $dir pkg magicchar.tcl]]} | 
|---|
 | 320 |  | 
|---|
 | 321 | removeFile [file join pkg magicchar.tcl] | 
|---|
 | 322 |  | 
|---|
 | 323 | makeFile { | 
|---|
 | 324 | proc {[magic mojo proc]} {} {} | 
|---|
 | 325 | } [file join pkg magicchar2.tcl] | 
|---|
 | 326 |  | 
|---|
 | 327 | test autoMkindex-5.2 {correctly locate auto loaded procs with []} { | 
|---|
 | 328 |     file delete tclIndex | 
|---|
 | 329 |     set result {} | 
|---|
 | 330 |     if { ![catch {auto_mkindex . pkg/magicchar2.tcl}] } { | 
|---|
 | 331 |         # Make a slave interp to test the autoloading | 
|---|
 | 332 |         set c [interp create] | 
|---|
 | 333 |         $c eval {lappend auto_path [pwd]} | 
|---|
 | 334 |         set result [$c eval {catch {{[magic mojo proc]}}}] | 
|---|
 | 335 |         interp delete $c | 
|---|
 | 336 |     } | 
|---|
 | 337 |     set result | 
|---|
 | 338 | } 0 | 
|---|
 | 339 |  | 
|---|
 | 340 | removeFile [file join pkg magicchar2.tcl] | 
|---|
 | 341 | removeDirectory pkg | 
|---|
 | 342 |  | 
|---|
 | 343 | # Clean up. | 
|---|
 | 344 |  | 
|---|
 | 345 | unset result | 
|---|
 | 346 | AutoMkindexTestReset | 
|---|
 | 347 | if {[info exists saveCommands]} { | 
|---|
 | 348 |     unset saveCommands | 
|---|
 | 349 | } | 
|---|
 | 350 | rename AutoMkindexTestReset "" | 
|---|
 | 351 |  | 
|---|
 | 352 | removeFile autoMkindex.tcl | 
|---|
 | 353 | if {[file exists tclIndex]} { | 
|---|
 | 354 |     file delete -force tclIndex | 
|---|
 | 355 | } | 
|---|
 | 356 |  | 
|---|
 | 357 | cd $origDir | 
|---|
 | 358 |  | 
|---|
 | 359 | ::tcltest::cleanupTests | 
|---|