Title: [277318] trunk/Tools
Revision
277318
Author
[email protected]
Date
2021-05-11 01:34:07 -0700 (Tue, 11 May 2021)

Log Message

[JSC] detect infrastructure failure for remote stress tests
https://bugs.webkit.org/show_bug.cgi?id=222601

Reviewed by Mark Lam.

run-jsc-stress-tests currently detects failures by the absence of
a failure file (that is generated by each failing test). This is
fragile to begin with, as it assumes that tests that fail to run
(e.g. because of an error in the runner script) are successful by
default.

However, the main motivation for this patch is to make execution
more robust when using remote hosts. Currently,
--gnu-parallel-runner will transparently reschedule jobs on a
different host when a remote host goes away. But detectFailures
expects to be able to connect to all hosts and fetch the failure
files, which fails if a remote host is still down when the run
finishes.

Instead, this patch changes the runners to always generate a status
file with the exit code. detectFailures then fetches all status
files from all hosts that are live on exit. Tests that failed to
run are explicitly accounted for as 'noreport' and are set to
ERROR in the final report.

* Scripts/run-_javascript_core-tests:
(runJSCStressTests):
* Scripts/run-jsc-stress-tests:
* Scripts/webkitruby/jsc-stress-test-writer-default.rb:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (277317 => 277318)


--- trunk/Tools/ChangeLog	2021-05-11 04:46:49 UTC (rev 277317)
+++ trunk/Tools/ChangeLog	2021-05-11 08:34:07 UTC (rev 277318)
@@ -1,3 +1,35 @@
+2021-05-11  Angelos Oikonomopoulos  <[email protected]>
+
+        [JSC] detect infrastructure failure for remote stress tests
+        https://bugs.webkit.org/show_bug.cgi?id=222601
+
+        Reviewed by Mark Lam.
+
+        run-jsc-stress-tests currently detects failures by the absence of
+        a failure file (that is generated by each failing test). This is
+        fragile to begin with, as it assumes that tests that fail to run
+        (e.g. because of an error in the runner script) are successful by
+        default.
+
+        However, the main motivation for this patch is to make execution
+        more robust when using remote hosts. Currently,
+        --gnu-parallel-runner will transparently reschedule jobs on a
+        different host when a remote host goes away. But detectFailures
+        expects to be able to connect to all hosts and fetch the failure
+        files, which fails if a remote host is still down when the run
+        finishes.
+
+        Instead, this patch changes the runners to always generate a status
+        file with the exit code. detectFailures then fetches all status
+        files from all hosts that are live on exit. Tests that failed to
+        run are explicitly accounted for as 'noreport' and are set to
+        ERROR in the final report.
+
+        * Scripts/run-_javascript_core-tests:
+        (runJSCStressTests):
+        * Scripts/run-jsc-stress-tests:
+        * Scripts/webkitruby/jsc-stress-test-writer-default.rb:
+
 2021-05-10  Chris Dumez  <[email protected]>
 
         Use non-throwing std::filesystem API in TestRunner

Modified: trunk/Tools/Scripts/run-_javascript_core-tests (277317 => 277318)


--- trunk/Tools/Scripts/run-_javascript_core-tests	2021-05-11 04:46:49 UTC (rev 277317)
+++ trunk/Tools/Scripts/run-_javascript_core-tests	2021-05-11 08:34:07 UTC (rev 277318)
@@ -932,9 +932,20 @@
     }
     print "\n";
 
+    my @jscStressNoResultList = readAllLines($jscStressResultsDir . "/noresult");
+    my $numJSCStressNoResultTests = @jscStressNoResultList;
+
+    if ($numJSCStressNoResultTests) {
+        $isTestFailed = 1;
+    }
+    foreach my $testNoResult (@jscStressNoResultList) {
+            $reportData{$testNoResult} = {actual => "ERROR"};
+    }
+
     print "Results for JSC stress tests:\n";
     printThingsFound($numJSCStressFailures, "failure", "failures", "found");
-    print "    OK.\n" if $numJSCStressFailures == 0;
+    printThingsFound($numJSCStressNoResultTests, "test", "tests", "failed to complete");
+    print "    OK.\n" if $numJSCStressFailures == 0 and $numJSCStressNoResultTests == 0;
 
     print "\n";
 

