diff options
| author | Vince Harron <vince@nethacker.com> | 2015-05-10 15:22:09 +0000 |
|---|---|---|
| committer | Vince Harron <vince@nethacker.com> | 2015-05-10 15:22:09 +0000 |
| commit | 9753dd98b367b0918d04a64c174783513166e978 (patch) | |
| tree | 0568fac41cc26d3c4d6eaa4d461212baea3303b9 /lldb/test/lldbtest.py | |
| parent | f40342d6a25952e0c43f51556c48ecbb1b2003f1 (diff) | |
| download | bcm5719-llvm-9753dd98b367b0918d04a64c174783513166e978.tar.gz bcm5719-llvm-9753dd98b367b0918d04a64c174783513166e978.zip | |
Add support for ./dotest.py --channel and --log-success
Summary:
New dotest options that allow arbitrary log channels and
categories to be enabled. Also enables logging for locally run
debug servers.
Log messages are separated into separate files per test case.
(this makes it possible to log in dosep runs)
These new log files are stored side-by-side with trace files in the
session directory.
These files are deleted by default if the test run is successful.
If --log-success is specified, even successful logs are retained.
--log-success is useful for creating reference log files.
Test Plan:
add '--channel "lldb all" --channel "gdb-remote packets" --log-success'
to your dotest options
Tested on OSX and Linux
Differential Revision: http://reviews.llvm.org/D9594
llvm-svn: 236956
Diffstat (limited to 'lldb/test/lldbtest.py')
| -rw-r--r-- | lldb/test/lldbtest.py | 138 |
1 files changed, 123 insertions, 15 deletions
diff --git a/lldb/test/lldbtest.py b/lldb/test/lldbtest.py index f6f02d9c39b..269b79190dd 100644 --- a/lldb/test/lldbtest.py +++ b/lldb/test/lldbtest.py @@ -32,6 +32,7 @@ $ """ import abc +import glob import os, sys, traceback import os.path import re @@ -42,6 +43,7 @@ import time import types import unittest2 import lldb +import lldbtest_config from _pyio import __metaclass__ # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables @@ -1284,6 +1286,8 @@ class Base(unittest2.TestCase): for dict in reversed(self.dicts): self.cleanup(dictionary=dict) + self.disableLogChannelsForCurrentTest() + # Decide whether to dump the session info. self.dumpSessionInfo() @@ -1342,7 +1346,33 @@ class Base(unittest2.TestCase): def getRerunArgs(self): return " -f %s.%s" % (self.__class__.__name__, self._testMethodName) - + + def getLogBasenameForCurrentTest(self, prefix=None): + """ + returns a partial path that can be used as the beginning of the name of multiple + log files pertaining to this test + + <session-dir>/<arch>-<compiler>-<test-file>.<test-class>.<test-method> + """ + dname = os.path.join(os.environ["LLDB_TEST"], + os.environ["LLDB_SESSION_DIRNAME"]) + if not os.path.isdir(dname): + os.mkdir(dname) + + compiler = self.getCompiler() + + if compiler[1] == ':': + compiler = compiler[2:] + + fname = "{}-{}-{}".format(self.getArchitecture(), "_".join(compiler.split(os.path.sep)), self.id()) + if len(fname) > 200: + fname = "{}-{}-{}".format(self.getArchitecture(), compiler.split(os.path.sep)[-1], self.id()) + + if prefix is not None: + fname = "{}-{}".format(prefix, fname) + + return os.path.join(dname, fname) + def dumpSessionInfo(self): """ Dump the debugger interactions leading to a test error/failure. This @@ -1363,6 +1393,9 @@ class Base(unittest2.TestCase): # formatted tracebacks. # # See http://docs.python.org/library/unittest.html#unittest.TestResult. + src_log_basename = self.getLogBasenameForCurrentTest() + + pairs = [] if self.__errored__: pairs = lldb.test_result.errors prefix = 'Error' @@ -1377,8 +1410,18 @@ class Base(unittest2.TestCase): elif self.__unexpected__: prefix = "UnexpectedSuccess" else: - # Simply return, there's no session info to dump! - return + prefix = "Success" + if not lldbtest_config.log_success: + # delete log files, return (don't output trace) + for i in glob.glob(src_log_basename + "*"): + os.unlink(i) + return + + # rename all log files - prepend with result + dst_log_basename = self.getLogBasenameForCurrentTest(prefix) + for src in glob.glob(self.getLogBasenameForCurrentTest() + "*"): + dst = src.replace(src_log_basename, dst_log_basename) + os.rename(src, dst) if not self.__unexpected__ and not self.__skipped__: for test, traceback in pairs: @@ -1391,18 +1434,7 @@ class Base(unittest2.TestCase): else: benchmarks = False - dname = os.path.join(os.environ["LLDB_TEST"], - os.environ["LLDB_SESSION_DIRNAME"]) - if not os.path.isdir(dname): - os.mkdir(dname) - compiler = self.getCompiler() - if compiler[1] == ':': - compiler = compiler[2:] - - fname = "%s-%s-%s-%s.log" % (prefix, self.getArchitecture(), "_".join(compiler.split(os.path.sep)), self.id()) - if len(fname) > 255: - fname = "%s-%s-%s-%s.log" % (prefix, self.getArchitecture(), compiler.split(os.path.sep)[-1], self.id()) - pname = os.path.join(dname, fname) + pname = "{}.log".format(dst_log_basename) with open(pname, "w") as f: import datetime print >> f, "Session info generated @", datetime.datetime.now().ctime() @@ -1835,6 +1867,55 @@ class TestBase(Base): folder = os.path.dirname(folder) continue + def enableLogChannelsForCurrentTest(self): + if len(lldbtest_config.channels) == 0: + return + + # if debug channels are specified in lldbtest_config.channels, + # create a new set of log files for every test + log_basename = self.getLogBasenameForCurrentTest() + + # confirm that the file is writeable + host_log_path = "{}-host.log".format(log_basename) + open(host_log_path, 'w').close() + + log_enable = "log enable -Tpn -f {} ".format(host_log_path) + for channel_with_categories in lldbtest_config.channels: + channel_then_categories = channel_with_categories.split(' ', 1) + channel = channel_then_categories[0] + if len(channel_then_categories) > 1: + categories = channel_then_categories[1] + else: + categories = "default" + + if channel == "gdb-remote": + # communicate gdb-remote categories to debugserver + os.environ["LLDB_DEBUGSERVER_LOG_FLAGS"] = categories + + self.ci.HandleCommand(log_enable + channel_with_categories, self.res) + if not self.res.Succeeded(): + raise Exception('log enable failed (check LLDB_LOG_OPTION env variable)') + + # Communicate log path name to debugserver & lldb-server + server_log_path = "{}-server.log".format(log_basename) + open(server_log_path, 'w').close() + os.environ["LLDB_DEBUGSERVER_LOG_FILE"] = server_log_path + + # Communicate channels to lldb-server + os.environ["LLDB_SERVER_LOG_CHANNELS"] = ":".join(lldbtest_config.channels) + + if len(lldbtest_config.channels) == 0: + return + + def disableLogChannelsForCurrentTest(self): + # close all log files that we opened + for channel_and_categories in lldbtest_config.channels: + # channel format - <channel-name> [<category0> [<category1> ...]] + channel = channel_and_categories.split(' ', 1)[0] + self.ci.HandleCommand("log disable " + channel, self.res) + if not self.res.Succeeded(): + raise Exception('log disable failed (check LLDB_LOG_OPTION env variable)') + def setUp(self): #import traceback #traceback.print_stack() @@ -1871,6 +1952,33 @@ class TestBase(Base): if not self.dbg: raise Exception('Invalid debugger instance') + # Retrieve the associated command interpreter instance. + self.ci = self.dbg.GetCommandInterpreter() + if not self.ci: + raise Exception('Could not get the command interpreter') + + # And the result object. + self.res = lldb.SBCommandReturnObject() + + # Create the debugger instance if necessary. + try: + self.dbg = lldb.DBG + except AttributeError: + self.dbg = lldb.SBDebugger.Create() + + if not self.dbg: + raise Exception('Invalid debugger instance') + + # Retrieve the associated command interpreter instance. + self.ci = self.dbg.GetCommandInterpreter() + if not self.ci: + raise Exception('Could not get the command interpreter') + + # And the result object. + self.res = lldb.SBCommandReturnObject() + + self.enableLogChannelsForCurrentTest() + # # Warning: MAJOR HACK AHEAD! # If we are running testsuite remotely (by checking lldb.lldbtest_remote_sandbox), |

