System.Data.SQLite
Check-in [10e4b21f8e]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Update Eagle in externals to the beta 41 release.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 10e4b21f8e73e21cf6ecc0a335d30875f9455795
User & Date: mistachkin 2017-11-30 12:54:43
Context
2017-11-30
23:59
Cleanup the database file for test 'tkt-0e48e80333-1.1'. check-in: bf8c54d97e user: mistachkin tags: trunk
12:54
Update Eagle in externals to the beta 41 release. check-in: 10e4b21f8e user: mistachkin tags: trunk
2017-11-29
02:24
Fix expected result for the 'tkt-0e48e80333-1.2' test to account for thread timing variations. Also, adjust its timeout to be a bit more reasonable. check-in: aa5b7a8df5 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Externals/Eagle/bin/Eagle.dll.

cannot compute difference between binary files

Changes to Externals/Eagle/bin/EagleShell.exe.

cannot compute difference between binary files

Changes to Externals/Eagle/bin/EagleShell32.exe.

cannot compute difference between binary files

Changes to Externals/Eagle/bin/x64/Spilornis.dll.

cannot compute difference between binary files

Changes to Externals/Eagle/bin/x86/Spilornis.dll.

cannot compute difference between binary files

Changes to Externals/Eagle/lib/Eagle1.0/init.eagle.

    22     22   namespace eval ::Eagle {
    23     23     #
    24     24     # NOTE: This is the procedure that detects whether or not we are
    25     25     #       running in Eagle (otherwise, we are running in vanilla Tcl).
    26     26     #       This procedure must function correctly in both Tcl and Eagle
    27     27     #       and must return non-zero only when running in Eagle.  This
    28     28     #       procedure must be defined in this script file because it is
    29         -  #       needed while this script file is being evaluated.
           29  +  #       needed while this script file is being evaluated.  The same
           30  +  #       procedure is also defined in the "platform.eagle" file.
    30     31     #
    31     32     # <bootstrap>
    32     33     proc isEagle {} {
    33     34       #
    34     35       # NOTE: Nothing too fancy or expensive should be done in here.  In
    35     36       #       theory, use of this routine should be rare; however, in
    36     37       #       practice, this routine is actually used quite a bit (e.g.

Changes to Externals/Eagle/lib/Eagle1.0/object.eagle.

   144    144   
   145    145     #
   146    146     # NOTE: This procedure returns a string obtained by using the specified
   147    147     #       value as an opaque object handle -OR- a default value (e.g. an
   148    148     #       empty string) if the value is not a valid opaque object handle.
   149    149     #
   150    150     proc getStringFromObjectHandle { value {default ""} } {
   151         -    global null
   152         -
   153         -    if {[isObjectHandle $value] && $value ne $null} then {
          151  +    if {[isNonNullObjectHandle $value]} then {
   154    152         return [object invoke $value ToString]
   155    153       }
   156    154   
   157    155       if {[string length $default] > 0} then {
   158    156         return $default
   159    157       }
   160    158   
................................................................................
   171    169   
   172    170       if {[llength $objects] == 1 && [lindex $objects 0] eq $value} then {
   173    171         return true
   174    172       }
   175    173   
   176    174       return false
   177    175     }
          176  +
          177  +  #
          178  +  # NOTE: This procedure returns non-zero if the specified value can be used
          179  +  #       as an opaque object handle -AND- the value does not represent a null
          180  +  #       value.
          181  +  #
          182  +  proc isNonNullObjectHandle { value } {
          183  +    global null
          184  +    return [expr {[isObjectHandle $value] && $value ne $null}]
          185  +  }
   178    186   
   179    187     #
   180    188     # NOTE: This procedure returns non-zero if the specified name represents
   181    189     #       a valid CLR type name.
   182    190     #
   183    191     proc isManagedType { name } {
   184    192       if {[llength [info commands object]] > 0} then {
................................................................................
   219    227             }
   220    228           }
   221    229         }
   222    230       }
   223    231   
   224    232       return false
   225    233     }
          234  +
          235  +  #
          236  +  # NOTE: This procedure evaluates a script asynchronously and optionally
          237  +  #       notifies another script upon its completion.  The first argument
          238  +  #       is the notification script; if an empty string, there will be no
          239  +  #       notification when asynchronous script evaluation is completed.
          240  +  #       If there is exactly one more argument, it is evaluated verbatim;
          241  +  #       otherwise, all remaining arguments are concatenated via [concat]
          242  +  #       and evaluated asynchronously.  If the script cannot be submitted
          243  +  #       for asynchronous evaluation, a script error will be raised.
          244  +  #
          245  +  proc evalAsync { doneScript args } {
          246  +    #
          247  +    # NOTE: This procedure requires the [object] command in order to work.
          248  +    #       If it is not available, bail out now.
          249  +    #
          250  +    if {[llength [info commands object]] == 0} then {
          251  +      error "cannot eval async: missing \[object\] command"
          252  +    }
          253  +
          254  +    #
          255  +    # NOTE: If the core library was not compiled with thread-safety enabled,
          256  +    #       this procedure cannot be used because it could corrupt the state
          257  +    #       of the interpreter.
          258  +    #
          259  +    if {[lsearch -exact -- \
          260  +        $::eagle_platform(compileOptions) THREADING] == -1} then {
          261  +      error "cannot eval async: library missing THREADING compile-option"
          262  +    }
          263  +
          264  +    #
          265  +    # NOTE: If there is more than one script optional argument, use [concat]
          266  +    #       to build up the final script; otherwise, use the single argument
          267  +    #       verbatim.  This mirrors the behavior of [eval].
          268  +    #
          269  +    if {[llength $args] > 1} then {
          270  +      set asyncScript [concat $args]
          271  +    } else {
          272  +      set asyncScript [lindex $args 0]
          273  +    }
          274  +
          275  +    #
          276  +    # NOTE: Is there a script to be evaluated when the asynchronous script
          277  +    #       evaluation is complete?  If so, build an anonymous procedure
          278  +    #       that wraps it; otherwise, set the callback argument to null, so
          279  +    #       the core marshaller will handle the lack of a callback correctly.
          280  +    #       The context argument will be added to this script prior to it
          281  +    #       being evaluated; however, it is not actually used by this script.
          282  +    #
          283  +    if {[string length $doneScript] > 0} then {
          284  +      set callback [list -callbackflags {+ResetCancel FireAndForget} \
          285  +          -- apply [list [list script context] {uplevel 1 $script}] \
          286  +          $doneScript]
          287  +    } else {
          288  +      set callback null
          289  +    }
          290  +
          291  +    #
          292  +    # NOTE: Initialize the local variable that will be used to receive the
          293  +    #       script error, if any.
          294  +    #
          295  +    set error null
          296  +
          297  +    #
          298  +    # NOTE: Attempt to submit the script for asynchonous evaluation.  Use
          299  +    #       the dynamic callback mechanism with the anonymous procedure we
          300  +    #       constructed above.
          301  +    #
          302  +    set code [object invoke -verbose \
          303  +        -marshalflags +DynamicCallback -- Interpreter.GetActive \
          304  +        EvaluateScript $asyncScript $callback null error]
          305  +
          306  +    #
          307  +    # NOTE: Check the return code, which only indicates if the script was
          308  +    #       actually submitted for asynchronous evaluation, to make sure
          309  +    #       it was successful.  If not, raise a script error.
          310  +    #
          311  +    if {$code ne "Ok"} then {
          312  +      error [getStringFromObjectHandle $error]
          313  +    }
          314  +
          315  +    #
          316  +    # NOTE: Upon success, return an empty string.  The actual script result
          317  +    #       will be sent to the callback script, if any.
          318  +    #
          319  +    return ""
          320  +  }
   226    321   
   227    322     #
   228    323     # NOTE: Provide the Eagle "object" package to the interpreter.
   229    324     #
   230    325     package provide Eagle.Object \
   231    326       [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}]
   232    327   }
   233    328   

Changes to Externals/Eagle/lib/Eagle1.0/pkgt.eagle.

    59     59       # NOTE: The URI where the Package Client Toolset may be downloaded.
    60     60       #
    61     61       variable packageToolsetUri; # DEFAULT: ${baseUri}/${packageToolsetUrn}
    62     62   
    63     63       if {$force || ![info exists packageToolsetUri]} then {
    64     64         set packageToolsetUri {${baseUri}/${packageToolsetUrn}}
    65     65       }
           66  +
           67  +    #
           68  +    # NOTE: The URN, relative to the base URI, where the TclKit DLL for
           69  +    #       a particular platform may be downloaded.
           70  +    #
           71  +    variable tclKitDllUrn; # DEFAULT: tclkit_dll_${platform}
           72  +
           73  +    if {$force || ![info exists tclKitDllUrn]} then {
           74  +      set tclKitDllUrn {tclkit_dll_${platform}}
           75  +    }
           76  +
           77  +    #
           78  +    # NOTE: The URI where the TclKit DLL for a particular platform may
           79  +    #       be downloaded.
           80  +    #
           81  +    variable tclKitDllUri; # DEFAULT: ${baseUri}/${urn}
           82  +
           83  +    if {$force || ![info exists tclKitDllUri]} then {
           84  +      set tclKitDllUri {${baseUri}/${urn}}
           85  +    }
           86  +
           87  +    #
           88  +    # NOTE: The URN, relative to the base URI, where the Harpy and Badge
           89  +    #       plugins for a particular build may be downloaded.
           90  +    #
           91  +    variable securityToolsetUrn; # DEFAULT: security_toolset_${platform}
           92  +
           93  +    if {$force || ![info exists securityToolsetUrn]} then {
           94  +      set securityToolsetUrn {security_toolset_${platform}}
           95  +    }
           96  +
           97  +    #
           98  +    # NOTE: The URI where the Harpy and Badge plugins for a particular
           99  +    #       build may be downloaded.
          100  +    #
          101  +    variable securityToolsetUri; # DEFAULT: ${baseUri}/${urn}
          102  +
          103  +    if {$force || ![info exists securityToolsetUri]} then {
          104  +      set securityToolsetUri {${baseUri}/${urn}}
          105  +    }
          106  +
          107  +    #
          108  +    # NOTE: The URN, relative to the base URI, where license certificate
          109  +    #       requests should be sent.
          110  +    #
          111  +    variable licenseUrn; # DEFAULT: get_license_01
          112  +
          113  +    if {$force || ![info exists licenseUrn]} then {
          114  +      set licenseUrn get_license_01
          115  +    }
          116  +
          117  +    #
          118  +    # NOTE: The URI where license certificate requests should be sent.
          119  +    #
          120  +    variable licenseUri; # DEFAULT: ${baseUri}/${urn}
          121  +
          122  +    if {$force || ![info exists licenseUri]} then {
          123  +      set licenseUri {${baseUri}/${urn}}
          124  +    }
    66    125     }
    67    126   
    68    127     #
    69    128     # NOTE: This procedure attempts to download and extract the Package Client
    70    129     #       Toolset.  The optional channel argument is the output channel where
    71    130     #       diagnostic information is sent.  The optional quiet argument should
    72    131     #       be non-zero to prevent diagnostic information from being emitted.