Modified: trunk/Tools/Scripts/run-jsc-stress-tests (277317 => 277318)


--- trunk/Tools/Scripts/run-jsc-stress-tests	2021-05-11 04:46:49 UTC (rev 277317)
+++ trunk/Tools/Scripts/run-jsc-stress-tests	2021-05-11 08:34:07 UTC (rev 277318)
@@ -57,6 +57,9 @@
 raise unless SCRIPTS_PATH.dirname.basename.to_s == "Tools"
 
 HELPERS_PATH = SCRIPTS_PATH + "jsc-stress-test-helpers"
+STATUS_FILE_PREFIX = "test_status_"
+STATUS_FILE_PASS = "P"
+STATUS_FILE_FAIL = "F"
 
 begin
     require 'shellwords'
@@ -135,6 +138,7 @@
 $ldd = nil
 $artifact_exec_wrapper = nil
 $numChildProcessesSetByUser = false
+$runUniqueId = Random.new.bytes(16).unpack("H*")[0]
 
 def usage
     puts "run-jsc-stress-tests -j <shell path> <collections path> [<collections path> ...]"
@@ -537,9 +541,6 @@
     end
 end
 
-$numFailures = 0
-$numPasses = 0
-
 # We force all tests to use a smaller (1.5M) stack so that stack overflow tests can run faster.
 BASE_OPTIONS = ["--useFTLJIT=false", "--useFunctionDotArguments=true", "--validateExceptionChecks=true", "--useDollarVM=true", "--maxPerThreadStackUsage=1572864"]
 EAGER_OPTIONS = ["--thresholdForJITAfterWarmUp=10", "--thresholdForJITSoon=10", "--thresholdForOptimizeAfterWarmUp=20", "--thresholdForOptimizeAfterLongWarmUp=20", "--thresholdForOptimizeSoon=20", "--thresholdForFTLOptimizeAfterWarmUp=20", "--thresholdForFTLOptimizeSoon=20", "--thresholdForOMGOptimizeAfterWarmUp=20", "--thresholdForOMGOptimizeSoon=20", "--maximumEvalCacheableSourceLength=150000", "--useEagerCodeBlockJettisonTiming=true", "--repatchBufferingCountdown=0"]
@@ -1823,7 +1824,6 @@
         | outp |
         outp.puts plan.name
     }
-    $numFailures += 1
 end
 
 def appendPass(plan)
@@ -1831,9 +1831,15 @@
         | outp |
         outp.puts plan.name
     }
-    $numPasses += 1
 end
 
+def appendNoResult(plan)
+    File.open($outputDir + "noresult", "a") {
+        | outp |
+        outp.puts plan.name
+    }
+end
+
 def appendResult(plan, didPass)
     File.open($outputDir + "results", "a") {
         | outp |
@@ -2039,7 +2045,7 @@
     }
 end
 
-def sshRead(cmd, remoteIndex=0)
+def sshRead(cmd, remoteIndex=0, options={})
     raise unless $remote
 
     remoteHost = $remoteHosts[remoteIndex]
@@ -2052,7 +2058,7 @@
         result += line
       }
     }
-    raise "#{$?}" unless $?.success?
+    raise "#{$?}" unless $?.success? or options[:ignoreFailure]
     result
 end
 
@@ -2207,52 +2213,110 @@
     end
 end
 
