mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1034272 - Convert cppunittests to structured logging.;r=ted
This commit is contained in:
parent
3c53568904
commit
644813fdf7
@ -253,8 +253,12 @@ class MachCommands(MachCommandBase):
|
||||
'executed.')
|
||||
|
||||
def run_cppunit_test(self, **params):
|
||||
from mozlog.structured import commandline
|
||||
import runcppunittests as cppunittests
|
||||
import logging
|
||||
|
||||
log = commandline.setup_logging("cppunittest",
|
||||
{},
|
||||
{"tbpl": sys.stdout})
|
||||
|
||||
if len(params['test_files']) == 0:
|
||||
testdir = os.path.join(self.distdir, 'cppunittests')
|
||||
@ -269,11 +273,9 @@ class MachCommands(MachCommandBase):
|
||||
|
||||
tester = cppunittests.CPPUnitTests()
|
||||
try:
|
||||
result = tester.run_tests(progs, self.bindir, symbols_path)
|
||||
except Exception, e:
|
||||
self.log(logging.ERROR, 'cppunittests',
|
||||
{'exception': str(e)},
|
||||
'Caught exception running cpp unit tests: {exception}')
|
||||
result = tester.run_tests(progs, self.bindir, symbols_path, interactive=True)
|
||||
except Exception as e:
|
||||
log.error("Caught exception running cpp unit tests: %s" % str(e))
|
||||
result = False
|
||||
|
||||
return 0 if result else 1
|
||||
|
@ -9,11 +9,12 @@ import subprocess
|
||||
import tempfile
|
||||
from zipfile import ZipFile
|
||||
import runcppunittests as cppunittests
|
||||
import mozcrash, mozlog
|
||||
import mozcrash
|
||||
import mozfile
|
||||
import StringIO
|
||||
import posixpath
|
||||
from mozdevice import devicemanager, devicemanagerADB, devicemanagerSUT
|
||||
from mozlog import structured
|
||||
|
||||
try:
|
||||
from mozbuild.base import MozbuildObject
|
||||
@ -21,8 +22,6 @@ try:
|
||||
except ImportError:
|
||||
build_obj = None
|
||||
|
||||
log = mozlog.getLogger('remotecppunittests')
|
||||
|
||||
class RemoteCPPUnitTests(cppunittests.CPPUnitTests):
|
||||
def __init__(self, devmgr, options, progs):
|
||||
cppunittests.CPPUnitTests.__init__(self)
|
||||
@ -110,11 +109,11 @@ class RemoteCPPUnitTests(cppunittests.CPPUnitTests):
|
||||
elif len(envdef_parts) == 1:
|
||||
env[envdef_parts[0]] = ""
|
||||
else:
|
||||
print >> sys.stderr, "warning: invalid --addEnv option skipped: "+envdef
|
||||
self.log.warning("invalid --addEnv option skipped: %s" % envdef)
|
||||
|
||||
return env
|
||||
|
||||
def run_one_test(self, prog, env, symbols_path=None):
|
||||
def run_one_test(self, prog, env, symbols_path=None, interactive=False):
|
||||
"""
|
||||
Run a single C++ unit test program remotely.
|
||||
|
||||
@ -128,21 +127,25 @@ class RemoteCPPUnitTests(cppunittests.CPPUnitTests):
|
||||
"""
|
||||
basename = os.path.basename(prog)
|
||||
remote_bin = posixpath.join(self.remote_bin_dir, basename)
|
||||
log.info("Running test %s", basename)
|
||||
self.log.test_start(basename)
|
||||
buf = StringIO.StringIO()
|
||||
returncode = self.device.shell([remote_bin], buf, env=env, cwd=self.remote_home_dir,
|
||||
timeout=cppunittests.CPPUnitTests.TEST_PROC_TIMEOUT)
|
||||
print >> sys.stdout, buf.getvalue()
|
||||
self.log.process_output(basename, "\n%s" % buf.getvalue(),
|
||||
command=[remote_bin])
|
||||
with mozfile.TemporaryDirectory() as tempdir:
|
||||
self.device.getDirectory(self.remote_home_dir, tempdir)
|
||||
if mozcrash.check_for_crashes(tempdir, symbols_path,
|
||||
test_name=basename):
|
||||
log.testFail("%s | test crashed", basename)
|
||||
self.log.test_end(basename, status='CRASH', expected='PASS')
|
||||
return False
|
||||
result = returncode == 0
|
||||
if not result:
|
||||
log.testFail("%s | test failed with return code %s",
|
||||
basename, returncode)
|
||||
self.log.test_end(basename, status='FAIL', expected='PASS',
|
||||
message=("test failed with return code %d" %
|
||||
returncode))
|
||||
else:
|
||||
self.log.test_end(basename, status='PASS', expected='PASS')
|
||||
return result
|
||||
|
||||
class RemoteCPPUnittestOptions(cppunittests.CPPUnittestOptions):
|
||||
@ -204,6 +207,7 @@ class RemoteCPPUnittestOptions(cppunittests.CPPUnittestOptions):
|
||||
|
||||
def main():
|
||||
parser = RemoteCPPUnittestOptions()
|
||||
structured.commandline.add_logging_group(parser)
|
||||
options, args = parser.parse_args()
|
||||
if not args:
|
||||
print >>sys.stderr, """Usage: %s <test binary> [<test binary>...]""" % sys.argv[0]
|
||||
@ -243,6 +247,12 @@ def main():
|
||||
if not options.device_ip:
|
||||
print "Error: you must provide a device IP to connect to via the --deviceIP option"
|
||||
sys.exit(1)
|
||||
|
||||
log = structured.commandline.setup_logging("remotecppunittests",
|
||||
options,
|
||||
{"tbpl": sys.stdout})
|
||||
|
||||
|
||||
options.xre_path = os.path.abspath(options.xre_path)
|
||||
progs = cppunittests.extract_unittests_from_args(args, options.manifest_file)
|
||||
tester = RemoteCPPUnitTests(dm, options, progs)
|
||||
|
@ -7,10 +7,13 @@
|
||||
from __future__ import with_statement
|
||||
import sys, os, tempfile, shutil
|
||||
from optparse import OptionParser
|
||||
import mozprocess, mozinfo, mozlog, mozcrash, mozfile
|
||||
import mozprocess
|
||||
import mozinfo
|
||||
import mozcrash
|
||||
import mozfile
|
||||
from contextlib import contextmanager
|
||||
|
||||
log = mozlog.getLogger('cppunittests')
|
||||
from mozlog import structured
|
||||
from subprocess import PIPE
|
||||
|
||||
class CPPUnitTests(object):
|
||||
# Time (seconds) to wait for test process to complete
|
||||
@ -18,7 +21,7 @@ class CPPUnitTests(object):
|
||||
# Time (seconds) in which process will be killed if it produces no output.
|
||||
TEST_PROC_NO_OUTPUT_TIMEOUT = 300
|
||||
|
||||
def run_one_test(self, prog, env, symbols_path=None):
|
||||
def run_one_test(self, prog, env, symbols_path=None, interactive=False):
|
||||
"""
|
||||
Run a single C++ unit test program.
|
||||
|
||||
@ -31,28 +34,44 @@ class CPPUnitTests(object):
|
||||
Return True if the program exits with a zero status, False otherwise.
|
||||
"""
|
||||
basename = os.path.basename(prog)
|
||||
log.info("Running test %s", basename)
|
||||
self.log.test_start(basename)
|
||||
with mozfile.TemporaryDirectory() as tempdir:
|
||||
proc = mozprocess.ProcessHandler([prog],
|
||||
cwd=tempdir,
|
||||
env=env)
|
||||
if interactive:
|
||||
# For tests run locally, via mach, print output directly
|
||||
proc = mozprocess.ProcessHandler([prog],
|
||||
cwd=tempdir,
|
||||
env=env,
|
||||
storeOutput=False)
|
||||
else:
|
||||
proc = mozprocess.ProcessHandler([prog],
|
||||
cwd=tempdir,
|
||||
env=env,
|
||||
storeOutput=True,
|
||||
processOutputLine=lambda _: None)
|
||||
#TODO: After bug 811320 is fixed, don't let .run() kill the process,
|
||||
# instead use a timeout in .wait() and then kill to get a stack.
|
||||
proc.run(timeout=CPPUnitTests.TEST_PROC_TIMEOUT,
|
||||
outputTimeout=CPPUnitTests.TEST_PROC_NO_OUTPUT_TIMEOUT)
|
||||
proc.wait()
|
||||
if proc.output:
|
||||
output = "\n%s" % "\n".join(proc.output)
|
||||
self.log.process_output(proc.pid, output, command=[prog])
|
||||
if proc.timedOut:
|
||||
log.testFail("%s | timed out after %d seconds",
|
||||
basename, CPPUnitTests.TEST_PROC_TIMEOUT)
|
||||
message = "timed out after %d seconds" % CPPUnitTests.TEST_PROC_TIMEOUT
|
||||
self.log.test_end(basename, status='TIMEOUT', expected='PASS',
|
||||
message=message)
|
||||
return False
|
||||
if mozcrash.check_for_crashes(tempdir, symbols_path,
|
||||
test_name=basename):
|
||||
log.testFail("%s | test crashed", basename)
|
||||
self.log.test_end(basename, status='CRASH', expected='PASS')
|
||||
return False
|
||||
result = proc.proc.returncode == 0
|
||||
if not result:
|
||||
log.testFail("%s | test failed with return code %d",
|
||||
basename, proc.proc.returncode)
|
||||
self.log.test_end(basename, status='FAIL', expected='PASS',
|
||||
message=("test failed with return code %d" %
|
||||
proc.proc.returncode))
|
||||
else:
|
||||
self.log.test_end(basename, status='PASS', expected='PASS')
|
||||
return result
|
||||
|
||||
def build_core_environment(self, env = {}):
|
||||
@ -94,13 +113,13 @@ class CPPUnitTests(object):
|
||||
llvmsym = os.path.join(self.xre_path, "llvm-symbolizer")
|
||||
if os.path.isfile(llvmsym):
|
||||
env["ASAN_SYMBOLIZER_PATH"] = llvmsym
|
||||
log.info("ASan using symbolizer at %s", llvmsym)
|
||||
self.log.info("ASan using symbolizer at %s" % llvmsym)
|
||||
else:
|
||||
log.info("Failed to find ASan symbolizer at %s", llvmsym)
|
||||
self.log.info("Failed to find ASan symbolizer at %s" % llvmsym)
|
||||
|
||||
return env
|
||||
|
||||
def run_tests(self, programs, xre_path, symbols_path=None):
|
||||
def run_tests(self, programs, xre_path, symbols_path=None, interactive=False):
|
||||
"""
|
||||
Run a set of C++ unit test programs.
|
||||
|
||||
@ -114,19 +133,23 @@ class CPPUnitTests(object):
|
||||
otherwise.
|
||||
"""
|
||||
self.xre_path = xre_path
|
||||
self.log = structured.structuredlog.get_default_logger()
|
||||
self.log.suite_start(programs)
|
||||
env = self.build_environment()
|
||||
pass_count = 0
|
||||
fail_count = 0
|
||||
for prog in programs:
|
||||
single_result = self.run_one_test(prog, env, symbols_path)
|
||||
single_result = self.run_one_test(prog, env, symbols_path, interactive)
|
||||
if single_result:
|
||||
pass_count += 1
|
||||
else:
|
||||
fail_count += 1
|
||||
self.log.suite_end()
|
||||
|
||||
log.info("Result summary:")
|
||||
log.info("Passed: %d" % pass_count)
|
||||
log.info("Failed: %d" % fail_count)
|
||||
# Mozharness-parseable summary formatting.
|
||||
self.log.info("Result summary:")
|
||||
self.log.info("cppunittests INFO | Passed: %d" % pass_count)
|
||||
self.log.info("cppunittests INFO | Failed: %d" % fail_count)
|
||||
return fail_count == 0
|
||||
|
||||
class CPPUnittestOptions(OptionParser):
|
||||
@ -171,6 +194,7 @@ def extract_unittests_from_args(args, manifest_file):
|
||||
|
||||
def main():
|
||||
parser = CPPUnittestOptions()
|
||||
structured.commandline.add_logging_group(parser)
|
||||
options, args = parser.parse_args()
|
||||
if not args:
|
||||
print >>sys.stderr, """Usage: %s <test binary> [<test binary>...]""" % sys.argv[0]
|
||||
@ -178,17 +202,22 @@ def main():
|
||||
if not options.xre_path:
|
||||
print >>sys.stderr, """Error: --xre-path is required"""
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
log = structured.commandline.setup_logging("cppunittests",
|
||||
options,
|
||||
{"tbpl": sys.stdout})
|
||||
|
||||
progs = extract_unittests_from_args(args, options.manifest_file)
|
||||
options.xre_path = os.path.abspath(options.xre_path)
|
||||
tester = CPPUnitTests()
|
||||
|
||||
try:
|
||||
result = tester.run_tests(progs, options.xre_path, options.symbols_path)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
log.error(str(e))
|
||||
result = False
|
||||
|
||||
sys.exit(0 if result else 1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user