................................................................................
   105    164   
   106    165         writeFile $fileName $data
   107    166       }
   108    167   
   109    168       set extractDirectory [extractZipArchive $fileName $extractRootDirectory]
   110    169       return [file join $extractDirectory pkgr_an_d client 1.0 neutral]
   111    170     }
          171  +
          172  +  #
          173  +  # NOTE: This procedure attempts to download and extract a native TclKit DLL
          174  +  #       for the current platform.  The optional channel argument is the
          175  +  #       output channel where diagnostic information is sent.  The optional
          176  +  #       quiet argument should be non-zero to prevent diagnostic information
          177  +  #       from being emitted.  This procedure may raise script errors.  The
          178  +  #       return value is the full path to the native TclKit DLL file.
          179  +  #
          180  +  proc downloadAndExtractNativeTclKitDll {
          181  +          {channel stdout} {quiet false} } {
          182  +    setupPackageToolsetVars false
          183  +
          184  +    variable baseUri
          185  +    variable tclKitDllUri
          186  +    variable tclKitDllUrn
          187  +
          188  +    package require Eagle.Test
          189  +    package require Eagle.Unzip
          190  +
          191  +    set extractRootDirectory [getTemporaryPath]
          192  +
          193  +    set directory [file join $extractRootDirectory [appendArgs \
          194  +        ea-td-di- [pid] - [string trim [clock seconds] -]]]
          195  +
          196  +    set platform [machineToPlatform $::tcl_platform(machine) true]
          197  +    set urn [subst $tclKitDllUrn]; set uri [subst $tclKitDllUri]
          198  +    set fileName [getTemporaryFileName]
          199  +
          200  +    if {[isEagle]} then {
          201  +      uri download $uri $fileName
          202  +    } else {
          203  +      package require Eagle.Tools.Common
          204  +
          205  +      namespace import \
          206  +          ::Eagle::Tools::Common::getFileViaHttp \
          207  +          ::Eagle::Tools::Common::writeFile
          208  +
          209  +      set data [getFileViaHttp $uri 20 $channel $quiet -binary true]
          210  +
          211  +      writeFile $fileName $data
          212  +    }
          213  +
          214  +    set extractDirectory [extractZipArchive $fileName $extractRootDirectory]
          215  +
          216  +    return [lindex [glob -nocomplain \
          217  +        [file join $extractDirectory lib *[info sharedlibextension]]] 0]
          218  +  }
          219  +
          220  +  #
          221  +  # NOTE: This procedure attempts to download and extract the Security Toolset,
          222  +  #       which includes the Harpy and Badge plugins.  The optional channel
          223  +  #       argument is the output channel where diagnostic information is sent.
          224  +  #       The optional quiet argument should be non-zero to prevent diagnostic
          225  +  #       information from being emitted.  This procedure may raise script
          226  +  #       errors.  The return value is the full path to a directory that should
          227  +  #       contain the "Harpy1.0" and "Badge1.0" plugin directories.
          228  +  #
          229  +  proc downloadAndExtractSecurityToolset {
          230  +          {channel stdout} {quiet false} } {
          231  +    setupPackageToolsetVars false
          232  +
          233  +    variable baseUri
          234  +    variable securityToolsetUri
          235  +    variable securityToolsetUrn
          236  +
          237  +    package require Eagle.Test
          238  +    package require Eagle.Unzip
          239  +
          240  +    set extractRootDirectory [getTemporaryPath]
          241  +
          242  +    set directory [file join $extractRootDirectory [appendArgs \
          243  +        ea-st-di- [pid] - [string trim [clock seconds] -]]]
          244  +
          245  +    if {[info exists ::eagle_platform(text)]} then {
          246  +      set platform [string tolower $::eagle_platform(text)]
          247  +    } else {
          248  +      set platform [string tolower netFx20]; # TODO: Good default?
          249  +    }
          250  +
          251  +    set dir [string map [list fx ""] $platform]; # netfx20 -> net20
          252  +    set urn [subst $securityToolsetUrn]; set uri [subst $securityToolsetUri]
          253  +    set fileName [getTemporaryFileName]
          254  +
          255  +    if {[isEagle]} then {
          256  +      uri download $uri $fileName
          257  +    } else {
          258  +      package require Eagle.Tools.Common
          259  +
          260  +      namespace import \
          261  +          ::Eagle::Tools::Common::getFileViaHttp \
          262  +          ::Eagle::Tools::Common::writeFile
          263  +
          264  +      set data [getFileViaHttp $uri 20 $channel $quiet -binary true]
          265  +
          266  +      writeFile $fileName $data
          267  +    }
          268  +
          269  +    set extractDirectory [extractZipArchive $fileName $extractRootDirectory]
          270  +    return [file join $extractDirectory build $dir lib]
          271  +  }
          272  +
          273  +  #
          274  +  # NOTE: This procedure attempts to request a license certificate for Eagle,
          275  +  #       which includes the Harpy and Badge plugins.  The optional channel
          276  +  #       argument is the output channel where diagnostic information is sent.
          277  +  #       The optional quiet argument should be non-zero to prevent diagnostic
          278  +  #       information from being emitted.  This procedure may raise script
          279  +  #       errors.  The return value is the fully qualified file name for the
          280  +  #       resulting license certificate.
          281  +  #
          282  +  # WARNING: This procedure will send the short name and display name of the
          283  +  #          currently logged on user to the Eagle license server as they are
          284  +  #          required for a new license certificate to be issued.  Abuse of
          285  +  #          this service may result in a permanent ban from the service and
          286  +  #          revocation of any previously issued license certificates.
          287  +  #
          288  +  proc requestLicenseCertificate {
          289  +          {channel stdout} {quiet false} } {
          290  +    setupPackageToolsetVars false
          291  +
          292  +    variable baseUri
          293  +    variable licenseUri
          294  +    variable licenseUrn
          295  +
          296  +    package require Eagle.Test
          297  +
          298  +    set certificateRootDirectory [getTemporaryPath]
          299  +
          300  +    set processDirectoryPrefix [file join $certificateRootDirectory \
          301  +        [appendArgs ea-lc-di- [pid] -]]
          302  +
          303  +    #
          304  +    # NOTE: Issue a warning to the user if it appears there is already a
          305  +    #       license certificate in a temporary directory that was created
          306  +    #       by this process.  Hopefully, this should reduce the number of
          307  +    #       duplicate requests.
          308  +    #
          309  +    set varName1 YES_PLEASE_FORCE_A_LICENSE_CERTIFICATE_REQUEST
          310  +
          311  +    if {![info exists ::env($varName1)] && [isWindows]} then {
          312  +      set processFileNames [list]
          313  +
          314  +      foreach processDirectory [findDirectories \
          315  +          [appendArgs $processDirectoryPrefix *]] {
          316  +        eval lappend processFileNames [findFiles \
          317  +            [file join $processDirectory *]]
          318  +      }
          319  +
          320  +      if {[llength $processFileNames] > 0} then {
          321  +        set warningCommand [list]
          322  +
          323  +        if {[isEagle]} then {
          324  +          lappend warningCommand host result Error
          325  +        } else {
          326  +          lappend warningCommand puts stderr
          327  +        }
          328  +
          329  +        set varName2 Master_Certificate
          330  +
          331  +        lappend warningCommand [appendArgs \
          332  +            "One or more temporary license certificate files " \
          333  +            "apparently belonging to this process were found.  " \
          334  +            "If you wish to override this warning and force a " \
          335  +            "new license certificate request to be submitted, " \
          336  +            "set the \"" $varName1 "\" environment variable " \
          337  +            "(to anything); however, please keep in mind that " \
          338  +            "requesting too many license certificates and/or " \
          339  +            "requesting license certificates too fast MAY be " \
          340  +            "considered abusive behavior.  Upon success, the " \
          341  +            "resulting temporary license certificate file " \
          342  +            "SHOULD be saved to a secure location on the local " \
          343  +            "file system, e.g. the home directory associated " \
          344  +            "with the user submitting the license certificate " \
          345  +            "request.  The fully qualified file name for the " \
          346  +            "temporary license certificate MUST used as the " \
          347  +            "value for the \"" $varName2 "\" environment " \
          348  +            "variable; otherwise, it MAY NOT be found when one " \
          349  +            "of its associated plugins attempts to load.\n"]
          350  +
          351  +        #
          352  +        # NOTE: Emit our carefully worded license warning message.
          353  +        #
          354  +        eval $warningCommand
          355  +
          356  +        #
          357  +        # NOTE: Return the first pre-existing license certificate file
          358  +        #       name that was found.
          359  +        #
          360  +        return [lindex $processFileNames 0]
          361  +      }
          362  +    }
          363  +
          364  +    set directory [appendArgs \
          365  +        $processDirectoryPrefix [string trim [clock seconds] -]]
          366  +
          367  +    set urn [subst $licenseUrn]; set uri [subst $licenseUri]
          368  +
          369  +    if {![isEagle] || [catch {
          370  +      object invoke System.Security.Principal.WindowsIdentity \
          371  +          GetCurrent.Name
          372  +    } userName]} then {
          373  +      #
          374  +      # HACK: Fallback to using a value from the "tcl_platform" array.
          375  +      #       For native Tcl, this is the only choice.  For Eagle, it
          376  +      #       is used as a fallback.
          377  +      #
          378  +      if {[info exists ::tcl_platform(user)]} then {
          379  +        set userName $::tcl_platform(user)
          380  +      } else {
          381  +        set userName "NO USER NAME"
          382  +      }
          383  +    }
          384  +
          385  +    if {![isEagle] || [catch {
          386  +      object load System.DirectoryServices.AccountManagement
          387  +
          388  +      object invoke \
          389  +          System.DirectoryServices.AccountManagement.UserPrincipal \
          390  +          Current.DisplayName
          391  +    } displayName]} then {
          392  +      #
          393  +      # HACK: Fallback to using a value from the "tcl_platform" array.
          394  +      #       This value is not set by native Tcl or Eagle; therefore,
          395  +      #       the user would have to set it manually prior to calling
          396  +      #       this procedure.
          397  +      #
          398  +      if {[info exists ::tcl_platform(userDisplayName)]} then {
          399  +        set displayName $::tcl_platform(userDisplayName)
          400  +      } else {
          401  +        set displayName "NO DISPLAY NAME"
          402  +      }
          403  +    }
          404  +
          405  +    #
          406  +    # NOTE: Add the necessary query parameters to the license request
          407  +    #       URI, making sure to properly escape their values.
          408  +    #
          409  +    if {[isEagle]} then {
          410  +      append uri ?userName= [uri escape data $userName]
          411  +      append uri &displayName= [uri escape data $displayName]
          412  +    } else {
          413  +      package require http 2.0
          414  +
          415  +      append uri ? [::http::formatQuery \
          416  +          userName $userName displayName $displayName]
          417  +    }
          418  +
          419  +    if {[isEagle]} then {
          420  +      set data [uri download -inline $uri]
          421  +    } else {
          422  +      package require Eagle.Tools.Common
          423  +
          424  +      namespace import \
          425  +          ::Eagle::Tools::Common::getFileViaHttp \
          426  +          ::Eagle::Tools::Common::writeFile
          427  +
          428  +      set data [getFileViaHttp $uri 20 $channel $quiet -binary true]
          429  +      package require Eagle.Auxiliary
          430  +    }
          431  +
          432  +    if {[getDictionaryValue $data returnCode] ne "Ok"} then {
          433  +      if {[string length $data] > 0} then {
          434  +        error [appendArgs \
          435  +            "request failed with error information: " $data]
          436  +      } else {
          437  +        error "request failed without providing error information"
          438  +      }
          439  +    }
          440  +
          441  +    set fileName [getTemporaryFileName]
          442  +    writeFile $fileName [getDictionaryValue $data result]
          443  +    set newFileName [file join $directory [file tail $fileName]]
          444  +
          445  +    file mkdir $directory; file copy $fileName $newFileName
          446  +    file delete $fileName
          447  +
          448  +    return $newFileName
          449  +  }
   112    450   
   113    451     #
   114    452     # NOTE: Provide the Eagle "package toolset" package to the interpreter.
   115    453     #
   116    454     package provide Eagle.Package.Toolset \
   117    455       [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}]
   118    456   }
   119    457   

