| [25] | 1 | # This file contains tests for the pkg_mkIndex command. | 
|---|
 | 2 | # Note that the tests are limited to Tcl scripts only, there are no shared | 
|---|
 | 3 | # libraries against which to test. | 
|---|
 | 4 | # | 
|---|
 | 5 | # Sourcing this file into Tcl runs the tests and generates output for | 
|---|
 | 6 | # errors.  No output means no errors were found. | 
|---|
 | 7 | # | 
|---|
 | 8 | # Copyright (c) 1998-1999 by Scriptics Corporation. | 
|---|
 | 9 | # All rights reserved. | 
|---|
 | 10 | # | 
|---|
 | 11 | # RCS: @(#) $Id: pkgMkIndex.test,v 1.29 2006/11/03 00:34:53 hobbs Exp $ | 
|---|
 | 12 |  | 
|---|
 | 13 | if {[lsearch [namespace children] ::tcltest] == -1} { | 
|---|
 | 14 |     package require tcltest 2 | 
|---|
 | 15 |     namespace import -force ::tcltest::* | 
|---|
 | 16 | } | 
|---|
 | 17 |  | 
|---|
 | 18 | set fullPkgPath [makeDirectory pkg] | 
|---|
 | 19 |  | 
|---|
 | 20 |  | 
|---|
 | 21 | namespace eval pkgtest { | 
|---|
 | 22 |     # Namespace for procs we can discard | 
|---|
 | 23 | } | 
|---|
 | 24 |  | 
|---|
 | 25 | # pkgtest::parseArgs -- | 
|---|
 | 26 | # | 
|---|
 | 27 | #  Parse an argument list. | 
|---|
 | 28 | # | 
|---|
 | 29 | # Arguments: | 
|---|
 | 30 | #  <flags>      (optional) arguments starting with a dash are collected | 
|---|
 | 31 | #               as options to pkg_mkIndex and passed to pkg_mkIndex. | 
|---|
 | 32 | #  dirPath      the directory to index | 
|---|
 | 33 | #  pattern0     pattern to index | 
|---|
 | 34 | #  ...          pattern to index | 
|---|
 | 35 | #  patternN     pattern to index | 
|---|
 | 36 | # | 
|---|
 | 37 | # Results: | 
|---|
 | 38 | #  Returns a three element list: | 
|---|
 | 39 | #    0: the options | 
|---|
 | 40 | #    1: the directory to index | 
|---|
 | 41 | #    2: the patterns list | 
|---|
 | 42 |  | 
|---|
 | 43 | proc pkgtest::parseArgs { args } { | 
|---|
 | 44 |     set options "" | 
|---|
 | 45 |  | 
|---|
 | 46 |     set argc [llength $args] | 
|---|
 | 47 |     for {set iarg 0} {$iarg < $argc} {incr iarg} { | 
|---|
 | 48 |         set a [lindex $args $iarg] | 
|---|
 | 49 |         if {[regexp {^-} $a]} { | 
|---|
 | 50 |             lappend options $a | 
|---|
 | 51 |             if {[string compare -load $a] == 0} { | 
|---|
 | 52 |                 incr iarg | 
|---|
 | 53 |                 lappend options [lindex $args $iarg] | 
|---|
 | 54 |             } | 
|---|
 | 55 |         } else { | 
|---|
 | 56 |             break | 
|---|
 | 57 |         } | 
|---|
 | 58 |     } | 
|---|
 | 59 |  | 
|---|
 | 60 |     set dirPath [lindex $args $iarg] | 
|---|
 | 61 |     incr iarg | 
|---|
 | 62 |     set patternList [lrange $args $iarg end] | 
|---|
 | 63 |  | 
|---|
 | 64 |     return [list $options $dirPath $patternList] | 
|---|
 | 65 | } | 
|---|
 | 66 |  | 
|---|
 | 67 | # pkgtest::parseIndex -- | 
|---|
 | 68 | # | 
|---|
 | 69 | #  Loads a pkgIndex.tcl file, records all the calls to "package ifneeded". | 
|---|
 | 70 | # | 
|---|
 | 71 | # Arguments: | 
|---|
 | 72 | #  filePath     path to the pkgIndex.tcl file. | 
|---|
 | 73 | # | 
|---|
 | 74 | # Results: | 
|---|
 | 75 | #  Returns a list, in "array set/get" format, where the keys are the package | 
|---|
 | 76 | #  name and version (in the form "$name:$version"), and the values the rest | 
|---|
 | 77 | #  of the command line. | 
|---|
 | 78 |  | 
