提交 d2a41697 编写于 作者: L Lucas Meneghel Rodrigues

Merge pull request #704 from clebergnu/usability_fixes

Usability fixes on "$ avocado run --help"
...@@ -35,19 +35,21 @@ class GDB(plugin.Plugin): ...@@ -35,19 +35,21 @@ class GDB(plugin.Plugin):
self.parser = parser self.parser = parser
gdb_grp = self.parser.runner.add_argument_group('GNU Debugger support') gdb_grp = self.parser.runner.add_argument_group('GNU Debugger support')
gdb_grp.add_argument('--gdb-run-bin', action='append', gdb_grp.add_argument('--gdb-run-bin', action='append',
default=[], metavar='BINARY_PATH', default=[], metavar='EXECUTABLE[:BREAKPOINT]',
help=('Set a breakpoint on a given binary to be ' help=('Run a given executable inside the GNU '
'run inside the GNU debugger. Format should ' 'debugger, pausing at a given breakpoint '
'be "<binary>[:breakpoint]". Breakpoint ' '(defaults to "main")'))
'defaults to "main"'))
# Because of a bug in Python's argparse, it's not possible to mark
# this option metavar as [EXECUTABLE:]COMMANDS, signalling that the
# EXECUTABLE is optional. https://bugs.python.org/issue11874
gdb_grp.add_argument('--gdb-prerun-commands', action='append', gdb_grp.add_argument('--gdb-prerun-commands', action='append',
default=[], metavar='BINARY_PATH:COMMANDS_PATH', default=[], metavar='EXECUTABLE:COMMANDS',
help=('After loading a binary in binary in GDB, ' help=('After loading an executable in GDB, '
'but before actually running it, execute ' 'but before actually running it, execute '
'the given GDB commands in the given file. ' 'the GDB commands in the given file. '
'BINARY_PATH is optional and if omitted ' 'EXECUTABLE is optional, if omitted '
'will apply to all binaries')) 'COMMANDS will apply to all executables'))
gdb_grp.add_argument('--gdb-coredump', choices=('on', 'off'), gdb_grp.add_argument('--gdb-coredump', choices=('on', 'off'),
default='off', default='off',
......
...@@ -279,8 +279,8 @@ class HTML(plugin.Plugin): ...@@ -279,8 +279,8 @@ class HTML(plugin.Plugin):
self.parser = parser self.parser = parser
self.parser.runner.output.add_argument( self.parser.runner.output.add_argument(
'--html', type=str, '--html', type=str,
dest='html_output', dest='html_output', metavar='FILE',
help=('Enable HTML output to the file where the result should be ' help=('Enable HTML output to the FILE where the result should be '
'written. The value - (output to stdout) is not supported ' 'written. The value - (output to stdout) is not supported '
'since not all HTML resources can be embedded into a ' 'since not all HTML resources can be embedded into a '
'single file (page resources will be copied to the ' 'single file (page resources will be copied to the '
......
...@@ -104,8 +104,8 @@ class JSON(plugin.Plugin): ...@@ -104,8 +104,8 @@ class JSON(plugin.Plugin):
self.parser = parser self.parser = parser
self.parser.runner.output.add_argument( self.parser.runner.output.add_argument(
'--json', type=str, '--json', type=str,
dest='json_output', dest='json_output', metavar='FILE',
help='Enable JSON output to the file where the result should be written. ' help='Enable JSON result format and write it to FILE. '
"Use '-' to redirect to the standard output.") "Use '-' to redirect to the standard output.")
self.configured = True self.configured = True
......
...@@ -37,7 +37,7 @@ class RunRemote(plugin.Plugin): ...@@ -37,7 +37,7 @@ class RunRemote(plugin.Plugin):
self.enabled = False self.enabled = False
return return
username = getpass.getuser() username = getpass.getuser()
msg = 'run on a remote machine arguments' msg = 'test execution on a remote machine'
self.remote_parser = parser.runner.add_argument_group(msg) self.remote_parser = parser.runner.add_argument_group(msg)
self.remote_parser.add_argument('--remote-hostname', self.remote_parser.add_argument('--remote-hostname',
dest='remote_hostname', default=None, dest='remote_hostname', default=None,
......
...@@ -82,7 +82,7 @@ class TestRunner(plugin.Plugin): ...@@ -82,7 +82,7 @@ class TestRunner(plugin.Plugin):
'(hardware details, profilers, etc.). ' '(hardware details, profilers, etc.). '
'Current: %(default)s')) 'Current: %(default)s'))
self.parser.output = self.parser.add_argument_group('output related arguments') self.parser.output = self.parser.add_argument_group('output and result format')
self.parser.output.add_argument( self.parser.output.add_argument(
'-s', '--silent', action='store_true', default=False, '-s', '--silent', action='store_true', default=False,
...@@ -116,10 +116,11 @@ class TestRunner(plugin.Plugin): ...@@ -116,10 +116,11 @@ class TestRunner(plugin.Plugin):
'Current: on (output check enabled)')) 'Current: on (output check enabled)'))
if multiplexer.MULTIPLEX_CAPABLE: if multiplexer.MULTIPLEX_CAPABLE:
mux = self.parser.add_argument_group('multiplex arguments') mux = self.parser.add_argument_group('multiplexer use on test execution')
mux.add_argument('-m', '--multiplex-files', nargs='*', default=None, mux.add_argument('-m', '--multiplex-files', nargs='*',
help='Path(s) to a avocado multiplex (.yaml) ' default=None, metavar='FILE',
'file(s) (order dependent)') help='Location of one or more Avocado multiplex (.yaml) '
'FILE(s) (order dependent)')
mux.add_argument('--filter-only', nargs='*', default=[], mux.add_argument('--filter-only', nargs='*', default=[],
help='Filter only path(s) from multiplexing') help='Filter only path(s) from multiplexing')
mux.add_argument('--filter-out', nargs='*', default=[], mux.add_argument('--filter-out', nargs='*', default=[],
......
...@@ -38,9 +38,8 @@ class RunVM(plugin.Plugin): ...@@ -38,9 +38,8 @@ class RunVM(plugin.Plugin):
return return
username = getpass.getuser() username = getpass.getuser()
default_hypervisor_uri = 'qemu:///system' default_hypervisor_uri = 'qemu:///system'
self.vm_parser = parser.runner.add_argument_group('run on a libvirt ' msg = 'test execution on a Virtual Machine'
'domain arguments') self.vm_parser = parser.runner.add_argument_group(msg)
self.vm_parser.add_argument('--vm-domain', dest='vm_domain', self.vm_parser.add_argument('--vm-domain', dest='vm_domain',
help=('Specify Libvirt Domain Name')) help=('Specify Libvirt Domain Name'))
self.vm_parser.add_argument('--vm-hypervisor-uri', self.vm_parser.add_argument('--vm-hypervisor-uri',
......
...@@ -33,16 +33,16 @@ class Wrapper(plugin.Plugin): ...@@ -33,16 +33,16 @@ class Wrapper(plugin.Plugin):
def configure(self, parser): def configure(self, parser):
self.parser = parser self.parser = parser
wrap_group = self.parser.runner.add_argument_group( wrap_group = self.parser.runner.add_argument_group(
'Wrap avocado.utils.process module') 'wrapper support')
wrap_group.add_argument('--wrapper', action='append', default=[], wrap_group.add_argument('--wrapper', action='append', default=[],
metavar='SCRIPT[:PROCESS]', metavar='SCRIPT[:EXECUTABLE]',
help='Use a script to wrap the execution of ' help='Use a script to wrap executables run by '
'process created by the test. The wrapper is ' 'a test. The wrapper is either a path to a '
'either a path to a script (aka global wrap) or ' 'script (AKA a global wrapper) or '
'a path to a script followed by colon symbol (:), ' 'a path to a script followed by colon symbol (:), '
'plus a shell like glob to the target process. ' 'plus a shell like glob to the target EXECUTABLE. '
'Multiple wrap lines are allowed, but only one global ' 'Multiple wrapper options are allowed, but '
'wrap can be defined.') 'only one global wrapper can be defined.')
self.configured = True self.configured = True
def activate(self, app_args): def activate(self, app_args):
......
...@@ -228,8 +228,8 @@ class XUnit(plugin.Plugin): ...@@ -228,8 +228,8 @@ class XUnit(plugin.Plugin):
def configure(self, parser): def configure(self, parser):
self.parser = parser self.parser = parser
self.parser.runner.output.add_argument( self.parser.runner.output.add_argument(
'--xunit', type=str, dest='xunit_output', '--xunit', type=str, dest='xunit_output', metavar='FILE',
help=('Enable xUnit output to the file where the result should be written. ' help=('Enable xUnit result format and write it to FILE. '
"Use '-' to redirect to the standard output.")) "Use '-' to redirect to the standard output."))
self.configured = True self.configured = True
......
...@@ -4,20 +4,20 @@ Debugging with GDB ...@@ -4,20 +4,20 @@ Debugging with GDB
Avocado has two different types of GDB support that complement each Avocado has two different types of GDB support that complement each
other: other:
* Transparent execution of binaries inside the GNU Debugger. This * Transparent execution of executables inside the GNU Debugger. This
takes standard and possibly unmodified tests that uses the takes standard and possibly unmodified tests that uses the
:mod:`avocado.utils.process` APIs for running processes. By using a :mod:`avocado.utils.process` APIs for running processes. By using a
command line option, the binary is run on GDB. This allows the user command line option, the executable is run on GDB. This allows the user
to interact with GDB, but to the test itself, things are pretty much to interact with GDB, but to the test itself, things are pretty much
transparent. transparent.
* The :mod:`avocado.gdb` APIs that allows a test to interact with GDB, * The :mod:`avocado.gdb` APIs that allows a test to interact with GDB,
including setting a binary to be run, setting breakpoints or any including setting a executable to be run, setting breakpoints or any
other types of commands. This requires a test written with that other types of commands. This requires a test written with that
approach and API in mind. approach and API in mind.
Transparent Execution of Binaries Transparent Execution of Executables
--------------------------------- ------------------------------------
This feature adds a few command line options to the Avocado ``run`` This feature adds a few command line options to the Avocado ``run``
command:: command::
...@@ -25,15 +25,15 @@ command:: ...@@ -25,15 +25,15 @@ command::
$ avocado run --help $ avocado run --help
... ...
GNU Debugger support: GNU Debugger support:
--gdb-run-bin BINARY_PATH
Set a breakpoint on a given binary to be run inside --gdb-run-bin EXECUTABLE[:BREAKPOINT]
the GNU debugger. Format should be Run a given executable inside the GNU debugger,
"<binary>[:breakpoint]". Breakpoint defaults to "main" pausing at a given breakpoint (defaults to "main")
--gdb-prerun-commands BINARY_PATH:COMMANDS_PATH --gdb-prerun-commands EXECUTABLE:COMMANDS
After loading a binary in binary in GDB, but before After loading an executable in GDB, but before
actually running it, execute the given GDB commands in actually running it, execute the GDB commands in the
the given file. BINARY_PATH is optional and if omitted given file. EXECUTABLE is optional, if omitted
will apply to all binaries COMMANDS will apply to all executables
--gdb-coredump {on,off} --gdb-coredump {on,off}
Automatically generate a core dump when the inferior Automatically generate a core dump when the inferior
process received a fatal signal such as SIGSEGV or process received a fatal signal such as SIGSEGV or
...@@ -47,8 +47,8 @@ Example ...@@ -47,8 +47,8 @@ Example
The simplest way is to just run The simplest way is to just run
``avocado run --gdb-run-bin=doublefree examples/tests/doublefree.py``, which ``avocado run --gdb-run-bin=doublefree examples/tests/doublefree.py``, which
wraps each executed binary with name ``doublefree`` inside GDB server and wraps each executed executable with name ``doublefree`` inside GDB server and
stops at the binary entry point. stops at the executable entry point.
Optionally you can specify single breakpoint using Optionally you can specify single breakpoint using
``--gdb-run-bin=doublefree:$breakpoint`` (eg: ``doublefree:1``) or just ``--gdb-run-bin=doublefree:$breakpoint`` (eg: ``doublefree:1``) or just
...@@ -171,7 +171,7 @@ Take a look at ``examples/tests/modify_variable.py`` test:: ...@@ -171,7 +171,7 @@ Take a look at ``examples/tests/modify_variable.py`` test::
app.exit() app.exit()
self.assertIn("MY VARIABLE 'A' IS: ff", out) self.assertIn("MY VARIABLE 'A' IS: ff", out)
You can see that instead of running the binary using ``process.run`` we invoke You can see that instead of running the executable using ``process.run`` we invoke
``gdb.GDB``. This allows us to automate the interaction with the GDB in means ``gdb.GDB``. This allows us to automate the interaction with the GDB in means
of setting breakpoints, executing commands and querying for output. of setting breakpoints, executing commands and querying for output.
......
Wrap process in tests Wrap executables run by tests
===================== =============================
Avocado allows the instrumentation of applications being run by a test Avocado allows the instrumentation of executables being run by a test
in a transparent way. The user specifies a script ("the wrapper") to be in a transparent way. The user specifies a script ("the wrapper") to be
used to run the actual program called by the test. used to run the actual program called by the test.
If the instrumentation script is implemented correctly, it should not If the instrumentation script is implemented correctly, it should not
interfere with the test behavior. That is, the wrapper should avoid interfere with the test behavior. That is, the wrapper should avoid
changing the return status, standard output and standard error messages changing the return status, standard output and standard error messages
of the original process. of the original executable.
The user can be specific about which program to wrap (with a shell-like glob), The user can be specific about which program to wrap (with a shell-like glob),
or if that is omitted, a global wrapper that will apply to all or if that is omitted, a global wrapper that will apply to all
...@@ -45,6 +45,6 @@ Caveats ...@@ -45,6 +45,6 @@ Caveats
present in two wrappers, you have to combine those into a single present in two wrappers, you have to combine those into a single
wrapper script. wrapper script.
* Only processes that are run with the :mod:`avocado.utils.process` APIs * Only executables that are run with the :mod:`avocado.utils.process` APIs
(and other API modules that make use of it, like mod:`avocado.utils.build`) (and other API modules that make use of it, like mod:`avocado.utils.build`)
are affected by this feature. are affected by this feature.
...@@ -356,11 +356,11 @@ variants. If no matches are found, then it would proceed to ``/qa/*`` ...@@ -356,11 +356,11 @@ variants. If no matches are found, then it would proceed to ``/qa/*``
Keep in mind that only slices defined in mux-path are taken into account for Keep in mind that only slices defined in mux-path are taken into account for
relative paths (the ones starting with ``*``). relative paths (the ones starting with ``*``).
DEBUGGING BINARIES RUN AS PART OF A TEST DEBUGGING EXECUTABLES RUN AS PART OF A TEST
======================================== ===========================================
One interesting avocado feature is the ability to automatically and One interesting avocado feature is the ability to automatically and
transparently run binaries that are used on a given test inside the transparently run executables that are used on a given test inside the
GNU debugger. GNU debugger.
Suppose you are running a test that uses an external, compiled, image Suppose you are running a test that uses an external, compiled, image
...@@ -378,7 +378,7 @@ The job starts running just as usual, and so does your test:: ...@@ -378,7 +378,7 @@ The job starts running just as usual, and so does your test::
TESTS : 1 TESTS : 1
(1/1) converttest.py: / (1/1) converttest.py: /
The `convert` binary though, automatically runs inside GDB. Avocado will The `convert` executable though, automatically runs inside GDB. Avocado will
stop when the given breakpoint is reached:: stop when the given breakpoint is reached::
TEST PAUSED because of debugger breakpoint. To DEBUG your application run: TEST PAUSED because of debugger breakpoint. To DEBUG your application run:
...@@ -390,7 +390,7 @@ From this point, you can run the generated script (`convert.gdb.sh`) to ...@@ -390,7 +390,7 @@ From this point, you can run the generated script (`convert.gdb.sh`) to
debug you application. debug you application.
As noted, it is strongly recommended that you *disconnect* from gdb while As noted, it is strongly recommended that you *disconnect* from gdb while
your binary is still running. That is, if the binary finished running your executable is still running. That is, if the executable finished running
while you are debugging it, avocado has no way to know about its status. while you are debugging it, avocado has no way to know about its status.
Avocado will automatically send a `continue` command to the debugger Avocado will automatically send a `continue` command to the debugger
...@@ -421,25 +421,25 @@ In this example, `/tmp/disable-signals` is a simple text file containing two lin ...@@ -421,25 +421,25 @@ In this example, `/tmp/disable-signals` is a simple text file containing two lin
Each line is a GDB command, so you can have from simple to very complex Each line is a GDB command, so you can have from simple to very complex
debugging environments configured like that. debugging environments configured like that.
WRAP PROCESS IN TESTS WRAP EXECUTABLE RUN BY TESTS
===================== ============================
Avocado allows the instrumentation of applications being Avocado allows the instrumentation of executables being run by a test
run by a test in a transparent way. The user specifies a script in a transparent way. The user specifies a script ("the wrapper") to be
("the wrapper") to be used to run the actual program called by the test. used to run the actual program called by the test.
If the instrument is implemented correctly, it should not interfere If the instrumentation script is implemented correctly, it should not
with the test behavior. So that, a perfect wrapper shall not interfere with the test behavior. That is, the wrapper should avoid
change the return status, standard output and standard error messages changing the return status, standard output and standard error messages
of the process being executed. of the original executable.
By using an optional parameter to the wrapper, you can specify a pattern The user can be specific about which program to wrap (with a shell-like glob),
in format of shell glob to select the "target binary" to wrap. or if that is omitted, a global wrapper that will apply to all
programs called by the test.
In this case, for every program spawned by the test, So, for every executable run by the test, the program name will be
the program name will be compared to the pattern to decide compared to the pattern to decide whether to wrap it or not. You can
whether to wrap it or not. You can have multiples wrappers and patterns have multiples wrappers and patterns defined.
defined.
Examples:: Examples::
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册