Index: Externals/Eagle/bin/Eagle.dll ================================================================== --- Externals/Eagle/bin/Eagle.dll +++ Externals/Eagle/bin/Eagle.dll cannot compute difference between binary files Index: Externals/Eagle/bin/EagleShell.exe ================================================================== --- Externals/Eagle/bin/EagleShell.exe +++ Externals/Eagle/bin/EagleShell.exe cannot compute difference between binary files Index: Externals/Eagle/bin/EagleShell32.exe ================================================================== --- Externals/Eagle/bin/EagleShell32.exe +++ Externals/Eagle/bin/EagleShell32.exe cannot compute difference between binary files Index: Externals/Eagle/bin/x64/Spilornis.dll ================================================================== --- Externals/Eagle/bin/x64/Spilornis.dll +++ Externals/Eagle/bin/x64/Spilornis.dll cannot compute difference between binary files Index: Externals/Eagle/bin/x86/Spilornis.dll ================================================================== --- Externals/Eagle/bin/x86/Spilornis.dll +++ Externals/Eagle/bin/x86/Spilornis.dll cannot compute difference between binary files Index: Externals/Eagle/lib/Eagle1.0/init.eagle ================================================================== --- Externals/Eagle/lib/Eagle1.0/init.eagle +++ Externals/Eagle/lib/Eagle1.0/init.eagle @@ -2035,11 +2035,11 @@ } upvar 1 $a array if {![array exists array]} { - error "\"$a\" isn't an array" + error [appendArgs \" $a "\" isn't an array"] } set names [lsort [eval array names array $args]] set maxLength 0 @@ -2156,19 +2156,156 @@ set command test1 } return [uplevel 1 [list $command $name $description] $args] } + + proc isObjectHandle { value } { + set pattern [string map [list \\ \\\\ \[ \\\[ \] \\\]] $value] + set objects [info objects $pattern] + + if {[llength $objects] == 1 && [lindex $objects 0] eq $value} then { + return true + } + + return false + } + + proc isManagedType { name } { + if {[llength [info commands object]] > 0} then { + if {![isObjectHandle $name]} then { + if {[catch { + object members -matchnameonly -nameonly -pattern Equals $name + } result] == 0 && $result eq "Equals"} then { + return true + } + } + } + + return false + } + + proc canGetManagedType { name {varName ""} } { + if {[llength [info commands object]] > 0} then { + if {![isObjectHandle $name]} then { + set cultureInfo [object invoke Interpreter.GetActive CultureInfo] + set type null + + set code [object invoke -create -alias -flags +NonPublic \ + Value GetType "" $name null null None $cultureInfo type] + + if {[$code ToString] eq "Ok"} then { + if {[string length $varName] > 0} then { + upvar 1 $varName typeName + } + + set typeName [$type AssemblyQualifiedName] + + if {[isManagedType $typeName]} then { + return true + } + } + } + } + + return false + } + + proc unknownObjectInvoke { level name args } { + # + # NOTE: This is an [unknown] procedure that attempts to lookup the + # name as a CLR type and then attempts to use [object invoke] + # with it, merging options and arguments as necessary. + # + if {[llength [info commands object]] > 0 && \ + ([isManagedType $name] || [canGetManagedType $name name])} then { + # + # NOTE: Get possible options for the [object invoke] sub-command. + # + set options [object invoke Utility GetInvokeOptions Invoke] + + # + # NOTE: Create argument list for the artificial [object invoke] + # alias. This always has two arguments. + # + set arguments1 [object create ArgumentList object invoke] + + # + # NOTE: Create argument list for the entire command being handled. + # There may be options right after the command name itself. + # + set arguments2 [eval \ + object create ArgumentList [concat [list $name] $args]] + + # + # NOTE: Setup output arguments needed for the MergeArguments method. + # + set arguments3 null; set error null + + # + # NOTE: Attempt to merge the option and non-option arguments into a + # single list of arguments. + # + set code [object invoke -alias -flags +NonPublic \ + Interpreter.GetActive MergeArguments $options $arguments1 \ + $arguments2 2 1 false false arguments3 error] + + # + # NOTE: Was the argument merging process successful? + # + if {$code eq "Ok"} then { + # + # NOTE: Jump up from our call frame (and optionally that of our + # caller) and attempt to invoke the specified static object + # method with the final list of merged arguments. + # + return [uplevel [expr {$level + 1}] [$arguments3 ToString]] + } else { + # + # NOTE: Failed to merge the arguments, raise an error. + # + error [$error ToString] + } + } + + continue; # NOTE: Not handled. + } proc unknown { name args } { # - # NOTE: This is a stub unknown procedure that simply produces an - # appropriate error message. + # NOTE: This is an [unknown] procedure that normally produces an + # appropriate error message; however, it can optionally try + # to invoke a static object method. # # TODO: Add support for auto-loading packages here in the future? # - return -code error "invalid command name \"$name\"" + if {[hasRuntimeOption unknownObjectInvoke] && \ + [llength [info commands object]] > 0} then { + # + # NOTE: In the context of the caller, attempt to invoke a static + # object method using the specified arguments (which may + # contain variable names). + # + if {[catch { + eval unknownObjectInvoke 1 [list $name] $args + } result] == 0} then { + # + # NOTE: The static object method was invoked successfully. + # Return its result. + # + return -code ok $result + } elseif {[string length $result] > 0} then { + # + # NOTE: Attempting to invoke the static object method raised + # an error. Re-raise it now. If no error message was + # provided, fallback on the default (below). + # + return -code error $result + } + } + + return -code error [appendArgs "invalid command name \"" $name \"] } namespace eval ::tcl::tm { # # NOTE: Ideally, this procedure should be created in the "::tcl::tm" @@ -2195,10 +2332,20 @@ # # NOTE: This should work properly in both Tcl and Eagle. # catch {puts stderr $string} } + + proc makeProcedureFast { name fast } { + # + # NOTE: This should work properly in Eagle only. + # + catch { + uplevel 1 [list object invoke -flags +NonPublic \ + Interpreter.GetActive MakeProcedureFast $name $fast] + } + } proc makeVariableFast { name fast } { # # NOTE: This should work properly in Eagle only. # @@ -2241,10 +2388,58 @@ } foreach dir [split [exec -unicode $::env(ComSpec) /u /c dir \ /ahd /b [appendArgs \" [file nativename $pattern] \"]] \n] { set dir [string trim $dir] + + if {[string length $dir] > 0} then { + set dir [getDirResultPath $pattern $dir] + + if {[lsearch -variable -exact -nocase result $dir] == -1} then { + lappend result $dir + } + } + } + + return $result + } + + proc findDirectoriesRecursive { pattern } { + # + # NOTE: Block non-Windows platforms since this is Windows specific. + # + if {![isWindows]} then { + error "not supported on this operating system" + } + + # + # NOTE: This should work properly in Eagle only. + # + set dir ""; set result [list] + + # + # HACK: Optimize the variable access in this procedure to be + # as fast as possible. + # + makeVariableFast dir true; makeVariableFast result true + + foreach dir [split [exec -unicode $::env(ComSpec) /u /c dir \ + /ad /s /b [appendArgs \" [file nativename $pattern] \"]] \n] { + set dir [string trim $dir] + + if {[string length $dir] > 0} then { + set dir [getDirResultPath $pattern $dir] + + if {[lsearch -variable -exact -nocase result $dir] == -1} then { + lappend result $dir + } + } + } + + foreach dir [split [exec -unicode $::env(ComSpec) /u /c dir \ + /ahd /s /b [appendArgs \" [file nativename $pattern] \"]] \n] { + set dir [string trim $dir] if {[string length $dir] > 0} then { set dir [getDirResultPath $pattern $dir] if {[lsearch -variable -exact -nocase result $dir] == -1} then { @@ -2395,10 +2590,78 @@ eval lappend result [glob -nocomplain -types {d hidden} \ [file normalize $pattern]] return $result } + + proc findDirectoriesRecursive { pattern } { + # + # NOTE: Block non-Windows platforms since this is Windows specific. + # + if {![isWindows]} then { + error "not supported on this operating system" + } + + # + # NOTE: This should work properly in Tcl only. + # + set result [list] + + catch { + foreach dir [split [exec $::env(ComSpec) /c dir /ad /s /b \ + [file nativename $pattern]] \n] { + set dir [string trim $dir] + + if {[string length $dir] > 0} then { + set dir [getDirResultPath $pattern $dir] + + # + # HACK: The -nocase option to [lsearch] is only available + # starting with Tcl 8.5. + # + if {$::tcl_version >= 8.5} then { + if {[lsearch -exact -nocase $result $dir] == -1} then { + lappend result $dir + } + } else { + if {[lsearch -exact [string tolower $result] \ + [string tolower $dir]] == -1} then { + lappend result $dir + } + } + } + } + } + + catch { + foreach dir [split [exec $::env(ComSpec) /c dir /ahd /s /b \ + [file nativename $pattern]] \n] { + set dir [string trim $dir] + + if {[string length $dir] > 0} then { + set dir [getDirResultPath $pattern $dir] + + # + # HACK: The -nocase option to [lsearch] is only available + # starting with Tcl 8.5. + # + if {$::tcl_version >= 8.5} then { + if {[lsearch -exact -nocase $result $dir] == -1} then { + lappend result $dir + } + } else { + if {[lsearch -exact [string tolower $result] \ + [string tolower $dir]] == -1} then { + lappend result $dir + } + } + } + } + } + + return $result + } proc findFiles { pattern } { # # NOTE: This should work properly in Tcl only. # @@ -2430,12 +2693,23 @@ set fileName [string trim $fileName] if {[string length $fileName] > 0} then { set fileName [getDirResultPath $pattern $fileName] - if {[lsearch -exact -nocase $result $fileName] == -1} then { - lappend result $fileName + # + # HACK: The -nocase option to [lsearch] is only available + # starting with Tcl 8.5. + # + if {$::tcl_version >= 8.5} then { + if {[lsearch -exact -nocase $result $fileName] == -1} then { + lappend result $fileName + } + } else { + if {[lsearch -exact [string tolower $result] \ + [string tolower $fileName]] == -1} then { + lappend result $fileName + } } } } } @@ -2445,12 +2719,23 @@ set fileName [string trim $fileName] if {[string length $fileName] > 0} then { set fileName [getDirResultPath $pattern $fileName] - if {[lsearch -exact -nocase $result $fileName] == -1} then { - lappend result $fileName + # + # HACK: The -nocase option to [lsearch] is only available + # starting with Tcl 8.5. + # + if {$::tcl_version >= 8.5} then { + if {[lsearch -exact -nocase $result $fileName] == -1} then { + lappend result $fileName + } + } else { + if {[lsearch -exact [string tolower $result] \ + [string tolower $fileName]] == -1} then { + lappend result $fileName + } } } } } @@ -2512,12 +2797,13 @@ getDictionaryValue getColumnValue getRowColumnValue tqputs tqlog \ readFile readSharedFile writeFile appendFile appendLogFile \ appendSharedFile appendSharedLogFile readAsciiFile writeAsciiFile \ readUnicodeFile writeUnicodeFile getDirResultPath addToPath \ removeFromPath execShell lshuffle ldifference filter map reduce \ - getLengthModifier debug findDirectories findFiles findFilesRecursive \ - exportAndImportPackageCommands] false false + getLengthModifier debug findDirectories findDirectoriesRecursive \ + findFiles findFilesRecursive exportAndImportPackageCommands] false \ + false ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } Index: Externals/Eagle/lib/Eagle1.0/shell.eagle ================================================================== --- Externals/Eagle/lib/Eagle1.0/shell.eagle +++ Externals/Eagle/lib/Eagle1.0/shell.eagle @@ -28,12 +28,116 @@ # # NOTE: Commands specific to initializing the Eagle interactive shell # environment should be placed here. # proc help { args } { + host result Break [appendArgs \ + "\nFor interactive help please use: #help " $args \ + "\nFor commercial support, please use: #support\n"] + + catch { + object invoke Interpreter.GetActive Host.WriteLine \ + "\nPlease press any key to continue...\n" + + set key null; object invoke Interpreter.GetActive \ + Host.ReadKey true key + } + eval lappend command #help $args; debug icommand $command - error "for interactive help please use: #help $args" + } + + proc #support {} { + # + # Shows the requirements for obtaining commercial support and/or + # redirects to the appropriate web site using the default browser. + # + + if {[catch { + package require Licensing.Enterprise + set fileName(1) [certificate current] + + if {[string length $fileName(1)] == 0} then { + error "No certificate file is available." + } + + set certificate [certificate import -alias $fileName(1)] + + if {[string length $certificate] == 0} then { + error [appendArgs \ + "No certificate is available, current file \"" \ + $fileName(1) "\" could not be imported."] + } + + if {[catch { + certificate flags -hasflags S -hasall -strict $certificate + } error(2)]} then { + error [appendArgs \ + "Support is not enabled for certificate \"" \ + [$certificate Id] " - " [$certificate EntityName] \ + "\", the original error message was: \{" $error(2) \ + \}.] + } + + set uri [$certificate -create -alias Support] + + if {[string length $uri] == 0} then { + error [appendArgs \ + "No support information found in certificate \"" \ + [$certificate Id] " - " [$certificate EntityName] \".] + } + + if {[$uri Scheme] ni [list http https]} then { + error [appendArgs \ + "Support URI scheme \"" [$uri Scheme] \ + "\" in certificate \"" [$certificate Id] " - " \ + [$certificate EntityName] "\" is not supported, " \ + "must be \"http\" or \"https\"."] + } + + exec -shell [$uri ToString] & + } error(1)]} then { + set fileName(2) [file tempname]; set fileData "" + + foreach varName [lsort [info vars]] { + if {$varName in [list fileData]} then { + continue + } + + if {$varName eq "certificate" && \ + [string length $certificate] > 0} then { + append fileData [appendArgs \n \ + [list array set certificate \ + [$certificate -flags +NonPublic \ + ToDictionary.KeysAndValuesToString \ + null false]]] + + continue + } + + if {[array exists $varName]} then { + append fileData [appendArgs \n \ + [list array set $varName [array get $varName]]] + } else { + append fileData [appendArgs \n \ + [list set $varName [set $varName]]] + } + } + + append fileData \n; writeFile $fileName(2) $fileData + set ::eagle_shell(errorFileName) $fileName(2) + + error [appendArgs \ + "\n\nIn order to obtain commercial support, at least " \ + "one of the\nfollowing requirements must be met:\n\n" \ + "\t1. Valid, non-expired commercial license agreement\n" \ + "\t for Eagle Enterprise Edition.\n\n" \ + "\t2. Valid, non-expired commercial support contract\n" \ + "\t for Eagle Standard Edition.\n\n" \ + "The original error information was saved to the file:\n\n" \ + [string repeat - 60] \n $fileName(2) \n [string repeat - 60] \ + "\n\nPlease provide this file when contacting support."] + } } ########################################################################### ############################# END Eagle ONLY ############################## ########################################################################### Index: Externals/Eagle/lib/Eagle1.0/test.eagle ================================================================== --- Externals/Eagle/lib/Eagle1.0/test.eagle +++ Externals/Eagle/lib/Eagle1.0/test.eagle @@ -235,10 +235,14 @@ proc testArrayGet { varName {integer false} } { # # NOTE: Returns the results of [array get] in a well-defined order. # + if {[string length $varName] == 0} then { + return [list] + } + upvar 1 $varName array # # NOTE: Build the command that will sort the array names into order. # @@ -479,25 +483,33 @@ "\", it does not exist\n"] } } } - proc processTestArguments { varName args } { + proc processTestArguments { varName strict args } { + # + # NOTE: Initially, there are no unknown (i.e. unprocessed) arguments. + # + set result [list] + # # NOTE: We are going to place the configured options in the variable # identified by the name provided by the caller. # - upvar 1 $varName array + if {[string length $varName] > 0} then { + upvar 1 $varName array + } # - # TODO: Add more support for standard tcltest options here. + # TODO: Add more support for standard "tcltest" options here. # set options [list \ - -breakOnLeak -configuration -constraints -exitOnComplete -file \ - -logFile -machine -match -no -notFile -platform -postTest -preTest \ - -postWait -preWait -randomOrder -skip -startFile -stopFile \ - -stopOnFailure -stopOnLeak -suffix -suite -tclsh -threshold] + -breakOnLeak -configuration -constraints -exitOnComplete \ + -file -logFile -machine -match -no -notFile -platform \ + -postTest -preTest -postWait -preWait -randomOrder -skip \ + -startFile -stopFile -stopOnFailure -stopOnLeak -suffix \ + -suite -tclsh -threshold] set length [llength $args] for {set index 0} {$index < $length} {incr index} { # @@ -537,32 +549,79 @@ # and value pattern. # if {$index + 1 < $length} then { incr index; set value [lindex $args $index] - tqputs $::test_channel [appendArgs \ - "---- unknown test option \"" $name "\" with value \"" \ - $value "\" ignored\n"] + if {!$strict && [lsearch -exact $options $value] != -1} then { + incr index -1; # HACK: Resynchronize with valid test option. + lappend result [list $name] + + tqputs $::test_channel [appendArgs \ + "---- no value for unknown test option \"" $name \ + "\", ignored, backing up one for test option \"" \ + $value \"...\n] + } else { + lappend result [list $name $value] + + tqputs $::test_channel [appendArgs \ + "---- unknown test option \"" $name "\" with value \"" \ + $value "\", ignored\n"] + } } else { + lappend result [list $name] + tqputs $::test_channel [appendArgs \ "---- no value for unknown test option \"" $name \ - "\" ignored\n"] + "\", ignored\n"] } } else { # - # NOTE: This is not an option of *any* kind that we know about. - # Ignore it and issue a warning. + # NOTE: Is there another list element available for the value? If + # not, it does not conform to the standard command line name + # and value pattern. # - tqputs $::test_channel [appendArgs \ - "---- unknown argument \"" $name "\" ignored\n"] + if {$index + 1 < $length} then { + incr index; set value [lindex $args $index] + + if {!$strict && [lsearch -exact $options $value] != -1} then { + incr index -1; # HACK: Resynchronize with valid test argument. + lappend result [list $name] + + tqputs $::test_channel [appendArgs \ + "---- no value for unknown argument \"" $name \ + "\", ignored, backing up one for test option \"" \ + $value \"...\n] + } else { + lappend result [list $name $value] + + tqputs $::test_channel [appendArgs \ + "---- unknown argument \"" $name "\" with value \"" \ + $value "\", ignored\n"] + } + } else { + # + # NOTE: This is not an option of *any* kind that we know about. + # Ignore it and issue a warning. + # + lappend result [list $name] + + tqputs $::test_channel [appendArgs \ + "---- unknown argument \"" $name "\", ignored\n"] + } } } # # NOTE: Now, attempt to flush the test log queue, if available. # tlog "" + + # + # NOTE: Return the nested list of unknown arguments, formatted as + # name/value pairs, to the caller. + # + return $result } proc getTclShellFileName { automatic kits } { # # NOTE: Start out with an empty list of candiate Tcl shells. @@ -571,11 +630,11 @@ # # NOTE: Check all environment variables we know about that # may contain the path where the Tcl shell is located. # - foreach name [list Eagle_Tcl_Shell Tcl_Shell] { + foreach name [list Eagle_Tcl_Shell Tcl_Shell EAGLE_TCLSH TCLSH] { set value [getEnvironmentVariable $name] # # TODO: Possibly add a check if the file actually exists # here. @@ -1294,12 +1353,12 @@ } } proc hookPuts {} { # - # NOTE: This code was stolen from tcltest and heavily modified to work - # with Eagle. + # NOTE: This code was stolen from "tcltest" and heavily modified to + # work with Eagle. # proc [namespace current]::testPuts { args } { switch [llength $args] { 1 { # @@ -2315,12 +2374,260 @@ # NOTE: Return non-zero if the test suite appears to be running. # return [expr {[info exists ::test_suite_running] && \ $::test_suite_running}] } + + proc getTestChannelOrDefault {} { + if {[info exists ::test_channel]} then { + return $::test_channel + } + + return stdout; # TODO: Good default? + } + + proc checkForAndSetTestPath { whatIf {quiet false} } { + # + # NOTE: Everything in this procedure requires access to the file system; + # therefore, it cannot be used in a stock "safe" interpreter. + # + if {![interp issafe] && ![info exists ::test_path]} then { + # + # NOTE: Grab the name of the current script file. If this is an empty + # string, many test path checks will have to be skipped. + # + set script [info script] + + # + # NOTE: Eagle and native Tcl have different requirements and possible + # locations for the test path; therefore, handle them separately. + # + if {[isEagle]} then { + # + # NOTE: Grab the base directory and the library directory. Without + # these, several test path checks will be skipped. + # + set library [getTestLibraryDirectory]; set base [info base] + + if {[string length $library] > 0} then { + # + # NOTE: Try the source release directory structure. For this + # case, the final test path would be: + # + # $library/../../Library/Tests + # + set ::test_path [file normalize [file join [file dirname [file \ + dirname $library]] Library Tests]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #1 for Eagle test path at \"" \ + $::test_path \"...\n] + } + } + + if {[string length $base] > 0 && ($whatIf || \ + ![info exists ::test_path] || ![file exists $::test_path] || \ + ![file isdirectory $::test_path])} then { + # + # NOTE: Try the source release directory structure again; this + # time, assume only the embedded script library was used. + # For this case, the final test path would be: + # + # $base/Library/Tests + # + set ::test_path [file normalize [file join $base Library Tests]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #2 for Eagle test path at \"" \ + $::test_path \"...\n] + } + } + + if {[string length $script] > 0 && ($whatIf || \ + ![info exists ::test_path] || ![file exists $::test_path] || \ + ![file isdirectory $::test_path])} then { + # + # NOTE: Try for the test package directory. For this case, the + # final test path would be: + # + # $script/../Test1.0 + # + set ::test_path [file normalize [file join [file dirname [file \ + dirname $script]] [appendArgs Test [info engine Version]]]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #3 for Eagle test path at \"" \ + $::test_path \"...\n] + } + } + + if {[string length $base] > 0 && ($whatIf || \ + ![info exists ::test_path] || ![file exists $::test_path] || \ + ![file isdirectory $::test_path])} then { + # + # NOTE: Try for the test package directory again; this time, use + # the base path and assume the source release directory + # structure. For this case, the final test path would be: + # + # $base/lib/Test1.0 + # + set ::test_path [file normalize [file join $base lib [appendArgs \ + Test [info engine Version]]]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #4 for Eagle test path at \"" \ + $::test_path \"...\n] + } + } + + if {[string length $base] > 0 && ($whatIf || \ + ![info exists ::test_path] || ![file exists $::test_path] || \ + ![file isdirectory $::test_path])} then { + # + # NOTE: Try for the test package directory again; this time, use + # the base path. For this case, the final test path would + # be: + # + # $base/Test1.0 + # + set ::test_path [file normalize [file join $base [appendArgs \ + Test [info engine Version]]]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #5 for Eagle test path at \"" \ + $::test_path \"...\n] + } + } + + if {[string length $library] > 0 && ($whatIf || \ + ![info exists ::test_path] || ![file exists $::test_path] || \ + ![file isdirectory $::test_path])} then { + # + # NOTE: This must be a binary release, no "Library" directory + # then. Also, binary releases have an upper-case "Tests" + # directory name that originates from the "update.bat" + # tool. This must match the casing used in "update.bat". + # For this case, the final test path would be: + # + # $library/../../Tests + # + set ::test_path [file normalize [file join [file dirname [file \ + dirname $library]] Tests]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #6 for Eagle test path at \"" \ + $::test_path \"...\n] + } + } + + if {[string length $base] > 0 && ($whatIf || \ + ![info exists ::test_path] || ![file exists $::test_path] || \ + ![file isdirectory $::test_path])} then { + # + # NOTE: Fallback to using the base directory and checking for a + # "Tests" directory beneath it. For this case, the final + # test path would be: + # + # $base/Tests + # + set ::test_path [file normalize [file join $base Tests]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #7 for Eagle test path at \"" \ + $::test_path \"...\n] + } + } + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- final Eagle test path is \"" \ + [expr {[info exists ::test_path] ? \ + $::test_path : ""}] \"\n] + } + } else { + if {[string length $script] > 0} then { + # + # NOTE: Try the source release directory structure. For this + # case, the final test path would be: + # + # $script/../../Library/Tests + # + set ::test_path [file normalize [file join [file dirname [file \ + dirname [file dirname $script]]] Library Tests]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #1 for Tcl test path at \"" \ + $::test_path \"...\n] + } + } + + if {[string length $script] > 0 && ($whatIf || \ + ![info exists ::test_path] || ![file exists $::test_path] || \ + ![file isdirectory $::test_path])} then { + # + # NOTE: Try for the test package directory. For this case, the + # final test path would be: + # + # $script/../Test1.0 + # + set ::test_path [file normalize [file join [file dirname [file \ + dirname $script]] Test1.0]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #2 for Tcl test path at \"" \ + $::test_path \"...\n] + } + } + + if {[string length $script] > 0 && ($whatIf || \ + ![info exists ::test_path] || ![file exists $::test_path] || \ + ![file isdirectory $::test_path])} then { + # + # NOTE: This must be a binary release, no "Library" directory + # then. Also, binary releases have an upper-case "Tests" + # directory name that originates from the "update.bat" + # tool. This must match the casing used in "update.bat". + # For this case, the final test path would be: + # + # $script/../../Tests + # + set ::test_path [file normalize [file join [file dirname [file \ + dirname [file dirname $script]]] Tests]] + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- checking #3 for Tcl test path at \"" \ + $::test_path \"...\n] + } + } + + if {!$quiet} then { + tqputs [getTestChannelOrDefault] [appendArgs \ + "---- final Tcl test path is \"" \ + [expr {[info exists ::test_path] ? \ + $::test_path : ""}] \"\n] + } + } + } + } proc configureTcltest { match skip constraints imports force } { + # + # NOTE: Eagle and native Tcl have different configuration requirements + # for the "tcltest" package. For Eagle, the necessary testing + # functionality is built-in. In native Tcl, the package must be + # loaded now and that cannot be done in a "safe" interpreter. + # if {[isEagle]} then { # # HACK: Flag the "test" and "runTest" script library procedures so # that they use the script location of their caller and not # their own. @@ -2335,26 +2642,26 @@ # namespace eval ::tcltest {}; # HACK: Force namespace creation now. setupTestShims true [expr {![isTestSuiteRunning]}] # - # NOTE: Fake having the tcltest package. + # NOTE: Fake having the package as the functionality is built-in. # package provide tcltest 2.2.10; # Tcl 8.4 - } else { + } elseif {![interp issafe]} then { # - # NOTE: Attempt to detect if the tcltest package is already loaded. + # NOTE: Attempt to detect if the package is already loaded. # set loaded [expr {[catch {package present tcltest}] == 0}] # - # NOTE: Always attempt to load the tcltest package. + # NOTE: Always attempt to load the package. # package require tcltest # - # NOTE: Configure tcltest for our use (only when it was not loaded). + # NOTE: Configure it for our use (only when it was not loaded). # if {!$loaded} then { ::tcltest::configure -verbose bpste } @@ -2529,18 +2836,10 @@ eval lappend eagle_tests(Constraints) $test_flags(-constraints) } } } - proc getTestChannelOrDefault {} { - if {[info exists ::test_channel]} then { - return $::test_channel - } - - return stdout; # TODO: Good default? - } - proc setupTestShims { setup {quiet false} } { if {$setup} then { # # HACK: Compatibility shim(s) for use with various tests in the Tcl # test suite. Make sure these commands do not already exist @@ -3090,122 +3389,43 @@ object unimport -importpattern System.Windows.Forms.VisualStyles } proc getTestLibraryDirectory {} { # - # NOTE: First, query the location of the script library. - # - set result [info library] - - # - # NOTE: Next, If the script library is embedded within the core - # library itself (i.e. the script library location refers - # to a file, not a directory), strip off the file name. - # - if {[file exists $result] && [file isfile $result]} then { - set result [file dirname $result] - } - - # - # NOTE: Finally, return the resulting script library directory. - # - return $result - } - - # - # NOTE: Setup the test path relative to the library path. - # - if {![interp issafe] && ![info exists ::test_path]} then { - # - # NOTE: Try the source release directory structure. For this case, - # the final test path would be: - # - # $library/../../Library/Tests - # - set ::test_path [file join [file normalize [file dirname \ - [file dirname [getTestLibraryDirectory]]]] Library Tests] - - if {![file exists $::test_path] || \ - ![file isdirectory $::test_path]} then { - # - # NOTE: Try the source release directory structure again; this time, - # assume only the embedded script library was used. For this - # case, the final test path would be: - # - # $base/Library/Tests - # - set ::test_path [file join [info base] Library Tests] - } - - if {![file exists $::test_path] || \ - ![file isdirectory $::test_path]} then { - # - # NOTE: Try for the test package directory. For this case, the final - # test path would be: - # - # $script/../Test1.0 - # - set ::test_path [file join [file normalize [file dirname \ - [file dirname [info script]]]] [appendArgs Test \ - [info engine Version]]] - } - - if {![file exists $::test_path] || \ - ![file isdirectory $::test_path]} then { - # - # NOTE: Try for the test package directory again; this time, use the - # base path and assume the source release directory structure. - # For this case, the final test path would be: - # - # $base/lib/Test1.0 - # - set ::test_path [file join [info base] lib [appendArgs Test \ - [info engine Version]]] - } - - if {![file exists $::test_path] || \ - ![file isdirectory $::test_path]} then { - # - # NOTE: Try for the test package directory again; this time, use the - # base path. For this case, the final test path would be: - # - # $base/Test1.0 - # - set ::test_path [file join [info base] [appendArgs Test \ - [info engine Version]]] - } - - if {![file exists $::test_path] || \ - ![file isdirectory $::test_path]} then { - # - # NOTE: This must be a binary release, no "Library" directory then. - # Also, binary releases have an upper-case "Tests" directory - # name that originates from the "update.bat" tool. This must - # match the casing used in "update.bat". For this case, the - # final test path would be: - # - # $library/../../Tests - # - set ::test_path [file join [file normalize [file dirname \ - [file dirname [getTestLibraryDirectory]]]] Tests] - } - - if {![file exists $::test_path] || \ - ![file isdirectory $::test_path]} then { - # - # NOTE: Fallback to using the base directory and checking for a - # "Tests" directory beneath it. For this case, the final - # test path would be: - # - # $base/Tests - # - set ::test_path [file join [info base] Tests] - } - } - - # - # NOTE: Fake having the tcltest package unless we are prevented. + # NOTE: First, query the location of the script library. This will + # not work right in a "safe" interpreter. + # + if {[catch {info library} result] == 0} then { + # + # NOTE: Next, If the script library is embedded within the core + # library itself (i.e. the script library location refers + # to a file, not a directory), strip off the file name. + # + if {[file exists $result] && [file isfile $result]} then { + set result [file dirname $result] + } + + # + # NOTE: Finally, return the resulting script library directory. + # + return $result + } + + return "" + } + + # + # NOTE: Check for the test path in the various well-known locations + # and set the associated variable. + # + if {![info exists ::no(checkForAndSetTestPath)]} then { + checkForAndSetTestPath false [expr {![isTestSuiteRunning]}] + } + + # + # NOTE: Fake loading and configuring the "tcltest" package unless we + # are prevented. # if {![info exists ::no(configureTcltest)]} then { configureTcltest [list] [list] [list] [list] false } @@ -3237,45 +3457,21 @@ return 0; # no tests were run, etc. } # - # NOTE: Setup the test path relative to the path of this file. - # - if {![interp issafe] && ![info exists ::test_path]} then { - # - # NOTE: Try the source release directory structure. - # - set ::test_path [file join [file normalize [file dirname \ - [file dirname [file dirname [info script]]]]] Library Tests] - - if {![file exists $::test_path] || \ - ![file isdirectory $::test_path]} then { - # - # NOTE: Try for the test package directory. - # - set ::test_path [file join [file normalize [file dirname \ - [file dirname [info script]]]] Test1.0] - } - - if {![file exists $::test_path] || \ - ![file isdirectory $::test_path]} then { - # - # NOTE: This must be a binary release, no "Library" directory then. - # Also, binary releases have an upper-case "Tests" directory - # name that originates from the "update.bat" tool. This must - # match the casing used in "update.bat". - # - set ::test_path [file join [file normalize [file dirname \ - [file dirname [file dirname [info script]]]]] Tests] - } - } - - # - # NOTE: Load and configure the tcltest package unless we are prevented. - # - if {![interp issafe] && ![info exists ::no(configureTcltest)]} then { + # NOTE: Check for the test path in the various well-known locations + # and set the associated variable. + # + if {![info exists ::no(checkForAndSetTestPath)]} then { + checkForAndSetTestPath false [expr {![isTestSuiteRunning]}] + } + + # + # NOTE: Load and configure the "tcltest" package unless we are prevented. + # + if {![info exists ::no(configureTcltest)]} then { configureTcltest [list] [list] [list] [list test testConstraint] false } # # NOTE: We need several of our test related commands in the global @@ -3294,12 +3490,12 @@ returnInfoScript runTestPrologue runTestEpilogue hookPuts unhookPuts \ runTest testDebugBreak testArrayGet testShim tsource \ recordTestStatistics reportTestStatistics formatList formatListAsDict \ pathToRegexp inverseLsearchGlob removePathFromFileNames formatDecimal \ clearTestPercent reportTestPercent runAllTests isTestSuiteRunning \ - configureTcltest machineToPlatform getPassPercentage \ - getSkipPercentage] false false + getTestChannelOrDefault checkForAndSetTestPath configureTcltest \ + machineToPlatform getPassPercentage getSkipPercentage] false false ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } Index: Externals/Eagle/lib/Test1.0/all.eagle ================================================================== --- Externals/Eagle/lib/Test1.0/all.eagle +++ Externals/Eagle/lib/Test1.0/all.eagle @@ -40,25 +40,32 @@ # be used at the very end of the corresponding "all.eagle" file instead # of evaluating the "epilogue.eagle" file directly: # # runTestEpilogue # +if {![info exists test_all_path]} then { + set test_all_path \ + [file normalize [file dirname [info script]]] +} + if {![info exists test_path]} then { - set test_path [file normalize [file dirname [info script]]] + set test_path [file normalize [file join \ + [file dirname [file dirname $test_all_path]] \ + Library Tests]] } -source [file join $test_path prologue.eagle] +source [file join $test_all_path prologue.eagle] set no(prologue.eagle) true set no(epilogue.eagle) true set test_time [time { runAllTests $test_channel $test_path \ [getTestFiles [list $test_path] $test_flags(-file) \ $test_flags(-notFile)] \ - [list [file tail [info script]] *.tcl pkgIndex.eagle \ - constraints.eagle epilogue.eagle prologue.eagle] \ + [list [file tail [info script]] *.tcl \ + epilogue.eagle prologue.eagle] \ $test_flags(-startFile) $test_flags(-stopFile) }] tputs $test_channel [appendArgs "---- all tests completed in " $test_time \n] unset test_time @@ -66,6 +73,6 @@ unset no(epilogue.eagle) unset no(prologue.eagle) if {[array size no] == 0} then {unset no} -source [file join $test_path epilogue.eagle] +source [file join $test_all_path epilogue.eagle] Index: Externals/Eagle/lib/Test1.0/constraints.eagle ================================================================== --- Externals/Eagle/lib/Test1.0/constraints.eagle +++ Externals/Eagle/lib/Test1.0/constraints.eagle @@ -54,11 +54,12 @@ # versions of Mono supported by the test suite infrastructure. # return [list \ [list 2 0] [list 2 2] [list 2 4] [list 2 6] [list 2 8] [list 2 10] \ [list 2 11] [list 2 12] [list 3 0] [list 3 1] [list 3 2] [list 3 3] \ - [list 3 4] [list 3 5] [list 3 6] [list 3 8] [list 3 10] [list 3 12]] + [list 3 4] [list 3 5] [list 3 6] [list 3 8] [list 3 10] [list 3 12] \ + [list 4 0]] } # # NOTE: This procedure was adapted from the one listed on the Tcl Wiki page # at "http://wiki.tcl.tk/43". It is only intended to be used on very @@ -101,11 +102,11 @@ # NOTE: If this Eagle version lacks [interp readylimit] -OR- it has # the default value (i.e. it always fully checks readiness), # return true. # return [expr { - [catch {interp readylimit {}} readylimit] != 0 || $readylimit == 0 + [catch {interp readylimit {}} readylimit] || $readylimit == 0 }] } # # NOTE: This procedure should return non-zero if the "whoami" command may @@ -313,10 +314,38 @@ # if {[file exists $fileName]} then { lappend fileNames $fileName } } + + # + # TODO: If additional test suite files are added within the base + # package path, add them here as well. + # + foreach fileNameOnly [list \ + all.eagle constraints.eagle epilogue.eagle pkgIndex.eagle \ + pkgIndex.tcl prologue.eagle] { + # + # NOTE: First, check if the file resides in the Eagle-specific + # package sub-directory. Failing that, fallback to using + # the base package path itself. + # + set fileName [file join \ + $::test_package_path Test1.0 $fileNameOnly] + + if {![file exists $fileName]} then { + set fileName [file join $::test_package_path $fileNameOnly] + } + + # + # NOTE: If the test suite file exists, add it to the list of file + # names to process. + # + if {[file exists $fileName]} then { + lappend fileNames $fileName + } + } } # # NOTE: Check if the test package path is available. # @@ -323,13 +352,11 @@ if {[info exists ::test_path]} then { # # TODO: If additional test suite files are added within the test # package path, add them here as well. # - foreach fileNameOnly [list \ - all.eagle constraints.eagle epilogue.eagle pkgIndex.eagle \ - pkgIndex.tcl prologue.eagle] { + foreach fileNameOnly [list all.eagle epilogue.eagle prologue.eagle] { # # NOTE: Check if the file resides in the test package directory. # set fileName [file join $::test_path $fileNameOnly] @@ -1584,10 +1611,26 @@ tputs $channel yes\n } else { tputs $channel no\n } } + + proc checkForFullTest { channel } { + tputs $channel "---- checking for full testing... " + + # + # NOTE: Are we allowed to do full testing (i.e. to run rarely + # needed tests)? + # + if {![info exists ::no(fullTest)]} then { + addConstraint fullTest + + tputs $channel yes\n + } else { + tputs $channel no\n + } + } proc checkForMemoryIntensive { channel } { tputs $channel "---- checking for memory intensive testing... " # @@ -1947,10 +1990,88 @@ tputs $channel yes\n } else { tputs $channel no\n } } + + proc checkForStrongNameKey { channel } { + tputs $channel "---- checking for strong name key... " + + if {[catch {info engine PublicKeyToken} publicKeyToken] == 0 && \ + [string length $publicKeyToken] > 0} then { + # + # NOTE: Add a test constraint for this specific strong name key. + # + addConstraint [appendArgs strongName. $publicKeyToken] + + # + # NOTE: Show the strong name key that we found. + # + tputs $channel [appendArgs "yes (" $publicKeyToken ")\n"] + + # + # BUGBUG: Tcl 8.4 does not seem to like this expression because it + # contains the "ni" operator added in Tcl 8.5 (and Tcl 8.4 + # tries to compile it even though it will only be evaluated + # in Eagle). + # + set expr {$publicKeyToken ni \ + "29c6297630be05eb 1e22ec67879739a2 358030063a832bc3"} + + if {[expr $expr]} then { + # + # NOTE: The Eagle core library is strong name signed with a key that + # is not official. This is also not an error, per se; however, + # it may cause some tests to fail and it should be reported to + # the user and noted in the test suite log file. + # + addConstraint strongName.unofficial + + # + # NOTE: Unless forbidden, issue and log a warning. + # + if {![info exists no(warningForStrongNameKey)] && \ + ![haveConstraint quiet]} then { + tputs $channel [appendArgs \ + "==== WARNING: unofficial Eagle strong name signature " \ + "detected: " $publicKeyToken \n] + } + } else { + # + # NOTE: Several tests require one of the official strong name keys to + # be used in order for them to pass. + # + addConstraint strongName.official + + tputs $channel [appendArgs \ + "---- official Eagle strong name signature detected: " \ + $publicKeyToken \n] + } + } else { + # + # NOTE: The Eagle core library is not signed with a strong name key. + # This is not an error, per se; however, it may cause selected + # tests to fail and it should be reported to the user and noted + # in the test suite log file. + # + addConstraint strongName.none + + # + # NOTE: Show that we did not find a strong name key. + # + tputs $channel no\n + + # + # NOTE: Unless forbidden, issue and log a warning. + # + if {![info exists no(warningForStrongNameKey)] && \ + ![haveConstraint quiet]} then { + tputs $channel \ + "==== WARNING: no Eagle strong name signature detected...\n" + } + } + } proc checkForCertificate { channel } { tputs $channel "---- checking for certificate... " if {[catch { @@ -1965,11 +2086,11 @@ # # NOTE: Attempt to query the subject from the certificate. # if {[catch { object invoke $certificate Subject - } subject] != 0 || [string length $subject] == 0} then { + } subject] || [string length $subject] == 0} then { # # TODO: No certificate subject, better handling here? # set subject unknown } @@ -2067,15 +2188,15 @@ if {[catch { object invoke AppDomain CurrentDomain } appDomain] == 0 && [string length $appDomain] > 0} then { if {[catch { object invoke $appDomain IsDefaultAppDomain - } default] != 0 || [string length $default] == 0} then { + } default] || [string length $default] == 0} then { set default false } - if {[catch {object invoke $appDomain Id} id] != 0 || \ + if {[catch {object invoke $appDomain Id} id] || \ [string length $id] == 0} then { set id unknown } if {$default} then { @@ -2374,10 +2495,57 @@ -bit " " $::tcl_platform(machine) \n] } else { tputs $channel "no, unknown\n" } } + + proc checkForTestCallStack { channel } { + tputs $channel "---- checking for test call stack... " + + # + # NOTE: Search for a call frame with associated arguments. + # At this point, there must be at least one such call + # frame (this one). Therefore, this loop will always + # terminate. + # + set index 0; set arguments [list] + set script {info level [info level]} + + while {1} { + set level [appendArgs ## $index] + + if {[catch {uplevel $level $script} arguments] == 0} then { + break + } + + incr index + } + + # + # NOTE: Grab the command name from the arguments, if any. + # + set command [expr { + [llength $arguments] > 0 ? [lindex $arguments 0] : "" + }] + + # + # HACK: Make sure the call stack does not end up confusing + # the tests that rely on absolute call frames. + # + if {$command in [list checkForTestCallStack]} then { + addConstraint testCallStack + + tputs $channel [appendArgs "yes (\"" $command "\")\n"] + + # + # NOTE: We are done here, return now. + # + return + } + + tputs $channel [appendArgs "no (\"" $command "\")\n"] + } proc checkForGarudaDll { channel } { # # NOTE: Skip automatic Tcl shell machine detection if we are not # allowed to execute external commands. @@ -3220,12 +3388,29 @@ } tputs $channel no\n } - proc checkForNetFx45 { channel } { - tputs $channel "---- checking for .NET Framework 4.5... " + proc getFrameworkSetup46Value {} { + # + # NOTE: Check if we are running on Windows 10 or later. + # + if {[isWindows] && $::tcl_platform(osVersion) >= 10.0} then { + # + # NOTE: We are running on Windows 10, return the special value. + # + return 393295 + } + + # + # NOTE: We are not running on Windows 10, return the normal value. + # + return 393297 + } + + proc checkForNetFx4x { channel } { + tputs $channel "---- checking for .NET Framework 4.x... " # # NOTE: Platform must be Windows for this constraint to even be # checked (i.e. we require the registry). # @@ -3262,22 +3447,23 @@ # (or 378675 for Windows 8.1), then the .NET Framework 4.5.1 # is installed. However, if the "release" value is also # greater than or equal to 379893, then the .NET Framework # 4.5.2 is installed, which is an in-place upgrade to 4.5.1 # (and 4.5). If the "release" value is also greater than or - # equal to 393246, then the .NET Framework 4.6 is installed, - # which is an in-place upgrade to 4.5.x. + # equal to 393297 (393295 on Windows 10), then the .NET + # Framework 4.6 is installed, which is an in-place upgrade + # to 4.5.x. # - # TODO: Change the value 393246 when the .NET Framework 4.6 goes - # final. - # - if {$release >= 393246} then { + if {$release >= [getFrameworkSetup46Value]} then { + addConstraint dotNet451OrHigher + addConstraint dotNet452OrHigher addConstraint dotNet46 addConstraint dotNet46OrHigher set version 4.6 } elseif {$release >= 379893} then { + addConstraint dotNet451OrHigher addConstraint dotNet452 addConstraint dotNet452OrHigher set version 4.5.2 } elseif {$release >= 378675} then { @@ -3522,14 +3708,14 @@ checkForTestMachine checkForTestPlatform checkForTestConfiguration \ checkForTestSuffix checkForFile checkForPathFile checkForNativeCode \ checkForTip127 checkForTip194 checkForTip207 checkForTip241 \ checkForTip285 checkForTip405 checkForTip426 checkForTip429 \ checkForTiming checkForPerformance checkForBigLists \ - checkForTimeIntensive checkForMemoryIntensive checkForStackIntensive \ - checkForInteractive checkForInteractiveCommand checkForUserInteraction \ - checkForNetwork checkForCompileOption checkForKnownCompileOptions] \ - false false + checkForTimeIntensive checkForFullTest checkForMemoryIntensive \ + checkForStackIntensive checkForInteractive checkForInteractiveCommand \ + checkForUserInteraction checkForNetwork checkForCompileOption \ + checkForKnownCompileOptions] false false ########################################################################### ############################## END Tcl ONLY ############################### ########################################################################### } Index: Externals/Eagle/lib/Test1.0/epilogue.eagle ================================================================== --- Externals/Eagle/lib/Test1.0/epilogue.eagle +++ Externals/Eagle/lib/Test1.0/epilogue.eagle @@ -23,21 +23,19 @@ # NOTE: Verify that the current call frame is correct and that the # interpreter call stack has not been imbalanced by previous # tests or other errors. This check only applies to Eagle. # if {[isEagle] && [llength [info commands object]] > 0} then { - catch { - # - # NOTE: Check the name of the current call frame against the one - # that should be used for evaluating this script file. - # - if {[object invoke -flags +NonPublic \ - Interpreter.GetActive.CurrentFrame Name] ne \ - [list source [file normalize [info script]]]} then { - unset -nocomplain test_suite_running - error "cannot run, current frame is not for this script" - } + # + # NOTE: Check the name of the current call frame against the one + # that should be used for evaluating this script file. + # + if {[object invoke -flags +NonPublic \ + Interpreter.GetActive.CurrentFrame Name] ne \ + [list source [file normalize [info script]]]} then { + unset -nocomplain test_suite_running + error "cannot run epilogue, current frame not for this script" } } # # NOTE: Make sure all the variables used by this epilogue are unset. Index: Externals/Eagle/lib/Test1.0/prologue.eagle ================================================================== --- Externals/Eagle/lib/Test1.0/prologue.eagle +++ Externals/Eagle/lib/Test1.0/prologue.eagle @@ -21,25 +21,33 @@ # # NOTE: Make sure all the variables used by this prologue are unset. # unset -nocomplain pkg_dir pattern dummy directory name value exec encoding \ - host memory stack drive publicKeyToken expr server database timeout \ - user password percent checkout timeStamp loaded + host memory stack drive server database timeout user password percent \ + checkout timeStamp loaded # # NOTE: Indicate that the test suite is currently running. # if {![info exists test_suite_running] || !$test_suite_running} then { set test_suite_running true } + # + # NOTE: Set the location of the test suite package, if necessary. + # + if {![info exists test_all_path]} then { + set test_all_path [file normalize [file dirname [info script]]] + } + # # NOTE: Set the location of the test suite, if necessary. # if {![info exists test_path]} then { - set test_path [file normalize [file dirname [info script]]] + set test_path [file normalize [file join \ + [file dirname [file dirname $test_all_path]] Library Tests]] } # # NOTE: Set the location of the test suite data, if necessary. # @@ -179,11 +187,19 @@ if {[lsearch -exact $auto_path $test_package_path] == -1} then { lappend auto_path $test_package_path } # - # NOTE: Make sure our test package path is part of the auto-path. + # NOTE: Make sure the test suite package is part of the auto-path. + # + if {[lsearch -exact $auto_path $test_all_path] == -1} then { + lappend auto_path $test_all_path + } + + # + # NOTE: Make sure the test suite is part of the auto-path. This is + # now done for legacy compatibility only. # if {[lsearch -exact $auto_path $test_path] == -1} then { lappend auto_path $test_path } @@ -218,21 +234,19 @@ # interpreter call stack has not been imbalanced by previous # tests or other errors. This check only applies to Eagle. # This block requires the "Eagle.Library" package. # if {[isEagle] && [llength [info commands object]] > 0} then { - catch { - # - # NOTE: Check the name of the current call frame against the one - # that should be used for evaluating this script file. - # - if {[object invoke -flags +NonPublic \ - Interpreter.GetActive.CurrentFrame Name] ne \ - [list source [file normalize [info script]]]} then { - unset -nocomplain test_suite_running - error "cannot run, current frame is not for this script" - } + # + # NOTE: Check the name of the current call frame against the one + # that should be used for evaluating this script file. + # + if {[object invoke -flags +NonPublic \ + Interpreter.GetActive.CurrentFrame Name] ne \ + [list source [file normalize [info script]]]} then { + unset -nocomplain test_suite_running + error "cannot run prologue, current frame not for this script" } } ############################################################################# @@ -307,16 +321,18 @@ set test_flags(-preTest) ""; # default to not evaluating anything. set test_flags(-postTest) ""; # default to not evaluating anything. set test_flags(-preWait) ""; # default to not waiting. set test_flags(-postWait) ""; # default to not waiting. set test_flags(-tclsh) ""; # Tcl shell, default to empty. + set test_flags(-bad) [list]; # these are the unrecognized arguments. + set test_flags(-no) [list]; # default to not having any restrictions. # # NOTE: Check for and process any command line arguments. # if {[info exists argv]} then { - eval processTestArguments test_flags $argv + set test_flags(-bad) [eval processTestArguments test_flags false $argv] if {[info exists test_flags(-no)] && \ [string length $test_flags(-no)] > 0} then { # # NOTE: Set the test run restrictions based on the provided command line @@ -730,10 +746,15 @@ $bin_file \"\n] tputs $test_channel [appendArgs "---- command line: " \ [expr {[info exists argv] && [string length $argv] > 0 ? \ $argv : ""}] \n] + + tputs $test_channel [appendArgs "---- unrecognized arguments: " \ + [expr {[info exists test_flags(-bad)] && \ + [string length $test_flags(-bad)] > 0 ? \ + $test_flags(-bad) : ""}] \n] tputs $test_channel [appendArgs "---- logging to: " \ [expr {[info exists test_log] && [string length $test_log] > 0 ? \ [appendArgs \" $test_log \"] : ""}] \n] @@ -882,78 +903,10 @@ # itself. # checkForQuiet $test_channel false } - # - # NOTE: Has strong name key detection been disabled? - # - if {![info exists no(strongNameKey)]} then { - catch {info engine PublicKeyToken} publicKeyToken - - if {[string length $publicKeyToken] == 0} then { - # - # NOTE: The Eagle core library is not signed with a strong name key. - # This is not an error, per se; however, it may cause selected - # tests to fail and it should be reported to the user and noted - # in the test suite log file. - # - addConstraint strongName.none - - if {![info exists no(warningForStrongNameKey)] && \ - ![haveConstraint quiet]} then { - tputs $test_channel \ - "==== WARNING: no Eagle strong name signature detected...\n" - } - } else { - # - # NOTE: Add a test constraint for this specific strong name key. - # - addConstraint [appendArgs strongName. $publicKeyToken] - - # - # BUGBUG: Tcl 8.4 does not seem to like this expression because it - # contains the "ni" operator added in Tcl 8.5 (and Tcl 8.4 - # tries to compile it even though it will only be evaluated - # in Eagle). - # - set expr {$publicKeyToken ni \ - "29c6297630be05eb 1e22ec67879739a2 358030063a832bc3"} - - if {[expr $expr]} then { - # - # NOTE: The Eagle core library is strong name signed with a key that - # is not official. This is also not an error, per se; however, - # it may cause some tests to fail and it should be reported to - # the user and noted in the test suite log file. - # - addConstraint strongName.unofficial - - if {![info exists no(warningForStrongNameKey)] && \ - ![haveConstraint quiet]} then { - tputs $test_channel [appendArgs \ - "==== WARNING: unofficial Eagle strong name signature " \ - "detected: " $publicKeyToken \n] - } - } else { - # - # NOTE: Several tests require one of the official strong name keys to - # be used in order for them to pass. - # - addConstraint strongName.official - - tputs $test_channel [appendArgs \ - "---- official Eagle strong name signature detected: " \ - $publicKeyToken \n] - } - - unset expr - } - - unset publicKeyToken - } - # # NOTE: Has administrator detection support been disabled? We do # this check [nearly] first as it may [eventually] be used # to help determine if other constraints should be skipped. # @@ -1041,10 +994,17 @@ checkForMachine $test_channel 32 arm; # (i.e. arm) checkForMachine $test_channel 64 ia64; # (i.e. itanium) checkForMachine $test_channel 64 amd64; # (i.e. x64) } + # + # NOTE: Has test suite call stack probing been disabled? + # + if {![info exists no(testCallStack)]} then { + checkForTestCallStack $test_channel + } + # # NOTE: Has culture detection support been disabled? # if {![info exists no(culture)]} then { checkForCulture $test_channel @@ -1068,10 +1028,17 @@ # NOTE: Has strong name detection support been disabled? # if {![info exists no(strongName)]} then { checkForStrongName $test_channel } + + # + # NOTE: Has strong name key detection been disabled? + # + if {![info exists no(strongNameKey)]} then { + checkForStrongNameKey $test_channel + } # # NOTE: Has certificate detection support been disabled? # if {![info exists no(certificate)]} then { @@ -1615,10 +1582,45 @@ # checkForObjectMember $test_channel Eagle._Tests.Default \ *TestPermute* } + if {![info exists no(testDynamicCallback)]} then { + # + # NOTE: For tests "object-8.1??". + # + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestCallDynamicCallback0* + + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestCallDynamicCallback1* + + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestCallDynamicCallback2* + + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestCallDynamicCallback3* + + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestGetDynamicCallbacks* + + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestCallStaticDynamicCallback0* + + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestCallStaticDynamicCallback1* + + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestCallStaticDynamicCallback2* + + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestCallStaticDynamicCallback3* + + checkForObjectMember $test_channel Eagle._Tests.Default \ + *TestGetStaticDynamicCallbacks* + } + # # NOTE: Has DateTime testing support been disabled? # if {![info exists no(testDateTime)]} then { # @@ -2117,17 +2119,17 @@ # checkForNetFx20ServicePack $test_channel } # - # NOTE: Has .NET Framework 4.5 testing support been disabled? + # NOTE: Has .NET Framework 4.x testing support been disabled? # - if {![info exists no(netFx45)]} then { + if {![info exists no(netFx4x)]} then { # # NOTE: For test "object-12.1.*". # - checkForNetFx45 $test_channel + checkForNetFx4x $test_channel } # # NOTE: Has target framework testing support been disabled? # @@ -2353,10 +2355,17 @@ # if {![info exists no(benchmark.txt)]} then { checkForFile $test_channel [file join $test_data_path benchmark.txt] } + # + # NOTE: For test "benchmark-1.42". + # + if {![info exists no(pngDump.txt)]} then { + checkForFile $test_channel [file join $test_data_path pngDump.txt] + } + # # NOTE: For test "garuda-1.1". # if {![info exists no(pkgAll.tcl)]} then { checkForFile $test_channel [file join $base_path Native Package \ @@ -2367,10 +2376,17 @@ # NOTE: For tests "subst-1.*". # if {![info exists no(bad_subst.txt)]} then { checkForFile $test_channel [file join $test_data_path bad_subst.txt] } + + # + # NOTE: For test "processIsolation-1.1". + # + if {![info exists no(isolated.eagle)]} then { + checkForFile $test_channel [file join $test_data_path isolated.eagle] + } # # NOTE: This is not currently used by any tests. # if {![info exists no(evaluate.eagle)]} then { @@ -2621,10 +2637,14 @@ } if {![info exists no(checkForTimeIntensive)]} then { checkForTimeIntensive $test_channel } + + if {![info exists no(checkForFullTest)]} then { + checkForFullTest $test_channel + } if {![info exists no(checkForMemoryIntensive)]} then { checkForMemoryIntensive $test_channel }