|---|
 | 79 | proc pkgtest::parseIndex { filePath } { | 
|---|
 | 80 |     # create a slave interpreter, where we override "package ifneeded" | 
|---|
 | 81 |  | 
|---|
 | 82 |     set slave [interp create] | 
|---|
 | 83 |     if {[catch { | 
|---|
 | 84 |         $slave eval { | 
|---|
 | 85 |             rename package package_original | 
|---|
 | 86 |             proc package { args } { | 
|---|
 | 87 |                 if {[string compare [lindex $args 0] ifneeded] == 0} { | 
|---|
 | 88 |                     set pkg [lindex $args 1] | 
|---|
 | 89 |                     set ver [lindex $args 2] | 
|---|
 | 90 |                     set ::PKGS($pkg:$ver) [lindex $args 3] | 
|---|
 | 91 |                 } else { | 
|---|
 | 92 |                     return [package_original {*}$args] | 
|---|
 | 93 |                 } | 
|---|
 | 94 |             } | 
|---|
 | 95 |             array set ::PKGS {} | 
|---|
 | 96 |         } | 
|---|
 | 97 |  | 
|---|
 | 98 |         set dir [file dirname $filePath] | 
|---|
 | 99 |         $slave eval {set curdir [pwd]} | 
|---|
 | 100 |         $slave eval [list cd $dir] | 
|---|
 | 101 |         $slave eval [list set dir $dir] | 
|---|
 | 102 |         $slave eval [list source [file tail $filePath]] | 
|---|
 | 103 |         $slave eval {cd $curdir} | 
|---|
 | 104 |  | 
|---|
 | 105 |         # Create the list in sorted order, so that we don't get spurious | 
|---|
 | 106 |         # errors because the order has changed. | 
|---|
 | 107 |  | 
|---|
 | 108 |         array set P {} | 
|---|
 | 109 |         foreach {k v} [$slave eval {array get ::PKGS}] { | 
|---|
 | 110 |             set P($k) $v | 
|---|
 | 111 |         } | 
|---|
 | 112 |  | 
|---|
 | 113 |         set PKGS "" | 
|---|
 | 114 |         foreach k [lsort [array names P]] { | 
|---|
 | 115 |             lappend PKGS $k $P($k) | 
|---|
 | 116 |         } | 
|---|
 | 117 |     } err]} { | 
|---|
 | 118 |         set ei $::errorInfo | 
|---|
 | 119 |         set ec $::errorCode | 
|---|
 | 120 |  | 
|---|
 | 121 |         catch {interp delete $slave} | 
|---|
 | 122 |  | 
|---|
 | 123 |         error $ei $ec | 
|---|
 | 124 |     } | 
|---|
 | 125 |  | 
|---|
 | 126 |     interp delete $slave | 
|---|
 | 127 |  | 
|---|
 | 128 |     return $PKGS | 
|---|
 | 129 | } | 
|---|
 | 130 |  | 
|---|
 | 131 | # pkgtest::createIndex -- | 
|---|
 | 132 | # | 
|---|
 | 133 | #  Runs pkg_mkIndex for the given directory and set of patterns. | 
|---|
 | 134 | #  This procedure deletes any pkgIndex.tcl file in the target directory, | 
|---|
 | 135 | #  then runs pkg_mkIndex. | 
|---|
 | 136 | # | 
|---|
 | 137 | # Arguments: | 
|---|
 | 138 | #  <flags>      (optional) arguments starting with a dash are collected | 
|---|
 | 139 | #               as options to pkg_mkIndex and passed to pkg_mkIndex. | 
|---|
 | 140 | #  dirPath      the directory to index | 
|---|
 | 141 | #  pattern0     pattern to index | 
|---|
 | 142 | #  ...          pattern to index | 
|---|
 | 143 | #  patternN     pattern to index | 
|---|
 | 144 | # | 
|---|
 | 145 | # Results: | 
|---|
 | 146 | #  Returns a two element list: | 
|---|
 | 147 | #    0: 1 if the procedure encountered an error, 0 otherwise. | 
|---|
 | 148 | #    1: the error result if element 0 was 1 | 
|---|
 | 149 |  | 
|---|
 | 150 | proc pkgtest::createIndex { args } { | 
|---|
 | 151 |     set parsed [parseArgs {*}$args] | 
|---|
 | 152 |     set options [lindex $parsed 0] | 
|---|
 | 153 |     set dirPath [lindex $parsed 1] | 
|---|
 | 154 |     set patternList [lindex $parsed 2] | 
|---|
 | 155 |  | 
|---|
 | 156 |     file mkdir $dirPath | 
|---|
 | 157 |  | 
|---|
 | 158 |     if {[catch { | 
|---|
 | 159 |         file delete [file join $dirPath pkgIndex.tcl] | 
|---|
 | 160 |         pkg_mkIndex {*}$options $dirPath {*}$patternList | 
|---|
 | 161 |     } err]} { | 
|---|
 | 162 |         return [list 1 $err] | 
|---|
 | 163 |     } | 
|---|
 | 164 |  | 
|---|
 | 165 |     return [list 0 {}] | 
|---|
 | 166 | } | 
|---|
 | 167 |  | 
|---|
 | 168 | # makePkgList -- | 
|---|
 | 169 | # | 
|---|
 | 170 | #  Takes the output of a pkgtest::parseIndex call, filters it and returns a | 
|---|
 | 171 | #  cleaned up list of packages and their actions. | 
|---|
 | 172 | # | 
|---|
 | 173 | # Arguments: | 
|---|
 | 174 | #  inList       output from a pkgtest::parseIndex. | 
|---|
 | 175 | # | 
|---|
 | 176 | # Results: | 
|---|
 | 177 | #  Returns a list of two element lists: | 
|---|
 | 178 | #    0: the name:version | 
|---|
 | 179 | #    1: a list describing the package. | 
|---|
 | 180 | #       For tclPkgSetup packages it consists of: | 
|---|
 | 181 | #        0: the keyword tclPkgSetup | 
|---|
 | 182 | #        1: the first file to source, with its exported procedures | 
|---|
 | 183 | #        2: the second file ... | 
|---|
 | 184 | #        N: the N-1st file ... | 
|---|
 | 185 |  | 
|---|
 | 186 | proc makePkgList { inList } { | 
|---|
 | 187 |     set pkgList "" | 
|---|
 | 188 |  | 
|---|
 | 189 |     foreach {k v} $inList { | 
|---|
 | 190 |         switch [lindex $v 0] { | 
|---|
 | 191 |             tclPkgSetup { | 
|---|
 | 192 |                 set l tclPkgSetup | 
|---|
 | 193 |                 foreach s [lindex $v 4] { | 
|---|
 | 194 |                     lappend l $s | 
|---|
 | 195 |                 } | 
|---|
 | 196 |             } | 
|---|
 | 197 |  | 
|---|
 | 198 |             source { | 
|---|
 | 199 |                 set l $v | 
|---|
 | 200 |             } | 
|---|
 | 201 |  | 
|---|
 | 202 |             default { | 
|---|
 | 203 |                 error "can't handle $k $v" | 
|---|
 | 204 |             } | 
|---|
 | 205 |         } | 
|---|
 | 206 |  | 
|---|
 | 207 |         lappend pkgList [list $k $l] | 
|---|
 | 208 |     } | 
|---|
 | 209 |  | 
|---|
 | 210 |     return $pkgList | 
|---|
 | 211 | } | 
