| 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 | |
|---|