571 lines · python
1"""2Test some target commands: create, list, select, variable.3"""4 5import os6import stat7import tempfile8 9import lldb10from lldbsuite.test.decorators import *11from lldbsuite.test.lldbtest import *12from lldbsuite.test import lldbutil13 14 15class targetCommandTestCase(TestBase):16 def setUp(self):17 # Call super's setUp().18 TestBase.setUp(self)19 # Find the line numbers for our breakpoints.20 self.line_b = line_number("b.c", "// Set break point at this line.")21 self.line_c = line_number("c.c", "// Set break point at this line.")22 23 def buildB(self):24 db = {"C_SOURCES": "b.c", "EXE": self.getBuildArtifact("b.out")}25 self.build(dictionary=db)26 self.addTearDownCleanup(dictionary=db)27 28 def buildAll(self):29 da = {"C_SOURCES": "a.c", "EXE": self.getBuildArtifact("a.out")}30 self.build(dictionary=da)31 self.addTearDownCleanup(dictionary=da)32 33 self.buildB()34 35 dc = {"C_SOURCES": "c.c", "EXE": self.getBuildArtifact("c.out")}36 self.build(dictionary=dc)37 self.addTearDownCleanup(dictionary=dc)38 39 def test_target_command(self):40 """Test some target commands: create, list, select."""41 self.buildAll()42 self.do_target_command()43 44 @skipIfDarwin # Chained Fixups45 def test_target_variable_command(self):46 """Test 'target variable' command before and after starting the inferior."""47 d = {"C_SOURCES": "globals.c", "EXE": self.getBuildArtifact("globals")}48 self.build(dictionary=d)49 self.addTearDownCleanup(dictionary=d)50 51 self.do_target_variable_command("globals")52 53 @skipIfDarwin # Chained Fixups54 def test_target_variable_command_no_fail(self):55 """Test 'target variable' command before and after starting the inferior."""56 d = {"C_SOURCES": "globals.c", "EXE": self.getBuildArtifact("globals")}57 self.build(dictionary=d)58 self.addTearDownCleanup(dictionary=d)59 60 self.do_target_variable_command_no_fail("globals")61 62 def do_target_command(self):63 """Exercise 'target create', 'target list', 'target select' commands."""64 exe_a = self.getBuildArtifact("a.out")65 exe_b = self.getBuildArtifact("b.out")66 exe_c = self.getBuildArtifact("c.out")67 68 self.runCmd("target list")69 output = self.res.GetOutput()70 if output.startswith("No targets"):71 # We start from index 0.72 base = 073 else:74 # Find the largest index of the existing list.75 import re76 77 pattern = re.compile(r"target #(\d+):")78 for line in reversed(output.split(os.linesep)):79 match = pattern.search(line)80 if match:81 # We will start from (index + 1) ....82 base = int(match.group(1), 10) + 183 self.trace("base is:", base)84 break85 86 self.runCmd("target create " + exe_a, CURRENT_EXECUTABLE_SET)87 self.runCmd("run", RUN_SUCCEEDED)88 89 self.runCmd("target create " + exe_b, CURRENT_EXECUTABLE_SET)90 lldbutil.run_break_set_by_file_and_line(91 self, "b.c", self.line_b, num_expected_locations=1, loc_exact=True92 )93 self.runCmd("run", RUN_SUCCEEDED)94 95 self.runCmd("target create " + exe_c, CURRENT_EXECUTABLE_SET)96 lldbutil.run_break_set_by_file_and_line(97 self, "c.c", self.line_c, num_expected_locations=1, loc_exact=True98 )99 self.runCmd("run", RUN_SUCCEEDED)100 101 self.runCmd("target list")102 103 self.runCmd("target select %d" % base)104 self.runCmd("thread backtrace")105 106 self.runCmd("target select %d" % (base + 2))107 self.expect(108 "thread backtrace",109 STOPPED_DUE_TO_BREAKPOINT,110 substrs=["stop reason = breakpoint", "c.c:%d" % self.line_c],111 )112 113 self.runCmd("target select %d" % (base + 1))114 self.expect(115 "thread backtrace",116 STOPPED_DUE_TO_BREAKPOINT,117 substrs=["stop reason = breakpoint", "b.c:%d" % self.line_b],118 )119 120 self.runCmd("target list")121 122 @no_debug_info_test123 def test_target_create_invalid_arch(self):124 exe = self.getBuildArtifact("a.out")125 self.expect(126 "target create {} --arch doesntexist".format(exe),127 error=True,128 patterns=["error: invalid triple 'doesntexist'"],129 )130 131 @no_debug_info_test132 def test_target_create_platform(self):133 self.buildB()134 exe = self.getBuildArtifact("b.out")135 self.expect("target create {} --platform host".format(exe))136 137 @no_debug_info_test138 def test_target_create_unsupported_platform(self):139 yaml = os.path.join(self.getSourceDir(), "bogus.yaml")140 exe = self.getBuildArtifact("bogus")141 self.yaml2obj(yaml, exe)142 self.expect(143 "target create {}".format(exe),144 error=True,145 patterns=["error: no matching platforms found for this file"],146 )147 148 @no_debug_info_test149 def test_target_create_invalid_platform(self):150 self.buildB()151 exe = self.getBuildArtifact("b.out")152 self.expect(153 "target create {} --platform doesntexist".format(exe),154 error=True,155 patterns=[156 'error: unable to find a plug-in for the platform named "doesntexist"'157 ],158 )159 160 def do_target_variable_command(self, exe_name):161 """Exercise 'target variable' command before and after starting the inferior."""162 self.runCmd("file " + self.getBuildArtifact(exe_name), CURRENT_EXECUTABLE_SET)163 164 self.expect(165 "target variable my_global_char",166 VARIABLES_DISPLAYED_CORRECTLY,167 substrs=["my_global_char", "'X'"],168 )169 self.expect(170 "target variable my_global_str",171 VARIABLES_DISPLAYED_CORRECTLY,172 substrs=["my_global_str", '"abc"'],173 )174 self.expect(175 "target variable my_static_int",176 VARIABLES_DISPLAYED_CORRECTLY,177 substrs=["my_static_int", "228"],178 )179 self.expect(180 "target variable my_global_str_ptr", matching=False, substrs=['"abc"']181 )182 self.expect(183 "target variable *my_global_str_ptr", matching=True, substrs=['"abc"']184 )185 self.expect(186 "target variable *my_global_str",187 VARIABLES_DISPLAYED_CORRECTLY,188 substrs=["a"],189 )190 191 self.runCmd("b main")192 self.runCmd("run")193 194 self.expect(195 "target variable my_global_str",196 VARIABLES_DISPLAYED_CORRECTLY,197 substrs=["my_global_str", '"abc"'],198 )199 self.expect(200 "target variable my_static_int",201 VARIABLES_DISPLAYED_CORRECTLY,202 substrs=["my_static_int", "228"],203 )204 self.expect(205 "target variable my_global_str_ptr", matching=False, substrs=['"abc"']206 )207 self.expect(208 "target variable *my_global_str_ptr", matching=True, substrs=['"abc"']209 )210 self.expect(211 "target variable *my_global_str",212 VARIABLES_DISPLAYED_CORRECTLY,213 substrs=["a"],214 )215 self.expect(216 "target variable my_global_char",217 VARIABLES_DISPLAYED_CORRECTLY,218 substrs=["my_global_char", "'X'"],219 )220 221 self.runCmd("c")222 223 self.expect(224 "target variable my_global_str",225 VARIABLES_DISPLAYED_CORRECTLY,226 substrs=["my_global_str", '"abc"'],227 )228 self.expect(229 "target variable my_static_int",230 VARIABLES_DISPLAYED_CORRECTLY,231 substrs=["my_static_int", "228"],232 )233 self.expect(234 "target variable my_global_str_ptr", matching=False, substrs=['"abc"']235 )236 self.expect(237 "target variable *my_global_str_ptr", matching=True, substrs=['"abc"']238 )239 self.expect(240 "target variable *my_global_str",241 VARIABLES_DISPLAYED_CORRECTLY,242 substrs=["a"],243 )244 self.expect(245 "target variable my_global_char",246 VARIABLES_DISPLAYED_CORRECTLY,247 substrs=["my_global_char", "'X'"],248 )249 250 def do_target_variable_command_no_fail(self, exe_name):251 """Exercise 'target variable' command before and after starting the inferior."""252 self.runCmd("file " + self.getBuildArtifact(exe_name), CURRENT_EXECUTABLE_SET)253 254 self.expect(255 "target variable my_global_char",256 VARIABLES_DISPLAYED_CORRECTLY,257 substrs=["my_global_char", "'X'"],258 )259 self.expect(260 "target variable my_global_str",261 VARIABLES_DISPLAYED_CORRECTLY,262 substrs=["my_global_str", '"abc"'],263 )264 self.expect(265 "target variable my_static_int",266 VARIABLES_DISPLAYED_CORRECTLY,267 substrs=["my_static_int", "228"],268 )269 self.expect(270 "target variable my_global_str_ptr", matching=False, substrs=['"abc"']271 )272 self.expect(273 "target variable *my_global_str_ptr", matching=True, substrs=['"abc"']274 )275 self.expect(276 "target variable *my_global_str",277 VARIABLES_DISPLAYED_CORRECTLY,278 substrs=["a"],279 )280 281 self.runCmd("b main")282 self.runCmd("run")283 284 # New feature: you don't need to specify the variable(s) to 'target vaiable'.285 # It will find all the global and static variables in the current286 # compile unit.287 self.expect(288 "target variable",289 ordered=False,290 substrs=[291 "my_global_char",292 "my_static_int",293 "my_global_str",294 "my_global_str_ptr",295 ],296 )297 298 self.expect(299 "target variable my_global_str",300 VARIABLES_DISPLAYED_CORRECTLY,301 substrs=["my_global_str", '"abc"'],302 )303 self.expect(304 "target variable my_static_int",305 VARIABLES_DISPLAYED_CORRECTLY,306 substrs=["my_static_int", "228"],307 )308 self.expect(309 "target variable my_global_str_ptr", matching=False, substrs=['"abc"']310 )311 self.expect(312 "target variable *my_global_str_ptr", matching=True, substrs=['"abc"']313 )314 self.expect(315 "target variable *my_global_str",316 VARIABLES_DISPLAYED_CORRECTLY,317 substrs=["a"],318 )319 self.expect(320 "target variable my_global_char",321 VARIABLES_DISPLAYED_CORRECTLY,322 substrs=["my_global_char", "'X'"],323 )324 325 @no_debug_info_test326 def test_target_stop_hook_disable_enable(self):327 self.buildB()328 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)329 330 self.expect(331 "target stop-hook disable 1",332 error=True,333 substrs=['unknown stop hook id: "1"'],334 )335 self.expect(336 "target stop-hook disable blub",337 error=True,338 substrs=['invalid stop hook id: "blub"'],339 )340 self.expect(341 "target stop-hook enable 1",342 error=True,343 substrs=['unknown stop hook id: "1"'],344 )345 self.expect(346 "target stop-hook enable blub",347 error=True,348 substrs=['invalid stop hook id: "blub"'],349 )350 351 @no_debug_info_test352 def test_target_stop_hook_delete(self):353 self.buildB()354 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)355 356 self.expect(357 "target stop-hook delete 1",358 error=True,359 substrs=['unknown stop hook id: "1"'],360 )361 self.expect(362 "target stop-hook delete blub",363 error=True,364 substrs=['invalid stop hook id: "blub"'],365 )366 367 @no_debug_info_test368 def test_target_list_args(self):369 self.expect(370 "target list blub",371 error=True,372 substrs=["'target list' doesn't take any arguments"],373 )374 375 @no_debug_info_test376 def test_target_select_no_index(self):377 self.expect(378 "target select",379 error=True,380 substrs=["'target select' takes a single argument: a target index"],381 )382 383 @no_debug_info_test384 def test_target_select_invalid_index(self):385 self.runCmd("target delete --all")386 self.expect(387 "target select 0",388 error=True,389 substrs=["index 0 is out of range since there are no active targets"],390 )391 self.buildB()392 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)393 self.expect(394 "target select 1",395 error=True,396 substrs=["index 1 is out of range, valid target indexes are 0 - 0"],397 )398 399 @no_debug_info_test400 def test_target_create_multiple_args(self):401 self.expect(402 "target create a b",403 error=True,404 substrs=["'target create' takes exactly one executable path"],405 )406 407 @skipIfWindowsAndNonEnglish408 @no_debug_info_test409 def test_target_create_nonexistent_core_file(self):410 self.expect(411 "target create -c doesntexist",412 error=True,413 patterns=[414 "Cannot open 'doesntexist'",415 ": (No such file or directory|The system cannot find the file specified)",416 ],417 )418 419 # Write only files don't seem to be supported on Windows.420 @skipIf(hostoslist=["windows"])421 @no_debug_info_test422 def test_target_create_unreadable_core_file(self):423 tf = tempfile.NamedTemporaryFile()424 os.chmod(tf.name, stat.S_IWRITE)425 self.expect(426 "target create -c '" + tf.name + "'",427 error=True,428 substrs=["Cannot open '", "': Permission denied"],429 )430 431 @skipIfWindowsAndNonEnglish432 @no_debug_info_test433 def test_target_create_nonexistent_sym_file(self):434 self.expect(435 "target create -s doesntexist doesntexisteither",436 error=True,437 patterns=[438 "Cannot open '",439 ": (No such file or directory|The system cannot find the file specified)",440 ],441 )442 443 @skipIf(hostoslist=["windows"])444 @no_debug_info_test445 def test_target_create_invalid_core_file(self):446 invalid_core_path = os.path.join(self.getSourceDir(), "invalid_core_file")447 self.expect(448 "target create -c '" + invalid_core_path + "'",449 error=True,450 substrs=["Unknown core file format '"],451 )452 453 # Write only files don't seem to be supported on Windows.454 @skipIf(hostoslist=["windows"])455 @no_debug_info_test456 def test_target_create_unreadable_sym_file(self):457 tf = tempfile.NamedTemporaryFile()458 os.chmod(tf.name, stat.S_IWRITE)459 self.expect(460 "target create -s '" + tf.name + "' no_exe",461 error=True,462 substrs=["Cannot open '", "': Permission denied"],463 )464 465 @no_debug_info_test466 def test_target_delete_all(self):467 self.buildAll()468 self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)469 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)470 self.expect("target delete --all")471 self.expect("target list", substrs=["No targets."])472 473 @no_debug_info_test474 def test_target_delete_by_index(self):475 self.buildAll()476 self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)477 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)478 self.runCmd("file " + self.getBuildArtifact("c.out"), CURRENT_EXECUTABLE_SET)479 self.expect(480 "target delete 3",481 error=True,482 substrs=["target index 3 is out of range, valid target indexes are 0 - 2"],483 )484 485 self.runCmd("target delete 1")486 self.expect("target list", matching=False, substrs=["b.out"])487 self.runCmd("target delete 1")488 self.expect("target list", matching=False, substrs=["c.out"])489 490 self.expect(491 "target delete 1",492 error=True,493 substrs=["target index 1 is out of range, the only valid index is 0"],494 )495 496 self.runCmd("target delete 0")497 self.expect("target list", matching=False, substrs=["a.out"])498 499 self.expect("target delete 0", error=True, substrs=["no targets to delete"])500 self.expect("target delete 1", error=True, substrs=["no targets to delete"])501 502 @no_debug_info_test503 def test_target_delete_by_index_multiple(self):504 self.buildAll()505 self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)506 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)507 self.runCmd("file " + self.getBuildArtifact("c.out"), CURRENT_EXECUTABLE_SET)508 509 self.expect(510 "target delete 0 1 2 3",511 error=True,512 substrs=["target index 3 is out of range, valid target indexes are 0 - 2"],513 )514 self.expect("target list", substrs=["a.out", "b.out", "c.out"])515 516 self.runCmd("target delete 0 1 2")517 self.expect("target list", matching=False, substrs=["a.out", "c.out"])518 519 @no_debug_info_test520 def test_target_delete_selected(self):521 self.buildAll()522 self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)523 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)524 self.runCmd("file " + self.getBuildArtifact("c.out"), CURRENT_EXECUTABLE_SET)525 self.runCmd("target select 1")526 self.runCmd("target delete")527 self.expect("target list", matching=False, substrs=["b.out"])528 self.runCmd("target delete")529 self.runCmd("target delete")530 self.expect("target list", substrs=["No targets."])531 self.expect(532 "target delete", error=True, substrs=["no target is currently selected"]533 )534 535 @no_debug_info_test536 def test_target_modules_search_paths_clear(self):537 self.buildB()538 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)539 self.runCmd("target modules search-paths add foo bar")540 self.runCmd("target modules search-paths add foz baz")541 self.runCmd("target modules search-paths clear")542 self.expect("target list", matching=False, substrs=["bar", "baz"])543 544 @no_debug_info_test545 def test_target_modules_search_paths_query(self):546 self.buildB()547 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)548 self.runCmd("target modules search-paths add foo bar")549 self.expect("target modules search-paths query foo", substrs=["bar"])550 # Query something that doesn't exist.551 self.expect("target modules search-paths query faz", substrs=["faz"])552 553 # Invalid arguments.554 self.expect(555 "target modules search-paths query faz baz",556 error=True,557 substrs=["query requires one argument"],558 )559 560 @no_debug_info_test561 @expectedFailureAll(562 oslist=["freebsd"], bugnumber="github.com/llvm/llvm-project/issues/56079"563 )564 def test_target_modules_type(self):565 self.buildB()566 self.runCmd("file " + self.getBuildArtifact("b.out"), CURRENT_EXECUTABLE_SET)567 self.expect(568 "target modules lookup --type int",569 substrs=["1 match found", 'name = "int"'],570 )571