1"""
2Tests imported namespaces in C++.
3"""
4import lldb
5from lldbsuite.test.decorators import *
6from lldbsuite.test.lldbtest import *
7from lldbsuite.test import lldbutil
8
9
10class TestCppNsImport(TestBase):
11
12    def test_with_run_command(self):
13        """Tests imported namespaces in C++."""
14        self.build()
15
16        # Get main source file
17        src_file = os.path.join(self.getSourceDir(), "main.cpp")
18        src_file_spec = lldb.SBFileSpec(src_file)
19        self.assertTrue(src_file_spec.IsValid(), "Main source file")
20
21        # Get the path of the executable
22        exe_path = self.getBuildArtifact("a.out")
23
24        # Load the executable
25        target = self.dbg.CreateTarget(exe_path)
26        self.assertTrue(target.IsValid(), VALID_TARGET)
27
28        # Break on main function
29        break_0 = target.BreakpointCreateBySourceRegex(
30            "// break 0", src_file_spec)
31        self.assertTrue(
32            break_0.IsValid() and break_0.GetNumLocations() >= 1,
33            VALID_BREAKPOINT)
34        break_1 = target.BreakpointCreateBySourceRegex(
35            "// break 1", src_file_spec)
36        self.assertTrue(
37            break_1.IsValid() and break_1.GetNumLocations() >= 1,
38            VALID_BREAKPOINT)
39
40        # Launch the process
41        args = None
42        env = None
43        process = target.LaunchSimple(
44            args, env, self.get_process_working_directory())
45        self.assertTrue(process.IsValid(), PROCESS_IS_VALID)
46
47        # Get the thread of the process
48        self.assertEqual(
49            process.GetState(), lldb.eStateStopped,
50            PROCESS_STOPPED)
51        thread = lldbutil.get_stopped_thread(
52            process, lldb.eStopReasonBreakpoint)
53
54        # Get current fream of the thread at the breakpoint
55        frame = thread.GetSelectedFrame()
56
57        # Test imported namespaces
58        test_result = frame.EvaluateExpression("n")
59        self.assertTrue(
60            test_result.IsValid() and test_result.GetValueAsSigned() == 1,
61            "n = 1")
62
63        test_result = frame.EvaluateExpression("N::n")
64        self.assertTrue(
65            test_result.IsValid() and test_result.GetValueAsSigned() == 1,
66            "N::n = 1")
67
68        test_result = frame.EvaluateExpression("nested")
69        self.assertTrue(
70            test_result.IsValid() and test_result.GetValueAsSigned() == 3,
71            "nested = 3")
72
73        test_result = frame.EvaluateExpression("anon")
74        self.assertTrue(
75            test_result.IsValid() and test_result.GetValueAsSigned() == 2,
76            "anon = 2")
77
78        test_result = frame.EvaluateExpression("global")
79        self.assertTrue(
80            test_result.IsValid() and test_result.GetValueAsSigned() == 4,
81            "global = 4")
82
83        test_result = frame.EvaluateExpression("fun_var")
84        self.assertTrue(
85            test_result.IsValid() and test_result.GetValueAsSigned() == 9,
86            "fun_var = 9")
87
88        test_result = frame.EvaluateExpression("Fun::fun_var")
89        self.assertTrue(
90            test_result.IsValid() and test_result.GetValueAsSigned() == 0,
91            "Fun::fun_var = 0")
92
93        test_result = frame.EvaluateExpression("not_imported")
94        self.assertTrue(
95            test_result.IsValid() and test_result.GetValueAsSigned() == 35,
96            "not_imported = 35")
97
98        # Currently there is no way to distinguish between "::imported" and "imported" in ClangExpressionDeclMap so this fails
99        #test_result = frame.EvaluateExpression("::imported")
100        #self.assertTrue(test_result.IsValid() and test_result.GetValueAsSigned() == 89, "::imported = 89")
101
102        test_result = frame.EvaluateExpression("Imported::imported")
103        self.assertTrue(
104            test_result.IsValid() and test_result.GetValueAsSigned() == 99,
105            "Imported::imported = 99")
106
107        test_result = frame.EvaluateExpression("imported")
108        self.assertTrue(
109            test_result.IsValid() and test_result.GetValueAsSigned() == 99,
110            "imported = 99")
111
112        test_result = frame.EvaluateExpression("single")
113        self.assertTrue(
114            test_result.IsValid() and test_result.GetValueAsSigned() == 3,
115            "single = 3")
116
117        # Continue to second breakpoint
118        process.Continue()
119
120        # Get the thread of the process
121        self.assertEqual(
122            process.GetState(), lldb.eStateStopped,
123            PROCESS_STOPPED)
124        thread = lldbutil.get_stopped_thread(
125            process, lldb.eStopReasonBreakpoint)
126
127        # Get current fream of the thread at the breakpoint
128        frame = thread.GetSelectedFrame()
129
130        # Test function inside namespace
131        test_result = frame.EvaluateExpression("fun_var")
132        self.assertTrue(
133            test_result.IsValid() and test_result.GetValueAsSigned() == 5,
134            "fun_var = 5")
135