summaryrefslogtreecommitdiff
path: root/cross-project-tests/debuginfo-tests
diff options
context:
space:
mode:
authorJeremy Morse <jeremy.morse@sony.com>2022-01-10 11:22:51 +0000
committerJeremy Morse <jeremy.morse@sony.com>2022-01-10 11:30:06 +0000
commit3a094d8b272c15aa329db92d85c6d483004b4f6e (patch)
treedeae31cbb70f2d451643a7fb8a8d6dd815fbf861 /cross-project-tests/debuginfo-tests
parentd17fb46e894501568a1bf3b11a5d920817444630 (diff)
downloadllvm-3a094d8b272c15aa329db92d85c6d483004b4f6e.tar.gz
[Dexter] Allow tests to specify command line options
This patch adds a "DexCommandLine" command, allowing dexter tests to specify what command line options the test should be started with. I've also plumbed it through into the debuggers. This eases the matter of pointing Dexter at larger tests, or controlling different paths through a single binary from a Dexter test. Differential Revision: https://reviews.llvm.org/D115330
Diffstat (limited to 'cross-project-tests/debuginfo-tests')
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/Commands.md20
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py6
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexCommandLine.py31
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py9
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py16
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py9
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py3
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py4
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py21
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/command_line.c16
10 files changed, 120 insertions, 15 deletions
diff --git a/cross-project-tests/debuginfo-tests/dexter/Commands.md b/cross-project-tests/debuginfo-tests/dexter/Commands.md
index 24f6f32f056e..2db8b859b1fe 100644
--- a/cross-project-tests/debuginfo-tests/dexter/Commands.md
+++ b/cross-project-tests/debuginfo-tests/dexter/Commands.md
@@ -12,6 +12,7 @@
* [DexDeclareAddress](Commands.md#DexDeclareAddress)
* [DexDeclareFile](Commands.md#DexDeclareFile)
* [DexFinishTest](Commands.md#DexFinishTest)
+* [DexCommandLine](Commands.md#DexCommandLine)
---
## DexExpectProgramState
@@ -336,6 +337,25 @@ for the first 'hit_count' times the line and condition are hit.
### Heuristic
This command does not contribute to the heuristic score.
+----
+## DexCommandLine
+ DexCommandLine(command_line)
+
+ Args:
+ command_line (list): List of strings that form the command line.
+
+### Description
+Specifies the command line with which to launch the test. The arguments will
+be appended to the default command line, i.e. the path to the compiled binary,
+and will be passed to the program under test.
+
+This command does not contribute to any part of the debug experience testing or
+runtime instrumentation -- it's only for communicating arguments to the program
+under test.
+
+### Heuristic
+This command does not contribute to the heuristic score.
+
---
## DexWatch
DexWatch(*expressions)
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py
index b0e7646f3063..cd93b2b289e6 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py
@@ -18,6 +18,7 @@ from collections import defaultdict, OrderedDict
from dex.utils.Exceptions import CommandParseError
from dex.command.CommandBase import CommandBase
+from dex.command.commands.DexCommandLine import DexCommandLine
from dex.command.commands.DexDeclareFile import DexDeclareFile
from dex.command.commands.DexDeclareAddress import DexDeclareAddress
from dex.command.commands.DexExpectProgramState import DexExpectProgramState
@@ -41,6 +42,7 @@ def _get_valid_commands():
{ name (str): command (class) }
"""
return {
+ DexCommandLine.get_name() : DexCommandLine,
DexDeclareAddress.get_name() : DexDeclareAddress,
DexDeclareFile.get_name() : DexDeclareFile,
DexExpectProgramState.get_name() : DexExpectProgramState,
@@ -322,6 +324,10 @@ def _find_all_commands_in_file(path, file_lines, valid_commands, source_root_dir
# TODO: keep stored paths as PurePaths for 'longer'.
cmd_path = str(PurePath(cmd_path))
declared_files.add(cmd_path)
+ elif type(command) is DexCommandLine and 'DexCommandLine' in commands:
+ msg = "More than one DexCommandLine in file"
+ raise format_parse_err(msg, path, file_lines, err_point)
+
assert (path, cmd_point) not in commands[command_name], (
command_name, commands[command_name])
commands[command_name][path, cmd_point] = command
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexCommandLine.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexCommandLine.py
new file mode 100644
index 000000000000..76b2ae5196c5
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexCommandLine.py
@@ -0,0 +1,31 @@
+# DExTer : Debugging Experience Tester
+# ~~~~~~ ~ ~~ ~ ~~
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+"""A Command that specifies the command line with which to run the test.
+"""
+
+from dex.command.CommandBase import CommandBase
+
+class DexCommandLine(CommandBase):
+ def __init__(self, the_cmdline):
+ if type(the_cmdline) is not list:
+ raise TypeError('Expected list, got {}'.format(type(the_cmdline)))
+ for x in the_cmdline:
+ if type(x) is not str:
+ raise TypeError('Command line element "{}" has type {}'.format(x, type(x)))
+ self.the_cmdline = the_cmdline
+ super(DexCommandLine, self).__init__()
+
+ def eval(self):
+ raise NotImplementedError('DexCommandLine commands cannot be evaled.')
+
+ @staticmethod
+ def get_name():
+ return __class__.__name__
+
+ @staticmethod
+ def get_subcommands() -> dict:
+ return None
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py
index 517a187f1160..569a2f941d3a 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py
@@ -69,16 +69,15 @@ class BreakpointRange:
class ConditionalController(DebuggerControllerBase):
def __init__(self, context, step_collection):
- self.context = context
- self.step_collection = step_collection
self._bp_ranges = None
- self._build_bp_ranges()
self._watches = set()
self._step_index = 0
self._pause_between_steps = context.options.pause_between_steps
self._max_steps = context.options.max_steps
# Map {id: BreakpointRange}
self._leading_bp_handles = {}
+ super(ConditionalController, self).__init__(context, step_collection)
+ self._build_bp_ranges()
def _build_bp_ranges(self):
commands = self.step_collection.commands
@@ -126,7 +125,7 @@ class ConditionalController(DebuggerControllerBase):
id = self.debugger.add_breakpoint(bpr.path, bpr.range_from)
self._leading_bp_handles[id] = bpr
- def _run_debugger_custom(self):
+ def _run_debugger_custom(self, cmdline):
# TODO: Add conditional and unconditional breakpoint support to dbgeng.
if self.debugger.get_name() == 'dbgeng':
raise DebuggerException('DexLimitSteps commands are not supported by dbgeng')
@@ -137,7 +136,7 @@ class ConditionalController(DebuggerControllerBase):
for command_obj in chain.from_iterable(self.step_collection.commands.values()):
self._watches.update(command_obj.get_watches())
- self.debugger.launch()
+ self.debugger.launch(cmdline)
time.sleep(self._pause_between_steps)
exit_desired = False
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py
index cd1a9b3c2f60..867345311e14 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py
@@ -9,6 +9,10 @@
import abc
class DebuggerControllerBase(object, metaclass=abc.ABCMeta):
+ def __init__(self, context, step_collection):
+ self.context = context
+ self.step_collection = step_collection
+
@abc.abstractclassmethod
def _run_debugger_custom(self):
"""Specify your own implementation of run_debugger_custom in your own
@@ -20,9 +24,19 @@ class DebuggerControllerBase(object, metaclass=abc.ABCMeta):
"""Responsible for correctly launching and tearing down the debugger.
"""
self.debugger = debugger
+
+ # Fetch command line options, if any.
+ the_cmdline = []
+ commands = self.step_collection.commands
+ if 'DexCommandLine' in commands:
+ cmd_line_objs = commands['DexCommandLine']
+ assert len(cmd_line_objs) == 1
+ cmd_line_obj = cmd_line_objs[0]
+ the_cmdline = cmd_line_obj.the_cmdline
+
with self.debugger:
if not self.debugger.loading_error:
- self._run_debugger_custom()
+ self._run_debugger_custom(the_cmdline)
# We may need to pickle this debugger controller after running the
# debugger. Debuggers are not picklable objects, so set to None.
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py
index 6923e23ef230..8315bb64c04c 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py
@@ -23,11 +23,10 @@ class EarlyExitCondition(object):
class DefaultController(DebuggerControllerBase):
def __init__(self, context, step_collection):
- self.context = context
- self.step_collection = step_collection
- self.source_files = self.context.options.source_files
+ self.source_files = context.options.source_files
self.watches = set()
self.step_index = 0
+ super(DefaultController, self).__init__(context, step_collection)
def _break_point_all_lines(self):
for s in self.context.options.source_files:
@@ -73,10 +72,10 @@ class DefaultController(DebuggerControllerBase):
return False
- def _run_debugger_custom(self):
+ def _run_debugger_custom(self, cmdline):
self.step_collection.debugger = self.debugger.debugger_info
self._break_point_all_lines()
- self.debugger.launch()
+ self.debugger.launch(cmdline)
for command_obj in chain.from_iterable(self.step_collection.commands.values()):
self.watches.update(command_obj.get_watches())
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
index 2b13398d0f30..a3021853eb14 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
@@ -95,7 +95,8 @@ class DbgEng(DebuggerBase):
# but is something that should be considered in the future.
raise NotImplementedError('delete_conditional_breakpoint is not yet implemented by dbgeng')
- def launch(self):
+ def launch(self, cmdline):
+ assert len(cmdline) == 0, "Command lines unimplemented for dbgeng right now"
# We are, by this point, already launched.
self.step_info = probe_process.probe_state(self.client)
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
index ce47619db135..cde83af82732 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
@@ -169,8 +169,8 @@ class LLDB(DebuggerBase):
pass
self._target.BreakpointDelete(id)
- def launch(self):
- self._process = self._target.LaunchSimple(None, None, os.getcwd())
+ def launch(self, cmdline):
+ self._process = self._target.LaunchSimple(cmdline, None, os.getcwd())
if not self._process or self._process.GetNumThreads() == 0:
raise DebuggerException('could not launch process')
if self._process.GetNumThreads() != 1:
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
index 4669fc3486ea..9a291a9f4982 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
@@ -229,7 +229,26 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst
bp.Delete()
break
- def launch(self):
+ def _fetch_property(self, props, name):
+ num_props = props.Count
+ result = None
+ for x in range(1, num_props+1):
+ item = props.Item(x)
+ if item.Name == name:
+ return item
+ assert False, "Couldn't find property {}".format(name)
+
+ def launch(self, cmdline):
+ cmdline_str = ' '.join(cmdline)
+
+ # In a slightly baroque manner, lookup the VS project that runs when
+ # you click "run", and set its command line options to the desired
+ # command line options.
+ startup_proj_name = str(self._fetch_property(self._interface.Solution.Properties, 'StartupProject'))
+ project = self._fetch_property(self._interface.Solution, startup_proj_name)
+ ActiveConfiguration = self._fetch_property(project.Properties, 'ActiveConfiguration').Object
+ ActiveConfiguration.DebugSettings.CommandArguments = cmdline_str
+
self._fn_go()
def step(self):
diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/command_line.c b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/command_line.c
new file mode 100644
index 000000000000..06887707ab85
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/command_line.c
@@ -0,0 +1,16 @@
+// UNSUPPORTED: dbgeng
+//
+// RUN: %dexter_regression_test -- %s | FileCheck %s
+// CHECK: command_line.c:
+
+int main(int argc, const char **argv) {
+ if (argc == 4)
+ return 0; // DexLabel('retline')
+
+ return 1; // DexUnreachable()
+}
+
+// DexExpectWatchValue('argc', '4', on_line=ref('retline'))
+
+// Three args will be appended to the 'default' argument.
+// DexCommandLine(['a', 'b', 'c'])