-def detectFailures
-    raise if $bundle
-    failures = []
+def getStatusMap
+    name_re = /^[.]\/#{STATUS_FILE_PREFIX}(\d+)$/
+    map = {}
     if $remote
         $remoteHosts.each_with_index {
             | host, remoteIndex |
-            output = sshRead("cd #{host.remoteDirectory}/#{$outputDir.basename}/.runner && find . -maxdepth 1 -name \"test_fail_*\"", remoteIndex)
+            output = sshRead("cd #{host.remoteDirectory}/#{$outputDir.basename}/.runner && find . -maxdepth 1 -name \"#{STATUS_FILE_PREFIX}*\" -exec sh -c \"printf \\\"%s \\\" {}; cat {}\" \\;", remoteIndex, :ignoreFailure => true)
             output.split(/\n/).each {
                 | line |
-                next unless line =~ /test_fail_/
-                failures << $~.post_match.to_i
+                name, run_id, _, result = line.split(' ')
+                md = name_re.match(name)
+                if md.nil?
+                    $stderr.puts("Could not parse name in `#{line}`")
+                    exit(1)
+                end
+                if run_id != $runUniqueId
+                    # This may conceivably happen if a remote goes
+                    # away in the middle of a run and comes back
+                    # online in the middle of a different run.
+                    $stderr.puts("Ignoring stale status file for #{name} (ID #{run_id} but current ID is #{$runUniqueId})")
+                    next
+                end
+                index = md[1].to_i
+                if map.has_key?(index)
+                    $stderr.puts("Duplicate state file for #{index}")
+                    # One scenario in which this could happen:
+                    # Test T runs on remote host A and
+                    #   1. the status file reaches A's disk
+                    #   2. somehow the gnu parallel runner is not made aware of the test's completion (packet loss?)
+                    #   3. A machine crashes
+                    #   4. gnu parallel re-schedules the test to run on remote host B, where it runs to completion
+                    #   5. B comes back online before the end of the run
+                    #   6. we collect the status files from all remotes and end up with two status files for T.
+                    prev = map[index]
+                    # map[index] holds
+                    # - a number, if all results codes we've observed for a test are the same
+                    # - an array, if they diverge.
+                    if prev.is_a?(Array)
+                        prev.push(result)
+                    elsif prev != result
+                        # If the two results differ, keep them
+                        # both. This is simply a way to make note of
+                        # the divergence (for later reporting).
+                        map[index] = [prev, result]
+                    else
+                        # Got the same result, no need to do anything.
+                    end
+                else
+                    map[index] = result
+                end
             }
         }
     else
         Dir.foreach($runnerDir) {
             | filename |
-            next unless filename =~ /test_fail_/
-            failures << $~.post_match.to_i
+            md = name_re.match("./#{filename}")
+            next unless md
+            File.open("#{$runnerDir}/#{filename}", "r") { |f|
+                runId, _, result = f.read.chomp.split(' ')
+                if runId != $runUniqueId
+                    # We clean the dir before a starting a run.
+                    raise "Can't happen"
+                end
+                map[md[1].to_i] = result
+            }
         }
     end
+    map
+end
 
-    failureSet = {}
+def detectFailures
+    raise if $bundle
+    noresult = 0
+    statusMap = getStatusMap
+    familyMap = {}
 
-    failures.each {
-        | failure | 
-        appendFailure($runlist[failure])
-        failureSet[failure] = true
-    }
-
-    familyMap = {}
     $runlist.each_with_index {
         | plan, index |
         unless familyMap[plan.family]
             familyMap[plan.family] = []
         end
-        if failureSet[index]
-            appendResult(plan, false)
-            familyMap[plan.family] << {:result => "FAIL", :plan => plan};
+        if not statusMap.has_key?(index) or statusMap[index].is_a?(Array)
+            appendNoResult(plan)
+            noresult += 1
             next
+        end
+        result = nil
+        if statusMap[index] == STATUS_FILE_PASS
+            appendPass(plan)
+            result = "PASS"
         else
-            appendResult(plan, true)
-            familyMap[plan.family] << {:result => "PASS", :plan => plan};
+            appendFailure(plan)
+            result = "FAIL"
         end
-        appendPass(plan)
+        appendResult(plan, statusMap[index] == STATUS_FILE_PASS)
+        familyMap[plan.family] << {:result => result, :plan => plan }
     }
 