|---|
 | 212 |  | 
|---|
 | 213 | # pkgtest::runIndex -- | 
|---|
 | 214 | # | 
|---|
 | 215 | #  Runs pkg_mkIndex, parses the generated index file. | 
|---|
 | 216 | # | 
|---|
 | 217 | # Arguments: | 
|---|
 | 218 | #  <flags>      (optional) arguments starting with a dash are collected | 
|---|
 | 219 | #               as options to pkg_mkIndex and passed to pkg_mkIndex. | 
|---|
 | 220 | #  dirPath      the directory to index | 
|---|
 | 221 | #  pattern0     pattern to index | 
|---|
 | 222 | #  ...          pattern to index | 
|---|
 | 223 | #  patternN     pattern to index | 
|---|
 | 224 | # | 
|---|
 | 225 | # Results: | 
|---|
 | 226 | #  Returns a two element list: | 
|---|
 | 227 | #    0: 1 if the procedure encountered an error, 0 otherwise. | 
|---|
 | 228 | #    1: if no error, this is the parsed generated index file, in the format | 
|---|
 | 229 | #       returned by pkgtest::parseIndex. | 
|---|
 | 230 | #       If error, this is the error result. | 
|---|
 | 231 |  | 
|---|
 | 232 | proc pkgtest::runCreatedIndex {rv args} { | 
|---|
 | 233 |     if {[lindex $rv 0] == 0} { | 
|---|
 | 234 |         set parsed [parseArgs {*}$args] | 
|---|
 | 235 |         set dirPath [lindex $parsed 1] | 
|---|
 | 236 |         set idxFile [file join $dirPath pkgIndex.tcl] | 
|---|
 | 237 |  | 
|---|
 | 238 |         if {[catch { | 
|---|
 | 239 |             set result [list 0 [makePkgList [parseIndex $idxFile]]] | 
|---|
 | 240 |         } err]} { | 
|---|
 | 241 |             set result [list 1 $err] | 
|---|
 | 242 |         }  | 
|---|
 | 243 |         file delete $idxFile | 
|---|
 | 244 |     } else { | 
|---|
 | 245 |         set result $rv | 
|---|
 | 246 |     } | 
|---|
 | 247 |  | 
|---|
 | 248 |     return $result | 
|---|
 | 249 | } | 
|---|
 | 250 | proc pkgtest::runIndex { args } { | 
|---|
 | 251 |     set rv [createIndex {*}$args] | 
|---|
 | 252 |     return [runCreatedIndex $rv {*}$args] | 
|---|
 | 253 | } | 
|---|
 | 254 |  | 
|---|
 | 255 | # If there is no match to the patterns, make sure the directory hasn't | 
|---|
 | 256 | # changed on us | 
|---|
 | 257 |  | 
|---|
 | 258 | test pkgMkIndex-1.1 {nothing matches pattern - current dir is the same} { | 
|---|
 | 259 |     list [pkgtest::runIndex -lazy $fullPkgPath nomatch.tcl] [pwd] | 
|---|
 | 260 | } [list {1 {no files matched glob pattern "nomatch.tcl"}} [pwd]] | 
|---|
 | 261 |  | 
|---|
 | 262 | makeFile { | 
|---|
 | 263 | #  This is a simple package, just to check basic functionality. | 
|---|
 | 264 | package provide simple 1.0 | 
|---|
 | 265 | namespace eval simple { | 
|---|
 | 266 |     namespace export lower upper | 
|---|
 | 267 | } | 
|---|
 | 268 | proc simple::lower { stg } { | 
|---|
 | 269 |     return [string tolower $stg] | 
|---|
 | 270 | } | 
|---|
 | 271 | proc simple::upper { stg } { | 
|---|
 | 272 |     return [string toupper $stg] | 
|---|
 | 273 | } | 
|---|
 | 274 | } [file join pkg simple.tcl] | 
|---|
 | 275 |  | 
|---|
 | 276 | test pkgMkIndex-2.1 {simple package} { | 
|---|
 | 277 |     pkgtest::runIndex -lazy $fullPkgPath simple.tcl | 
|---|
 | 278 | } {0 {{simple:1.0 {tclPkgSetup {simple.tcl source {::simple::lower ::simple::upper}}}}}} | 
|---|
 | 279 |  | 
|---|
 | 280 | test pkgMkIndex-2.2 {simple package - use -direct} { | 
|---|
 | 281 |     pkgtest::runIndex -direct $fullPkgPath simple.tcl | 
|---|
 | 282 | } "0 {{simple:1.0 {[list source [file join $fullPkgPath simple.tcl]]}}}" | 
|---|
 | 283 |  | 
|---|
 | 284 | test pkgMkIndex-2.3 {simple package - direct loading is default} { | 
|---|
 | 285 |     pkgtest::runIndex $fullPkgPath simple.tcl | 
|---|
 | 286 | } "0 {{simple:1.0 {[list source [file join $fullPkgPath simple.tcl]]}}}" | 
|---|
 | 287 |  | 
|---|
 | 288 | test pkgMkIndex-2.4 {simple package - use -verbose} -body { | 
|---|
 | 289 |     pkgtest::runIndex -verbose $fullPkgPath simple.tcl | 
|---|
 | 290 | } -result "0 {{simple:1.0 {[list source [file join $fullPkgPath simple.tcl]]}}}" \ | 
