[test] Disable reduce result on the main process
Since we're not winning anything by changing the result between processors on the main process, reduce is noop there and result is immutable. Bug: v8:6917 Change-Id: Ieb282e7abd4ab31162aee6b52493a6e1b6a25109 Cq-Include-Trybots: luci.v8.try:v8_linux64_fyi_rel_ng Reviewed-on: https://chromium-review.googlesource.com/878239 Commit-Queue: Michał Majewski <majeski@google.com> Reviewed-by: Michael Achenbach <machenbach@chromium.org> Cr-Commit-Position: refs/heads/master@{#50784}
This commit is contained in:
parent
a262b54474
commit
0998eda9a4
@ -27,9 +27,11 @@
|
||||
|
||||
|
||||
import signal
|
||||
import copy
|
||||
|
||||
from ..local import utils
|
||||
|
||||
|
||||
class Output(object):
|
||||
|
||||
def __init__(self, exit_code, timed_out, stdout, stderr, pid, duration):
|
||||
@ -40,6 +42,13 @@ class Output(object):
|
||||
self.pid = pid
|
||||
self.duration = duration
|
||||
|
||||
def without_text(self):
|
||||
"""Returns copy of the output without stdout and stderr."""
|
||||
other = copy.copy(self)
|
||||
other.stdout = None
|
||||
other.stderr = None
|
||||
return other
|
||||
|
||||
def HasCrashed(self):
|
||||
if utils.IsWindows():
|
||||
return 0x80000000 & self.exit_code and not (0x3FFFFF00 & self.exit_code)
|
||||
|
@ -31,9 +31,6 @@ class OutProc(outproc_base.BaseOutProc):
|
||||
super(OutProc, self).__init__()
|
||||
self._outproc = _outproc
|
||||
|
||||
def process(self, output):
|
||||
return Result(self.has_unexpected_output(output), output)
|
||||
|
||||
def has_unexpected_output(self, output):
|
||||
return output.exit_code != 0
|
||||
|
||||
|
@ -2,9 +2,10 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import collections
|
||||
import itertools
|
||||
|
||||
from ..testproc.base import (
|
||||
DROP_RESULT, DROP_OUTPUT, DROP_PASS_OUTPUT, DROP_PASS_STDOUT)
|
||||
from ..local import statusfile
|
||||
from ..testproc.result import Result
|
||||
|
||||
@ -14,12 +15,30 @@ OUTCOMES_FAIL = [statusfile.FAIL]
|
||||
|
||||
|
||||
class BaseOutProc(object):
|
||||
def process(self, output):
|
||||
return Result(self.has_unexpected_output(output), output)
|
||||
def process(self, output, reduction=None):
|
||||
has_unexpected_output = self.has_unexpected_output(output)
|
||||
return self._create_result(has_unexpected_output, output, reduction)
|
||||
|
||||
def has_unexpected_output(self, output):
|
||||
return self.get_outcome(output) not in self.expected_outcomes
|
||||
|
||||
def _create_result(self, has_unexpected_output, output, reduction):
|
||||
"""Creates Result instance. When reduction is passed it tries to drop some
|
||||
parts of the result to save memory and time needed to send the result
|
||||
across process boundary. None disables reduction and full result is created.
|
||||
"""
|
||||
if reduction == DROP_RESULT:
|
||||
return None
|
||||
if reduction == DROP_OUTPUT:
|
||||
return Result(has_unexpected_output, None)
|
||||
if not has_unexpected_output:
|
||||
if reduction == DROP_PASS_OUTPUT:
|
||||
return Result(has_unexpected_output, None)
|
||||
if reduction == DROP_PASS_STDOUT:
|
||||
return Result(has_unexpected_output, output.without_text())
|
||||
|
||||
return Result(has_unexpected_output, output)
|
||||
|
||||
def get_outcome(self, output):
|
||||
if output.HasCrashed():
|
||||
return statusfile.CRASH
|
||||
|
@ -37,31 +37,6 @@ DROP_OUTPUT = 1
|
||||
DROP_PASS_OUTPUT = 2
|
||||
DROP_PASS_STDOUT = 3
|
||||
|
||||
def get_reduce_result_function(requirement):
|
||||
if requirement == DROP_RESULT:
|
||||
return lambda _: None
|
||||
|
||||
if requirement == DROP_OUTPUT:
|
||||
def f(result):
|
||||
result.output = None
|
||||
return result
|
||||
return f
|
||||
|
||||
if requirement == DROP_PASS_OUTPUT:
|
||||
def f(result):
|
||||
if not result.has_unexpected_output:
|
||||
result.output = None
|
||||
return result
|
||||
return f
|
||||
|
||||
if requirement == DROP_PASS_STDOUT:
|
||||
def f(result):
|
||||
if not result.has_unexpected_output:
|
||||
result.output.stdout = None
|
||||
result.output.stderr = None
|
||||
return result
|
||||
return f
|
||||
|
||||
|
||||
class TestProc(object):
|
||||
def __init__(self):
|
||||
@ -90,8 +65,14 @@ class TestProc(object):
|
||||
self._prev_requirement = requirement
|
||||
if self._next_proc:
|
||||
self._next_proc.setup(max(requirement, self._requirement))
|
||||
if self._prev_requirement < self._requirement:
|
||||
self._reduce_result = get_reduce_result_function(self._prev_requirement)
|
||||
|
||||
# Since we're not winning anything by droping part of the result we are
|
||||
# dropping the whole result or pass it as it is. The real reduction happens
|
||||
# during result creation (in the output processor), so the result is
|
||||
# immutable.
|
||||
if (self._prev_requirement < self._requirement and
|
||||
self._prev_requirement == DROP_RESULT):
|
||||
self._reduce_result = lambda _: None
|
||||
|
||||
def next_test(self, test):
|
||||
"""
|
||||
|
@ -15,12 +15,12 @@ def run_job(job, process_context):
|
||||
return job.run(process_context)
|
||||
|
||||
|
||||
def create_process_context(requirement):
|
||||
return ProcessContext(base.get_reduce_result_function(requirement))
|
||||
def create_process_context(result_reduction):
|
||||
return ProcessContext(result_reduction)
|
||||
|
||||
|
||||
JobResult = collections.namedtuple('JobResult', ['id', 'result'])
|
||||
ProcessContext = collections.namedtuple('ProcessContext', ['reduce_result_f'])
|
||||
ProcessContext = collections.namedtuple('ProcessContext', ['result_reduction'])
|
||||
|
||||
|
||||
class Job(object):
|
||||
@ -32,9 +32,8 @@ class Job(object):
|
||||
|
||||
def run(self, process_ctx):
|
||||
output = self.cmd.execute()
|
||||
result = self.outproc.process(output)
|
||||
if not self.keep_output:
|
||||
result = process_ctx.reduce_result_f(result)
|
||||
reduction = process_ctx.result_reduction if not self.keep_output else None
|
||||
result = self.outproc.process(output, reduction)
|
||||
return JobResult(self.test_id, result)
|
||||
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
@ -70,25 +69,25 @@ class SimpleProgressIndicator(ProgressIndicator):
|
||||
def _on_result_for(self, test, result):
|
||||
# TODO(majeski): Support for dummy/grouped results
|
||||
if result.has_unexpected_output:
|
||||
self._failed.append((test, result.cmd, copy.copy(result.output)))
|
||||
self._failed.append((test, result))
|
||||
|
||||
def finished(self):
|
||||
crashed = 0
|
||||
print
|
||||
for test, cmd, output in self._failed:
|
||||
for test, result in self._failed:
|
||||
print_failure_header(test)
|
||||
if output.stderr:
|
||||
if result.output.stderr:
|
||||
print "--- stderr ---"
|
||||
print output.stderr.strip()
|
||||
if output.stdout:
|
||||
print result.output.stderr.strip()
|
||||
if result.output.stdout:
|
||||
print "--- stdout ---"
|
||||
print output.stdout.strip()
|
||||
print "Command: %s" % cmd.to_string()
|
||||
if output.HasCrashed():
|
||||
print "exit code: %d" % output.exit_code
|
||||
print result.output.stdout.strip()
|
||||
print "Command: %s" % result.cmd.to_string()
|
||||
if result.output.HasCrashed():
|
||||
print "exit code: %d" % result.output.exit_code
|
||||
print "--- CRASHED ---"
|
||||
crashed += 1
|
||||
if output.HasTimedOut():
|
||||
if result.output.HasTimedOut():
|
||||
print "--- TIMEOUT ---"
|
||||
if len(self._failed) == 0:
|
||||
print "==="
|
||||
|
Loading…
Reference in New Issue
Block a user