summaryrefslogtreecommitdiff
path: root/cross-project-tests
diff options
context:
space:
mode:
authorStephen Tozer <stephen.tozer@sony.com>2022-04-28 15:01:28 +0100
committerStephen Tozer <stephen.tozer@sony.com>2022-06-13 14:44:28 +0100
commit30bb659c6f992d2dcf03cfc1d19c560f704035f6 (patch)
treeda8e895448db83cae66b38078657393ac9d567b8 /cross-project-tests
parent3f4a63e5f882eb062da33a5643499597efefe1ba (diff)
downloadllvm-30bb659c6f992d2dcf03cfc1d19c560f704035f6.tar.gz
[Dexter] Allow Dexter watch commands to specify a range of acceptable FP values
This patch adds an optional argument to DexExpectWatchBase, float_range, which defines a +- acceptance range for expected floating point values. If passed, this assumes every expected value to be a floating point value, and an exception will be thrown if this is not the case. Differential Revision: https://reviews.llvm.org/D124511
Diffstat (limited to 'cross-project-tests')
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/Commands.md5
-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/DexExpectWatchBase.py55
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/dex/utils/Exceptions.py8
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_out_range.cpp16
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_zero_nonmatch.cpp15
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_multiple.cpp18
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_no_arg.cpp16
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_small.cpp16
-rw-r--r--cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_zero_match.cpp14
10 files changed, 159 insertions, 10 deletions
diff --git a/cross-project-tests/debuginfo-tests/dexter/Commands.md b/cross-project-tests/debuginfo-tests/dexter/Commands.md
index e15110301751..d5bd999f5adf 100644
--- a/cross-project-tests/debuginfo-tests/dexter/Commands.md
+++ b/cross-project-tests/debuginfo-tests/dexter/Commands.md
@@ -144,7 +144,7 @@ type checked against the list of `types`
---
## DexExpectWatchValue
DexExpectWatchValue(expr, *values [,**from_line=1][,**to_line=Max]
- [,**on_line][,**require_in_order=True])
+ [,**on_line][,**require_in_order=True][,**float_range])
Args:
expr (str): expression to evaluate.
@@ -159,6 +159,9 @@ type checked against the list of `types`
on_line (int): Only evaluate the expression on this line. If provided,
this overrides from_line and to_line.
require_in_order (bool): If False the values can appear in any order.
+ float_range (float): If provided, `values` must be floats, and will
+ match an actual value if they are within `float_range` of each other.
+
### Description
Expect the expression `expr` to evaluate to the list of `values`
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 cd93b2b289e6..1027ba0d9beb 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/ParseCommand.py
@@ -15,7 +15,7 @@ from copy import copy
from pathlib import PurePath
from collections import defaultdict, OrderedDict
-from dex.utils.Exceptions import CommandParseError
+from dex.utils.Exceptions import CommandParseError, NonFloatValueInCommand
from dex.command.CommandBase import CommandBase
from dex.command.commands.DexCommandLine import DexCommandLine
@@ -310,6 +310,10 @@ def _find_all_commands_in_file(path, file_lines, valid_commands, source_root_dir
err_point = copy(cmd_point)
err_point.char += len(command_name)
raise format_parse_err(str(e), path, file_lines, err_point)
+ except NonFloatValueInCommand as e:
+ err_point = copy(cmd_point)
+ err_point.char += len(command_name)
+ raise format_parse_err(str(e), path, file_lines, err_point)
else:
if type(command) is DexLabel:
add_line_label(labels, command, path, cmd_point.get_lineno())
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py
index 6dd30adac289..e79b1bb711e6 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py
@@ -18,6 +18,7 @@ from pathlib import PurePath
from dex.command.CommandBase import CommandBase, StepExpectInfo
from dex.command.StepValueInfo import StepValueInfo
+from dex.utils.Exceptions import NonFloatValueInCommand
class AddressExpression(object):
def __init__(self, name, offset=0):
@@ -56,6 +57,13 @@ class DexExpectWatchBase(CommandBase):
self._from_line = kwargs.pop('from_line', 1)
self._to_line = kwargs.pop('to_line', 999999)
self._require_in_order = kwargs.pop('require_in_order', True)
+ self.float_range = kwargs.pop('float_range', None)
+ if self.float_range is not None:
+ for value in self.values:
+ try:
+ float(value)
+ except ValueError:
+ raise NonFloatValueInCommand(f'Non-float value \'{value}\' when float_range arg provided')
if kwargs:
raise TypeError('unexpected named args: {}'.format(
', '.join(kwargs)))
@@ -135,6 +143,33 @@ class DexExpectWatchBase(CommandBase):
"""Return a field from watch that this ExpectWatch command is checking.
"""
+ def _match_expected_floating_point(self, value):
+ """Checks to see whether value is a float that falls within the
+ acceptance range of one of this command's expected float values, and
+ returns the expected value if so; otherwise returns the original
+ value."""
+ try:
+ value_as_float = float(value)
+ except ValueError:
+ return value
+
+ possible_values = self.values
+ for expected in possible_values:
+ try:
+ expected_as_float = float(expected)
+ difference = abs(value_as_float - expected_as_float)
+ if difference <= self.float_range:
+ return expected
+ except ValueError:
+ pass
+ return value
+
+ def _maybe_fix_float(self, value):
+ if self.float_range is not None:
+ return self._match_expected_floating_point(value)
+ else:
+ return value
+
def _handle_watch(self, step_info):
self.times_encountered += 1
@@ -150,23 +185,25 @@ class DexExpectWatchBase(CommandBase):
self.irretrievable_watches.append(step_info)
return
+ expected_value = self._maybe_fix_float(step_info.expected_value)
+
# Check to see if this value matches with a resolved address.
matching_address = None
for v in self.values:
if (isinstance(v, AddressExpression) and
v.name in self.address_resolutions and
- self.resolve_value(v) == step_info.expected_value):
+ self.resolve_value(v) == expected_value):
matching_address = v
break
# If this is not an expected value, either a direct value or an address,
# then this is an unexpected watch.
- if step_info.expected_value not in self.values and matching_address is None:
+ if expected_value not in self.values and matching_address is None:
self.unexpected_watches.append(step_info)
return
self.expected_watches.append(step_info)
- value_to_remove = matching_address if matching_address is not None else step_info.expected_value
+ value_to_remove = matching_address if matching_address is not None else expected_value
try:
self._missing_values.remove(value_to_remove)
except KeyError:
@@ -177,7 +214,7 @@ class DexExpectWatchBase(CommandBase):
or not.
"""
differences = []
- actual_values = [w.expected_value for w in actual_watches]
+ actual_values = [self._maybe_fix_float(w.expected_value) for w in actual_watches]
value_differences = list(difflib.Differ().compare(actual_values,
expected_values))
@@ -229,14 +266,16 @@ class DexExpectWatchBase(CommandBase):
# A list of all watches where the value has changed.
value_change_watches = []
prev_value = None
+ all_expected_values = []
for watch in self.expected_watches:
- if watch.expected_value != prev_value:
+ expected_value = self._maybe_fix_float(watch.expected_value)
+ all_expected_values.append(expected_value)
+ if expected_value != prev_value:
value_change_watches.append(watch)
- prev_value = watch.expected_value
+ prev_value = expected_value
resolved_values = [self.resolve_value(v) for v in self.values]
self.misordered_watches = self._check_watch_order(
value_change_watches, [
- v for v in resolved_values if v in
- [w.expected_value for w in self.expected_watches]
+ v for v in resolved_values if v in all_expected_values
])
diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/utils/Exceptions.py b/cross-project-tests/debuginfo-tests/dexter/dex/utils/Exceptions.py
index 39c0c2f16952..b636acbc0cee 100644
--- a/cross-project-tests/debuginfo-tests/dexter/dex/utils/Exceptions.py
+++ b/cross-project-tests/debuginfo-tests/dexter/dex/utils/Exceptions.py
@@ -54,6 +54,14 @@ class CommandParseError(Dexception):
self.caret = None
+class NonFloatValueInCommand(CommandParseError):
+ """If a command has the float_range arg but at least one of its expected
+ values cannot be converted to a float."""
+
+ def __init__(self, *args, **kwargs):
+ super(NonFloatValueInCommand, self).__init__(*args, **kwargs)
+ self.value = None
+
class ToolArgumentError(Dexception):
"""If a tool argument is invalid."""
pass
diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_out_range.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_out_range.cpp
new file mode 100644
index 000000000000..519a99a05d0d
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_out_range.cpp
@@ -0,0 +1,16 @@
+// Purpose:
+// Check that a \DexExpectWatchValue float_range that is not large enough
+// detects unexpected watch values.
+//
+// UNSUPPORTED: system-darwin
+//
+// RUN: not %dexter_regression_test -- %s | FileCheck %s
+// CHECK: float_range_out_range.cpp:
+
+int main() {
+ float a = 1.0f;
+ a = a - 0.5f;
+ return a; //DexLabel('check')
+}
+
+// DexExpectWatchValue('a', '1.00000', from_line=ref('check1'), to_line=ref('check2'), float_range=0.4)
diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_zero_nonmatch.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_zero_nonmatch.cpp
new file mode 100644
index 000000000000..e7e04c9f98e6
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/penalty/float_range_zero_nonmatch.cpp
@@ -0,0 +1,15 @@
+// Purpose:
+// Check that \DexExpectWatchValue float_range=0.0 matches only exact
+// values.
+//
+// UNSUPPORTED: system-darwin
+//
+// RUN: not %dexter_regression_test -- %s | FileCheck %s
+// CHECK: float_range_zero_nonmatch.cpp:
+
+int main() {
+ float a = 1.0f;
+ return a; //DexLabel('check')
+}
+
+// DexExpectWatchValue('a', '1.0000001', on_line=ref('check'), float_range=0.0)
diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_multiple.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_multiple.cpp
new file mode 100644
index 000000000000..5ca1c7425a18
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_multiple.cpp
@@ -0,0 +1,18 @@
+// Purpose:
+// Check that \DexExpectWatchValue float_range=0.5 considers a range
+// difference of 0.49999 to be an expected watch value for multple values.
+//
+// UNSUPPORTED: system-darwin
+//
+// RUN: %dexter_regression_test -- %s | FileCheck %s
+// CHECK: float_range_multiple.cpp:
+
+int main() {
+ float a = 1.0f;
+ float b = 100.f;
+ a = a + 0.4999f;
+ a = a + b; // DexLabel('check1')
+ return a; //DexLabel('check2')
+}
+
+// DexExpectWatchValue('a', '1.0', '100.0', from_line=ref('check1'), to_line=ref('check2'), float_range=0.5)
diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_no_arg.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_no_arg.cpp
new file mode 100644
index 000000000000..b9e1d229f198
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_no_arg.cpp
@@ -0,0 +1,16 @@
+// Purpose:
+// Check that omitted float_range from \DexExpectWatchValue turns off
+// the floating point range evalution and defaults back to
+// pre-float evalution.
+//
+// UNSUPPORTED: system-darwin
+//
+// RUN: %dexter_regression_test -- %s | FileCheck %s
+// CHECK: float_range_no_arg.cpp:
+
+int main() {
+ float a = 1.0f;
+ return a; //DexLabel('check')
+}
+
+// DexExpectWatchValue('a', '1.00000', on_line=ref('check'))
diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_small.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_small.cpp
new file mode 100644
index 000000000000..6a844e7da2cd
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_small.cpp
@@ -0,0 +1,16 @@
+// Purpose:
+// Check that \DexExpectWatchValue float_range=0.5 considers a range
+// difference of 0.49999 to be an expected watch value.
+//
+// UNSUPPORTED: system-darwin
+//
+// RUN: %dexter_regression_test -- %s | FileCheck %s
+// CHECK: float_range_small.cpp:
+
+int main() {
+ float a = 1.0f;
+ a = a - 0.49999f;
+ return a; //DexLabel('check')
+}
+
+// DexExpectWatchValue('a', '1.0', on_line=ref('check'), float_range=0.5)
diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_zero_match.cpp b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_zero_match.cpp
new file mode 100644
index 000000000000..7dbd515e717b
--- /dev/null
+++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/commands/perfect/float_range_watch/float_range_zero_match.cpp
@@ -0,0 +1,14 @@
+// Purpose:
+// Check that \DexExpectWatchValue float_range=0.0 matches exact values.
+//
+// UNSUPPORTED: system-darwin
+//
+// RUN: %dexter_regression_test -- %s | FileCheck %s
+// CHECK: float_range_zero_match.cpp:
+
+int main() {
+ float a = 1.0f;
+ return a; //DexLabel('check')
+}
+
+// DexExpectWatchValue('a', '1.0000000', on_line=ref('check'), float_range=0.0)