1172 lines · python
1"""2Test lldb settings command.3"""4 5import json6import os7import re8 9import lldb10from lldbsuite.test import lldbutil11from lldbsuite.test.decorators import *12from lldbsuite.test.lldbtest import *13 14 15class SettingsCommandTestCase(TestBase):16 NO_DEBUG_INFO_TESTCASE = True17 18 def test_apropos_should_also_search_settings_description(self):19 """Test that 'apropos' command should also search descriptions for the settings variables."""20 21 self.expect(22 "apropos 'environment variable'",23 substrs=[24 "target.env-vars",25 "environment variables",26 "executable's environment",27 ],28 )29 30 def test_set_interpreter_repeat_prev_command(self):31 """Test the `interpreter.repeat-previous-command` setting."""32 self.build()33 34 exe = self.getBuildArtifact("a.out")35 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)36 setting = "interpreter.repeat-previous-command"37 38 def cleanup(setting):39 self.runCmd("settings clear %s" % setting, check=False)40 41 # Execute the cleanup function during test case tear down.42 self.addTearDownHook(cleanup(setting))43 44 # First, check for the setting default value.45 self.expect(46 "setting show %s" % setting,47 substrs=["interpreter.repeat-previous-command (boolean) = true"],48 )49 50 # Then, invert the setting, and check that was set correctly51 self.runCmd("setting set %s false" % setting)52 self.expect(53 "setting show %s" % setting,54 substrs=["interpreter.repeat-previous-command (boolean) = false"],55 )56 57 ci = self.dbg.GetCommandInterpreter()58 self.assertTrue(ci.IsValid(), "Invalid command interpreter.")59 # Now, test the functionnality60 res = lldb.SBCommandReturnObject()61 ci.HandleCommand("breakpoint set -n main", res)62 self.assertTrue(res.Succeeded(), "Command failed.")63 ci.HandleCommand("", res)64 self.assertTrue(res.Succeeded(), "Empty command failed.")65 self.assertEqual(self.dbg.GetSelectedTarget().GetNumBreakpoints(), 1)66 67 def test_append_target_env_vars(self):68 """Test that 'append target.env-vars' works."""69 # Append the env-vars.70 self.runCmd("settings append target.env-vars MY_ENV_VAR=YES")71 # And add hooks to restore the settings during tearDown().72 self.addTearDownHook(lambda: self.runCmd("settings clear target.env-vars"))73 74 # Check it immediately!75 self.expect("settings show target.env-vars", substrs=["MY_ENV_VAR=YES"])76 77 def test_insert_before_and_after_target_run_args(self):78 """Test that 'insert-before/after target.run-args' works."""79 # Set the run-args first.80 self.runCmd("settings set target.run-args a b c")81 # And add hooks to restore the settings during tearDown().82 self.addTearDownHook(lambda: self.runCmd("settings clear target.run-args"))83 84 # Now insert-before the index-0 element with '__a__'.85 self.runCmd("settings insert-before target.run-args 0 __a__")86 # And insert-after the index-1 element with '__A__'.87 self.runCmd("settings insert-after target.run-args 1 __A__")88 # Check it immediately!89 self.expect(90 "settings show target.run-args",91 substrs=[92 "target.run-args",93 '[0]: "__a__"',94 '[1]: "a"',95 '[2]: "__A__"',96 '[3]: "b"',97 '[4]: "c"',98 ],99 )100 101 def test_replace_target_run_args(self):102 """Test that 'replace target.run-args' works."""103 # Set the run-args and then replace the index-0 element.104 self.runCmd("settings set target.run-args a b c")105 # And add hooks to restore the settings during tearDown().106 self.addTearDownHook(lambda: self.runCmd("settings clear target.run-args"))107 108 # Now replace the index-0 element with 'A', instead.109 self.runCmd("settings replace target.run-args 0 A")110 # Check it immediately!111 self.expect(112 "settings show target.run-args",113 substrs=[114 "target.run-args (arguments) =",115 '[0]: "A"',116 '[1]: "b"',117 '[2]: "c"',118 ],119 )120 121 def test_set_prompt(self):122 """Test that 'set prompt' actually changes the prompt."""123 124 # Set prompt to 'lldb2'.125 self.runCmd("settings set prompt 'lldb2 '")126 127 # Immediately test the setting.128 self.expect(129 "settings show prompt",130 SETTING_MSG("prompt"),131 startstr='prompt (string) = "lldb2 "',132 )133 134 # The overall display should also reflect the new setting.135 self.expect(136 "settings show",137 SETTING_MSG("prompt"),138 substrs=['prompt (string) = "lldb2 "'],139 )140 141 # Use '-r' option to reset to the original default prompt.142 self.runCmd("settings clear prompt")143 144 def test_set_term_width(self):145 """Test that 'set term-width' actually changes the term-width."""146 147 self.runCmd("settings set term-width 70")148 149 # Immediately test the setting.150 self.expect(151 "settings show term-width",152 SETTING_MSG("term-width"),153 startstr="term-width (unsigned) = 70",154 )155 156 # The overall display should also reflect the new setting.157 self.expect(158 "settings show",159 SETTING_MSG("term-width"),160 substrs=["term-width (unsigned) = 70"],161 )162 163 self.dbg.SetTerminalWidth(60)164 165 self.expect(166 "settings show",167 SETTING_MSG("term-width"),168 substrs=["term-width (unsigned) = 60"],169 )170 171 def test_set_frame_format(self):172 """Test that 'set frame-format' with a backtick char in the format string works as well as fullpath."""173 self.build()174 175 exe = self.getBuildArtifact("a.out")176 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)177 178 def cleanup():179 self.runCmd(180 "settings set frame-format %s" % self.format_string, check=False181 )182 183 # Execute the cleanup function during test case tear down.184 self.addTearDownHook(cleanup)185 186 self.runCmd("settings show frame-format")187 m = re.match(r'^frame-format \(format-string\) = "(.*)"$', self.res.GetOutput())188 self.assertTrue(m, "Bad settings string")189 self.format_string = m.group(1)190 191 # Change the default format to print function.name rather than192 # function.name-with-args193 format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}\\`${function.name}{${function.pc-offset}}}{ at ${line.file.fullpath}:${line.number}}{, lang=${language}}\n"194 self.runCmd("settings set frame-format %s" % format_string)195 196 # Immediately test the setting.197 self.expect(198 "settings show frame-format",199 SETTING_MSG("frame-format"),200 substrs=[format_string],201 )202 203 self.runCmd("breakpoint set -n main")204 self.runCmd(205 "process launch --working-dir '{0}'".format(206 self.get_process_working_directory()207 ),208 RUN_SUCCEEDED,209 )210 self.expect("thread backtrace", substrs=["`main", self.getSourceDir()])211 212 def test_set_auto_confirm(self):213 """Test that after 'set auto-confirm true', manual confirmation should not kick in."""214 self.build()215 216 exe = self.getBuildArtifact("a.out")217 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)218 219 self.runCmd("settings set auto-confirm true")220 221 # Immediately test the setting.222 self.expect(223 "settings show auto-confirm",224 SETTING_MSG("auto-confirm"),225 startstr="auto-confirm (boolean) = true",226 )227 228 # Now 'breakpoint delete' should just work fine without confirmation229 # prompt from the command interpreter.230 self.runCmd("breakpoint set -n main")231 self.expect("breakpoint delete", startstr="All breakpoints removed")232 233 # Restore the original setting of auto-confirm.234 self.runCmd("settings clear auto-confirm")235 self.expect(236 "settings show auto-confirm",237 SETTING_MSG("auto-confirm"),238 startstr="auto-confirm (boolean) = false",239 )240 241 @skipIf(archs=no_match(["x86_64", "i386", "i686"]))242 def test_disassembler_settings(self):243 """Test that user options for the disassembler take effect."""244 self.build()245 246 exe = self.getBuildArtifact("a.out")247 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)248 249 # AT&T syntax250 self.runCmd("settings set target.x86-disassembly-flavor att")251 self.runCmd("settings set target.use-hex-immediates false")252 self.expect("disassemble -n numberfn", substrs=["$90"])253 self.runCmd("settings set target.use-hex-immediates true")254 self.runCmd("settings set target.hex-immediate-style c")255 self.expect("disassemble -n numberfn", substrs=["$0x5a"])256 self.runCmd("settings set target.hex-immediate-style asm")257 self.expect("disassemble -n numberfn", substrs=["$5ah"])258 259 # Intel syntax260 self.runCmd("settings set target.x86-disassembly-flavor intel")261 self.runCmd("settings set target.use-hex-immediates false")262 self.expect("disassemble -n numberfn", substrs=["90"])263 self.runCmd("settings set target.use-hex-immediates true")264 self.runCmd("settings set target.hex-immediate-style c")265 self.expect("disassemble -n numberfn", substrs=["0x5a"])266 self.runCmd("settings set target.hex-immediate-style asm")267 self.expect("disassemble -n numberfn", substrs=["5ah"])268 269 @skipIfDarwinEmbedded # <rdar://problem/34446098> debugserver on ios etc can't write files270 def test_run_args_and_env_vars(self):271 self.do_test_run_args_and_env_vars(use_launchsimple=False)272 273 @skipIfDarwinEmbedded # <rdar://problem/34446098> debugserver on ios etc can't write files274 def test_launchsimple_args_and_env_vars(self):275 self.do_test_run_args_and_env_vars(use_launchsimple=True)276 277 def do_test_run_args_and_env_vars(self, use_launchsimple):278 """Test that run-args and env-vars are passed to the launched process."""279 self.build()280 281 # Set the run-args and the env-vars.282 # And add hooks to restore the settings during tearDown().283 self.runCmd("settings set target.run-args A B C")284 self.addTearDownHook(lambda: self.runCmd("settings clear target.run-args"))285 self.runCmd('settings set target.env-vars ["MY_ENV_VAR"]=YES')286 self.addTearDownHook(lambda: self.runCmd("settings clear target.env-vars"))287 288 exe = self.getBuildArtifact("a.out")289 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)290 291 target = self.dbg.GetTargetAtIndex(0)292 launch_info = target.GetLaunchInfo()293 found_env_var = False294 for i in range(0, launch_info.GetNumEnvironmentEntries()):295 if launch_info.GetEnvironmentEntryAtIndex(i) == "MY_ENV_VAR=YES":296 found_env_var = True297 break298 self.assertTrue(found_env_var, "MY_ENV_VAR was not set in LaunchInfo object")299 300 self.assertEqual(launch_info.GetNumArguments(), 3)301 self.assertEqual(launch_info.GetArgumentAtIndex(0), "A")302 self.assertEqual(launch_info.GetArgumentAtIndex(1), "B")303 self.assertEqual(launch_info.GetArgumentAtIndex(2), "C")304 305 self.expect("target show-launch-environment", substrs=["MY_ENV_VAR=YES"])306 307 wd = self.get_process_working_directory()308 if use_launchsimple:309 process = target.LaunchSimple(None, None, wd)310 self.assertTrue(process)311 else:312 self.runCmd("process launch --working-dir '{0}'".format(wd), RUN_SUCCEEDED)313 314 # Read the output file produced by running the program.315 output = lldbutil.read_file_from_process_wd(self, "output2.txt")316 317 self.expect(318 output,319 exe=False,320 substrs=[321 "argv[1] matches",322 "argv[2] matches",323 "argv[3] matches",324 "Environment variable 'MY_ENV_VAR' successfully passed.",325 ],326 )327 328 # Check that env-vars overrides unset-env-vars.329 self.runCmd("settings set target.unset-env-vars MY_ENV_VAR")330 331 self.expect(332 "target show-launch-environment",333 "env-vars overrides unset-env-vars",334 substrs=["MY_ENV_VAR=YES"],335 )336 337 wd = self.get_process_working_directory()338 if use_launchsimple:339 process = target.LaunchSimple(None, None, wd)340 self.assertTrue(process)341 else:342 self.runCmd("process launch --working-dir '{0}'".format(wd), RUN_SUCCEEDED)343 344 # Read the output file produced by running the program.345 output = lldbutil.read_file_from_process_wd(self, "output2.txt")346 347 self.expect(348 output,349 exe=False,350 substrs=["Environment variable 'MY_ENV_VAR' successfully passed."],351 )352 353 @skipIfRemote # it doesn't make sense to send host env to remote target354 def test_pass_host_env_vars(self):355 """Test that the host env vars are passed to the launched process."""356 self.build()357 358 # Set some host environment variables now.359 os.environ["MY_HOST_ENV_VAR1"] = "VAR1"360 os.environ["MY_HOST_ENV_VAR2"] = "VAR2"361 362 # This is the function to unset the two env variables set above.363 def unset_env_variables():364 os.environ.pop("MY_HOST_ENV_VAR1")365 os.environ.pop("MY_HOST_ENV_VAR2")366 367 self.addTearDownHook(unset_env_variables)368 369 exe = self.getBuildArtifact("a.out")370 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)371 372 # By default, inherit-env is 'true'.373 self.expect(374 "settings show target.inherit-env",375 "Default inherit-env is 'true'",376 startstr="target.inherit-env (boolean) = true",377 )378 379 self.expect(380 "target show-launch-environment",381 "Host environment is passed correctly",382 substrs=["MY_HOST_ENV_VAR1=VAR1", "MY_HOST_ENV_VAR2=VAR2"],383 )384 self.runCmd(385 "process launch --working-dir '{0}'".format(386 self.get_process_working_directory()387 ),388 RUN_SUCCEEDED,389 )390 391 # Read the output file produced by running the program.392 output = lldbutil.read_file_from_process_wd(self, "output1.txt")393 394 self.expect(395 output,396 exe=False,397 substrs=[398 "The host environment variable 'MY_HOST_ENV_VAR1' successfully passed.",399 "The host environment variable 'MY_HOST_ENV_VAR2' successfully passed.",400 ],401 )402 403 # Now test that we can prevent the inferior from inheriting the404 # environment.405 self.runCmd("settings set target.inherit-env false")406 407 self.expect(408 "target show-launch-environment",409 "target.inherit-env affects `target show-launch-environment`",410 matching=False,411 substrs=["MY_HOST_ENV_VAR1=VAR1", "MY_HOST_ENV_VAR2=VAR2"],412 )413 414 self.runCmd(415 "process launch --working-dir '{0}'".format(416 self.get_process_working_directory()417 ),418 RUN_SUCCEEDED,419 )420 421 # Read the output file produced by running the program.422 output = lldbutil.read_file_from_process_wd(self, "output1.txt")423 424 self.expect(425 output,426 exe=False,427 matching=False,428 substrs=[429 "The host environment variable 'MY_HOST_ENV_VAR1' successfully passed.",430 "The host environment variable 'MY_HOST_ENV_VAR2' successfully passed.",431 ],432 )433 434 # Now test that we can unset variables from the inherited environment.435 self.runCmd("settings set target.inherit-env true")436 self.runCmd("settings set target.unset-env-vars MY_HOST_ENV_VAR1")437 self.runCmd(438 "process launch --working-dir '{0}'".format(439 self.get_process_working_directory()440 ),441 RUN_SUCCEEDED,442 )443 444 # Read the output file produced by running the program.445 output = lldbutil.read_file_from_process_wd(self, "output1.txt")446 447 self.expect(448 "target show-launch-environment",449 "MY_HOST_ENV_VAR1 is unset, it shouldn't be in `target show-launch-environment`",450 matching=False,451 substrs=["MY_HOST_ENV_VAR1=VAR1"],452 )453 self.expect(454 "target show-launch-environment",455 "MY_HOST_ENV_VAR2 shouldn be in `target show-launch-environment`",456 substrs=["MY_HOST_ENV_VAR2=VAR2"],457 )458 459 self.expect(460 output,461 exe=False,462 matching=False,463 substrs=[464 "The host environment variable 'MY_HOST_ENV_VAR1' successfully passed."465 ],466 )467 self.expect(468 output,469 exe=False,470 substrs=[471 "The host environment variable 'MY_HOST_ENV_VAR2' successfully passed."472 ],473 )474 475 @skipIfDarwinEmbedded # <rdar://problem/34446098> debugserver on ios etc can't write files476 def test_set_error_output_path(self):477 """Test that setting target.error/output-path for the launched process works."""478 self.build()479 480 exe = self.getBuildArtifact("a.out")481 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)482 483 # Set the error-path and output-path and verify both are set.484 self.runCmd(485 "settings set target.error-path '{0}'".format(486 lldbutil.append_to_process_working_directory(self, "stderr.txt")487 )488 )489 self.runCmd(490 "settings set target.output-path '{0}".format(491 lldbutil.append_to_process_working_directory(self, "stdout.txt")492 )493 )494 # And add hooks to restore the original settings during tearDown().495 self.addTearDownHook(lambda: self.runCmd("settings clear target.output-path"))496 self.addTearDownHook(lambda: self.runCmd("settings clear target.error-path"))497 498 self.expect(499 "settings show target.error-path",500 SETTING_MSG("target.error-path"),501 substrs=["target.error-path (file)", 'stderr.txt"'],502 )503 504 self.expect(505 "settings show target.output-path",506 SETTING_MSG("target.output-path"),507 substrs=["target.output-path (file)", 'stdout.txt"'],508 )509 510 self.runCmd(511 "process launch --working-dir '{0}'".format(512 self.get_process_working_directory()513 ),514 RUN_SUCCEEDED,515 )516 517 output = lldbutil.read_file_from_process_wd(self, "stderr.txt")518 message = "This message should go to standard error."519 if lldbplatformutil.hasChattyStderr(self):520 self.expect(output, exe=False, substrs=[message])521 else:522 self.expect(output, exe=False, startstr=message)523 524 output = lldbutil.read_file_from_process_wd(self, "stdout.txt")525 self.expect(526 output, exe=False, startstr="This message should go to standard out."527 )528 529 @skipIfDarwinEmbedded # <rdar://problem/34446098> debugserver on ios etc can't write files530 def test_same_error_output_path(self):531 """Test that setting target.error and output-path to the same file path for the launched process works."""532 self.build()533 534 exe = self.getBuildArtifact("a.out")535 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)536 537 # Set the error-path and output-path and verify both are set.538 self.runCmd(539 "settings set target.error-path '{0}'".format(540 lldbutil.append_to_process_working_directory(self, "output.txt")541 )542 )543 self.runCmd(544 "settings set target.output-path '{0}".format(545 lldbutil.append_to_process_working_directory(self, "output.txt")546 )547 )548 # And add hooks to restore the original settings during tearDown().549 self.addTearDownHook(lambda: self.runCmd("settings clear target.output-path"))550 self.addTearDownHook(lambda: self.runCmd("settings clear target.error-path"))551 552 self.expect(553 "settings show target.error-path",554 SETTING_MSG("target.error-path"),555 substrs=["target.error-path (file)", 'output.txt"'],556 )557 558 self.expect(559 "settings show target.output-path",560 SETTING_MSG("target.output-path"),561 substrs=["target.output-path (file)", 'output.txt"'],562 )563 564 self.runCmd(565 "process launch --working-dir '{0}'".format(566 self.get_process_working_directory()567 ),568 RUN_SUCCEEDED,569 )570 571 output = lldbutil.read_file_from_process_wd(self, "output.txt")572 err_message = "This message should go to standard error."573 out_message = "This message should go to standard out."574 # Error msg should get flushed by the output msg575 self.expect(output, exe=False, substrs=[out_message])576 self.assertNotIn(577 err_message,578 output,579 "Race condition when both stderr/stdout redirects to the same file",580 )581 582 def test_print_dictionary_setting(self):583 self.runCmd("settings clear target.env-vars")584 self.runCmd('settings set target.env-vars ["MY_VAR"]=some-value')585 self.expect("settings show target.env-vars", substrs=["MY_VAR=some-value"])586 self.runCmd("settings clear target.env-vars")587 588 def test_print_array_setting(self):589 self.runCmd("settings clear target.run-args")590 self.runCmd("settings set target.run-args gobbledy-gook")591 self.expect("settings show target.run-args", substrs=['[0]: "gobbledy-gook"'])592 self.runCmd("settings clear target.run-args")593 594 def test_settings_with_quotes(self):595 self.runCmd("settings clear target.run-args")596 self.runCmd("settings set target.run-args a b c")597 self.expect(598 "settings show target.run-args",599 substrs=['[0]: "a"', '[1]: "b"', '[2]: "c"'],600 )601 self.runCmd("settings set target.run-args 'a b c'")602 self.expect("settings show target.run-args", substrs=['[0]: "a b c"'])603 self.runCmd("settings clear target.run-args")604 self.runCmd("settings clear target.env-vars")605 self.runCmd(606 'settings set target.env-vars ["MY_FILE"]="this is a file name with spaces.txt"'607 )608 self.expect(609 "settings show target.env-vars",610 substrs=["MY_FILE=this is a file name with spaces.txt"],611 )612 self.runCmd("settings clear target.env-vars")613 # Test and make sure that setting "format-string" settings obeys quotes614 # if they are provided615 self.runCmd("settings set thread-format 'abc def' ")616 self.expect(617 "settings show thread-format",618 startstr='thread-format (format-string) = "abc def"',619 )620 self.runCmd('settings set thread-format "abc def" ')621 self.expect(622 "settings show thread-format",623 startstr='thread-format (format-string) = "abc def"',624 )625 # Make sure when no quotes are provided that we maintain any trailing626 # spaces627 self.runCmd("settings set thread-format abc def ")628 self.expect(629 "settings show thread-format",630 startstr='thread-format (format-string) = "abc def "',631 )632 self.runCmd("settings clear thread-format")633 634 def test_settings_with_trailing_whitespace(self):635 # boolean636 # Set to known value637 self.runCmd("settings set target.skip-prologue true")638 # Set to new value with trailing whitespace639 self.runCmd("settings set target.skip-prologue false ")640 # Make sure the setting was correctly set to "false"641 self.expect(642 "settings show target.skip-prologue",643 SETTING_MSG("target.skip-prologue"),644 startstr="target.skip-prologue (boolean) = false",645 )646 self.runCmd("settings clear target.skip-prologue", check=False)647 # integer648 self.runCmd("settings set term-width 70") # Set to known value649 # Set to new value with trailing whitespaces650 self.runCmd("settings set term-width 60 \t")651 self.expect(652 "settings show term-width",653 SETTING_MSG("term-width"),654 startstr="term-width (unsigned) = 60",655 )656 self.runCmd("settings clear term-width", check=False)657 # string658 self.runCmd("settings set target.arg0 abc") # Set to known value659 # Set to new value with trailing whitespaces660 self.runCmd("settings set target.arg0 cde\t ")661 self.expect(662 "settings show target.arg0",663 SETTING_MSG("target.arg0"),664 startstr='target.arg0 (string) = "cde"',665 )666 self.runCmd("settings clear target.arg0", check=False)667 # file668 path1 = self.getBuildArtifact("path1.txt")669 path2 = self.getBuildArtifact("path2.txt")670 self.runCmd("settings set target.output-path %s" % path1) # Set to known value671 self.expect(672 "settings show target.output-path",673 SETTING_MSG("target.output-path"),674 startstr="target.output-path (file) = ",675 substrs=[path1],676 )677 self.runCmd(678 "settings set target.output-path %s " % path2679 ) # Set to new value with trailing whitespaces680 self.expect(681 "settings show target.output-path",682 SETTING_MSG("target.output-path"),683 startstr="target.output-path (file) = ",684 substrs=[path2],685 )686 self.runCmd("settings clear target.output-path", check=False)687 # enum688 # Set to known value689 self.runCmd("settings set stop-disassembly-display never")690 # Set to new value with trailing whitespaces691 self.runCmd("settings set stop-disassembly-display always ")692 self.expect(693 "settings show stop-disassembly-display",694 SETTING_MSG("stop-disassembly-display"),695 startstr="stop-disassembly-display (enum) = always",696 )697 self.runCmd("settings clear stop-disassembly-display", check=False)698 # language699 # Set to known value700 self.runCmd("settings set target.language c89")701 # Set to new value with trailing whitespace702 self.runCmd("settings set target.language c11 ")703 self.expect(704 "settings show target.language",705 SETTING_MSG("target.language"),706 startstr="target.language (language) = c11",707 )708 self.runCmd("settings clear target.language", check=False)709 # arguments710 self.runCmd("settings set target.run-args 1 2 3") # Set to known value711 # Set to new value with trailing whitespaces712 self.runCmd("settings set target.run-args 3 4 5 ")713 self.expect(714 "settings show target.run-args",715 SETTING_MSG("target.run-args"),716 substrs=[717 "target.run-args (arguments) =",718 '[0]: "3"',719 '[1]: "4"',720 '[2]: "5"',721 ],722 )723 self.runCmd("settings set target.run-args 1 2 3") # Set to known value724 # Set to new value with trailing whitespaces725 self.runCmd(r"settings set target.run-args 3 \ \ ")726 self.expect(727 "settings show target.run-args",728 SETTING_MSG("target.run-args"),729 substrs=[730 "target.run-args (arguments) =",731 '[0]: "3"',732 '[1]: " "',733 '[2]: " "',734 ],735 )736 self.runCmd("settings clear target.run-args", check=False)737 # dictionaries738 self.runCmd("settings clear target.env-vars") # Set to known value739 # Set to new value with trailing whitespaces740 self.runCmd("settings set target.env-vars A=B C=D\t ")741 self.expect(742 "settings show target.env-vars",743 SETTING_MSG("target.env-vars"),744 substrs=["target.env-vars (dictionary of strings) =", "A=B", "C=D"],745 )746 self.runCmd("settings clear target.env-vars", check=False)747 # regex748 # Set to known value749 self.runCmd("settings clear target.process.thread.step-avoid-regexp")750 # Set to new value with trailing whitespaces751 self.runCmd("settings set target.process.thread.step-avoid-regexp foo\\ ")752 self.expect(753 "settings show target.process.thread.step-avoid-regexp",754 SETTING_MSG("target.process.thread.step-avoid-regexp"),755 substrs=["target.process.thread.step-avoid-regexp (regex) = foo\\ "],756 )757 self.runCmd(758 "settings clear target.process.thread.step-avoid-regexp", check=False759 )760 # format-string761 self.runCmd("settings clear disassembly-format") # Set to known value762 # Set to new value with trailing whitespaces763 self.runCmd("settings set disassembly-format foo ")764 self.expect(765 "settings show disassembly-format",766 SETTING_MSG("disassembly-format"),767 substrs=['disassembly-format (format-string) = "foo "'],768 )769 self.runCmd("settings clear disassembly-format", check=False)770 771 def test_settings_list(self):772 # List settings (and optionally test the filter to only show 'target' settings).773 self.expect(774 "settings list target", substrs=["arg0", "detach-on-error", "language"]775 )776 self.expect("settings list target", matching=False, substrs=["packet-timeout"])777 self.expect(778 "settings list",779 substrs=["language", "arg0", "detach-on-error", "packet-timeout"],780 )781 782 def test_settings_remove_single(self):783 # Set some environment variables and use 'remove' to delete them.784 self.runCmd("settings set target.env-vars a=b c=d")785 self.expect("settings show target.env-vars", substrs=["a=b", "c=d"])786 self.runCmd("settings remove target.env-vars a")787 self.expect("settings show target.env-vars", matching=False, substrs=["a=b"])788 self.expect("settings show target.env-vars", substrs=["c=d"])789 self.runCmd("settings remove target.env-vars c")790 self.expect(791 "settings show target.env-vars", matching=False, substrs=["a=b", "c=d"]792 )793 794 def test_settings_remove_multiple(self):795 self.runCmd("settings set target.env-vars a=b c=d e=f")796 self.expect("settings show target.env-vars", substrs=["a=b", "c=d", "e=f"])797 self.runCmd("settings remove target.env-vars a e")798 self.expect(799 "settings show target.env-vars", matching=False, substrs=["a=b", "e=f"]800 )801 self.expect("settings show target.env-vars", substrs=["c=d"])802 803 def test_settings_remove_nonexistent_value(self):804 self.expect(805 "settings remove target.env-vars doesntexist",806 error=True,807 substrs=["no value found named 'doesntexist'"],808 )809 810 def test_settings_remove_nonexistent_settings(self):811 self.expect(812 "settings remove doesntexist alsodoesntexist",813 error=True,814 substrs=["error: invalid value path 'doesntexist'"],815 )816 817 def test_settings_remove_missing_arg(self):818 self.expect(819 "settings remove",820 error=True,821 substrs=["'settings remove' takes an array or dictionary item, or"],822 )823 824 def test_settings_remove_empty_arg(self):825 self.expect(826 "settings remove ''",827 error=True,828 substrs=["'settings remove' command requires a valid variable name"],829 )830 831 def test_settings_clear_all(self):832 # Change a dictionary.833 self.runCmd("settings set target.env-vars a=1 b=2 c=3")834 # Change an array.835 self.runCmd("settings set target.run-args a1 b2 c3")836 # Change a single boolean value.837 self.runCmd("settings set auto-confirm true")838 # Change a single integer value.839 self.runCmd("settings set tab-size 4")840 841 # Clear everything.842 self.runCmd("settings clear --all")843 844 # Check that settings have their default values after clearing.845 self.expect(846 "settings show target.env-vars",847 patterns=[r"^target.env-vars \(dictionary of strings\) =\s*$"],848 )849 self.expect(850 "settings show target.run-args",851 patterns=[r"^target.run-args \(arguments\) =\s*$"],852 )853 self.expect("settings show auto-confirm", substrs=["false"])854 self.expect("settings show tab-size", substrs=["2"])855 856 # Check that the command fails if we combine '--all' option with any arguments.857 self.expect(858 "settings clear --all auto-confirm",859 COMMAND_FAILED_AS_EXPECTED,860 error=True,861 substrs=["'settings clear --all' doesn't take any arguments"],862 )863 864 def test_all_settings_exist(self):865 self.expect(866 "settings show",867 substrs=[868 "auto-confirm",869 "frame-format",870 "notify-void",871 "prompt",872 "script-lang",873 "stop-disassembly-count",874 "stop-disassembly-display",875 "stop-line-count-after",876 "stop-line-count-before",877 "stop-show-column",878 "term-width",879 "thread-format",880 "use-external-editor",881 "target.breakpoints-use-platform-avoid-list",882 "target.default-arch",883 "target.disable-aslr",884 "target.disable-stdio",885 "target.x86-disassembly-flavor",886 "target.enable-synthetic-value",887 "target.env-vars",888 "target.error-path",889 "target.exec-search-paths",890 "target.expr-prefix",891 "target.hex-immediate-style",892 "target.inherit-env",893 "target.input-path",894 "target.language",895 "target.max-children-count",896 "target.max-string-summary-length",897 "target.move-to-nearest-code",898 "target.output-path",899 "target.prefer-dynamic-value",900 "target.run-args",901 "target.skip-prologue",902 "target.source-map",903 "target.use-hex-immediates",904 "target.process.disable-memory-cache",905 "target.process.extra-startup-command",906 "target.process.track-memory-cache-changes",907 "target.process.thread.trace-thread",908 "target.process.thread.step-avoid-regexp",909 ],910 )911 912 # settings under an ".experimental" domain should have two properties:913 # 1. If the name does not exist with "experimental" in the name path,914 # the name lookup should try to find it without "experimental". So915 # a previously-experimental setting that has been promoted to a916 # "real" setting will still be set by the original name.917 # 2. Changing a setting with .experimental., name, where the setting918 # does not exist either with ".experimental." or without, should919 # not generate an error. So if an experimental setting is removed,920 # people who may have that in their ~/.lldbinit files should not see921 # any errors.922 def test_experimental_settings(self):923 cmdinterp = self.dbg.GetCommandInterpreter()924 result = lldb.SBCommandReturnObject()925 926 # Set target.arg0 to a known value, check that we can retrieve it via927 # the actual name and via .experimental.928 self.expect("settings set target.arg0 first-value")929 self.expect("settings show target.arg0", substrs=["first-value"])930 self.expect(931 "settings show target.experimental.arg0",932 substrs=["first-value"],933 error=False,934 )935 936 # Set target.arg0 to a new value via a target.experimental.arg0 name,937 # verify that we can read it back via both .experimental., and not.938 self.expect("settings set target.experimental.arg0 second-value", error=False)939 self.expect("settings show target.arg0", substrs=["second-value"])940 self.expect(941 "settings show target.experimental.arg0",942 substrs=["second-value"],943 error=False,944 )945 946 # showing & setting an undefined .experimental. setting should generate no errors.947 self.expect(948 "settings show target.experimental.setting-which-does-not-exist",949 patterns=[r"^\s$"],950 error=False,951 )952 self.expect(953 "settings set target.experimental.setting-which-does-not-exist true",954 error=False,955 )956 957 # A domain component before .experimental. which does not exist should give an error958 # But the code does not yet do that.959 # self.expect('settings set target.setting-which-does-not-exist.experimental.arg0 true', error=True)960 961 # finally, confirm that trying to set a setting that does not exist still fails.962 # (SHOWING a setting that does not exist does not currently yield an error.)963 self.expect("settings set target.setting-which-does-not-exist true", error=True)964 965 def test_settings_set_exists(self):966 cmdinterp = self.dbg.GetCommandInterpreter()967 968 # An unknown option should succeed.969 self.expect("settings set -e foo bar")970 self.expect("settings set --exists foo bar")971 972 # A known option should fail if its argument is invalid.973 self.expect("settings set auto-confirm bogus", error=True)974 975 def test_settings_show_defaults(self):976 # boolean977 self.expect(978 "settings show --defaults auto-one-line-summaries",979 matching=False,980 substrs=["(default: true)"],981 )982 self.runCmd("settings set auto-one-line-summaries false")983 self.expect(984 "settings show --defaults auto-one-line-summaries",985 substrs=["= false (default: true)"],986 )987 # unsigned988 self.expect(989 "settings show --defaults stop-line-count-before",990 matching=False,991 patterns=[r"\(default: \d+\)"],992 )993 self.runCmd("settings set stop-line-count-before 99")994 self.expect(995 "settings show --defaults stop-line-count-before",996 patterns=[r"= 99 \(default: \d+\)"],997 )998 # string999 self.expect(1000 "settings show --defaults prompt",1001 matching=False,1002 patterns=[r'\(default: ".+"\)'],1003 )1004 self.runCmd("settings set prompt '<LlDb> '")1005 self.expect(1006 "settings show --defaults prompt",1007 patterns=[r'= "<LlDb> " \(default: ".+"\)'],1008 )1009 # enum1010 self.expect(1011 "settings show --defaults stop-disassembly-display",1012 matching=False,1013 patterns=[r"\(default: .+\)"],1014 )1015 self.runCmd("settings set stop-disassembly-display no-source")1016 self.expect(1017 "settings show --defaults stop-disassembly-display",1018 patterns=[r"= no-source \(default: .+\)"],1019 )1020 # regex1021 self.expect(1022 "settings show --defaults target.process.thread.step-avoid-regexp",1023 matching=False,1024 patterns=[r"\(default: .+\)"],1025 )1026 self.runCmd("settings set target.process.thread.step-avoid-regexp dotstar")1027 self.expect(1028 "settings show --defaults target.process.thread.step-avoid-regexp",1029 patterns=[r"= dotstar \(default: .+\)"],1030 )1031 # format-string1032 self.expect(1033 "settings show --defaults disassembly-format",1034 matching=False,1035 patterns=[r'\(default: ".+"\)'],1036 )1037 self.runCmd("settings set disassembly-format dollar")1038 self.expect(1039 "settings show --defaults disassembly-format",1040 patterns=[r'= "dollar" \(default: ".+"\)'],1041 )1042 # arrays1043 self.expect(1044 "settings show --defaults target.unset-env-vars",1045 matching=False,1046 substrs=["(default: empty)"],1047 )1048 self.runCmd("settings set target.unset-env-vars PATH")1049 self.expect(1050 "settings show --defaults target.unset-env-vars",1051 substrs=["(default: empty)", '[0]: "PATH"'],1052 )1053 # dictionaries1054 self.runCmd("settings clear target.env-vars")1055 self.expect(1056 "settings show --defaults target.env-vars",1057 matching=False,1058 substrs=["(default: empty)"],1059 )1060 self.runCmd("settings set target.env-vars THING=value")1061 self.expect(1062 "settings show --defaults target.env-vars",1063 substrs=["(default: empty)", "THING=value"],1064 )1065 pwd = os.getcwd()1066 # file list1067 self.expect(1068 "settings show --defaults target.exec-search-paths",1069 matching=False,1070 substrs=["(default: empty)"],1071 )1072 self.runCmd(f"settings set target.exec-search-paths {pwd}")1073 self.expect(1074 "settings show --defaults target.exec-search-paths",1075 substrs=["(default: empty)", f"[0]: {pwd}"],1076 )1077 # path map1078 self.expect(1079 "settings show --defaults target.source-map",1080 matching=False,1081 substrs=["(default: empty)"],1082 )1083 self.runCmd(f"settings set target.source-map /abc {pwd}")1084 self.expect(1085 "settings show --defaults target.source-map",1086 patterns=[1087 r"\(default: empty\)",1088 rf'\[0\] "[/\\]abc" -> "{re.escape(pwd)}"',1089 ],1090 )1091 1092 def get_setting_json(self, setting_path=None):1093 settings_data = self.dbg.GetSetting(setting_path)1094 stream = lldb.SBStream()1095 settings_data.GetAsJSON(stream)1096 return json.loads(stream.GetData())1097 1098 def verify_setting_value_json(self, setting_path, setting_value):1099 self.runCmd("settings set %s %s" % (setting_path, setting_value))1100 settings_json = self.get_setting_json(setting_path)1101 self.assertEqual(settings_json, setting_value)1102 1103 def test_settings_api(self):1104 """1105 Test that ensures SBDebugger::GetSetting() APIs1106 can correctly fetch settings.1107 """1108 1109 # Test basic values and embedding special JSON escaping characters.1110 self.runCmd("settings set auto-confirm true")1111 self.runCmd("settings set tab-size 4")1112 arg_value = 'hello "world"'1113 self.runCmd("settings set target.arg0 %s" % arg_value)1114 1115 settings_json = self.get_setting_json()1116 self.assertEqual(settings_json["auto-confirm"], True)1117 self.assertEqual(settings_json["tab-size"], 4)1118 self.assertEqual(settings_json["target"]["arg0"], arg_value)1119 1120 settings_data = self.get_setting_json("target.arg0")1121 self.assertEqual(settings_data, arg_value)1122 1123 # Test OptionValueFileSpec1124 self.verify_setting_value_json(1125 "platform.module-cache-directory", self.getBuildDir()1126 )1127 1128 # Test OptionValueArray1129 setting_path = "target.run-args"1130 setting_value = ["value1", "value2", "value3"]1131 self.runCmd("settings set %s %s" % (setting_path, " ".join(setting_value)))1132 settings_json = self.get_setting_json(setting_path)1133 self.assertEqual(settings_json, setting_value)1134 1135 # Test OptionValueFileSpec and OptionValueFileSpecList1136 setting_path = "target.debug-file-search-paths"1137 path1 = os.path.join(self.getSourceDir(), "tmp")1138 path2 = os.path.join(self.getSourceDir(), "tmp2")1139 self.runCmd("settings set %s '%s' '%s'" % (setting_path, path1, path2))1140 settings_json = self.get_setting_json(setting_path)1141 self.assertEqual(settings_json, [path1, path2])1142 1143 # Test OptionValueFormatEntity1144 setting_value = """thread #${thread.index}{, name = \\'${thread.name}\\1145 '}{, queue = ${ansi.fg.green}\\'${thread.queue}\\'${ansi.normal}}{,1146 activity = ${ansi.fg.green}\\'${thread.info.activity.name}\\'${ansi.normal}}1147 {, ${thread.info.trace_messages} messages}{, stop reason = ${ansi.fg.red}$1148 {thread.stop-reason}${ansi.normal}}{\\\\nReturn value: ${thread.return-value}}1149 {\\\\nCompleted expression: ${thread.completed-expression}}\\\\n"""1150 self.verify_setting_value_json("thread-stop-format", setting_value)1151 1152 # Test OptionValueRegex1153 self.verify_setting_value_json(1154 "target.process.thread.step-avoid-regexp", "^std::"1155 )1156 1157 # Test OptionValueLanguage1158 self.verify_setting_value_json("repl-lang", "c++")1159 1160 # Test OptionValueEnumeration1161 self.verify_setting_value_json("target.x86-disassembly-flavor", "intel")1162 1163 # Test OptionValueArch1164 self.verify_setting_value_json("target.default-arch", "x86_64")1165 self.runCmd("settings clear target.default-arch")1166 1167 def test_global_option(self):1168 # This command used to crash the settings because -g was signaled by a1169 # NULL execution context (not one with an empty Target...) and in the1170 # special handling for load-script-from-symbol-file this wasn't checked.1171 self.runCmd("settings set -g target.load-script-from-symbol-file true")1172