+    if noresult > 0
+        $stderr.puts("Could not get the exit status for #{noresult} tests")
+        # We can't change our exit code, as run-_javascript_core-tests
+        # expects 0 even when there are failures.
+    end
+
     File.open($outputDir + "resultsByFamily", "w") {
         | outp |
         first = true
@@ -2263,7 +2327,7 @@
             else
                 outp.puts
             end
-            
+
             outp.print "#{familyName}:"
 
             numPassed = 0
@@ -2301,6 +2365,7 @@
 
 clean($outputDir + "failed")
 clean($outputDir + "passed")
+clean($outputDir + "noresult")
 clean($outputDir + "results")
 clean($outputDir + "resultsByFamily")
 clean($outputDir + ".vm")

Modified: trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-default.rb (277317 => 277318)


--- trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-default.rb	2021-05-11 04:46:49 UTC (rev 277317)
+++ trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-default.rb	2021-05-11 08:34:07 UTC (rev 277318)
@@ -37,7 +37,7 @@
 def silentOutputHandler
     Proc.new {
         | name |
-        " | " + pipeAndPrefixCommand((Pathname("..") + (name + ".out")).to_s, name)
+        pipeAndPrefixCommand((Pathname("..") + (name + ".out")).to_s, name)
     }
 end
 
@@ -45,18 +45,24 @@
 def noisyOutputHandler
     Proc.new {
         | name |
-        " | cat > " + Shellwords.shellescape((Pathname("..") + (name + ".out")).to_s)
+        "cat > " + Shellwords.shellescape((Pathname("..") + (name + ".out")).to_s)
     }
 end
 
+def getAndTestExitCode(plan, condition)
+    <<-EOF
+    if test "$exitCode" #{condition}
+EOF
+end
+
 # Error handler for tests that fail exactly when they return non-zero exit status.
 # This is useful when a test is expected to fail.
 def simpleErrorHandler
     Proc.new {
         | outp, plan |
-        outp.puts "if test -e #{plan.failFile}"
+        outp.puts getAndTestExitCode(plan, "-ne 0")
         outp.puts "then"
-        outp.puts "    (echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | " + redirectAndPrefixCommand(plan.name)
+        outp.puts "    (echo ERROR: Unexpected exit code: $exitCode) | " + redirectAndPrefixCommand(plan.name)
         outp.puts "    " + plan.failCommand
         outp.puts "else"
         outp.puts "    " + plan.successCommand
@@ -68,7 +74,7 @@
 def expectedFailErrorHandler
     Proc.new {
         | outp, plan |
-        outp.puts "if test -e #{plan.failFile}"
+        outp.puts getAndTestExitCode(plan, "-ne 0")
         outp.puts "then"
         outp.puts "    " + plan.successCommand
         outp.puts "else"
@@ -84,10 +90,10 @@
     Proc.new {
         | outp, plan |
         outputFilename = Shellwords.shellescape((Pathname("..") + (plan.name + ".out")).to_s)
-    
-        outp.puts "if test -e #{plan.failFile}"
+
+        outp.puts getAndTestExitCode(plan, "-ne 0")
         outp.puts "then"
-        outp.puts "    (cat #{outputFilename} && echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | " + redirectAndPrefixCommand(plan.name)
+        outp.puts "    (cat #{outputFilename} && echo ERROR: Unexpected exit code: $exitCode) | " + redirectAndPrefixCommand(plan.name)
         outp.puts "    " + plan.failCommand
         outp.puts "else"
         outp.puts "    " + plan.successCommand
@@ -101,10 +107,10 @@
         | outp, plan |
         outputFilename = Shellwords.shellescape((Pathname("..") + (plan.name + ".out")).to_s)
         diffFilename = Shellwords.shellescape((Pathname("..") + (plan.name + ".diff")).to_s)
-        
-        outp.puts "if test -e #{plan.failFile}"
+
+        outp.puts getAndTestExitCode(plan, "-ne 0")
         outp.puts "then"
-        outp.puts "    (cat #{outputFilename} && echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | " + redirectAndPrefixCommand(plan.name)
+        outp.puts "    (cat #{outputFilename} && echo ERROR: Unexpected exit code: $exitCode) | " + redirectAndPrefixCommand(plan.name)
         outp.puts "    " + plan.failCommand
         outp.puts "elif test -e ../#{Shellwords.shellescape(expectedFilename)}"
         outp.puts "then"
@@ -130,9 +136,9 @@
         | outp, plan |
         outputFilename = Shellwords.shellescape((Pathname("..") + (plan.name + ".out")).to_s)
 
-        outp.puts "if test -e #{plan.failFile}"
+        outp.puts getAndTestExitCode(plan, "-ne 0")
         outp.puts "then"
-        outp.puts "    (cat #{outputFilename} && echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | " + redirectAndPrefixCommand(plan.name)
+        outp.puts "    (cat #{outputFilename} && echo ERROR: Unexpected exit code: $exitCode) | " + redirectAndPrefixCommand(plan.name)
         outp.puts "    " + plan.failCommand
         outp.puts "elif grep -i -q failed! #{outputFilename}"
         outp.puts "then"
@@ -151,7 +157,7 @@
         | outp, plan |
         outputFilename = Shellwords.shellescape((Pathname("..") + (plan.name + ".out")).to_s)
 
-        outp.puts "if test -e #{plan.failFile}"
+        outp.puts getAndTestExitCode(plan, "-ne 0")
         outp.puts "then"
         outp.puts "    " + plan.successCommand
         outp.puts "elif grep -i -q failed! #{outputFilename}"
@@ -171,9 +177,9 @@
         | outp, plan |
         outputFilename = Shellwords.shellescape((Pathname("..") + (plan.name + ".out")).to_s)
 
-        outp.puts "if test -e #{plan.failFile}"
+        outp.puts getAndTestExitCode(plan, "-ne 0")
         outp.puts "then"
-        outp.puts "    if [ `cat #{plan.failFile}` -eq 3 ]"
+        outp.puts "    if [ \"$exitCode\" -eq 3 ]"
         outp.puts "    then"
         outp.puts "        if grep -i -q failed! #{outputFilename}"
         outp.puts "        then"
@@ -183,7 +189,7 @@
         outp.puts "            " + plan.successCommand
         outp.puts "        fi"
         outp.puts "    else"
-        outp.puts "        (cat #{outputFilename} && echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | " + redirectAndPrefixCommand(plan.name)
+        outp.puts "        (cat #{outputFilename} && echo ERROR: Unexpected exit code: $exitCode) | " + redirectAndPrefixCommand(plan.name)
         outp.puts "        " + plan.failCommand
         outp.puts "    fi"
         outp.puts "else"
@@ -200,9 +206,9 @@
         | outp, plan |
         outputFilename = Shellwords.shellescape((Pathname("..") + (plan.name + ".out")).to_s)
 
-        outp.puts "if test -e #{plan.failFile}"
+        outp.puts getAndTestExitCode(plan, "-ne 0")
         outp.puts "then"
-        outp.puts "    (cat #{outputFilename} && echo ERROR: Unexpected exit code: `cat #{plan.failFile}`) | " + redirectAndPrefixCommand(plan.name)
+        outp.puts "    (cat #{outputFilename} && echo ERROR: Unexpected exit code: $exitCode) | " + redirectAndPrefixCommand(plan.name)
         outp.puts "    " + plan.failCommand
         outp.puts "elif grep -i -q FAILED #{outputFilename}"
         outp.puts "then"
@@ -262,25 +268,29 @@
         script += "#{shellCommand} || exit 1"
         "echo #{Shellwords.shellescape(script)} > #{Shellwords.shellescape((Pathname.new("..") + @name).to_s)}"
     end
-    
+
+    def statusCommand(status)
+        "echo #{$runUniqueId} $exitCode #{status} > #{statusFile}"
+    end
+
     def failCommand
-        "echo FAIL: #{Shellwords.shellescape(@name)} ; touch #{failFile} ; " + reproScriptCommand
+        "#{statusCommand(STATUS_FILE_FAIL)}; echo FAIL: #{Shellwords.shellescape(@name)}; " + reproScriptCommand
     end
     
     def successCommand
+        command = ""
         executionTimeMessage = ""
         if $reportExecutionTime
             executionTimeMessage = " $(($SECONDS - $START_TIME))s"
         end
         if $progressMeter or $reportExecutionTime or $verbosity >= 2
-            "rm -f #{failFile} ; echo PASS: #{Shellwords.shellescape(@name)}#{executionTimeMessage}"
-        else
-            "rm -f #{failFile}"
+            command = "echo PASS: #{Shellwords.shellescape(@name)}#{executionTimeMessage}"
         end
+        "#{statusCommand(STATUS_FILE_PASS)}; #{command}"
     end
     
-    def failFile
-        "test_fail_#{@index}"
+    def statusFile
+        "#{STATUS_FILE_PREFIX}#{@index}"
     end
     
     def writeRunScript(filename)
@@ -290,8 +300,42 @@
                 outp.puts "START_TIME=$SECONDS"
             end
             outp.puts "echo Running #{Shellwords.shellescape(@name)}"
-            cmd  = "(" + shellCommand + " || (echo $? > #{failFile})) 2>&1 "
-            cmd += @outputHandler.call(@name)
+            #
+            # +--------------------------------------------------------------------+
+            # | +-----------------------------------------------+                  |
+            # | | +--------------+     +-------------------+    |                  |
+            # | | | cmd 1 ----> 1|---> |0 --> outH 1 ---> 4|-> 4|---------------> 1|
+            # | | |     2 /      |     +-------------------+    |   +-----------+  |
+            # | | |echo $? 0 -> 3|---------------------------> 1|-> |0 read xs  |  |
+            # | | +--------------+                              |   |  exit $xs |  |
+            # | |                                               |   +-----------+  |
+            # | +-----------------------------------------------+                  |
+            # +--------------------------------------------------------------------+
+            # From the top down (i.e. reading from the outer _expression_ inwards):
+            #
+            # - Redirect FD 4 to our stdout
+            #
+            # - Build a pipe of two command sequences. The
+            #   right-hand-side sequence reads a number from stdin and
+            #   exits with it. Since it's the last command in the
+            #   pipeline, this will be the value of $? after the
+            #   pipeline completes.
+            #
+            # - In the left-hand-side sequence, redirect FD 3 to FD 1.
+            #
+            # - Build a pipe of two commands
+            #   - run shellCommand, writing its exit code to FD 3.
+            #   - run the outputHandler, with its stdin coming from
+            #     the pipe, redirecting its output to FD 4. The
+            #     outputHandler needs to be in a command sequence
+            #     (i.e. in { cmd; ...}) as it may do its own
+            #     redirections.
+            #
+            # We do all this
+            # - to avoid having to use a temporary file for the exit code
+            # - to keep within the bounds of POSIX sh (i.e. can't use
+            #   PIPESTATUS)
+            cmd = "{ { { { #{shellCommand} 2>&1; echo $? >&3; } | { #{outputHandler.call(@name)} ;} >&4; } 3>&1; } | { read xs; exit $xs; } } 4>&1\nexitCode=$?\n"
             if $verbosity >= 3
                 outp.puts "echo #{Shellwords.shellescape(cmd)}"
             end

Modified: trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-playstation.rb (277317 => 277318)


--- trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-playstation.rb	2021-05-11 04:46:49 UTC (rev 277317)
+++ trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-playstation.rb	2021-05-11 08:34:07 UTC (rev 277318)
@@ -305,10 +305,21 @@
         return ""
     end
 
+    def statusCommand(status_code)
+        # May be called in th rescue block, so status is not
+        # guaranteed to be set; if it isn't, set the exit code to
+        # something that's clearly invalid.
+        <<-END_STATUS_COMMAND
+          File.open("#{statusFile}", "w") { |f|
+              f.puts("#{$runUniqueId} \#{status.nil? ? 999999999 : status.exitstatus} #{status_code}")
+          }
+        END_STATUS_COMMAND
+    end
+
     def failCommand
         <<-END_FAIL_COMMAND
             print "FAIL: #{Shellwords.shellescape(@name)}\n"
-            FileUtils.touch("#{failFile}")
+            #{statusCommand(STATUS_FILE_FAIL)}
             #{reproScriptCommand}
         END_FAIL_COMMAND
     end
@@ -316,28 +327,18 @@
     def successCommand
         if $progressMeter or $verbosity >= 2
             <<-END_VERBOSE_SUCCESS_COMMAND
-                File.unlink("#{failFile}") if File.exists?("#{failFile}")
                 print "PASS: #{Shellwords.shellescape(@name)}\n"
+                #{statusCommand(STATUS_FILE_PASS)}
             END_VERBOSE_SUCCESS_COMMAND
         else
-            "File.unlink(\"#{failFile}\") if File.exists?(\"#{failFile}\")\n"
+            "#{statusCommand(STATUS_FILE_PASS)}\n"
         end
     end
 
-    def failFile
-        "test_fail_#{@index}"
+    def statusFile
+        "#{STATUS_FILE_PREFIX}#{@index}"
     end
 
-    def statusWrite
-        <<-END_STATUS_WRITE
-            if !success
-                File.open("#{failFile}", "w") do |code_file|
-                    code_file.puts status
-                end
-            end
-        END_STATUS_WRITE
-    end
-
     def writeRunScript(filename)
         jsonfilepart = filename.basename.to_s + ".json"
         jsondir = filename.dirname.parent + ".json"
@@ -357,7 +358,6 @@
                 outputName: @name.gsub(/(\\|\/)/, '_'),
                 checkScript: filename,
                 args: @arguments,
-                failFile: "#{failFile}"
             })
         }
 
@@ -371,8 +371,6 @@
 
             cmd = shellCommand
 
-            cmd += statusWrite
-
             cmd += @outputHandler.call(@name)
 
             if $verbosity >= 3
@@ -382,7 +380,7 @@
             @errorHandler.call(outp, self)
             outp.puts "rescue RuntimeError => e"
             outp.puts "    print \"FAIL: #{Shellwords.shellescape(@name)}\\n\""
-            outp.puts "    FileUtils.touch(\"#{failFile}\")"
+            outp.puts "    #{statusCommand(STATUS_FILE_FAIL)}"
             outp.puts "end"
         }
     end