|---|
 | 291 |     -errorOutput {successful sourcing of simple.tcl | 
|---|
 | 292 | packages provided were {simple 1.0} | 
|---|
 | 293 | processed simple.tcl | 
|---|
 | 294 | } | 
|---|
 | 295 |  | 
|---|
 | 296 | removeFile [file join pkg simple.tcl] | 
|---|
 | 297 |  | 
|---|
 | 298 | makeFile { | 
|---|
 | 299 | #  Contains global symbols, used to check that they don't have a leading :: | 
|---|
 | 300 | package provide global 1.0 | 
|---|
 | 301 | proc global_lower { stg } { | 
|---|
 | 302 |     return [string tolower $stg] | 
|---|
 | 303 | } | 
|---|
 | 304 | proc global_upper { stg } { | 
|---|
 | 305 |     return [string toupper $stg] | 
|---|
 | 306 | } | 
|---|
 | 307 | } [file join pkg global.tcl] | 
|---|
 | 308 |  | 
|---|
 | 309 | test pkgMkIndex-3.1 {simple package with global symbols} { | 
|---|
 | 310 |     pkgtest::runIndex -lazy $fullPkgPath global.tcl | 
|---|
 | 311 | } {0 {{global:1.0 {tclPkgSetup {global.tcl source {global_lower global_upper}}}}}} | 
|---|
 | 312 |  | 
|---|
 | 313 | removeFile [file join pkg global.tcl] | 
|---|
 | 314 |  | 
|---|
 | 315 | makeFile { | 
|---|
 | 316 | #  This package is required by pkg1. | 
|---|
 | 317 | #  This package is split into two files, to test packages that are split | 
|---|
 | 318 | #  over multiple files. | 
|---|
 | 319 | package provide pkg2 1.0 | 
|---|
 | 320 | namespace eval pkg2 { | 
|---|
 | 321 |     namespace export p2-1 | 
|---|
 | 322 | } | 
|---|
 | 323 | proc pkg2::p2-1 { num } { | 
|---|
 | 324 |     return [expr $num * 2] | 
|---|
 | 325 | } | 
|---|
 | 326 | } [file join pkg pkg2_a.tcl] | 
|---|
 | 327 |  | 
|---|
 | 328 | makeFile { | 
|---|
 | 329 | #  This package is required by pkg1. | 
|---|
 | 330 | #  This package is split into two files, to test packages that are split | 
|---|
 | 331 | #  over multiple files. | 
|---|
 | 332 | package provide pkg2 1.0 | 
|---|
 | 333 | namespace eval pkg2 { | 
|---|
 | 334 |     namespace export p2-2 | 
|---|
 | 335 | } | 
|---|
 | 336 | proc pkg2::p2-2 { num } { | 
|---|
 | 337 |     return [expr $num * 3] | 
|---|
 | 338 | } | 
|---|
 | 339 | } [file join pkg pkg2_b.tcl] | 
|---|
 | 340 |  | 
|---|
 | 341 | test pkgMkIndex-4.1 {split package} { | 
|---|
 | 342 |     pkgtest::runIndex -lazy $fullPkgPath pkg2_a.tcl pkg2_b.tcl | 
|---|
 | 343 | } {0 {{pkg2:1.0 {tclPkgSetup {pkg2_a.tcl source ::pkg2::p2-1} {pkg2_b.tcl source ::pkg2::p2-2}}}}} | 
|---|
 | 344 |  | 
|---|
 | 345 | test pkgMkIndex-4.2 {split package - direct loading} { | 
|---|
 | 346 |     pkgtest::runIndex -direct $fullPkgPath pkg2_a.tcl pkg2_b.tcl | 
|---|
 | 347 | } "0 {{pkg2:1.0 {[list source [file join $fullPkgPath pkg2_a.tcl]] | 
|---|
 | 348 | [list source [file join $fullPkgPath pkg2_b.tcl]]}}}" | 
|---|
 | 349 |  | 
|---|
 | 350 | # Add the direct1 directory to auto_path, so that the direct1 package  | 
|---|
 | 351 | # can be found. | 
|---|
 | 352 | set direct1 [makeDirectory direct1] | 
|---|
 | 353 | lappend auto_path $direct1 | 
|---|
 | 354 | makeFile { | 
|---|
 | 355 | #  This is referenced by pkgIndex.tcl as a -direct script. | 
|---|
 | 356 | package provide direct1 1.0 | 
|---|
 | 357 | namespace eval direct1 { | 
|---|
 | 358 |     namespace export pd1 pd2 | 
|---|
 | 359 | } | 
|---|
 | 360 | proc direct1::pd1 { stg } { | 
|---|
 | 361 |     return [string tolower $stg] | 
|---|
 | 362 | } | 
|---|
 | 363 | proc direct1::pd2 { stg } { | 
|---|
 | 364 |     return [string toupper $stg] | 
|---|
 | 365 | } | 
|---|
 | 366 | } [file join direct1 direct1.tcl] | 
|---|
 | 367 | pkg_mkIndex -direct $direct1 direct1.tcl | 
|---|
 | 368 |  | 
|---|
 | 369 | makeFile { | 
|---|
 | 370 | #  Does a package require of direct1, whose pkgIndex.tcl entry | 
|---|
 | 371 | #  is created above with option -direct.  This tests that pkg_mkIndex | 
|---|
 | 372 | #  can handle code that is sourced in pkgIndex.tcl files. | 
|---|
 | 373 | package require direct1 | 
|---|
 | 374 | package provide std 1.0 | 
|---|
 | 375 | namespace eval std { | 
|---|
 | 376 |     namespace export p1 p2 | 
|---|
 | 377 | } | 
|---|
 | 378 | proc std::p1 { stg } { | 
|---|
 | 379 |     return [string tolower $stg] | 
|---|
 | 380 | } | 
|---|
 | 381 | proc std::p2 { stg } { | 
|---|
 | 382 |     return [string toupper $stg] | 
|---|
 | 383 | } | 
|---|
 | 384 | } [file join pkg std.tcl] | 