Changes to Externals/Eagle/lib/Eagle1.0/platform.eagle.

    20     20   #       namespace if this script actually ends up being evaluated in Tcl.
    21     21   #
    22     22   namespace eval ::Eagle {
    23     23     #
    24     24     # NOTE: This is the procedure that detects whether or not we are running
    25     25     #       in Eagle (otherwise, it is assumed that we are running in vanilla
    26     26     #       Tcl).  This procedure must work correctly in both Tcl and Eagle
    27         -  #       and must return non-zero only when running in Eagle.
           27  +  #       and must return non-zero only when running in Eagle.  The same
           28  +  #       procedure is also defined in the "init.eagle" file.
    28     29     #
    29     30     proc isEagle {} {
    30     31       #
    31     32       # NOTE: Nothing too fancy or expensive should be done here.  In theory,
    32     33       #       use of this procedure should be rare; however, in practice, this
    33     34       #       procedure is actually used quite a bit (e.g. by the test suite).
    34     35       #

Changes to Externals/Eagle/lib/Eagle1.0/safe.eagle.

    22     22   namespace eval ::Eagle {
    23     23     #
    24     24     # NOTE: This is the procedure that detects whether or not we are
    25     25     #       running in Eagle (otherwise, we are running in vanilla Tcl).
    26     26     #       This procedure must function correctly in both Tcl and Eagle
    27     27     #       and must return non-zero only when running in Eagle.  This
    28     28     #       procedure must be defined in this script file because it is
    29         -  #       needed while this script file is being evaluated.
           29  +  #       needed while this script file is being evaluated.  The same
           30  +  #       procedure is also defined in the "init.eagle" file.
    30     31     #
    31     32     # <bootstrap>
    32     33     proc isEagle {} {
    33     34       #
    34     35       # NOTE: Nothing too fancy or expensive should be done in here.  In
    35     36       #       theory, use of this routine should be rare; however, in
    36     37       #       practice, this routine is actually used quite a bit (e.g.

Changes to Externals/Eagle/lib/Eagle1.0/test.eagle.

   266    266       #
   267    267       # NOTE: Returns the results of [array get] in a well-defined order.
   268    268       #
   269    269       if {[string length $varName] == 0} then {
   270    270         return [list]
   271    271       }
   272    272   
          273  +    #
          274  +    # NOTE: Refer to the array in the context of the caller.
          275  +    #
   273    276       upvar 1 $varName array
   274    277   
   275    278       #
   276    279       # NOTE: Build the command that will sort the array names into order.
   277    280       #
   278    281       set command [list lsort]
   279    282       if {$integer} then {lappend command -integer}
................................................................................
   283    286   
   284    287       foreach name [eval $command] {
   285    288         lappend result $name $array($name)
   286    289       }
   287    290   
   288    291       return $result
   289    292     }
          293  +
          294  +  proc testResultGet { script } {
          295  +    set code [catch {uplevel 1 $script} result]
          296  +    return [expr {$code == 0 ? $result : "<error>"}]
          297  +  }
          298  +
          299  +  proc testValueGet { varName {integer false} } {
          300  +    #
          301  +    # NOTE: Returns the results of [array get] in a well-defined order
          302  +    #       -OR- the value of the scalar variable.
          303  +    #
          304  +    if {[string length $varName] == 0} then {
          305  +      return [list]
          306  +    }
          307  +
          308  +    #
          309  +    # NOTE: Is the specified variable (in the context of the caller) an
          310  +    #       array?
          311  +    #
          312  +    if {[uplevel 1 [list array exists $varName]]} then {
          313  +      #
          314  +      # NOTE: Refer to the array in the context of the caller.
          315  +      #
          316  +      upvar 1 $varName array
          317  +
          318  +      #
          319  +      # NOTE: Build the command that will sort the array names into order.
          320  +      #
          321  +      set command [list lsort]
          322  +      if {$integer} then {lappend command -integer}
          323  +      lappend command [array names array]
          324  +
          325  +      set result [list]
          326  +
          327  +      foreach name [eval $command] {
          328  +        lappend result $name $array($name)
          329  +      }
          330  +    } else {
          331  +      #
          332  +      # NOTE: Grab the value of the scalar variable in the context of the
          333  +      #       caller and then return both the name and the value.
          334  +      #
          335  +      set varValue [uplevel 1 [list set $varName]]
          336  +      set result [list $varValue]
          337  +    }
          338  +
          339  +    return $result
          340  +  }
          341  +
          342  +  proc getFirstLineOfError { error } {
          343  +    set error [string map [list \r\n \n] $error]
          344  +    set index [string first \n $error]
          345  +
          346  +    if {$index != -1} then {
          347  +      incr index -1
          348  +
          349  +      if {$index > 0} then {
          350  +        return [string range $error 0 $index]
          351  +      }
          352  +    }
          353  +
          354  +    return $error
          355  +  }
   290    356   
   291    357     proc calculateBogoCops { {milliseconds 2000} {legacy false} } {
   292    358       #
   293    359       # NOTE: Verify that the number of milliseconds requested is greater than
   294    360       #       zero.
   295    361       #
   296    362       if {$milliseconds <= 0} then {
................................................................................
   377    443                 return 0
   378    444               }
   379    445             } finally {
   380    446               if {[info exists event]} then {
   381    447                 catch {after cancel $event}
   382    448               }
   383    449   
   384         -            after flags =$flags
          450  +            after flags [appendArgs = $flags]
   385    451             }
   386    452           } finally {
   387    453             interp bgerror {} $bgerror
   388    454           }
   389    455         } finally {
   390    456           interp readylimit {} $readylimit
   391    457         }
................................................................................
  1378   1444     }
  1379   1445   
  1380   1446     proc isBreakOnLeak {} {
  1381   1447       return [expr {[info exists ::test_break_on_leak] && \
  1382   1448                     [string is boolean -strict $::test_break_on_leak] && \
  1383   1449                     $::test_break_on_leak}]
  1384   1450     }
         1451  +
         1452  +  proc isBreakOnDemand {} {
         1453  +    global env
         1454  +
         1455  +    return [expr {[info exists env(isBreakOnDemand)] && \
         1456  +                  [string is boolean -strict $env(isBreakOnDemand)] && \
         1457  +                  $env(isBreakOnDemand)}]
         1458  +  }
  1385   1459   
  1386   1460     proc isStopOnFailure {} {
  1387   1461       return [expr {[info exists ::test_stop_on_failure] && \
  1388   1462                     [string is boolean -strict $::test_stop_on_failure] && \
  1389   1463                     $::test_stop_on_failure}]
  1390   1464     }
  1391   1465   