Modified: trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-ruby.rb (277317 => 277318)


--- trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-ruby.rb	2021-05-11 04:46:49 UTC (rev 277317)
+++ trunk/Tools/Scripts/webkitruby/jsc-stress-test-writer-ruby.rb	2021-05-11 08:34:07 UTC (rev 277318)
@@ -335,10 +335,21 @@
         END_REPRO_SCRIPT_COMMAND
     end
 
+    def statusCommand(status_code)
+        # May be called in th rescue block, so status is not
+        # guaranteed to be set; if it isn't, set the exit code to
+        # something that's clearly invalid.
+        <<-END_STATUS_COMMAND
+          File.open("#{statusFile}", "w") { |f|
+              f.puts("#{$runUniqueId} \#{status.nil? ? 999999999 : status.exitstatus} #{status_code}")
+          }
+        END_STATUS_COMMAND
+    end
+
     def failCommand
         <<-END_FAIL_COMMAND
             print "FAIL: #{Shellwords.shellescape(@name)}\n"
-            FileUtils.touch("#{failFile}")
+            #{statusCommand(STATUS_FILE_FAIL)}
             #{reproScriptCommand}
         END_FAIL_COMMAND
     end
@@ -346,28 +357,18 @@
     def successCommand
         if $progressMeter or $verbosity >= 2
             <<-END_VERBOSE_SUCCESS_COMMAND