|---|
 | 385 |  | 
|---|
 | 386 | test pkgMkIndex-5.1 {requires -direct package} { | 
|---|
 | 387 |     pkgtest::runIndex -lazy $fullPkgPath std.tcl | 
|---|
 | 388 | } {0 {{std:1.0 {tclPkgSetup {std.tcl source {::std::p1 ::std::p2}}}}}} | 
|---|
 | 389 |  | 
|---|
 | 390 | removeFile [file join direct1 direct1.tcl] | 
|---|
 | 391 | file delete [file join $direct1 pkgIndex.tcl] | 
|---|
 | 392 | removeDirectory direct1 | 
|---|
 | 393 | removeFile [file join pkg std.tcl] | 
|---|
 | 394 |  | 
|---|
 | 395 | makeFile { | 
|---|
 | 396 | #  This package requires pkg3, but it does | 
|---|
 | 397 | #  not use any of pkg3's procs in the code that is executed by the file | 
|---|
 | 398 | #  (i.e. references to pkg3's procs are in the proc bodies only). | 
|---|
 | 399 | package require pkg3 1.0 | 
|---|
 | 400 | package provide pkg1 1.0 | 
|---|
 | 401 | namespace eval pkg1 { | 
|---|
 | 402 |     namespace export p1-1 p1-2 | 
|---|
 | 403 | } | 
|---|
 | 404 | proc pkg1::p1-1 { num } { | 
|---|
 | 405 |     return [pkg3::p3-1 $num] | 
|---|
 | 406 | } | 
|---|
 | 407 | proc pkg1::p1-2 { num } { | 
|---|
 | 408 |     return [pkg3::p3-2 $num] | 
|---|
 | 409 | } | 
|---|
 | 410 | } [file join pkg pkg1.tcl] | 
|---|
 | 411 |  | 
|---|
 | 412 | makeFile { | 
|---|
 | 413 | package provide pkg3 1.0 | 
|---|
 | 414 | namespace eval pkg3 { | 
|---|
 | 415 |     namespace export p3-1 p3-2 | 
|---|
 | 416 | } | 
|---|
 | 417 | proc pkg3::p3-1 { num } { | 
|---|
 | 418 |     return {[expr $num * 2]} | 
|---|
 | 419 | } | 
|---|
 | 420 | proc pkg3::p3-2 { num } { | 
|---|
 | 421 |     return {[expr $num * 3]} | 
|---|
 | 422 | } | 
|---|
 | 423 | } [file join pkg pkg3.tcl] | 
|---|
 | 424 |  | 
|---|
 | 425 | test pkgMkIndex-6.1 {pkg1 requires pkg3} { | 
|---|
 | 426 |     pkgtest::runIndex -lazy $fullPkgPath pkg1.tcl pkg3.tcl | 
|---|
 | 427 | } {0 {{pkg1:1.0 {tclPkgSetup {pkg1.tcl source {::pkg1::p1-1 ::pkg1::p1-2}}}} {pkg3:1.0 {tclPkgSetup {pkg3.tcl source {::pkg3::p3-1 ::pkg3::p3-2}}}}}} | 
|---|
 | 428 |  | 
|---|
 | 429 | test pkgMkIndex-6.2 {pkg1 requires pkg3 - use -direct} { | 
|---|
 | 430 |     pkgtest::runIndex -direct $fullPkgPath pkg1.tcl pkg3.tcl | 
|---|
 | 431 | } "0 {{pkg1:1.0 {[list source [file join $fullPkgPath pkg1.tcl]]}} {pkg3:1.0 {[list source [file join $fullPkgPath pkg3.tcl]]}}}" | 
|---|
 | 432 |  | 
|---|
 | 433 | removeFile [file join pkg pkg1.tcl] | 
|---|
 | 434 |  | 
|---|
 | 435 | makeFile { | 
|---|
 | 436 | #  This package requires pkg3, and it calls | 
|---|
 | 437 | #  a pkg3 proc in the code that is executed by the file | 
|---|
 | 438 | package require pkg3 1.0 | 
|---|
 | 439 | package provide pkg4 1.0 | 
|---|
 | 440 | namespace eval pkg4 { | 
|---|
 | 441 |     namespace export p4-1 p4-2 | 
|---|
 | 442 |     variable m2 [pkg3::p3-1 10] | 
|---|
 | 443 | } | 
|---|
 | 444 | proc pkg4::p4-1 { num } { | 
|---|
 | 445 |     variable m2 | 
|---|
 | 446 |     return [expr {$m2 * $num}] | 
|---|
 | 447 | } | 
|---|
 | 448 | proc pkg4::p4-2 { num } { | 
|---|
 | 449 |     return [pkg3::p3-2 $num] | 
|---|
 | 450 | } | 
|---|
 | 451 | } [file join pkg pkg4.tcl] | 
|---|
 | 452 |  | 
|---|
 | 453 | test pkgMkIndex-7.1 {pkg4 uses pkg3} { | 
|---|
 | 454 |     pkgtest::runIndex -lazy $fullPkgPath pkg4.tcl pkg3.tcl | 
|---|
 | 455 | } {0 {{pkg3:1.0 {tclPkgSetup {pkg3.tcl source {::pkg3::p3-1 ::pkg3::p3-2}}}} {pkg4:1.0 {tclPkgSetup {pkg4.tcl source {::pkg4::p4-1 ::pkg4::p4-2}}}}}} | 
|---|
 | 456 |  | 
