brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.8 KiB · 9deebe2 Raw
327 lines · python
1"""2Test option and argument definitions in parsed script commands3"""4 5 6import sys7import os8import lldb9from lldbsuite.test.decorators import *10from lldbsuite.test.lldbtest import *11 12 13class ParsedCommandTestCase(TestBase):14    NO_DEBUG_INFO_TESTCASE = True15 16    def test(self):17        self.pycmd_tests()18 19    def setUp(self):20        TestBase.setUp(self)21        self.stdin_path = self.getBuildArtifact("stdin.txt")22        self.stdout_path = self.getBuildArtifact("stdout.txt")23 24    def check_help_options(self, cmd_name, opt_list, substrs=[]):25        """26        Pass the command name in cmd_name and a vector of the short option, type & long option.27        This will append the checks for all the options and test "help command".28        Any strings already in substrs will also be checked.29        Any element in opt list that begin with "+" will be added to the checked strings as is.30        """31        for elem in opt_list:32            if elem[0] == "+":33                substrs.append(elem[1:])34            else:35                (short_opt, type, long_opt) = elem36                substrs.append(f"-{short_opt} <{type}> ( --{long_opt} <{type}> )")37 38        self.expect("help " + cmd_name, substrs=substrs)39 40    def run_one_repeat(self, commands, expected_num_errors):41        with open(self.stdin_path, "w") as input_handle:42            input_handle.write(commands)43 44        in_fileH = open(self.stdin_path, "r")45        self.dbg.SetInputFileHandle(in_fileH, False)46 47        out_fileH = open(self.stdout_path, "w")48        self.dbg.SetOutputFileHandle(out_fileH, False)49        self.dbg.SetErrorFileHandle(out_fileH, False)50 51        options = lldb.SBCommandInterpreterRunOptions()52        options.SetEchoCommands(False)53        options.SetPrintResults(True)54        options.SetPrintErrors(True)55        options.SetAllowRepeats(True)56 57        n_errors, quit_requested, has_crashed = self.dbg.RunCommandInterpreter(58            True, False, options, 0, False, False59        )60 61        in_fileH.close()62        out_fileH.close()63 64        results = None65        with open(self.stdout_path, "r") as out_fileH:66            results = out_fileH.read()67 68        self.assertEqual(n_errors, expected_num_errors)69 70        return results71 72    def handle_completion(73        self,74        cmd_str,75        exp_num_completions,76        exp_matches,77        exp_descriptions,78        match_description,79    ):80        matches = lldb.SBStringList()81        descriptions = lldb.SBStringList()82 83        interp = self.dbg.GetCommandInterpreter()84        num_completions = interp.HandleCompletionWithDescriptions(85            cmd_str, len(cmd_str), 0, 1000, matches, descriptions86        )87        self.assertEqual(88            num_completions, exp_num_completions, "Number of completions is right."89        )90        num_matches = matches.GetSize()91        self.assertEqual(92            num_matches,93            exp_matches.GetSize(),94            "matches and expected matches of different lengths",95        )96        num_descriptions = descriptions.GetSize()97        if match_description:98            self.assertEqual(99                num_descriptions,100                exp_descriptions.GetSize(),101                "descriptions and expected of different lengths",102            )103 104        self.assertEqual(105            matches.GetSize(),106            num_completions + 1,107            "The first element is the complete additional text",108        )109 110        for idx in range(0, num_matches):111            match = matches.GetStringAtIndex(idx)112            exp_match = exp_matches.GetStringAtIndex(idx)113            self.assertEqual(114                match, exp_match, f"{match} did not match expectation: {exp_match}"115            )116        if match_description:117            desc = descriptions.GetStringAtIndex(idx)118            exp_desc = exp_descriptions.GetStringAtIndex(idx)119            self.assertEqual(120                desc, exp_desc, f"{desc} didn't match expectation: {exp_desc}"121            )122 123    def pycmd_tests(self):124        source_dir = self.getSourceDir()125        test_file_path = os.path.join(source_dir, "test_commands.py")126        self.runCmd("command script import " + test_file_path)127        self.expect("help", substrs=["no-args", "one-arg-no-opt", "two-args"])128 129        # Test that we did indeed add these commands as user commands:130 131        # This is the function to remove the custom commands in order to have a132        # clean slate for the next test case.133        def cleanup():134            self.runCmd(135                "command script delete no-args one-arg-no-opt two-args", check=False136            )137 138        # Execute the cleanup function during test case tear down.139        self.addTearDownHook(cleanup)140 141        # First test the no arguments command.  Make sure the help is right:142        no_arg_opts = [143            ["b", "boolean", "bool-arg"],144            "+a boolean arg, defaults to True",145            ["d", "filename", "disk-file-name"],146            "+An on disk filename",147            ["e", "none", "enum-option"],148            "+An enum, doesn't actually do anything",149            "+Values: foo | bar | baz",150            ["l", "linenum", "line-num"],151            "+A line number",152            ["s", "shlib-name", "shlib-name"],153            "+A shared library name",154        ]155        substrs = [156            "Example command for use in debugging",157            "Syntax: no-args <cmd-options>",158        ]159 160        self.check_help_options("no-args", no_arg_opts, substrs)161 162        # Make sure the command doesn't accept arguments:163        self.expect(164            "no-args an-arg",165            substrs=["'no-args' doesn't take any arguments."],166            error=True,167        )168 169        # Try setting the bool with the wrong value:170        self.expect(171            "no-args -b Something",172            substrs=["Error setting option: bool-arg to Something"],173            error=True,174        )175        # Try setting the enum to an illegal value as well:176        self.expect(177            "no-args --enum-option Something",178            substrs=["error: Error setting option: enum-option to Something"],179            error=True,180        )181 182        # Check some of the command groups:183        self.expect(184            "no-args -b true -s Something -l 10",185            substrs=["error: invalid combination of options for the given command"],186            error=True,187        )188 189        # Now set the bool arg correctly, note only the first option was set:190        self.expect(191            "no-args -b true",192            substrs=[193                "bool-arg (set: True): True",194                "shlib-name (set: False):",195                "disk-file-name (set: False):",196                "line-num (set: False):",197                "enum-option (set: False):",198            ],199        )200 201        # Now set the enum arg correctly, note only the first option was set:202        self.expect(203            "no-args -e foo",204            substrs=[205                "bool-arg (set: False):",206                "shlib-name (set: False):",207                "disk-file-name (set: False):",208                "line-num (set: False):",209                "enum-option (set: True): foo",210            ],211        )212        # Try a pair together:213        self.expect(214            "no-args -b false -s Something",215            substrs=[216                "bool-arg (set: True): False",217                "shlib-name (set: True): Something",218                "disk-file-name (set: False):",219                "flag-value (set: False):",220                "line-num (set: False):",221                "enum-option (set: False):",222            ],223        )224        # Make sure flag values work:225        self.expect(226            "no-args -b false -s Something -f",227            substrs=[228                "bool-arg (set: True): False",229                "shlib-name (set: True): Something",230                "disk-file-name (set: False):",231                "flag-value (set: True):",232                "line-num (set: False):",233                "enum-option (set: False):",234            ],235        )236 237        # Next try some completion tests:238 239        interp = self.dbg.GetCommandInterpreter()240        matches = lldb.SBStringList()241        descriptions = lldb.SBStringList()242 243        # First try an enum completion:244        # Note - this is an enum so all the values are returned:245        matches.AppendList(["oo ", "foo"], 2)246 247        self.handle_completion("no-args -e f", 1, matches, descriptions, False)248 249        # Now try an internal completer, the on disk file one is handy:250        partial_name = os.path.join(source_dir, "test_")251        cmd_str = f"no-args -d '{partial_name}'"252 253        matches.Clear()254        descriptions.Clear()255        matches.AppendList(["commands.py' ", test_file_path], 2)256        # We don't have descriptions for the file path completer:257        self.handle_completion(cmd_str, 1, matches, descriptions, False)258 259        # Try a command with arguments.260        # FIXME: It should be enough to define an argument and it's type to get the completer261        # wired up for that argument type if it is a known type. But that isn't wired up in the262        # command parser yet, so I don't have any tests for that.  We also don't currently check263        # that the arguments passed match the argument specifications, so here I just pass a couple264        # sets of arguments and make sure we get back what we put in:265        self.expect(266            "two-args 'First Argument' 'Second Argument'",267            substrs=["0: First Argument", "1: Second Argument"],268        )269 270        # Now test custom completions - two-args has both option and arg completers.  In both271        # completers we return different values if the -p option is set, so we can test that too:272        matches.Clear()273        descriptions.Clear()274        cmd_str = "two-args -p something -c other_"275        matches.AppendString("something ")276        matches.AppendString("other_something")277        # This is a full match so no descriptions:278        self.handle_completion(cmd_str, 1, matches, descriptions, False)279 280        matches.Clear()281        descriptions.Clear()282        cmd_str = "two-args -c other_"283        matches.AppendList(["", "other_nice", "other_not_nice", "other_mediocre"], 4)284        # The option doesn't return descriptions either:285        self.handle_completion(cmd_str, 3, matches, descriptions, False)286 287        # Now try the argument - it says "no completions" if the proc_name was set:288        matches.Clear()289        descriptions.Clear()290        cmd_str = "two-args -p something arg"291        matches.AppendString("")292        self.handle_completion(cmd_str, 0, matches, descriptions, False)293 294        cmd_str = "two-args arg_"295        matches.Clear()296        descriptions.Clear()297        matches.AppendList(["", "arg_cool", "arg_yuck"], 3)298        descriptions.AppendList(["", "good idea", "bad idea"], 3)299        self.handle_completion(cmd_str, 2, matches, descriptions, True)300 301        # This one gets a single unique match:302        cmd_str = "two-args correct_"303        matches.Clear()304        descriptions.Clear()305        matches.AppendList(["answer ", "correct_answer"], 2)306        self.handle_completion(cmd_str, 1, matches, descriptions, False)307 308        # Now make sure get_repeat_command works properly:309 310        # no-args turns off auto-repeat311        results = self.run_one_repeat("no-args\n\n", 1)312        self.assertIn("no auto repeat", results, "Got auto-repeat error")313 314        # one-args does the normal repeat315        results = self.run_one_repeat("one-arg-no-opt ONE_ARG\n\n", 0)316        self.assertEqual(results.count("ONE_ARG"), 2, "We did a normal repeat")317 318        # two-args adds an argument:319        results = self.run_one_repeat("two-args FIRST_ARG SECOND_ARG\n\n", 0)320        self.assertEqual(321            results.count("FIRST_ARG"), 2, "Passed first arg to both commands"322        )323        self.assertEqual(324            results.count("SECOND_ARG"), 2, "Passed second arg to both commands"325        )326        self.assertEqual(results.count("THIRD_ARG"), 1, "Passed third arg in repeat")327