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