1"""
2Test lldb data formatter subsystem.
3"""
4
5import lldb
6from lldbsuite.test.decorators import *
7from lldbsuite.test.lldbtest import *
8from lldbsuite.test import lldbutil
9
10
11class DataFormatterSynthValueTestCase(TestBase):
12    def setUp(self):
13        # Call super's setUp().
14        TestBase.setUp(self)
15        # Find the line number to break at.
16        self.line = line_number("main.cpp", "break here")
17
18    @expectedFailureAll(bugnumber="llvm.org/pr50814", compiler="gcc")
19    def test_with_run_command(self):
20        """Test using Python synthetic children provider to provide a value."""
21        self.build()
22        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
23
24        lldbutil.run_break_set_by_file_and_line(
25            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True
26        )
27
28        self.runCmd("run", RUN_SUCCEEDED)
29
30        # The stop reason of the thread should be breakpoint.
31        self.expect(
32            "thread list",
33            STOPPED_DUE_TO_BREAKPOINT,
34            substrs=["stopped", "stop reason = breakpoint"],
35        )
36
37        # This is the function to remove the custom formats in order to have a
38        # clean slate for the next test case.
39        def cleanup():
40            self.runCmd("type format clear", check=False)
41            self.runCmd("type summary clear", check=False)
42            self.runCmd("type filter clear", check=False)
43            self.runCmd("type synth clear", check=False)
44
45        # Execute the cleanup function during test case tear down.
46        self.addTearDownHook(cleanup)
47
48        x = self.frame().FindVariable("x")
49        x.SetPreferSyntheticValue(True)
50        y = self.frame().FindVariable("y")
51        y.SetPreferSyntheticValue(True)
52        z = self.frame().FindVariable("z")
53        z.SetPreferSyntheticValue(True)
54        q = self.frame().FindVariable("q")
55        z.SetPreferSyntheticValue(True)
56
57        x_val = x.GetValueAsUnsigned
58        y_val = y.GetValueAsUnsigned
59        z_val = z.GetValueAsUnsigned
60        q_val = q.GetValueAsUnsigned
61
62        if self.TraceOn():
63            print(
64                "x_val = %s; y_val = %s; z_val = %s; q_val = %s"
65                % (x_val(), y_val(), z_val(), q_val())
66            )
67
68        self.assertNotEqual(x_val(), 3, "x == 3 before synthetics")
69        self.assertNotEqual(y_val(), 4, "y == 4 before synthetics")
70        self.assertNotEqual(z_val(), 7, "z == 7 before synthetics")
71        self.assertNotEqual(q_val(), 8, "q == 8 before synthetics")
72
73        # now set up the synth
74        self.runCmd("script from myIntSynthProvider import *")
75        self.runCmd("type synth add -l myIntSynthProvider myInt")
76        self.runCmd("type synth add -l myArraySynthProvider myArray")
77        self.runCmd("type synth add -l myIntSynthProvider myIntAndStuff")
78
79        if self.TraceOn():
80            print(
81                "x_val = %s; y_val = %s; z_val = %s; q_val = %s"
82                % (x_val(), y_val(), z_val(), q_val())
83            )
84
85        self.assertEqual(x_val(), 3, "x != 3 after synthetics")
86        self.assertEqual(y_val(), 4, "y != 4 after synthetics")
87        self.assertEqual(z_val(), 7, "z != 7 after synthetics")
88        self.assertEqual(q_val(), 8, "q != 8 after synthetics")
89
90        self.expect("frame variable x", substrs=["3"])
91        self.expect("frame variable x", substrs=["theValue = 3"], matching=False)
92        self.expect("frame variable q", substrs=["8"])
93        self.expect("frame variable q", substrs=["theValue = 8"], matching=False)
94
95        # check that an aptly defined synthetic provider does not affect
96        # one-lining
97        if not self.isAArch64Windows():
98            self.expect(
99                "expression struct Struct { myInt theInt{12}; }; Struct()",
100                substrs=["(theInt = 12)"],
101            )
102
103        # check that we can use a synthetic value in a summary
104        self.runCmd("type summary add hasAnInt -s ${var.theInt}")
105        hi = self.frame().FindVariable("hi")
106        self.assertEqual(hi.GetSummary(), "42")
107
108        ma = self.frame().FindVariable("ma")
109        self.assertTrue(ma.IsValid())
110        self.assertEqual(ma.GetNumChildren(15), 15)
111        self.assertEqual(ma.GetNumChildren(16), 16)
112        self.assertEqual(ma.GetNumChildren(17), 16)
113