1""" 2Test lldb-vscode setBreakpoints request 3""" 4 5 6import unittest2 7import vscode 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11import lldbvscode_testcase 12import os 13 14 15class TestVSCode_launch(lldbvscode_testcase.VSCodeTestCaseBase): 16 17 mydir = TestBase.compute_mydir(__file__) 18 19 @skipIfWindows 20 @skipIfDarwin # Flaky 21 def test_default(self): 22 ''' 23 Tests the default launch of a simple program. No arguments, 24 environment, or anything else is specified. 25 ''' 26 program = self.getBuildArtifact("a.out") 27 self.build_and_launch(program) 28 self.continue_to_exit() 29 # Now get the STDOUT and verify our program argument is correct 30 output = self.get_stdout() 31 self.assertTrue(output and len(output) > 0, 32 "expect program output") 33 lines = output.splitlines() 34 self.assertTrue(program in lines[0], 35 "make sure program path is in first argument") 36 37 @skipIfWindows 38 def test_stopOnEntry(self): 39 ''' 40 Tests the default launch of a simple program that stops at the 41 entry point instead of continuing. 42 ''' 43 program = self.getBuildArtifact("a.out") 44 self.build_and_launch(program, stopOnEntry=True) 45 self.set_function_breakpoints(['main']) 46 stopped_events = self.continue_to_next_stop() 47 for stopped_event in stopped_events: 48 if 'body' in stopped_event: 49 body = stopped_event['body'] 50 if 'reason' in body: 51 reason = body['reason'] 52 self.assertTrue( 53 reason != 'breakpoint', 54 'verify stop isn\'t "main" breakpoint') 55 56 @skipIfWindows 57 def test_cwd(self): 58 ''' 59 Tests the default launch of a simple program with a current working 60 directory. 61 ''' 62 program = self.getBuildArtifact("a.out") 63 program_parent_dir = os.path.realpath( 64 os.path.dirname(os.path.dirname(program))) 65 self.build_and_launch(program, 66 cwd=program_parent_dir) 67 self.continue_to_exit() 68 # Now get the STDOUT and verify our program argument is correct 69 output = self.get_stdout() 70 self.assertTrue(output and len(output) > 0, 71 "expect program output") 72 lines = output.splitlines() 73 found = False 74 for line in lines: 75 if line.startswith('cwd = \"'): 76 quote_path = '"%s"' % (program_parent_dir) 77 found = True 78 self.assertTrue(quote_path in line, 79 "working directory '%s' not in '%s'" % ( 80 program_parent_dir, line)) 81 self.assertTrue(found, "verified program working directory") 82 83 @skipIfWindows 84 def test_debuggerRoot(self): 85 ''' 86 Tests the "debuggerRoot" will change the working directory of 87 the lldb-vscode debug adaptor. 88 ''' 89 program = self.getBuildArtifact("a.out") 90 program_parent_dir = os.path.realpath( 91 os.path.dirname(os.path.dirname(program))) 92 commands = ['platform shell echo cwd = $PWD'] 93 self.build_and_launch(program, 94 debuggerRoot=program_parent_dir, 95 initCommands=commands) 96 output = self.get_console() 97 self.assertTrue(output and len(output) > 0, 98 "expect console output") 99 lines = output.splitlines() 100 prefix = 'cwd = ' 101 found = False 102 for line in lines: 103 if line.startswith(prefix): 104 found = True 105 self.assertEquals(program_parent_dir, line[len(prefix):], 106 "lldb-vscode working dir '%s' == '%s'" % ( 107 program_parent_dir, line[6:])) 108 self.assertTrue(found, "verified lldb-vscode working directory") 109 self.continue_to_exit() 110 111 @skipIfWindows 112 def test_sourcePath(self): 113 ''' 114 Tests the "sourcePath" will set the target.source-map. 115 ''' 116 program = self.getBuildArtifact("a.out") 117 program_dir = os.path.dirname(program) 118 self.build_and_launch(program, 119 sourcePath=program_dir) 120 output = self.get_console() 121 self.assertTrue(output and len(output) > 0, 122 "expect console output") 123 lines = output.splitlines() 124 prefix = '(lldb) settings set target.source-map "." ' 125 found = False 126 for line in lines: 127 if line.startswith(prefix): 128 found = True 129 quoted_path = '"%s"' % (program_dir) 130 self.assertEquals(quoted_path, line[len(prefix):], 131 "lldb-vscode working dir %s == %s" % ( 132 quoted_path, line[6:])) 133 self.assertTrue(found, 'found "sourcePath" in console output') 134 self.continue_to_exit() 135 136 @skipIfWindows 137 def test_disableSTDIO(self): 138 ''' 139 Tests the default launch of a simple program with STDIO disabled. 140 ''' 141 program = self.getBuildArtifact("a.out") 142 self.build_and_launch(program, 143 disableSTDIO=True) 144 self.continue_to_exit() 145 # Now get the STDOUT and verify our program argument is correct 146 output = self.get_stdout() 147 self.assertEquals(output, None, 148 "expect no program output") 149 150 @skipIfWindows 151 @skipIfLinux # shell argument expansion doesn't seem to work on Linux 152 @expectedFailureNetBSD 153 def test_shellExpandArguments_enabled(self): 154 ''' 155 Tests the default launch of a simple program with shell expansion 156 enabled. 157 ''' 158 program = self.getBuildArtifact("a.out") 159 program_dir = os.path.dirname(program) 160 glob = os.path.join(program_dir, '*.out') 161 self.build_and_launch(program, args=[glob], shellExpandArguments=True) 162 self.continue_to_exit() 163 # Now get the STDOUT and verify our program argument is correct 164 output = self.get_stdout() 165 self.assertTrue(output and len(output) > 0, 166 "expect no program output") 167 lines = output.splitlines() 168 for line in lines: 169 quote_path = '"%s"' % (program) 170 if line.startswith("arg[1] ="): 171 self.assertTrue(quote_path in line, 172 'verify "%s" expanded to "%s"' % ( 173 glob, program)) 174 175 @skipIfWindows 176 def test_shellExpandArguments_disabled(self): 177 ''' 178 Tests the default launch of a simple program with shell expansion 179 disabled. 180 ''' 181 program = self.getBuildArtifact("a.out") 182 program_dir = os.path.dirname(program) 183 glob = os.path.join(program_dir, '*.out') 184 self.build_and_launch(program, 185 args=[glob], 186 shellExpandArguments=False) 187 self.continue_to_exit() 188 # Now get the STDOUT and verify our program argument is correct 189 output = self.get_stdout() 190 self.assertTrue(output and len(output) > 0, 191 "expect no program output") 192 lines = output.splitlines() 193 for line in lines: 194 quote_path = '"%s"' % (glob) 195 if line.startswith("arg[1] ="): 196 self.assertTrue(quote_path in line, 197 'verify "%s" stayed to "%s"' % ( 198 glob, glob)) 199 200 @skipIfWindows 201 def test_args(self): 202 ''' 203 Tests launch of a simple program with arguments 204 ''' 205 program = self.getBuildArtifact("a.out") 206 args = ["one", "with space", "'with single quotes'", 207 '"with double quotes"'] 208 self.build_and_launch(program, 209 args=args) 210 self.continue_to_exit() 211 212 # Now get the STDOUT and verify our arguments got passed correctly 213 output = self.get_stdout() 214 self.assertTrue(output and len(output) > 0, 215 "expect program output") 216 lines = output.splitlines() 217 # Skip the first argument that contains the program name 218 lines.pop(0) 219 # Make sure arguments we specified are correct 220 for (i, arg) in enumerate(args): 221 quoted_arg = '"%s"' % (arg) 222 self.assertTrue(quoted_arg in lines[i], 223 'arg[%i] "%s" not in "%s"' % (i+1, quoted_arg, lines[i])) 224 225 @skipIfWindows 226 def test_environment(self): 227 ''' 228 Tests launch of a simple program with environment variables 229 ''' 230 program = self.getBuildArtifact("a.out") 231 env = ["NO_VALUE", "WITH_VALUE=BAR", "EMPTY_VALUE=", 232 "SPACE=Hello World"] 233 self.build_and_launch(program, 234 env=env) 235 self.continue_to_exit() 236 237 # Now get the STDOUT and verify our arguments got passed correctly 238 output = self.get_stdout() 239 self.assertTrue(output and len(output) > 0, 240 "expect program output") 241 lines = output.splitlines() 242 # Skip the all arguments so we have only environment vars left 243 while len(lines) and lines[0].startswith("arg["): 244 lines.pop(0) 245 # Make sure each environment variable in "env" is actually set in the 246 # program environment that was printed to STDOUT 247 for var in env: 248 found = False 249 for program_var in lines: 250 if var in program_var: 251 found = True 252 break 253 self.assertTrue(found, 254 '"%s" must exist in program environment (%s)' % ( 255 var, lines)) 256 257 @skipIfWindows 258 def test_commands(self): 259 ''' 260 Tests the "initCommands", "preRunCommands", "stopCommands" and 261 "exitCommands" that can be passed during launch. 262 263 "initCommands" are a list of LLDB commands that get executed 264 before the targt is created. 265 "preRunCommands" are a list of LLDB commands that get executed 266 after the target has been created and before the launch. 267 "stopCommands" are a list of LLDB commands that get executed each 268 time the program stops. 269 "exitCommands" are a list of LLDB commands that get executed when 270 the process exits 271 ''' 272 program = self.getBuildArtifact("a.out") 273 initCommands = ['target list', 'platform list'] 274 preRunCommands = ['image list a.out', 'image dump sections a.out'] 275 stopCommands = ['frame variable', 'bt'] 276 exitCommands = ['expr 2+3', 'expr 3+4'] 277 self.build_and_launch(program, 278 initCommands=initCommands, 279 preRunCommands=preRunCommands, 280 stopCommands=stopCommands, 281 exitCommands=exitCommands) 282 283 # Get output from the console. This should contain both the 284 # "initCommands" and the "preRunCommands". 285 output = self.get_console() 286 # Verify all "initCommands" were found in console output 287 self.verify_commands('initCommands', output, initCommands) 288 # Verify all "preRunCommands" were found in console output 289 self.verify_commands('preRunCommands', output, preRunCommands) 290 291 source = 'main.c' 292 first_line = line_number(source, '// breakpoint 1') 293 second_line = line_number(source, '// breakpoint 2') 294 lines = [first_line, second_line] 295 296 # Set 2 breakoints so we can verify that "stopCommands" get run as the 297 # breakpoints get hit 298 breakpoint_ids = self.set_source_breakpoints(source, lines) 299 self.assertEquals(len(breakpoint_ids), len(lines), 300 "expect correct number of breakpoints") 301 302 # Continue after launch and hit the first breakpoint. 303 # Get output from the console. This should contain both the 304 # "stopCommands" that were run after the first breakpoint was hit 305 self.continue_to_breakpoints(breakpoint_ids) 306 output = self.get_console(timeout=1.0) 307 self.verify_commands('stopCommands', output, stopCommands) 308 309 # Continue again and hit the second breakpoint. 310 # Get output from the console. This should contain both the 311 # "stopCommands" that were run after the second breakpoint was hit 312 self.continue_to_breakpoints(breakpoint_ids) 313 output = self.get_console(timeout=1.0) 314 self.verify_commands('stopCommands', output, stopCommands) 315 316 # Continue until the program exits 317 self.continue_to_exit() 318 # Get output from the console. This should contain both the 319 # "exitCommands" that were run after the second breakpoint was hit 320 output = self.get_console(timeout=1.0) 321 self.verify_commands('exitCommands', output, exitCommands) 322 323 @skipIfWindows 324 def test_extra_launch_commands(self): 325 ''' 326 Tests the "luanchCommands" with extra launching settings 327 ''' 328 self.build_and_create_debug_adaptor() 329 program = self.getBuildArtifact("a.out") 330 331 source = 'main.c' 332 first_line = line_number(source, '// breakpoint 1') 333 second_line = line_number(source, '// breakpoint 2') 334 # Set target binary and 2 breakoints 335 # then we can varify the "launchCommands" get run 336 # also we can verify that "stopCommands" get run as the 337 # breakpoints get hit 338 launchCommands = [ 339 'target create "%s"' % (program), 340 'br s -f main.c -l %d' % first_line, 341 'br s -f main.c -l %d' % second_line, 342 'process launch --stop-at-entry' 343 ] 344 345 initCommands = ['target list', 'platform list'] 346 preRunCommands = ['image list a.out', 'image dump sections a.out'] 347 stopCommands = ['frame variable', 'bt'] 348 exitCommands = ['expr 2+3', 'expr 3+4'] 349 self.launch(program, 350 initCommands=initCommands, 351 preRunCommands=preRunCommands, 352 stopCommands=stopCommands, 353 exitCommands=exitCommands, 354 launchCommands=launchCommands) 355 356 # Get output from the console. This should contain both the 357 # "initCommands" and the "preRunCommands". 358 output = self.get_console() 359 # Verify all "initCommands" were found in console output 360 self.verify_commands('initCommands', output, initCommands) 361 # Verify all "preRunCommands" were found in console output 362 self.verify_commands('preRunCommands', output, preRunCommands) 363 364 # Verify all "launchCommands" were founc in console output 365 # After execution, program should launch 366 self.verify_commands('launchCommands', output, launchCommands) 367 # Verify the "stopCommands" here 368 self.continue_to_next_stop() 369 output = self.get_console(timeout=1.0) 370 self.verify_commands('stopCommands', output, stopCommands) 371 372 # Continue and hit the second breakpoint. 373 # Get output from the console. This should contain both the 374 # "stopCommands" that were run after the first breakpoint was hit 375 self.continue_to_next_stop() 376 output = self.get_console(timeout=1.0) 377 self.verify_commands('stopCommands', output, stopCommands) 378 379 # Continue until the program exits 380 self.continue_to_exit() 381 # Get output from the console. This should contain both the 382 # "exitCommands" that were run after the second breakpoint was hit 383 output = self.get_console(timeout=1.0) 384 self.verify_commands('exitCommands', output, exitCommands) 385