1"""
2Test top-level expressions.
3"""
4
5
6
7import unittest2
8
9import lldb
10from lldbsuite.test.decorators import *
11from lldbsuite.test.lldbtest import *
12from lldbsuite.test import lldbutil
13
14
15class TopLevelExpressionsTestCase(TestBase):
16
17    def setUp(self):
18        # Call super's setUp().
19        TestBase.setUp(self)
20        # Find the line number to break for main.c.
21        self.line = line_number('main.cpp',
22                                '// Set breakpoint here')
23        self.dummy_line = line_number('dummy.cpp',
24                                      '// Set breakpoint here')
25
26        # Disable confirmation prompt to avoid infinite wait
27        self.runCmd("settings set auto-confirm true")
28        self.addTearDownHook(
29            lambda: self.runCmd("settings clear auto-confirm"))
30
31    def build_and_run(self):
32        """Test top-level expressions."""
33        self.build()
34
35        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
36
37        lldbutil.run_break_set_by_file_and_line(
38            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False)
39
40        self.runCmd("run", RUN_SUCCEEDED)
41
42    def run_dummy(self):
43        self.runCmd("file " + self.getBuildArtifact("dummy"),
44                    CURRENT_EXECUTABLE_SET)
45
46        lldbutil.run_break_set_by_file_and_line(
47            self,
48            "dummy.cpp",
49            self.dummy_line,
50            num_expected_locations=1,
51            loc_exact=False)
52
53        self.runCmd("run", RUN_SUCCEEDED)
54
55    @add_test_categories(['pyapi'])
56    @skipIf(debug_info="gmodules")  # not relevant
57    @skipIf(oslist=["windows"])  # Error in record layout on Windows
58    def test_top_level_expressions(self):
59        self.build_and_run()
60
61        resultFromCode = self.frame().EvaluateExpression("doTest()").GetValueAsUnsigned()
62
63        self.runCmd("kill")
64
65        self.run_dummy()
66
67        codeFile = open('test.cpp', 'r')
68
69        expressions = []
70        current_expression = ""
71
72        for line in codeFile:
73            if line.startswith("// --"):
74                expressions.append(current_expression)
75                current_expression = ""
76            else:
77                current_expression += line
78
79        options = lldb.SBExpressionOptions()
80        options.SetLanguage(lldb.eLanguageTypeC_plus_plus)
81        options.SetTopLevel(True)
82
83        for expression in expressions:
84            self.frame().EvaluateExpression(expression, options)
85
86        resultFromTopLevel = self.frame().EvaluateExpression("doTest()")
87
88        self.assertTrue(resultFromTopLevel.IsValid())
89        self.assertEqual(
90            resultFromCode,
91            resultFromTopLevel.GetValueAsUnsigned())
92
93        # Make sure the command line version works as well:
94        self.runCmd("expr --top-level -- int TopLevelFunction() { return 101; }")
95        resultFromTopLevel = self.frame().EvaluateExpression("TopLevelFunction()")
96        self.assertTrue(resultFromTopLevel.IsValid())
97        self.assertEqual(101, resultFromTopLevel.GetValueAsUnsigned(), "Command line version works.")
98
99    def test_top_level_expression_without_target(self):
100        self.expect("expr --top-level -- void func() {}", error=True,
101                    substrs=["Top-level code needs to be inserted into a runnable target"])
102
103        # FIXME: This doesn't actually generate any code, so LLDB should probably
104        # allow these expressions.
105        self.expect("expr --top-level -- template<typename T> struct StructT { T m; };", error=True,
106                    substrs=["Top-level code needs to be inserted into a runnable target"])
107        self.expect("expr --top-level -- struct Struct { int i; };", error=True,
108                    substrs=["Top-level code needs to be inserted into a runnable target"])
109