1""" 2Test display and Python APIs on file and class static variables. 3""" 4 5 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 12 13class StaticVariableTestCase(TestBase): 14 15 def setUp(self): 16 # Call super's setUp(). 17 TestBase.setUp(self) 18 # Find the line number to break at. 19 self.line = line_number('main.cpp', '// Set break point at this line.') 20 21 def test_with_run_command(self): 22 """Test that file and class static variables display correctly.""" 23 self.build() 24 self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) 25 26 lldbutil.run_break_set_by_file_and_line( 27 self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) 28 29 self.runCmd("run", RUN_SUCCEEDED) 30 31 # The stop reason of the thread should be breakpoint. 32 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 33 substrs=['stopped', 34 'stop reason = breakpoint']) 35 36 # Global variables are no longer displayed with the "frame variable" 37 # command. 38 self.expect( 39 'target variable A::g_points', 40 VARIABLES_DISPLAYED_CORRECTLY, 41 patterns=['\(PointType\[[1-9]*\]\) A::g_points = {']) 42 self.expect('target variable g_points', VARIABLES_DISPLAYED_CORRECTLY, 43 substrs=['(PointType[2]) g_points']) 44 45 # On Mac OS X, gcc 4.2 emits the wrong debug info for A::g_points. 46 # A::g_points is an array of two elements. 47 if self.platformIsDarwin() or self.getPlatform() == "linux": 48 self.expect( 49 "target variable A::g_points[1].x", 50 VARIABLES_DISPLAYED_CORRECTLY, 51 startstr="(int) A::g_points[1].x = 11") 52 53 @expectedFailureAll( 54 compiler=["gcc"], 55 bugnumber="Compiler emits incomplete debug info") 56 @expectedFailureAll( 57 compiler=["clang"], 58 compiler_version=["<", "3.9"], 59 bugnumber='llvm.org/pr20550') 60 def test_with_run_command_complete(self): 61 """ 62 Test that file and class static variables display correctly with 63 complete debug information. 64 """ 65 self.build() 66 target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) 67 self.assertTrue(target, VALID_TARGET) 68 69 # Global variables are no longer displayed with the "frame variable" 70 # command. 71 self.expect( 72 'target variable A::g_points', 73 VARIABLES_DISPLAYED_CORRECTLY, 74 patterns=[ 75 '\(PointType\[[1-9]*\]\) A::g_points = {', '(x = 1, y = 2)', 76 '(x = 11, y = 22)' 77 ]) 78 79 # Ensure that we take the context into account and only print 80 # A::g_points. 81 self.expect( 82 'target variable A::g_points', 83 VARIABLES_DISPLAYED_CORRECTLY, 84 matching=False, 85 patterns=['(x = 3, y = 4)', '(x = 33, y = 44)']) 86 87 # Finally, ensure that we print both points when not specifying a 88 # context. 89 self.expect( 90 'target variable g_points', 91 VARIABLES_DISPLAYED_CORRECTLY, 92 substrs=[ 93 '(PointType[2]) g_points', '(x = 1, y = 2)', 94 '(x = 11, y = 22)', '(x = 3, y = 4)', '(x = 33, y = 44)' 95 ]) 96 97 @expectedFailureAll( 98 compiler=["gcc"], 99 bugnumber="Compiler emits incomplete debug info") 100 @expectedFailureAll( 101 compiler=["clang"], 102 compiler_version=["<", "3.9"], 103 bugnumber='llvm.org/pr20550') 104 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764") 105 @add_test_categories(['pyapi']) 106 def test_with_python_api(self): 107 """Test Python APIs on file and class static variables.""" 108 self.build() 109 exe = self.getBuildArtifact("a.out") 110 111 target = self.dbg.CreateTarget(exe) 112 self.assertTrue(target, VALID_TARGET) 113 114 breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line) 115 self.assertTrue(breakpoint, VALID_BREAKPOINT) 116 117 # Now launch the process, and do not stop at entry point. 118 process = target.LaunchSimple( 119 None, None, self.get_process_working_directory()) 120 self.assertTrue(process, PROCESS_IS_VALID) 121 122 # The stop reason of the thread should be breakpoint. 123 thread = lldbutil.get_stopped_thread( 124 process, lldb.eStopReasonBreakpoint) 125 self.assertIsNotNone(thread) 126 127 # Get the SBValue of 'A::g_points' and 'g_points'. 128 frame = thread.GetFrameAtIndex(0) 129 130 # arguments => False 131 # locals => False 132 # statics => True 133 # in_scope_only => False 134 valList = frame.GetVariables(False, False, True, False) 135 136 for val in valList: 137 self.DebugSBValue(val) 138 name = val.GetName() 139 self.assertIn(name, ['g_points', 'A::g_points']) 140 if name == 'g_points': 141 self.assertEqual( 142 val.GetValueType(), lldb.eValueTypeVariableStatic) 143 self.assertEqual(val.GetNumChildren(), 2) 144 elif name == 'A::g_points': 145 self.assertEqual( 146 val.GetValueType(), lldb.eValueTypeVariableGlobal) 147 self.assertEqual(val.GetNumChildren(), 2) 148 child1 = val.GetChildAtIndex(1) 149 self.DebugSBValue(child1) 150 child1_x = child1.GetChildAtIndex(0) 151 self.DebugSBValue(child1_x) 152 self.assertEqual(child1_x.GetTypeName(), 'int') 153 self.assertEqual(child1_x.GetValue(), '11') 154 155 # SBFrame.FindValue() should also work. 156 val = frame.FindValue("A::g_points", lldb.eValueTypeVariableGlobal) 157 self.DebugSBValue(val) 158 self.assertEqual(val.GetName(), 'A::g_points') 159 160 # Also exercise the "parameter" and "local" scopes while we are at it. 161 val = frame.FindValue("argc", lldb.eValueTypeVariableArgument) 162 self.DebugSBValue(val) 163 self.assertEqual(val.GetName(), 'argc') 164 165 val = frame.FindValue("argv", lldb.eValueTypeVariableArgument) 166 self.DebugSBValue(val) 167 self.assertEqual(val.GetName(), 'argv') 168 169 val = frame.FindValue("hello_world", lldb.eValueTypeVariableLocal) 170 self.DebugSBValue(val) 171 self.assertEqual(val.GetName(), 'hello_world') 172