|---|
 | 457 | test pkgMkIndex-7.2 {pkg4 uses pkg3 - use -direct} { | 
|---|
 | 458 |     pkgtest::runIndex -direct $fullPkgPath pkg4.tcl pkg3.tcl | 
|---|
 | 459 | } "0 {{pkg3:1.0 {[list source [file join $fullPkgPath pkg3.tcl]]}} {pkg4:1.0 {[list source [file join $fullPkgPath pkg4.tcl]]}}}" | 
|---|
 | 460 |  | 
|---|
 | 461 | removeFile [file join pkg pkg4.tcl] | 
|---|
 | 462 | removeFile [file join pkg pkg3.tcl] | 
|---|
 | 463 |  | 
|---|
 | 464 | makeFile { | 
|---|
 | 465 | #  This package requires pkg2, and it calls | 
|---|
 | 466 | #  a pkg2 proc in the code that is executed by the file. | 
|---|
 | 467 | #  Pkg2 is a split package. | 
|---|
 | 468 | package require pkg2 1.0 | 
|---|
 | 469 | package provide pkg5 1.0 | 
|---|
 | 470 | namespace eval pkg5 { | 
|---|
 | 471 |     namespace export p5-1 p5-2 | 
|---|
 | 472 |     variable m2 [pkg2::p2-1 10] | 
|---|
 | 473 |     variable m3 [pkg2::p2-2 10] | 
|---|
 | 474 | } | 
|---|
 | 475 | proc pkg5::p5-1 { num } { | 
|---|
 | 476 |     variable m2 | 
|---|
 | 477 |     return [expr {$m2 * $num}] | 
|---|
 | 478 | } | 
|---|
 | 479 | proc pkg5::p5-2 { num } { | 
|---|
 | 480 |     variable m2 | 
|---|
 | 481 |     return [expr {$m2 * $num}] | 
|---|
 | 482 | } | 
|---|
 | 483 | } [file join pkg pkg5.tcl] | 
|---|
 | 484 |  | 
|---|
 | 485 | test pkgMkIndex-8.1 {pkg5 uses pkg2} { | 
|---|
 | 486 |     pkgtest::runIndex -lazy $fullPkgPath pkg5.tcl pkg2_a.tcl pkg2_b.tcl | 
|---|
 | 487 | } {0 {{pkg2:1.0 {tclPkgSetup {pkg2_a.tcl source ::pkg2::p2-1} {pkg2_b.tcl source ::pkg2::p2-2}}} {pkg5:1.0 {tclPkgSetup {pkg5.tcl source {::pkg5::p5-1 ::pkg5::p5-2}}}}}} | 
|---|
 | 488 |  | 
|---|
 | 489 | test pkgMkIndex-8.2 {pkg5 uses pkg2 - use -direct} { | 
|---|
 | 490 |     pkgtest::runIndex -direct $fullPkgPath pkg5.tcl pkg2_a.tcl pkg2_b.tcl | 
|---|
 | 491 | } "0 {{pkg2:1.0 {[list source [file join $fullPkgPath pkg2_a.tcl]] | 
|---|
 | 492 | [list source [file join $fullPkgPath pkg2_b.tcl]]}} {pkg5:1.0 {[list source [file join $fullPkgPath pkg5.tcl]]}}}" | 
|---|
 | 493 |  | 
|---|
 | 494 | removeFile [file join pkg pkg5.tcl] | 
|---|
 | 495 | removeFile [file join pkg pkg2_a.tcl] | 
|---|
 | 496 | removeFile [file join pkg pkg2_b.tcl] | 
|---|
 | 497 |  | 
|---|
 | 498 | makeFile { | 
|---|
 | 499 | #  This package requires circ2, and circ2 | 
|---|
 | 500 | #  requires circ3, which in turn requires circ1. | 
|---|
 | 501 | #  In case of cirularities, pkg_mkIndex should give up when it gets stuck. | 
|---|
 | 502 | package require circ2 1.0 | 
|---|
 | 503 | package provide circ1 1.0 | 
|---|
 | 504 | namespace eval circ1 { | 
|---|
 | 505 |     namespace export c1-1 c1-2 c1-3 c1-4 | 
|---|
 | 506 | } | 
|---|
 | 507 | proc circ1::c1-1 { num } { | 
|---|
 | 508 |     return [circ2::c2-1 $num] | 
|---|
 | 509 | } | 
|---|
 | 510 | proc circ1::c1-2 { num } { | 
|---|
 | 511 |     return [circ2::c2-2 $num] | 
|---|
 | 512 | } | 
|---|
 | 513 | proc circ1::c1-3 {} { | 
|---|
 | 514 |     return 10 | 
|---|
 | 515 | } | 
|---|
 | 516 | proc circ1::c1-4 {} { | 
|---|
 | 517 |     return 20 | 
|---|
 | 518 | } | 
|---|
 | 519 | } [file join pkg circ1.tcl] | 
|---|
 | 520 |  | 
|---|
 | 521 | makeFile { | 
|---|
 | 522 | #  This package is required by circ1, and | 
|---|
 | 523 | #  requires circ3. Circ3, in turn, requires circ1 to give us a circularity. | 
|---|
 | 524 | package require circ3 1.0 | 
|---|
 | 525 | package provide circ2 1.0 | 
|---|
 | 526 | namespace eval circ2 { | 
|---|
 | 527 |     namespace export c2-1 c2-2 | 
|---|
 | 528 | } | 
|---|
 | 529 | proc circ2::c2-1 { num } { | 
|---|
 | 530 |     return [expr $num * [circ3::c3-1]] | 
|---|
 | 531 | } | 
|---|
 | 532 | proc circ2::c2-2 { num } { | 
|---|
 | 533 |     return [expr $num * [circ3::c3-2]] | 
|---|
 | 534 | } | 
|---|
 | 535 | } [file join pkg circ2.tcl] | 
|---|
 | 536 |  | 
