brintos

brintos / llvm-project-archived public Read only

0
0
Text · 45.4 KiB · 95b07f8 Raw
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