................................................................................
  1558   1632         #
  1559   1633         if {$code != 0 && [isStopOnFailure]} then {
  1560   1634           tresult Error "OVERALL RESULT: STOP-ON-FAILURE\n"
  1561   1635   
  1562   1636           unset -nocomplain ::test_suite_running
  1563   1637           error ""; # no message
  1564   1638         }
         1639  +
         1640  +      #
         1641  +      # NOTE: Unless forbidden from doing so, attempt to automatically
         1642  +      #       cleanup any stale (e.g. temporary) object references now.
         1643  +      #
         1644  +      if {![info exists ::no(cleanupReferences)]} then {
         1645  +        catch {object cleanup -references}
         1646  +      }
  1565   1647       } else {
  1566   1648         if {$error} then {
  1567   1649           #
  1568   1650           # HACK: Prevent spurious errors dealing with [test] command options
  1569   1651           #       that are missing from native Tcl.
  1570   1652           #
  1571   1653           set badOptionPattern {^bad option ".*?":\
................................................................................
  1744   1826         catch {set array(connections,$index) [llength [info connections]]}
  1745   1827         catch {set array(transactions,$index) [llength [info transactions]]}
  1746   1828         catch {set array(modules,$index) [llength [info modules]]}
  1747   1829         catch {set array(delegates,$index) [llength [info delegates]]}
  1748   1830   
  1749   1831         if {[llength [info commands tcl]] > 0} then {
  1750   1832           catch {set array(tcl,$index) [tcl ready]}
         1833  +        catch {set array(tclInterps,$index) [llength [tcl interps]]}
         1834  +        catch {set array(tclThreads,$index) [llength [tcl threads]]}
         1835  +        catch {set array(tclCommands,$index) [llength [tcl command list]]}
  1751   1836         }
  1752   1837   
  1753         -      catch {set array(tclInterps,$index) [llength [tcl interps]]}
  1754         -      catch {set array(tclThreads,$index) [llength [tcl threads]]}
  1755         -      catch {set array(tclCommands,$index) [llength [tcl command list]]}
  1756         -
  1757   1838         #
  1758   1839         # NOTE: Grab the number of active threads that are active because
  1759   1840         #       of ScriptThread object instances.  This only works if Eagle
  1760   1841         #       is Beta 31 or higher.
  1761   1842         #
  1762   1843         catch {
  1763   1844           set array(scriptThreads,$index) \
................................................................................
  2172   2253       #
  2173   2254       set failed [list]
  2174   2255       set leaked [list]
  2175   2256   
  2176   2257       #
  2177   2258       # NOTE: Process each file name we have been given by the caller...
  2178   2259       #
  2179         -    set total [llength $fileNames]; set lastPercent -1
         2260  +    set total 0; set lastPercent -1
  2180   2261   
  2181   2262       foreach fileName $fileNames {
         2263  +      #
         2264  +      # NOTE: If configured to break into the debugger before running the
         2265  +      #       test file, do it now.
         2266  +      #
         2267  +      if {[isBreakOnDemand]} then {
         2268  +        testDebugBreak
         2269  +      }
         2270  +
  2182   2271         #
  2183   2272         # NOTE: In terms of files, not tests, what percent done are we now?
  2184   2273         #
  2185   2274         set percent [formatDecimal \
  2186   2275             [expr {$total != 0 ? 100.0 * ($count / double($total)) : 100}]]
  2187   2276   
  2188   2277         if {$percent != $lastPercent} then {
................................................................................
  2353   2442               #
  2354   2443               # NOTE: Log that this test file has ended.
  2355   2444               #
  2356   2445               if {![info exists ::no(runEndFile)]} then {
  2357   2446                 tputs $channel [appendArgs "==== \"" $fileName "\" END\n"]
  2358   2447               }
  2359   2448   
         2449  +            #
         2450  +            # NOTE: At this point, we know that another test file was
         2451  +            #       processed successfully.
         2452  +            #
         2453  +            incr total
         2454  +
         2455  +            if {![info exists ::no(runPercent)]} then {
         2456  +              reportTestPercent $channel $percent \
         2457  +                  $total [llength $failed] [llength $leaked]
         2458  +            }
         2459  +
  2360   2460               #
  2361   2461               # NOTE: Are we being prevented from waiting after the file?
  2362   2462               #
  2363   2463               if {![info exists ::no(postWait)]} then {
  2364   2464                 if {[info exists ::test_wait(post)] && \
  2365   2465                     [string is integer -strict $::test_wait(post)]} then {
  2366   2466                   if {![info exists ::no(runMetadata)]} then {
................................................................................
  2419   2519                 #       probably caused it to skip a bunch of tests -AND- the
  2420   2520                 #       option to stop-testing-on-error is not enabled.  That
  2421   2521                 #       being said, we must not simply ignore the error.  The
  2422   2522                 #       overall results of the test suite run must now reflect
  2423   2523                 #       the failure.  Set a special variable for the epilogue
  2424   2524                 #       to pick up on (later).
  2425   2525                 #
  2426         -              lappend ::test_suite_errors $error
         2526  +              lappend ::test_suite_errors [list $fileName $error]
  2427   2527               }
  2428   2528             }
  2429   2529   
  2430   2530             #
  2431   2531             # NOTE: We evaluated another test file.
  2432   2532             #
  2433   2533             incr count
................................................................................
  2491   2591             # NOTE: This entire file has been skipped.  Record that fact in the
  2492   2592             #       test suite log file.
  2493   2593             #
  2494   2594             if {![info exists ::no(runNonTestFile)]} then {
  2495   2595               tputs $channel [appendArgs \
  2496   2596                   "==== \"" $fileName "\" NON_TEST_FILE\n"]
  2497   2597             }
  2498         -
  2499         -          #
  2500         -          # NOTE: This file does not actually count towards the total (i.e.
  2501         -          #       it contains no actual tests).
  2502         -          #
  2503         -          incr total -1
  2504   2598           }
  2505   2599   
  2506   2600           #
  2507   2601           # NOTE: In terms of files, not tests, what percent done are we now?
  2508   2602           #
  2509   2603           set percent [formatDecimal \
  2510   2604               [expr {$total != 0 ? 100.0 * ($count / double($total)) : 100}]]
................................................................................
  2530   2624           #
  2531   2625           # NOTE: This entire file has been skipped.  Record that fact in the
  2532   2626           #       test suite log file.
  2533   2627           #
  2534   2628           if {![info exists ::no(runSkippedFile)]} then {
  2535   2629             tputs $channel [appendArgs "==== \"" $fileName "\" SKIPPED\n"]
  2536   2630           }
  2537         -
  2538         -        #
  2539         -        # NOTE: This file does not actually count towards the total (i.e.
  2540         -        #       it is part of the test suite infrastructure).
  2541         -        #
  2542         -        incr total -1
  2543   2631         }
  2544   2632   
  2545   2633         #
  2546   2634         # NOTE: In terms of files, not tests, what percent done are we now?
  2547   2635         #
  2548   2636         set percent [formatDecimal \
  2549   2637             [expr {$total != 0 ? 100.0 * ($count / double($total)) : 100}]]
................................................................................
  3333   3421         tputs $channel [appendArgs \
  3334   3422             "---- purge \"" $name "\" results: " $result \n]
  3335   3423   
  3336   3424         catch {uplevel 1 [list debug cleanup]} result
  3337   3425   
  3338   3426         tputs $channel [appendArgs \
  3339   3427             "---- cleanup \"" $name "\" results: " $result \n]
         3428  +
         3429  +      catch {uplevel 1 [list object invoke -flags +NonPublic \
         3430  +          Eagle._Components.Private.ProcessOps ClearOutputCache]} result
         3431  +
         3432  +      tputs $channel [appendArgs \
         3433  +          "---- ProcessOps cleanup results: " $result \n]
  3340   3434   
  3341   3435         catch {uplevel 1 [list object invoke -flags +NonPublic \
  3342   3436             Eagle._Components.Private.EnumOps ClearEnumCache]} result
  3343   3437   
  3344   3438         tputs $channel [appendArgs \
  3345   3439             "---- EnumOps cleanup results: " $result \n]
  3346   3440   
................................................................................
  3369   3463         #       zero.
  3370   3464         #
  3371   3465         if {$milliseconds <= 0} then {
  3372   3466           error "number of milliseconds must be greater than zero"
  3373   3467         }
  3374   3468   
  3375   3469         #
  3376         -      # NOTE: Save the current background error handler for later restoration
  3377         -      #       and then reset the current background error handler to nothing.
         3470  +      # NOTE: Force any [vwait] that may be in the contained script to stop
         3471  +      #       when it hits the script cancellation, saving the preexisting
         3472  +      #       event wait flags first for later restoration.
  3378   3473         #
  3379         -      set bgerror [interp bgerror {}]
  3380         -      interp bgerror {} ""
         3474  +      set savedEventWaitFlags [object invoke -flags +NonPublic \
         3475  +          Interpreter.GetActive eventWaitFlags]
         3476  +
         3477  +      object invoke -flags +NonPublic Interpreter.GetActive \
         3478  +          eventWaitFlags [combineFlags $savedEventWaitFlags StopOnError]
  3381   3479   
  3382   3480         try {
  3383   3481           #
  3384   3482           # NOTE: Save the current [after] flags for later restoration and then
  3385   3483           #       reset them to process events immediately.
  3386   3484           #
  3387   3485           set flags [after flags]
................................................................................
  3401   3499               # NOTE: First, make sure that the [after] event queue for the
  3402   3500               #       interpreter is totally empty.
  3403   3501               #
  3404   3502               catch {foreach id [after info] {after cancel $id}}
  3405   3503   
  3406   3504               #
  3407   3505               # NOTE: Schedule the event to cancel the script we are about to
  3408         -            #       evaluate, capturing the name so we can cancel it later, if
  3409         -            #       necessary.
         3506  +            #       evaluate, capturing the name so we can cancel it later,
         3507  +            #       if necessary.
  3410   3508               #
  3411   3509               set event [after $milliseconds [list interp cancel]]
  3412   3510   
  3413   3511               #
  3414   3512               # NOTE: Evaluate the script in the context of the caller.
  3415   3513               #
  3416   3514               uplevel 1 $script
  3417   3515             } result]
  3418   3516           } finally {
  3419   3517             if {[info exists event]} then {
  3420   3518               catch {after cancel $event}
  3421   3519             }
  3422   3520   
  3423         -          after flags =$flags
         3521  +          after flags [appendArgs = $flags]
         3522  +        }
         3523  +      } finally {
         3524  +        if {[info exists savedEventWaitFlags]} then {
         3525  +          object invoke -flags +NonPublic Interpreter.GetActive \
         3526  +              eventWaitFlags $savedEventWaitFlags
         3527  +        }
         3528  +      }
         3529  +    }
         3530  +
         3531  +    proc vwaitWithTimeout { varName {milliseconds 2000} } {
         3532  +      #
         3533  +      # NOTE: Verify that the number of milliseconds requested is positive or
         3534  +      #       zero.
         3535  +      #
         3536  +      if {$milliseconds < 0} then {
         3537  +        error "number of milliseconds cannot be negative"
         3538  +      }
         3539  +
         3540  +      try {
         3541  +        #
         3542  +        # NOTE: Schedule the event to cancel the script we are about to
         3543  +        #       evaluate, capturing the name so we can cancel it later,
         3544  +        #       if necessary.
         3545  +        #
         3546  +        set event [after $milliseconds [list interp cancel]]
         3547  +
         3548  +        if {[catch {
         3549  +          #
         3550  +          # NOTE: Refer to the specified variable in the context of our
         3551  +          #       caller.
         3552  +          #
         3553  +          upvar 1 $varName variable
         3554  +
         3555  +          #
         3556  +          # NOTE: Wait for the variable to be changed -OR- for the wait
         3557  +          #       to be canceled.
         3558  +          #
         3559  +          vwait -eventwaitflags {+NoBgError StopOnError} -- variable
         3560  +        }] == 0} then {
         3561  +          #
         3562  +          # NOTE: The wait completed successfully, the variable should
         3563  +          #       have been changed.
         3564  +          #
         3565  +          return true
         3566  +        } else {
         3567  +          #
         3568  +          # NOTE: The wait did not complete, it may have been canceled
         3569  +          #       and the variable may or may not have been changed.
         3570  +          #
         3571  +          return false
  3424   3572           }
  3425   3573         } finally {
  3426         -        interp bgerror {} $bgerror
         3574  +        if {[info exists event]} then {
         3575  +          catch {after cancel $event}
         3576  +        }
  3427   3577         }
  3428   3578       }
  3429   3579   
  3430   3580       proc tclLoadForTest { {varName ""} {findFlags ""} {loadFlags ""} } {
  3431   3581         if {[string length $varName] > 0} then {
  3432   3582           upvar 1 $varName loaded
  3433   3583         }
................................................................................
  3795   3945           fixConstraints fixTimingConstraints calculateBogoCops \
  3796   3946           calculateRelativePerformance formatTimeStamp formatElapsedTime \
  3797   3947           sourceIfValid processTestArguments getTclShellFileName \
  3798   3948           getTemporaryPath getFiles getTestFiles getTestRunId getTestLogId \
  3799   3949           getDefaultTestLog getTestLog getLastTestLog getTestSuite \
  3800   3950           getTestMachine getTestPlatform getTestConfiguration getTestSuffix \
  3801   3951           getTestUncountedLeaks getTestAssemblyName canTestExec testExec \
  3802         -        testClrExec execTestShell isRandomOrder isBreakOnLeak \
         3952  +        testClrExec execTestShell isRandomOrder isBreakOnDemand isBreakOnLeak \
  3803   3953           isStopOnFailure isStopOnLeak isExitOnComplete returnInfoScript \
  3804   3954           runTestPrologue runTestEpilogue hookPuts unhookPuts runTest \
  3805   3955           testDebugBreak testArrayGet testShim tsource recordTestStatistics \
  3806   3956           reportTestStatistics formatList formatListAsDict pathToRegexp \
  3807   3957           inverseLsearchGlob removePathFromFileNames formatDecimal \
  3808   3958           clearTestPercent reportTestPercent runAllTests isTestSuiteRunning \
  3809   3959           getTestChannelOrDefault tryVerifyTestPath checkForAndSetTestPath \

Changes to Externals/Eagle/lib/Test1.0/constraints.eagle.

    19     19   #       support namespaces ourselves, we do not want to pollute the global
    20     20   #       namespace if this script actually ends up being evaluated in Tcl.
    21     21   #
    22     22   namespace eval ::Eagle {
    23     23     proc getKnownBuildTypes {} {
    24     24       return [list \
    25     25           NetFx20 NetFx35 NetFx40 NetFx45 NetFx451 NetFx452 \
    26         -        NetFx46 NetFx461 NetFx462 NetFx47 Bare LeanAndMean \
    27         -        Database MonoOnUnix Development]
           26  +        NetFx46 NetFx461 NetFx462 NetFx47 NetFx471 Bare \
           27  +        LeanAndMean Database MonoOnUnix Development]
    28     28     }
    29     29   
    30     30     proc getKnownCompileOptions {} {
    31     31       return [list \
    32         -        APPDOMAINS APPROVED_VERBS ARGUMENT_CACHE ARM ARM64 ASSEMBLY_RELEASE \
    33         -        ASSEMBLY_STRONG_NAME_TAG ASSEMBLY_TAG ASSEMBLY_TEXT ASSEMBLY_URI \
    34         -        BREAK_ON_EXITING BREAKPOINTS CACHE_ARGUMENT_TOSTRING \
           32  +        APPDOMAINS APPROVED_VERBS ARGUMENT_CACHE ARM ARM64 ASSEMBLY_DATETIME \
           33  +        ASSEMBLY_RELEASE ASSEMBLY_STRONG_NAME_TAG ASSEMBLY_TAG ASSEMBLY_TEXT \
           34  +        ASSEMBLY_URI BREAK_ON_EXITING BREAKPOINTS CACHE_ARGUMENT_TOSTRING \
    35     35           CACHE_ARGUMENTLIST_TOSTRING CACHE_DICTIONARY CACHE_RESULT_TOSTRING \
    36     36           CACHE_STATISTICS CACHE_STRINGLIST_TOSTRING CALLBACK_QUEUE CAS_POLICY \
    37     37           CERTIFICATE_PLUGIN CERTIFICATE_POLICY CERTIFICATE_RENEWAL \
    38     38           CODE_ANALYSIS COM_TYPE_CACHE CONSOLE DAEMON DATA DEAD_CODE DEBUG \
    39     39           DEBUGGER DEBUGGER_ARGUMENTS DEBUGGER_ENGINE DEBUGGER_EXECUTE \
    40         -        DEBUGGER_EXPRESSION DEBUGGER_VARIABLE DEBUG_TRACE DEBUG_WRITE DRAWING \
    41         -        DYNAMIC EAGLE EMBEDDED_LIBRARY EMBED_CERTIFICATES ENTERPRISE_LOCKDOWN \
    42         -        EXECUTE_CACHE EXPRESSION_FLAGS FAST_ERRORCODE FAST_ERRORINFO \
    43         -        FOR_TEST_USE_ONLY HAVE_SIZEOF HISTORY IA64 INTERACTIVE_COMMANDS \
    44         -        INTERNALS_VISIBLE_TO ISOLATED_INTERPRETERS ISOLATED_PLUGINS LIBRARY \
    45         -        LICENSING LICENSE_MANAGER LIMITED_EDITION LIST_CACHE MONO MONO_BUILD \
    46         -        MONO_HACKS MONO_LEGACY NATIVE NATIVE_PACKAGE NATIVE_THREAD_ID \
    47         -        NATIVE_UTILITY NATIVE_UTILITY_BSTR NETWORK NET_20 NET_20_FAST_ENUM \
    48         -        NET_20_ONLY NET_20_SP1 NET_20_SP2 NET_30 NET_35 NET_40 NET_45 NET_451 \
    49         -        NET_452 NET_46 NET_461 NET_462 NET_47 NON_WORKING_CODE NOTIFY \
    50         -        NOTIFY_ACTIVE NOTIFY_ARGUMENTS NOTIFY_EXCEPTION NOTIFY_EXECUTE \
    51         -        NOTIFY_EXPRESSION NOTIFY_GLOBAL NOTIFY_OBJECT OBSOLETE OBFUSCATION \
    52         -        OFFICIAL PARSE_CACHE PATCHLEVEL PLUGIN_COMMANDS POLICY_TRACE \
    53         -        PREVIOUS_RESULT RANDOMIZE_ID REMOTING SAMPLE SECURITY SERIALIZATION \
    54         -        SHARED_ID_POOL SHELL SOURCE_ID SOURCE_TIMESTAMP STATIC TCL TCL_KITS \
    55         -        TCL_THREADED TCL_THREADS TCL_UNICODE TCL_WRAPPER TEST TEST_PLUGIN \
    56         -        THREADING THROW_ON_DISPOSED TRACE TYPE_CACHE UNIX \
    57         -        USE_APPDOMAIN_FOR_ID USE_NAMESPACES VERBOSE WEB WINDOWS WINFORMS \
    58         -        WIX_30 WIX_35 WIX_36 WIX_37 WIX_38 WIX_39 WIX_310 X64 X86 XML]
           40  +        DEBUGGER_EXPRESSION DEBUGGER_VARIABLE DEBUG_TRACE DEBUG_WRITE \
           41  +        DEMO_EDITION DRAWING DYNAMIC EAGLE EMBEDDED_LIBRARY \
           42  +        EMBED_CERTIFICATES ENTERPRISE_LOCKDOWN EXECUTE_CACHE EXPRESSION_FLAGS \
           43  +        FAST_ERRORCODE FAST_ERRORINFO FOR_TEST_USE_ONLY HAVE_SIZEOF HISTORY \
           44  +        IA64 INTERACTIVE_COMMANDS INTERNALS_VISIBLE_TO ISOLATED_INTERPRETERS \
           45  +        ISOLATED_PLUGINS LIBRARY LICENSING LICENSE_MANAGER LIMITED_EDITION \
           46  +        LIST_CACHE MONO MONO_BUILD MONO_HACKS MONO_LEGACY NATIVE \
           47  +        NATIVE_PACKAGE NATIVE_THREAD_ID NATIVE_UTILITY NATIVE_UTILITY_BSTR \
           48  +        NETWORK NET_20 NET_20_FAST_ENUM NET_20_ONLY NET_20_SP1 NET_20_SP2 \
           49  +        NET_30 NET_35 NET_40 NET_45 NET_451 NET_452 NET_46 NET_461 NET_462 \
           50  +        NET_47 NET_471 NON_WORKING_CODE NOTIFY NOTIFY_ACTIVE NOTIFY_ARGUMENTS \
           51  +        NOTIFY_EXCEPTION NOTIFY_EXECUTE NOTIFY_EXPRESSION NOTIFY_GLOBAL \
           52  +        NOTIFY_OBJECT OBSOLETE OBFUSCATION OFFICIAL PARSE_CACHE PATCHLEVEL \
           53  +        PLUGIN_COMMANDS POLICY_TRACE PREVIOUS_RESULT RANDOMIZE_ID REMOTING \
           54  +        RESULT_LIMITS SAMPLE SECURITY SERIALIZATION SHARED_ID_POOL SHELL \
           55  +        SOURCE_ID SOURCE_TIMESTAMP STATIC TCL TCL_KITS TCL_THREADED \
           56  +        TCL_THREADS TCL_UNICODE TCL_WRAPPER TEST TEST_PLUGIN THREADING \
           57  +        THROW_ON_DISPOSED TRACE TYPE_CACHE UNIX USE_APPDOMAIN_FOR_ID \
           58  +        USE_NAMESPACES VERBOSE WEB WINDOWS WINFORMS WIX_30 WIX_35 WIX_36 \
           59  +        WIX_37 WIX_38 WIX_39 WIX_310 WIX_311 X64 X86 XML]
    59     60     }
    60     61   
    61     62     proc getKnownMonoVersions { {force false} } {
    62     63       #
    63     64       # NOTE: This job of this procedure is to return the list of "known"
    64     65       #       versions of Mono supported by the test suite infrastructure.
    65     66       #
................................................................................
   436    437         #
   437    438         return true
   438    439       }
   439    440   
   440    441       set reason "skipped, need Eagle"
   441    442       return false
   442    443     }
          444  +
          445  +  proc cleanConstraintName { name } {
          446  +    #
          447  +    # NOTE: Start with the original constraint name, removing surrounding
          448  +    #       whitespace.  If this results in an empty string, we are done.
          449  +    #
          450  +    set result [string trim $name]
          451  +
          452  +    if {[string length $result] == 0} then {
          453  +      return $result
          454  +    }
          455  +
          456  +    #
          457  +    # NOTE: The constraints for a test are actually a list; therefore, we
          458  +    #       must remove anything that might confuse the list parser.
          459  +    #
          460  +    set result [string map [list \" "" \\ "" \{ "" \} ""] $result]
          461  +
          462  +    #
          463  +    # NOTE: In order to avoid semantic confusion, remove other characters
          464  +    #       that may be reserved by the test suite subsystems.
          465  +    #
          466  +    set result [string map [list ! "" # "" \$ "" \; "" \[ "" \] ""] $result]
          467  +
          468  +    #
          469  +    # NOTE: Finally, remove all remaining whitespace.
          470  +    #
          471  +    regsub -all -- {\s} $result "" result; return $result
          472  +  }
   443    473   
   444    474     proc cleanPackageName { package full } {
   445    475       #
   446    476       # NOTE: Start out with the original package name, removing surrounding
   447    477       #       whitespace.  If this results in an empty string, we are done.
   448    478       #
   449    479       set result [string trim $package]
................................................................................
   471    501       #       names.  For now, they are all replaced with underscores by this
   472    502       #       procedure.  Any existing underscores in the string are doubled.
   473    503       #
   474    504       set charMap [list _ __ " " _ + _ , _ . _ = _ \[ _ \\ _ \] _ ` _]
   475    505   
   476    506       return [string map $charMap $result]
   477    507     }
          508  +
          509  +  proc haveTclPlatformOsExtraUpdateName { name } {
          510  +    if {[info exists ::tcl_platform(osExtra)]} then {
          511  +      set updateNames [getDictionaryValue $::tcl_platform(osExtra) \
          512  +          UpdateNames]
          513  +
          514  +      if {[lsearch -exact $updateNames $name] != -1} then {
          515  +        return true
          516  +      }
          517  +    }
          518  +
          519  +    return false
          520  +  }
   478    521   
   479    522     proc checkForTestSuiteFiles { channel } {
   480    523       tputs $channel "---- checking for test suite files... "
   481    524   
   482    525       #
   483    526       # NOTE: Start out with no test suite files to check.
   484    527       #
................................................................................
   729    772           #
   730    773           return
   731    774         }
   732    775       }
   733    776   
   734    777       tputs $channel no\n
   735    778     }
          779  +
          780  +  proc checkForOperatingSystemUpdate { channel name } {
          781  +    tputs $channel [appendArgs \
          782  +        "---- checking for operating system update \"" \
          783  +        $name "\"... "]
          784  +
          785  +    #
          786  +    # NOTE: Is the specific OS update currently installed?
          787  +    #
          788  +    if {[haveTclPlatformOsExtraUpdateName $name]} then {
          789  +      addConstraint [appendArgs osUpdate . [cleanConstraintName $name]]
          790  +
          791  +      tputs $channel yes\n
          792  +    } else {
          793  +      tputs $channel no\n
          794  +    }
          795  +  }
   736    796   
   737    797     proc checkForScriptLibrary { channel } {
   738    798       tputs $channel "---- checking for script library... "
   739    799   
   740    800       #
   741    801       # NOTE: See if the variable containing the script library location
   742    802       #       exists.
................................................................................
  1942   2002       #
  1943   2003       # NOTE: Does the interpreter have TIP #405 (i.e. [lmap])?
  1944   2004       #
  1945   2005       catch {lmap} error
  1946   2006   
  1947   2007       if {$error ne "invalid command name \"lmap\""} then {
  1948   2008         addConstraint tip405
         2009  +
         2010  +      tputs $channel yes\n
         2011  +    } else {
         2012  +      tputs $channel no\n
         2013  +    }
         2014  +  }
         2015  +
         2016  +  proc checkForTip421 { channel } {
         2017  +    tputs $channel "---- checking for TIP #421... "
         2018  +
         2019  +    #
         2020  +    # NOTE: Is the interpreter TIP #421 ready?
         2021  +    #
         2022  +    if {[catch {
         2023  +      set array(1) one; set list [list]
         2024  +
         2025  +      array for {name value} array {
         2026  +        lappend list $name $value
         2027  +      }
         2028  +
         2029  +      set list
         2030  +    } result] == 0 && $result eq [list 1 one]} then {
         2031  +      addConstraint tip421
  1949   2032   
  1950   2033         tputs $channel yes\n
  1951   2034       } else {
  1952   2035         tputs $channel no\n
  1953   2036       }
  1954   2037     }
  1955   2038   
................................................................................
  3957   4040             #
  3958   4041             set key [appendArgs HKEY_LOCAL_MACHINE\\ \
  3959   4042                 [getSoftwareRegistryKey true] {\Microsoft\Windows Installer XML}]
  3960   4043   
  3961   4044             #
  3962   4045             # NOTE: The versions of WiX that we support.
  3963   4046             #
  3964         -          set versions [list 3.7 3.6 3.5 3.0]
         4047  +          set versions [list 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.0]
  3965   4048   
  3966   4049             #
  3967   4050             # NOTE: Check each version, stopping when one is found.
  3968   4051             #
  3969   4052             foreach version $versions {
  3970   4053               #
  3971   4054               # NOTE: Attempt to fetch the WiX install directory value from the
................................................................................
  4161   4244             #
  4162   4245             return
  4163   4246           }
  4164   4247         }
  4165   4248   
  4166   4249         tputs $channel no\n
  4167   4250       }
         4251  +
         4252  +    proc getFrameworkSetup451Value {} {
         4253  +      #
         4254  +      # NOTE: Check if we are running on Windows 8.1.
         4255  +      #
         4256  +      # BUGBUG: Is exact matching correct here?
         4257  +      #
         4258  +      if {[isWindows] && [info exists ::tcl_platform(osVersion)] && \
         4259  +          $::tcl_platform(osVersion) == 6.3} then {
         4260  +        #
         4261  +        # NOTE: We are running on Windows 8.1, return the special value.
         4262  +        #
         4263  +        return 378675
         4264  +      }
         4265  +
         4266  +      #
         4267  +      # NOTE: We are not running on Windows 8.1, return the normal value.
         4268  +      #
         4269  +      return 378758
         4270  +    }
  4168   4271   
  4169   4272       proc getFrameworkSetup46Value {} {
  4170   4273         #
  4171   4274         # NOTE: Check if we are running on Windows 10 or later.
  4172   4275         #
  4173         -      if {[isWindows] && $::tcl_platform(osVersion) >= 10.0} then {
         4276  +      # BUGBUG: Is greater-than-or-equal-to matching correct here?
         4277  +      #
         4278  +      if {[isWindows] && [info exists ::tcl_platform(osVersion)] && \
         4279  +          $::tcl_platform(osVersion) >= 10.0} then {
  4174   4280           #
  4175   4281           # NOTE: We are running on Windows 10, return the special value.
  4176   4282           #
  4177   4283           return 393295
  4178   4284         }
  4179   4285   
  4180   4286         #
................................................................................
  4183   4289         return 393297
  4184   4290       }
  4185   4291   
  4186   4292       proc getFrameworkSetup461Value {} {
  4187   4293         #
  4188   4294         # NOTE: Check if we are running on Windows 10 or later.
  4189   4295         #
  4190         -      if {[isWindows] && $::tcl_platform(osVersion) >= 10.0} then {
         4296  +      # BUGBUG: Is greater-than-or-equal-to matching correct here?
         4297  +      #
         4298  +      if {[isWindows] && [info exists ::tcl_platform(osVersion)] && \
         4299  +          $::tcl_platform(osVersion) >= 10.0 && \
         4300  +          [haveTclPlatformOsExtraUpdateName "November Update"]} then {
  4191   4301           #
  4192   4302           # NOTE: We are running on Windows 10, return the special value.
  4193   4303           #
  4194         -        return 394254
         4304  +        return 394254; # BUGBUG: November Update only?
  4195   4305         }
  4196   4306   
  4197   4307         #
  4198   4308         # NOTE: We are not running on Windows 10, return the normal value.
  4199   4309         #
  4200   4310         return 394271
  4201   4311       }
  4202   4312   
  4203   4313       proc getFrameworkSetup462Value {} {
  4204   4314         #
  4205   4315         # NOTE: Check if we are running on Windows 10 or later.
  4206   4316         #
  4207         -      if {[isWindows] && $::tcl_platform(osVersion) >= 10.0} then {
         4317  +      # BUGBUG: Is greater-than-or-equal-to matching correct here?
         4318  +      #
         4319  +      if {[isWindows] && [info exists ::tcl_platform(osVersion)] && \
         4320  +          $::tcl_platform(osVersion) >= 10.0 && \
         4321  +          [haveTclPlatformOsExtraUpdateName "Anniversary Update"]} then {
  4208   4322           #
  4209   4323           # NOTE: We are running on Windows 10, return the special value.
  4210   4324           #
  4211         -        return 394802
         4325  +        return 394802; # BUGBUG: Anniversary Update only?
  4212   4326         }
  4213   4327   
  4214   4328         #
  4215   4329         # NOTE: We are not running on Windows 10, return the normal value.
  4216   4330         #
  4217   4331         return 394806
  4218   4332       }
  4219   4333   
  4220   4334       proc getFrameworkSetup47Value {} {
  4221   4335         #
  4222   4336         # NOTE: Check if we are running on Windows 10 or later.
  4223   4337         #
  4224         -      if {[isWindows] && $::tcl_platform(osVersion) >= 10.0} then {
         4338  +      # BUGBUG: Is greater-than-or-equal-to matching correct here?
         4339  +      #
         4340  +      if {[isWindows] && [info exists ::tcl_platform(osVersion)] && \
         4341  +          $::tcl_platform(osVersion) >= 10.0 && \
         4342  +          [haveTclPlatformOsExtraUpdateName "Creators Update"]} then {
  4225   4343           #
  4226   4344           # NOTE: We are running on Windows 10, return the special value.
  4227   4345           #
  4228         -        return 460798
         4346  +        return 460798; # BUGBUG: Creators Update only?
  4229   4347         }
  4230   4348   
  4231   4349         #
  4232   4350         # NOTE: We are not running on Windows 10, return the normal value.
  4233   4351         #
  4234   4352         return 460805
  4235   4353       }
         4354  +
         4355  +    proc getFrameworkSetup471Value {} {
         4356  +      #
         4357  +      # NOTE: Check if we are running on Windows 10 or later.
         4358  +      #
         4359  +      # BUGBUG: Is greater-than-or-equal-to matching correct here?
         4360  +      #
         4361  +      if {[isWindows] && [info exists ::tcl_platform(osVersion)] && \
         4362  +          $::tcl_platform(osVersion) >= 10.0 && \
         4363  +          [haveTclPlatformOsExtraUpdateName "Fall Creators Update"]} then {
         4364  +        #
         4365  +        # NOTE: We are running on Windows 10, return the special value.
         4366  +        #
         4367  +        return 461308; # BUGBUG: Fall Creators Update only?
         4368  +      }
         4369  +
         4370  +      #
         4371  +      # NOTE: We are not running on Windows 10, return the normal value.
         4372  +      #
         4373  +      return 461310
         4374  +    }
  4236   4375   
  4237   4376       proc checkForNetFx4x { channel } {
  4238   4377         tputs $channel "---- checking for .NET Framework 4.x... "
  4239   4378   
  4240   4379         #
  4241   4380         # NOTE: Platform must be Windows for this constraint to even be
  4242   4381         #       checked (i.e. we require the registry).
................................................................................
  4275   4414             #       is installed.  However, if the "release" value is also
  4276   4415             #       greater than or equal to 379893, then the .NET Framework
  4277   4416             #       4.5.2 is installed, which is an in-place upgrade to 4.5.1
  4278   4417             #       (and 4.5).  If the "release" value is also greater than or
  4279   4418             #       equal to 393297 (393295 on Windows 10), then the .NET
  4280   4419             #       Framework 4.6 is installed, which is an in-place upgrade
  4281   4420             #       to 4.5.x.  Similar handling is necessary for the .NET
  4282         -          #       Framework 4.6.1, 4.6.2, and 4.7.  For more information,
         4421  +          #       Framework 4.6.1, 4.6.2, 4.7, and 4.7.1.  For information,
  4283   4422             #       see:
  4284   4423             #
  4285   4424             #       https://msdn.microsoft.com/en-us/library/hh925568.aspx
  4286   4425             #
  4287         -          if {$release >= [getFrameworkSetup47Value]} then {
         4426  +          if {$release >= [getFrameworkSetup471Value]} then {
         4427  +            addConstraint dotNet451OrHigher
         4428  +            addConstraint dotNet452OrHigher
         4429  +            addConstraint dotNet46OrHigher
         4430  +            addConstraint dotNet461OrHigher
         4431  +            addConstraint dotNet462OrHigher
         4432  +            addConstraint dotNet47OrHigher
         4433  +            addConstraint dotNet471
         4434  +            addConstraint dotNet471OrHigher
         4435  +
         4436  +            set version 4.7.1
         4437  +          } elseif {$release >= [getFrameworkSetup47Value]} then {
  4288   4438               addConstraint dotNet451OrHigher
  4289   4439               addConstraint dotNet452OrHigher
  4290   4440               addConstraint dotNet46OrHigher
  4291   4441               addConstraint dotNet461OrHigher
  4292   4442               addConstraint dotNet462OrHigher
  4293   4443               addConstraint dotNet47
  4294   4444               addConstraint dotNet47OrHigher
................................................................................
  4320   4470               set version 4.6
  4321   4471             } elseif {$release >= 379893} then {
  4322   4472               addConstraint dotNet451OrHigher
  4323   4473               addConstraint dotNet452
  4324   4474               addConstraint dotNet452OrHigher
  4325   4475   
  4326   4476               set version 4.5.2
  4327         -          } elseif {$release >= 378675} then {
         4477  +          } elseif {$release >= [getFrameworkSetup451Value]} then {
  4328   4478               addConstraint dotNet451
  4329   4479               addConstraint dotNet451OrHigher
  4330   4480   
  4331   4481               set version 4.5.1
  4332   4482             } else {
  4333   4483               addConstraint dotNet45
  4334   4484   
................................................................................
  4568   4718       # NOTE: We need several of our test constraint related commands in the
  4569   4719       #       global namespace.
  4570   4720       #
  4571   4721       exportAndImportPackageCommands [namespace current] [list \
  4572   4722           getKnownBuildTypes getKnownCompileOptions getKnownMonoVersions \
  4573   4723           addKnownMonoConstraints lpermute alwaysFullInterpReady canExecComSpec \
  4574   4724           canExecWhoAmI canExecTclShell canExecFossil canExecVsWhere isTestMono \
  4575         -        isTestAdministrator canPing cleanPackageName checkForTestSuiteFiles \
  4576         -        checkForPlatform checkForWindowsVersion checkForScriptLibrary \
  4577         -        checkForVariable checkForTclOptions checkForWindowsCommandProcessor \
  4578         -        checkForPackage checkForFossil checkForVisualStudioViaVsWhere \
  4579         -        checkForEagle checkForSymbols checkForLogFile checkForGaruda \
  4580         -        checkForShell checkForOfficialStableReleaseInProgress checkForDebug \
  4581         -        checkForTk checkForVersion checkForCommand checkForSubCommand \
  4582         -        checkForNamespaces checkForTestExec checkForTestMachine \
  4583         -        checkForTestPlatform checkForTestConfiguration checkForTestSuffix \
  4584         -        checkForFile checkForPathFile checkForNativeCode checkForTip127 \
  4585         -        checkForTip194 checkForTip207 checkForTip241 checkForTip285 \
  4586         -        checkForTip405 checkForTip426 checkForTip429 checkForTip440 \
         4725  +        isTestAdministrator canPing cleanConstraintName cleanPackageName \
         4726  +        haveTclPlatformOsExtraUpdateName checkForTestSuiteFiles \
         4727  +        checkForPlatform checkForWindowsVersion checkForOperatingSystemUpdate \
         4728  +        checkForScriptLibrary checkForVariable checkForTclOptions \
         4729  +        checkForWindowsCommandProcessor checkForPackage checkForFossil \
         4730  +        checkForVisualStudioViaVsWhere checkForEagle checkForSymbols \
         4731  +        checkForLogFile checkForGaruda checkForShell \
         4732  +        checkForOfficialStableReleaseInProgress checkForDebug checkForTk \
         4733  +        checkForVersion checkForCommand checkForSubCommand checkForNamespaces \
         4734  +        checkForTestExec checkForTestMachine checkForTestPlatform \
         4735  +        checkForTestConfiguration checkForTestSuffix checkForFile \
         4736  +        checkForPathFile checkForNativeCode checkForTip127 checkForTip194 \
         4737  +        checkForTip207 checkForTip241 checkForTip285 checkForTip405 \
         4738  +        checkForTip421 checkForTip426 checkForTip429 checkForTip440 \
  4587   4739           checkForTip461 checkForTip463 checkForTip471 checkForTiming \
  4588   4740           checkForPerformance checkForBigLists checkForProcessorIntensive \
  4589   4741           checkForTimeIntensive checkForFullTest checkForMemoryIntensive \
  4590   4742           checkForStackIntensive checkForStackSize checkForInteractive \
  4591   4743           checkForInteractiveCommand checkForUserInteraction checkForNetwork \
  4592   4744           checkForCompileOption checkForKnownCompileOptions] false false
  4593   4745   

Changes to Externals/Eagle/lib/Test1.0/prologue.eagle.

  1697   1697           #
  1698   1698           if {![info exists no(compileLimitedEdition)]} then {
  1699   1699             #
  1700   1700             # NOTE: This is not currently used by any tests.
  1701   1701             #
  1702   1702             checkForCompileOption $test_channel LIMITED_EDITION
  1703   1703           }
         1704  +
         1705  +        #
         1706  +        # NOTE: Has runtime "demo edition" checking support been
         1707  +        #       disabled (at compile-time)?  This only applies to
         1708  +        #       third-party plugins and applications.
         1709  +        #
         1710  +        if {![info exists no(compileDemoEdition)]} then {
         1711  +          #
         1712  +          # NOTE: This is not currently used by any tests.
         1713  +          #
         1714  +          checkForCompileOption $test_channel DEMO_EDITION
         1715  +        }
  1704   1716         }
  1705   1717       }
  1706   1718   
  1707   1719       #
  1708   1720       # NOTE: Has dynamic loading testing support been disabled?
  1709   1721       #
  1710   1722       if {![info exists no(dynamic)]} then {
................................................................................
  1971   1983           checkForObjectMember $test_channel Eagle._Tests.Default \
  1972   1984               *TestRemotingHaveChannel*
  1973   1985   
  1974   1986           checkForObjectMember $test_channel Eagle._Tests.Default \
  1975   1987               *TestRemotingTryGetChannel*
  1976   1988         }
  1977   1989   
         1990  +      #
         1991  +      # NOTE: Has embedded resource testing support been disabled?
         1992  +      #
         1993  +      if {![info exists no(testResources)]} then {
         1994  +        #
         1995  +        # NOTE: For test "interp-1.400".
         1996  +        #
         1997  +        checkForObjectMember $test_channel Eagle._Tests.Default \
         1998  +            *TestGetResourceString*
         1999  +      }
         2000  +
  1978   2001         #
  1979   2002         # NOTE: Has asynchronous testing support been disabled?
  1980   2003         #
  1981   2004         if {![info exists no(testAsynchronous)]} then {
  1982   2005           #
  1983   2006           # NOTE: For tests "basic-1.20" and "basic-1.21".
  1984   2007           #
................................................................................
  2060   2083         if {![info exists no(testSetComplain)]} then {
  2061   2084           #
  2062   2085           # NOTE: This is not currently used by any tests.
  2063   2086           #
  2064   2087           checkForObjectMember $test_channel Eagle._Tests.Default \
  2065   2088               *TestSetComplain*
  2066   2089         }
         2090  +
         2091  +      #
         2092  +      # NOTE: Has enumerable variable testing support been disabled?
         2093  +      #
         2094  +      if {![info exists no(testEnumerableVariables)]} then {
         2095  +        #
         2096  +        # NOTE: For test "basic-1.105".
         2097  +        #
         2098  +        checkForObjectMember $test_channel Eagle._Tests.Default \
         2099  +            *TestSetupIntArray*
         2100  +
         2101  +        checkForObjectMember $test_channel Eagle._Tests.Default \
         2102  +            *TestSetVariableEnumerable*
         2103  +
         2104  +        checkForObjectMember $test_channel Eagle._Tests.Default \
         2105  +            *TestUnsetVariableEnumerable*
         2106  +      }
  2067   2107   
  2068   2108         #
  2069   2109         # NOTE: Has linked variable testing support been disabled?
  2070   2110         #
  2071   2111         if {![info exists no(testLinkedVariables)]} then {
  2072   2112           #
  2073   2113           # NOTE: For tests "basic-1.39", "basic-1.40", "basic-1.41",
................................................................................
  2242   2282   
  2243   2283           #
  2244   2284           # NOTE: For tests "object-3.14" and "object-3.15".
  2245   2285           #
  2246   2286           checkForObjectMember $test_channel Eagle._Tests.Default \
  2247   2287               *TestReturnOfSelf*
  2248   2288   
         2289  +        #
         2290  +        # NOTE: For test "object-3.17".
         2291  +        #
         2292  +        checkForObjectMember $test_channel Eagle._Tests.Default \
         2293  +            *TestByRefByteArray*
         2294  +
  2249   2295           #
  2250   2296           # NOTE: For test "object-4.1".
  2251   2297           #
  2252   2298           checkForObjectMember $test_channel Eagle._Tests.Default \
  2253   2299               *TestExpr*
  2254   2300   
  2255   2301           #
................................................................................
  3065   3111     if {![info exists no(platform)]} then {
  3066   3112       checkForPlatform $test_channel
  3067   3113     }
  3068   3114   
  3069   3115     if {![info exists no(windowsVersion)]} then {
  3070   3116       checkForWindowsVersion $test_channel
  3071   3117     }
         3118  +
         3119  +  if {![info exists no(operatingSystemUpdates)]} then {
         3120  +    if {[isEagle] && [info exists tcl_platform(osExtra)]} then {
         3121  +      vwaitWithTimeout tcl_platform(osExtra) $test_timeout
         3122  +    }
         3123  +
         3124  +    checkForOperatingSystemUpdate $test_channel KB936929
         3125  +    checkForOperatingSystemUpdate $test_channel KB976932
         3126  +    checkForOperatingSystemUpdate $test_channel "November Update"
         3127  +    checkForOperatingSystemUpdate $test_channel "Anniversary Update"
         3128  +    checkForOperatingSystemUpdate $test_channel "Creators Update"
         3129  +    checkForOperatingSystemUpdate $test_channel "Fall Creators Update"
         3130  +  }
  3072   3131   
  3073   3132     if {![info exists no(scriptLibrary)]} then {
  3074   3133       checkForScriptLibrary $test_channel
  3075   3134     }
  3076   3135   
  3077   3136     if {![info exists no(tclOptions)]} then {
  3078   3137       checkForTclOptions $test_channel
................................................................................
  3309   3368     if {![info exists no(tip285)]} then {
  3310   3369       checkForTip285 $test_channel
  3311   3370     }
  3312   3371   
  3313   3372     if {![info exists no(tip405)]} then {
  3314   3373       checkForTip405 $test_channel
  3315   3374     }
         3375  +
         3376  +  if {![info exists no(tip421)]} then {
         3377  +    checkForTip421 $test_channel
         3378  +  }
  3316   3379   
  3317   3380     if {![info exists no(tip426)]} then {
  3318   3381       checkForTip426 $test_channel
  3319   3382     }
  3320   3383   
  3321   3384     if {![info exists no(tip429)]} then {
  3322   3385       checkForTip429 $test_channel