|---|
 | 537 | makeFile { | 
|---|
 | 538 | #  This package is required by circ2, and in | 
|---|
 | 539 | #  turn requires circ1. This closes the circularity. | 
|---|
 | 540 | package require circ1 1.0 | 
|---|
 | 541 | package provide circ3 1.0 | 
|---|
 | 542 | namespace eval circ3 { | 
|---|
 | 543 |     namespace export c3-1 c3-4 | 
|---|
 | 544 | } | 
|---|
 | 545 | proc circ3::c3-1 {} { | 
|---|
 | 546 |     return [circ1::c1-3] | 
|---|
 | 547 | } | 
|---|
 | 548 | proc circ3::c3-2 {} { | 
|---|
 | 549 |     return [circ1::c1-4] | 
|---|
 | 550 | } | 
|---|
 | 551 | } [file join pkg circ3.tcl] | 
|---|
 | 552 |  | 
|---|
 | 553 | test pkgMkIndex-9.1 {circular packages} { | 
|---|
 | 554 |     pkgtest::runIndex -lazy $fullPkgPath circ1.tcl circ2.tcl circ3.tcl | 
|---|
 | 555 | } {0 {{circ1:1.0 {tclPkgSetup {circ1.tcl source {::circ1::c1-1 ::circ1::c1-2 ::circ1::c1-3 ::circ1::c1-4}}}} {circ2:1.0 {tclPkgSetup {circ2.tcl source {::circ2::c2-1 ::circ2::c2-2}}}} {circ3:1.0 {tclPkgSetup {circ3.tcl source ::circ3::c3-1}}}}} | 
|---|
 | 556 |  | 
|---|
 | 557 | removeFile [file join pkg circ1.tcl] | 
|---|
 | 558 | removeFile [file join pkg circ2.tcl] | 
|---|
 | 559 | removeFile [file join pkg circ3.tcl] | 
|---|
 | 560 |  | 
|---|
 | 561 | # Some tests require the existence of one of the DLLs in the dltest directory | 
|---|
 | 562 | set x [file join [file dirname [info nameofexecutable]] dltest \ | 
|---|
 | 563 |         pkga[info sharedlibextension]] | 
|---|
 | 564 | set dll "[file tail $x]Required" | 
|---|
 | 565 | testConstraint $dll [file exists $x] | 
|---|
 | 566 |  | 
|---|
 | 567 | if {[testConstraint $dll]} { | 
|---|
 | 568 |     makeFile { | 
|---|
 | 569 | #  This package provides Pkga, which is also provided by a DLL. | 
|---|
 | 570 | package provide Pkga 1.0 | 
|---|
 | 571 | proc pkga_neq { x } { | 
|---|
 | 572 |     return [expr {! [pkgq_eq $x]}] | 
|---|
 | 573 | } | 
|---|
 | 574 | } [file join pkg pkga.tcl] | 
|---|
 | 575 |     file copy -force $x $fullPkgPath | 
|---|
 | 576 | } | 
|---|
 | 577 | testConstraint exec [llength [info commands ::exec]] | 
|---|
 | 578 |  | 
|---|
 | 579 | test pkgMkIndex-10.1 {package in DLL and script} [list exec $dll] { | 
|---|
 | 580 |     # Do all [load]ing of shared libraries in another process, so  | 
|---|
 | 581 |     # we can delete the file and not get stuck because we're holding | 
|---|
 | 582 |     # a reference to it. | 
|---|
 | 583 |     set cmd [list pkg_mkIndex -lazy $fullPkgPath [file tail $x] pkga.tcl] | 
|---|
 | 584 |     exec [interpreter] << $cmd | 
|---|
 | 585 |     pkgtest::runCreatedIndex {0 {}} -lazy $fullPkgPath pkga[info sharedlibextension] pkga.tcl | 
|---|
 | 586 | } "0 {{Pkga:1.0 {tclPkgSetup {pkga[info sharedlibextension] load {pkga_eq pkga_quote}} {pkga.tcl source pkga_neq}}}}" | 
|---|
 | 587 | test pkgMkIndex-10.2 {package in DLL hidden by -load} [list exec $dll] { | 
|---|
 | 588 |     # Do all [load]ing of shared libraries in another process, so  | 
|---|
 | 589 |     # we can delete the file and not get stuck because we're holding | 
|---|
 | 590 |     # a reference to it. | 
|---|
 | 591 |     # | 
|---|
 | 592 |     # This test depends on context from prior test, so repeat it. | 
|---|
 | 593 |     set script "[list pkg_mkIndex -lazy $fullPkgPath [file tail $x] pkga.tcl]\n" | 
|---|
 | 594 |     append script \ | 
|---|
 | 595 |             "[list pkg_mkIndex -lazy -load Pkg* $fullPkgPath [file tail $x]]" | 
|---|
 | 596 |     exec [interpreter] << $script | 
|---|
 | 597 |     pkgtest::runCreatedIndex {0 {}} -lazy -load Pkg* -- $fullPkgPath pkga[info sharedlibextension] | 
|---|
 | 598 | } {0 {}} | 
|---|
 | 599 |  | 
|---|
 | 600 | if {[testConstraint $dll]} { | 
|---|
 | 601 |     file delete -force [file join $fullPkgPath [file tail $x]] | 
|---|
 | 602 |     removeFile [file join pkg pkga.tcl] | 
|---|
 | 603 | } | 
|---|
 | 604 |  | 
|---|
 | 605 | # Tolerate "namespace import" at the global scope | 
|---|
 | 606 |  | 
|---|
 | 607 | makeFile { | 
|---|
 | 608 | package provide fubar 1.0 | 
|---|
 | 609 | namespace eval ::fubar:: { | 
|---|
 | 610 |     # | 
|---|
 | 611 |     # export only public functions. | 
|---|
 | 612 |     # | 
|---|
 | 613 |     namespace export {[a-z]*} | 
|---|
 | 614 | } | 
|---|
 | 615 | proc ::fubar::foo {bar} { | 
|---|
 | 616 |     puts "$bar" | 
|---|
 | 617 |     return true | 
|---|
 | 618 | } | 
|---|
 | 619 | namespace import ::fubar::foo | 
|---|
 | 620 | } [file join pkg import.tcl] | 