-                File.unlink("#{failFile}") if File.exists?("#{failFile}")
                 print "PASS: #{Shellwords.shellescape(@name)}\n"
+                #{statusCommand(STATUS_FILE_PASS)}
             END_VERBOSE_SUCCESS_COMMAND
         else
-            "File.unlink(\"#{failFile}\") if File.exists?(\"#{failFile}\")\n"
+            "#{statusCommand(STATUS_FILE_PASS)}\n"
         end
     end
     
-    def failFile
-        "test_fail_#{@index}"
+    def statusFile
+        "#{STATUS_FILE_PREFIX}#{@index}"
     end
 
-    def statusWrite
-        <<-END_STATUS_WRITE
-            if !success(status)
-                File.open("#{failFile}", "w") do |code_file|
-                    code_file.puts status.exitstatus
-                end
-            end
-        END_STATUS_WRITE
-    end
-    
     def writeRunScript(filename)
         File.open(filename, "w") {
             | outp |
@@ -382,8 +383,6 @@
 
             cmd = shellCommand
 
-            cmd += statusWrite
-
             cmd += @outputHandler.call(@name)
 
             if $verbosity >= 3
@@ -393,7 +392,7 @@
             @errorHandler.call(outp, self)
             outp.puts "rescue"
             outp.puts "    print \"FAIL: #{Shellwords.shellescape(@name)}\\n\""
-            outp.puts "    FileUtils.touch(\"#{failFile}\")"
+            outp.puts "    #{statusCommand(STATUS_FILE_FAIL)}"
             outp.puts "end"
         }
     end
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to