199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest breakpoint conditions with 'breakpoint modify -c <expr> id'.
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprechtimport lldb
699451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
799451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
899451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
999451b44SJordan Rupprecht
1099451b44SJordan Rupprecht
1199451b44SJordan Rupprechtclass BreakpointConditionsTestCase(TestBase):
1299451b44SJordan Rupprecht    def test_breakpoint_condition_and_run_command(self):
1399451b44SJordan Rupprecht        """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'."""
1499451b44SJordan Rupprecht        self.build()
1599451b44SJordan Rupprecht        self.breakpoint_conditions()
1699451b44SJordan Rupprecht
1799451b44SJordan Rupprecht    def test_breakpoint_condition_inline_and_run_command(self):
1899451b44SJordan Rupprecht        """Exercise breakpoint condition inline with 'breakpoint set'."""
1999451b44SJordan Rupprecht        self.build()
2099451b44SJordan Rupprecht        self.breakpoint_conditions(inline=True)
2199451b44SJordan Rupprecht
222238dcc3SJonas Devlieghere    @add_test_categories(["pyapi"])
2399451b44SJordan Rupprecht    def test_breakpoint_condition_and_python_api(self):
2499451b44SJordan Rupprecht        """Use Python APIs to set breakpoint conditions."""
2599451b44SJordan Rupprecht        self.build()
2699451b44SJordan Rupprecht        self.breakpoint_conditions_python()
2799451b44SJordan Rupprecht
282238dcc3SJonas Devlieghere    @add_test_categories(["pyapi"])
2999451b44SJordan Rupprecht    def test_breakpoint_invalid_condition_and_python_api(self):
3099451b44SJordan Rupprecht        """Use Python APIs to set breakpoint conditions."""
3199451b44SJordan Rupprecht        self.build()
3299451b44SJordan Rupprecht        self.breakpoint_invalid_conditions_python()
3399451b44SJordan Rupprecht
3499451b44SJordan Rupprecht    def setUp(self):
3599451b44SJordan Rupprecht        # Call super's setUp().
3699451b44SJordan Rupprecht        TestBase.setUp(self)
3799451b44SJordan Rupprecht        # Find the line number to of function 'c'.
3899451b44SJordan Rupprecht        self.line1 = line_number(
392238dcc3SJonas Devlieghere            "main.c", '// Find the line number of function "c" here.'
402238dcc3SJonas Devlieghere        )
4199451b44SJordan Rupprecht        self.line2 = line_number(
422238dcc3SJonas Devlieghere            "main.c", "// Find the line number of c's parent call here."
432238dcc3SJonas Devlieghere        )
4499451b44SJordan Rupprecht
4599451b44SJordan Rupprecht    def breakpoint_conditions(self, inline=False):
4699451b44SJordan Rupprecht        """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'."""
4799451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
4899451b44SJordan Rupprecht        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
4999451b44SJordan Rupprecht
5099451b44SJordan Rupprecht        if inline:
5199451b44SJordan Rupprecht            # Create a breakpoint by function name 'c' and set the condition.
5299451b44SJordan Rupprecht            lldbutil.run_break_set_by_symbol(
5399451b44SJordan Rupprecht                self,
5499451b44SJordan Rupprecht                "c",
5599451b44SJordan Rupprecht                extra_options="-c 'val == 3'",
5699451b44SJordan Rupprecht                num_expected_locations=1,
572238dcc3SJonas Devlieghere                sym_exact=True,
582238dcc3SJonas Devlieghere            )
5999451b44SJordan Rupprecht        else:
6099451b44SJordan Rupprecht            # Create a breakpoint by function name 'c'.
6199451b44SJordan Rupprecht            lldbutil.run_break_set_by_symbol(
622238dcc3SJonas Devlieghere                self, "c", num_expected_locations=1, sym_exact=True
632238dcc3SJonas Devlieghere            )
6499451b44SJordan Rupprecht
6599451b44SJordan Rupprecht            # And set a condition on the breakpoint to stop on when 'val == 3'.
6699451b44SJordan Rupprecht            self.runCmd("breakpoint modify -c 'val == 3' 1")
6799451b44SJordan Rupprecht
6899451b44SJordan Rupprecht        # Now run the program.
6999451b44SJordan Rupprecht        self.runCmd("run", RUN_SUCCEEDED)
7099451b44SJordan Rupprecht
7199451b44SJordan Rupprecht        # The process should be stopped at this point.
722238dcc3SJonas Devlieghere        self.expect("process status", PROCESS_STOPPED, patterns=["Process .* stopped"])
7399451b44SJordan Rupprecht
7499451b44SJordan Rupprecht        # 'frame variable --show-types val' should return 3 due to breakpoint condition.
7599451b44SJordan Rupprecht        self.expect(
7699451b44SJordan Rupprecht            "frame variable --show-types val",
7799451b44SJordan Rupprecht            VARIABLES_DISPLAYED_CORRECTLY,
782238dcc3SJonas Devlieghere            startstr="(int) val = 3",
792238dcc3SJonas Devlieghere        )
8099451b44SJordan Rupprecht
8199451b44SJordan Rupprecht        # Also check the hit count, which should be 3, by design.
822238dcc3SJonas Devlieghere        self.expect(
832238dcc3SJonas Devlieghere            "breakpoint list -f",
842238dcc3SJonas Devlieghere            BREAKPOINT_HIT_ONCE,
852238dcc3SJonas Devlieghere            substrs=["resolved = 1", "Condition: val == 3", "hit count = 1"],
862238dcc3SJonas Devlieghere        )
8799451b44SJordan Rupprecht
8899451b44SJordan Rupprecht        # The frame #0 should correspond to main.c:36, the executable statement
8999451b44SJordan Rupprecht        # in function name 'c'.  And the parent frame should point to
9099451b44SJordan Rupprecht        # main.c:24.
912238dcc3SJonas Devlieghere        self.expect(
922238dcc3SJonas Devlieghere            "thread backtrace",
932238dcc3SJonas Devlieghere            STOPPED_DUE_TO_BREAKPOINT_CONDITION,
9499451b44SJordan Rupprecht            # substrs = ["stop reason = breakpoint"],
952238dcc3SJonas Devlieghere            patterns=[
962238dcc3SJonas Devlieghere                "frame #0.*main.c:%d" % self.line1,
972238dcc3SJonas Devlieghere                "frame #1.*main.c:%d" % self.line2,
982238dcc3SJonas Devlieghere            ],
992238dcc3SJonas Devlieghere        )
10099451b44SJordan Rupprecht
10199451b44SJordan Rupprecht        # Test that "breakpoint modify -c ''" clears the condition for the last
10299451b44SJordan Rupprecht        # created breakpoint, so that when the breakpoint hits, val == 1.
10399451b44SJordan Rupprecht        self.runCmd("process kill")
10499451b44SJordan Rupprecht        self.runCmd("breakpoint modify -c ''")
10599451b44SJordan Rupprecht        self.expect(
10699451b44SJordan Rupprecht            "breakpoint list -f",
10799451b44SJordan Rupprecht            BREAKPOINT_STATE_CORRECT,
10899451b44SJordan Rupprecht            matching=False,
1092238dcc3SJonas Devlieghere            substrs=["Condition:"],
1102238dcc3SJonas Devlieghere        )
11199451b44SJordan Rupprecht
11299451b44SJordan Rupprecht        # Now run the program again.
11399451b44SJordan Rupprecht        self.runCmd("run", RUN_SUCCEEDED)
11499451b44SJordan Rupprecht
11599451b44SJordan Rupprecht        # The process should be stopped at this point.
1162238dcc3SJonas Devlieghere        self.expect("process status", PROCESS_STOPPED, patterns=["Process .* stopped"])
11799451b44SJordan Rupprecht
11899451b44SJordan Rupprecht        # 'frame variable --show-types val' should return 1 since it is the first breakpoint hit.
11999451b44SJordan Rupprecht        self.expect(
12099451b44SJordan Rupprecht            "frame variable --show-types val",
12199451b44SJordan Rupprecht            VARIABLES_DISPLAYED_CORRECTLY,
1222238dcc3SJonas Devlieghere            startstr="(int) val = 1",
1232238dcc3SJonas Devlieghere        )
12499451b44SJordan Rupprecht
12599451b44SJordan Rupprecht        self.runCmd("process kill")
12699451b44SJordan Rupprecht
12799451b44SJordan Rupprecht    def breakpoint_conditions_python(self):
12899451b44SJordan Rupprecht        """Use Python APIs to set breakpoint conditions."""
12954c26872SRaphael Isemann        target = self.createTestTarget()
13099451b44SJordan Rupprecht
13199451b44SJordan Rupprecht        # Now create a breakpoint on main.c by name 'c'.
1322238dcc3SJonas Devlieghere        breakpoint = target.BreakpointCreateByName("c", "a.out")
133b321b429SJonas Devlieghere        self.trace("breakpoint:", breakpoint)
1342238dcc3SJonas Devlieghere        self.assertTrue(
1352238dcc3SJonas Devlieghere            breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT
1362238dcc3SJonas Devlieghere        )
13799451b44SJordan Rupprecht
13899451b44SJordan Rupprecht        # We didn't associate a thread index with the breakpoint, so it should
13999451b44SJordan Rupprecht        # be invalid.
1402238dcc3SJonas Devlieghere        self.assertEqual(
1412238dcc3SJonas Devlieghere            breakpoint.GetThreadIndex(),
1422238dcc3SJonas Devlieghere            lldb.UINT32_MAX,
1432238dcc3SJonas Devlieghere            "The thread index should be invalid",
1442238dcc3SJonas Devlieghere        )
14599451b44SJordan Rupprecht        # The thread name should be invalid, too.
1469c246882SJordan Rupprecht        self.assertIsNone(
1479c246882SJordan Rupprecht            breakpoint.GetThreadName(), "The thread name should be invalid"
1482238dcc3SJonas Devlieghere        )
14999451b44SJordan Rupprecht
15099451b44SJordan Rupprecht        # Let's set the thread index for this breakpoint and verify that it is,
15199451b44SJordan Rupprecht        # indeed, being set correctly.
15299451b44SJordan Rupprecht        # There's only one thread for the process.
15399451b44SJordan Rupprecht        breakpoint.SetThreadIndex(1)
1542238dcc3SJonas Devlieghere        self.assertEqual(
1552238dcc3SJonas Devlieghere            breakpoint.GetThreadIndex(), 1, "The thread index has been set correctly"
1562238dcc3SJonas Devlieghere        )
15799451b44SJordan Rupprecht
15899451b44SJordan Rupprecht        # Get the breakpoint location from breakpoint after we verified that,
15999451b44SJordan Rupprecht        # indeed, it has one location.
16099451b44SJordan Rupprecht        location = breakpoint.GetLocationAtIndex(0)
1612238dcc3SJonas Devlieghere        self.assertTrue(location and location.IsEnabled(), VALID_BREAKPOINT_LOCATION)
16299451b44SJordan Rupprecht
16399451b44SJordan Rupprecht        # Set the condition on the breakpoint location.
1642238dcc3SJonas Devlieghere        location.SetCondition("val == 3")
1652238dcc3SJonas Devlieghere        self.expect(location.GetCondition(), exe=False, startstr="val == 3")
16699451b44SJordan Rupprecht
16799451b44SJordan Rupprecht        # Now launch the process, and do not stop at entry point.
1682238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
16999451b44SJordan Rupprecht        self.assertTrue(process, PROCESS_IS_VALID)
17099451b44SJordan Rupprecht
17199451b44SJordan Rupprecht        # Frame #0 should be on self.line1 and the break condition should hold.
17299451b44SJordan Rupprecht        from lldbsuite.test.lldbutil import get_stopped_thread
1732238dcc3SJonas Devlieghere
17499451b44SJordan Rupprecht        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
17599451b44SJordan Rupprecht        self.assertTrue(
17699451b44SJordan Rupprecht            thread.IsValid(),
1772238dcc3SJonas Devlieghere            "There should be a thread stopped due to breakpoint condition",
1782238dcc3SJonas Devlieghere        )
179*3c3851f3SKendal Harland
18099451b44SJordan Rupprecht        frame0 = thread.GetFrameAtIndex(0)
1812238dcc3SJonas Devlieghere        var = frame0.FindValue("val", lldb.eValueTypeVariableArgument)
182*3c3851f3SKendal Harland        self.assertEqual(
183*3c3851f3SKendal Harland            frame0.GetLineEntry().GetLine(),
184*3c3851f3SKendal Harland            self.line1,
185*3c3851f3SKendal Harland            "The debugger stopped on the correct line",
1862238dcc3SJonas Devlieghere        )
187*3c3851f3SKendal Harland        self.assertEqual(var.GetValue(), "3")
18899451b44SJordan Rupprecht
18999451b44SJordan Rupprecht        # The hit count for the breakpoint should be 1.
190619e2e09SDave Lee        self.assertEqual(breakpoint.GetHitCount(), 1)
19199451b44SJordan Rupprecht
19299451b44SJordan Rupprecht        # Test that the condition expression didn't create a result variable:
19399451b44SJordan Rupprecht        options = lldb.SBExpressionOptions()
19499451b44SJordan Rupprecht        value = frame0.EvaluateExpression("$0", options)
1952238dcc3SJonas Devlieghere        self.assertTrue(
1962238dcc3SJonas Devlieghere            value.GetError().Fail(), "Conditions should not make result variables."
1972238dcc3SJonas Devlieghere        )
19899451b44SJordan Rupprecht        process.Continue()
19999451b44SJordan Rupprecht
20099451b44SJordan Rupprecht    def breakpoint_invalid_conditions_python(self):
20199451b44SJordan Rupprecht        """Use Python APIs to set breakpoint conditions."""
20299451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
20399451b44SJordan Rupprecht
20499451b44SJordan Rupprecht        # Create a target by the debugger.
20599451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
20699451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
20799451b44SJordan Rupprecht
20899451b44SJordan Rupprecht        # Now create a breakpoint on main.c by name 'c'.
2092238dcc3SJonas Devlieghere        breakpoint = target.BreakpointCreateByName("c", "a.out")
210b321b429SJonas Devlieghere        self.trace("breakpoint:", breakpoint)
2112238dcc3SJonas Devlieghere        self.assertTrue(
2122238dcc3SJonas Devlieghere            breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT
2132238dcc3SJonas Devlieghere        )
21499451b44SJordan Rupprecht
21599451b44SJordan Rupprecht        # Set the condition on the breakpoint.
2162238dcc3SJonas Devlieghere        breakpoint.SetCondition("no_such_variable == not_this_one_either")
2172238dcc3SJonas Devlieghere        self.expect(
2182238dcc3SJonas Devlieghere            breakpoint.GetCondition(),
2192238dcc3SJonas Devlieghere            exe=False,
2202238dcc3SJonas Devlieghere            startstr="no_such_variable == not_this_one_either",
2212238dcc3SJonas Devlieghere        )
22299451b44SJordan Rupprecht
22399451b44SJordan Rupprecht        # Now launch the process, and do not stop at entry point.
2242238dcc3SJonas Devlieghere        process = target.LaunchSimple(None, None, self.get_process_working_directory())
22599451b44SJordan Rupprecht        self.assertTrue(process, PROCESS_IS_VALID)
22699451b44SJordan Rupprecht
22799451b44SJordan Rupprecht        # Frame #0 should be on self.line1 and the break condition should hold.
22899451b44SJordan Rupprecht        from lldbsuite.test.lldbutil import get_stopped_thread
2292238dcc3SJonas Devlieghere
23099451b44SJordan Rupprecht        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
23199451b44SJordan Rupprecht        self.assertTrue(
23299451b44SJordan Rupprecht            thread.IsValid(),
2332238dcc3SJonas Devlieghere            "There should be a thread stopped due to breakpoint condition",
2342238dcc3SJonas Devlieghere        )
23599451b44SJordan Rupprecht        frame0 = thread.GetFrameAtIndex(0)
2362238dcc3SJonas Devlieghere        var = frame0.FindValue("val", lldb.eValueTypeVariableArgument)
237619e2e09SDave Lee        self.assertEqual(frame0.GetLineEntry().GetLine(), self.line1)
23899451b44SJordan Rupprecht
23999451b44SJordan Rupprecht        # The hit count for the breakpoint should be 1.
240619e2e09SDave Lee        self.assertEqual(breakpoint.GetHitCount(), 1)
241