|---|
 | 621 |  | 
|---|
 | 622 | test pkgMkIndex-11.1 {conflicting namespace imports} { | 
|---|
 | 623 |     pkgtest::runIndex -lazy $fullPkgPath import.tcl | 
|---|
 | 624 | } {0 {{fubar:1.0 {tclPkgSetup {import.tcl source ::fubar::foo}}}}} | 
|---|
 | 625 |  | 
|---|
 | 626 | removeFile [file join pkg import.tcl] | 
|---|
 | 627 |  | 
|---|
 | 628 | # Verify that the auto load list generated is correct even when there | 
|---|
 | 629 | # is a proc name conflict between two namespaces (ie, ::foo::baz and | 
|---|
 | 630 | # ::bar::baz) | 
|---|
 | 631 |  | 
|---|
 | 632 | makeFile { | 
|---|
 | 633 | package provide football 1.0 | 
|---|
 | 634 | namespace eval ::pro:: { | 
|---|
 | 635 |     # | 
|---|
 | 636 |     # export only public functions. | 
|---|
 | 637 |     # | 
|---|
 | 638 |     namespace export {[a-z]*} | 
|---|
 | 639 | } | 
|---|
 | 640 | namespace eval ::college:: { | 
|---|
 | 641 |     # | 
|---|
 | 642 |     # export only public functions. | 
|---|
 | 643 |     # | 
|---|
 | 644 |     namespace export {[a-z]*} | 
|---|
 | 645 | } | 
|---|
 | 646 | proc ::pro::team {} { | 
|---|
 | 647 |     puts "go packers!" | 
|---|
 | 648 |     return true | 
|---|
 | 649 | } | 
|---|
 | 650 | proc ::college::team {} { | 
|---|
 | 651 |     puts "go badgers!" | 
|---|
 | 652 |     return true | 
|---|
 | 653 | } | 
|---|
 | 654 | } [file join pkg samename.tcl] | 
|---|
 | 655 |  | 
|---|
 | 656 | test pkgMkIndex-12.1 {same name procs in different namespace} { | 
|---|
 | 657 |     pkgtest::runIndex -lazy $fullPkgPath samename.tcl | 
|---|
 | 658 | } {0 {{football:1.0 {tclPkgSetup {samename.tcl source {::college::team ::pro::team}}}}}} | 
|---|
 | 659 |  | 
|---|
 | 660 | removeFile [file join pkg samename.tcl] | 
|---|
 | 661 |  | 
|---|
 | 662 | # Proc names with embedded spaces are properly listed (ie, correct number of | 
|---|
 | 663 | # braces) in result | 
|---|
 | 664 | makeFile { | 
|---|
 | 665 | package provide spacename 1.0 | 
|---|
 | 666 | proc {a b} {} {} | 
|---|
 | 667 | proc {c d} {} {} | 
|---|
 | 668 | } [file join pkg spacename.tcl] | 
|---|
 | 669 |  | 
|---|
 | 670 | test pkgMkIndex-13.1 {proc names with embedded spaces} { | 
|---|
 | 671 |     pkgtest::runIndex -lazy $fullPkgPath spacename.tcl | 
|---|
 | 672 | } {0 {{spacename:1.0 {tclPkgSetup {spacename.tcl source {{a b} {c d}}}}}}} | 
|---|
 | 673 |  | 
|---|
 | 674 | removeFile [file join pkg spacename.tcl] | 
|---|
 | 675 |  | 
|---|
 | 676 | # Test the tcl::Pkg::CompareExtension helper function | 
|---|
 | 677 | test pkgMkIndex-14.1 {tcl::Pkg::CompareExtension} {unix} { | 
|---|
 | 678 |     tcl::Pkg::CompareExtension foo.so .so | 
|---|
 | 679 | } 1 | 
|---|
 | 680 | test pkgMkIndex-14.2 {tcl::Pkg::CompareExtension} {unix} { | 
|---|
 | 681 |     tcl::Pkg::CompareExtension foo.so.bar .so | 
|---|
 | 682 | } 0 | 
|---|
 | 683 | test pkgMkIndex-14.3 {tcl::Pkg::CompareExtension} {unix} { | 
|---|
 | 684 |     tcl::Pkg::CompareExtension foo.so.1 .so | 
|---|
 | 685 | } 1 | 
|---|
 | 686 | test pkgMkIndex-14.4 {tcl::Pkg::CompareExtension} {unix} { | 
|---|
 | 687 |     tcl::Pkg::CompareExtension foo.so.1.2 .so | 
|---|
 | 688 | } 1 | 
|---|
 | 689 | test pkgMkIndex-14.5 {tcl::Pkg::CompareExtension} {unix} { | 
|---|
 | 690 |     tcl::Pkg::CompareExtension foo .so | 
|---|
 | 691 | } 0 | 
|---|
 | 692 | test pkgMkIndex-14.6 {tcl::Pkg::CompareExtension} {unix} { | 
|---|
 | 693 |     tcl::Pkg::CompareExtension foo.so.1.2.bar .so | 
|---|
 | 694 | } 0 | 
|---|
 | 695 |  | 
|---|
 | 696 | # cleanup | 
|---|
 | 697 |  | 
|---|
 | 698 | removeDirectory pkg | 
|---|
 | 699 |  | 
|---|
 | 700 | namespace delete pkgtest | 
|---|
 | 701 | ::tcltest::cleanupTests | 
|---|
 | 702 | return | 
|---|
 | 703 |  | 
|---|