diff --git a/waflib/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py index a2f34a31..17983302 100644 --- a/waflib/Tools/waf_unit_test.py +++ b/waflib/Tools/waf_unit_test.py @@ -31,9 +31,13 @@ the predefined callback:: bld(features='cxx cxxprogram test', source='main.c', target='app') from waflib.Tools import waf_unit_test bld.add_post_fun(waf_unit_test.summary) + +By passing --dump-test-runner the execution will also create in the build directory a python file named as the task name with -run.py appended +that can be executed manually to reproduce the exact execution manually for debugging purposes. +If the script is run with arguments these will be used instead of the command itself. This can be used to run for example a debugger or profiler on the test manually. """ -import os +import os, sys from waflib.TaskGen import feature, after_method, taskgen_method from waflib import Utils, Task, Logs, Options from waflib.Tools import ccroot @@ -151,6 +155,13 @@ class utest(Task.Task): def exec_command(self, cmd, **kw): Logs.debug('runner: %r', cmd) + if getattr(Options.options, 'dump_test_runner', False): + if not self.generator.name: + Logs.warn('waf_unit_test: --dump-test-runner task with no name, outputs may collide') + runnername=os.path.join(str(self.generator.path.get_bld()), ( "%s-run.py" % (self.generator.name or 'dump-test-runner'))) + Utils.writef(runnername, ENVFILE_TEXT % { 'pyexe': sys.executable, 'env': self.get_test_env(), 'cwd': self.get_cwd().abspath(), 'cmd': cmd[0], 'cmdline': cmd }) + os.chmod(runnername, Utils.O755) + proc = Utils.subprocess.Popen(cmd, cwd=self.get_cwd().abspath(), env=self.get_test_env(), stderr=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE) (stdout, stderr) = proc.communicate() @@ -224,4 +235,39 @@ def options(opt): help = 'Run the unit tests using the test-cmd string' ' example "--test-cmd="valgrind --error-exitcode=1' ' %s" to run under valgrind', dest='testcmd') + opt.add_option('--dump-test-runner', action='store_true', default=False, + help='Create a python script with full environment to run the test manually for debugging purposes', dest='dump_test_runner') + + +""" +ENVFILE_TEXT specifies the contents of the test runner script generated if +--dump-test-runner is used. This can be used to manually run tests which are +failing in the exact environment as waf tests are run. +By default when executed it will just run the test and exit. If any arguments +are passed then those are executed. The use case is for example to pass +'bash' and this will open the shell when gdb can then be used in the same +environment as waf would have run the test. +Test command line is exported as $UT_CMDLINE so this can be used inside the +executed environment. +To execute directly gdb something like 'bash -c "gdb \$UT_CMDLINE"' can be +specified as argument as well. +""" +ENVFILE_TEXT = """#! %(pyexe)s +# If executed with no parametrs the script will run the test exactly as waf +# If parameters are passed they will be executed instead but in a waf-like +# environment. Example executions: +# Create a shell when you can manually invoke gdb or other tools: +#