Commit 13f22f5d authored by Raphael Isemann's avatar Raphael Isemann
Browse files

[lldb] Add expect_expr function for testing expression evaluation in dotests.

Summary:
This patch adds a new function to lldbtest: `expect_expr`. This function is supposed to replace the current approach
of calling `expect`/`runCmd` with `expr`, `p` etc.

`expect_expr` allows evaluating expressions and matching their value/summary/type/error message without
having to do any string matching that might allow unintended passes (e.g., `self.expect("expr 3+4", substrs=["7"])`
can unexpectedly pass for results like `(Class7) $0 = 7`, `(int) $7 = 22`, `(int) $0 = 77` and so on).

This only uses the function in a few places to test and demonstrate it. I'll migrate the tests in follow up commits.

Reviewers: JDevlieghere, shafik, labath

Reviewed By: labath

Subscribers: christof, abidh, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D70314
parent 06cfcdcc
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ class ExprCommandCallBuiltinFunction(TestBase):

        # Test different builtin functions.

        self.expect("expr __builtin_isinf(0.0f)", substrs=["(int) $", " = 0\n"])
        self.expect("expr __builtin_isnormal(0.0f)", substrs=["(int) $", " = 0\n"])
        self.expect("expr __builtin_constant_p(1)", substrs=["(int) $", " = 1\n"])
        self.expect("expr __builtin_abs(-14)", substrs=["(int) $", " = 14\n"])
        self.expect_expr("__builtin_isinf(0.0f)", result_type="int", result_value="0")
        self.expect_expr("__builtin_isnormal(0.0f)", result_type="int", result_value="0")
        self.expect_expr("__builtin_constant_p(1)", result_type="int", result_value="1")
        self.expect_expr("__builtin_abs(-14)", result_type="int", result_value="14")
+2 −1
Original line number Diff line number Diff line
@@ -96,10 +96,11 @@ class LibcxxStringDataFormatterTestCase(TestBase):
            cappedSummary.find("someText") <= 0,
            "cappedSummary includes the full string")

        self.expect_expr("s", result_type=ns+"::wstring", result_summary='L"hello world! מזל טוב!"')

        self.expect(
            "frame variable",
            substrs=[
                '(%s::wstring) s = L"hello world! מזל טוב!"'%ns,
                '(%s::wstring) S = L"!!!!!"'%ns,
                '(const wchar_t *) mazeltov = 0x',
                'L"מזל טוב"',
+39 −0
Original line number Diff line number Diff line
@@ -2366,6 +2366,45 @@ FileCheck output:
        self.assertTrue(matched if matching else not matched,
                        msg if msg else EXP_MSG(str, output, exe))

    def expect_expr(
            self,
            expr,
            result_summary=None,
            result_value=None,
            result_type=None,
            error_msg=None,
            ):
        """
        Evaluates the given expression and verifies the result.
        :param expr: The expression as a string.
        :param result_summary: The summary that the expression should have. None if the summary should not be checked.
        :param result_value: The value that the expression should have. None if the value should not be checked.
        :param result_type: The type that the expression result should have. None if the type should not be checked.
        :param error_msg: The error message the expression should return. None if the error output should not be checked.
        """
        self.assertTrue(expr.strip() == expr, "Expression contains trailing/leading whitespace: '" + expr + "'")

        frame = self.frame()
        eval_result = frame.EvaluateExpression(expr)

        if error_msg:
            self.assertFalse(eval_result.IsValid())
            self.assertEqual(error_msg, eval_result.GetError().GetCString())
            return

        if not eval_result.GetError().Success():
            self.assertTrue(eval_result.GetError().Success(),
                "Unexpected failure with msg: " + eval_result.GetError().GetCString())

        if result_type:
            self.assertEqual(result_type, eval_result.GetTypeName())

        if result_value:
            self.assertEqual(result_value, eval_result.GetValue())

        if result_summary:
            self.assertEqual(result_summary, eval_result.GetSummary())

    def invoke(self, obj, name, trace=False):
        """Use reflection to call a method dynamically with no argument."""
        trace = (True if traceAlways else trace)