xref: /llvm-project/lldb/test/API/commands/command/container/TestContainerCommands.py (revision d518ed42ae85786c371fd4578f72ab7eb286cb30)
1"""
2Test user added container commands
3"""
4
5
6import sys
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10
11
12class TestCmdContainer(TestBase):
13    NO_DEBUG_INFO_TESTCASE = True
14
15    def test_container_add(self):
16        self.container_add()
17
18    def check_command_tree_exists(self):
19        """This makes sure we can still run the command tree we added."""
20        self.runCmd("test-multi")
21        self.runCmd("test-multi test-multi-sub")
22        self.runCmd("test-multi test-multi-sub welcome")
23
24    def container_add(self):
25        # Make sure we can't overwrite built-in commands:
26        self.expect("command container add process", "Can't replace builtin container command",
27                    substrs=["can't replace builtin command"], error=True)
28        self.expect("command container add process non_such_subcommand", "Can't add to built-in subcommand",
29                    substrs=["Path component: 'process' is not a user command"], error=True)
30        self.expect("command container add process launch", "Can't replace builtin subcommand",
31                    substrs=["Path component: 'process' is not a user command"], error=True)
32
33        # Now lets make a container command:
34        self.runCmd("command container add -h 'A test container command' test-multi")
35        # Make sure the help works:
36        self.expect("help test-multi", "Help works for top-level multi",
37                    substrs=["A test container command"])
38        # Add a subcommand:
39        self.runCmd("command container add -h 'A test container sub-command' test-multi test-multi-sub")
40        # Make sure the help works:
41        self.expect("help test-multi", "Help shows sub-multi",
42                    substrs=["A test container command", "test-multi-sub -- A test container sub-command"])
43        self.expect("help test-multi test-multi-sub", "Help shows sub-multi",
44                    substrs=["A test container sub-command"])
45
46        # Now add a script based command to the container command:
47        self.runCmd("command script import welcome.py")
48        self.runCmd("command script add -c welcome.WelcomeCommand test-multi test-multi-sub welcome")
49        # Make sure the help still works:
50        self.expect("help test-multi test-multi-sub", "Listing subcommands works",
51                    substrs=["A test container sub-command", "welcome -- Just a docstring for Welcome"])
52        self.expect("help test-multi test-multi-sub welcome", "Subcommand help works",
53                    substrs=["Just a docstring for Welcome"])
54        # And make sure it actually works:
55        self.expect("test-multi test-multi-sub welcome friend", "Test command works",
56                    substrs=["Hello friend, welcome to LLDB"])
57
58        # Make sure we can make an alias to this:
59        self.runCmd("command alias my-welcome test-multi test-multi-sub welcome", "We can make an alias to multi-word")
60        self.expect("my-welcome friend", "Test command works",
61                    substrs=["Hello friend, welcome to LLDB"])
62        self.runCmd("command unalias my-welcome")
63
64        # Make sure overwriting works on the leaf command.  First using the
65        # explicit option so we should not be able to remove extant commands by default:
66
67        self.expect("command script add -c welcome.WelcomeCommand2 test-multi test-multi-sub welcome",
68                    "overwrite command w/o -o",
69                    substrs=["cannot add command: sub-command already exists"], error=True)
70        # But we can with the -o option:
71        self.runCmd("command script add -c welcome.WelcomeCommand2 -o test-multi test-multi-sub welcome")
72        # Make sure we really did overwrite:
73        self.expect("test-multi test-multi-sub welcome friend", "Used the new command class",
74                    substrs=["Hello friend, welcome again to LLDB"])
75        self.expect("apropos welcome", "welcome should show up in apropos", substrs=["A docstring for the second Welcome"])
76        self.expect("help test-multi test-multi-sub welcome", "welcome should show up in help", substrs=["A docstring for the second Welcome"])
77        self.expect("help", "test-multi should show up in help", substrs=["test-multi"])
78
79        # Now switch the default and make sure we can now delete w/o the overwrite option:
80        self.runCmd("settings set interpreter.require-overwrite 0")
81        self.runCmd("command script add -c welcome.WelcomeCommand test-multi test-multi-sub welcome")
82        # Make sure we really did overwrite:
83        self.expect("test-multi test-multi-sub welcome friend", "Used the new command class",
84                    substrs=["Hello friend, welcome to LLDB"])
85
86        # Make sure we give good errors when the input is wrong:
87        self.expect("command script delete test-mult test-multi-sub welcome", "Delete script command - wrong first path component",
88                    substrs=["'test-mult' not found"], error=True)
89
90        self.expect("command script delete test-multi test-multi-su welcome", "Delete script command - wrong second path component",
91                    substrs=["'test-multi-su' not found"], error=True)
92        self.check_command_tree_exists()
93
94        self.expect("command script delete test-multi test-multi-sub welcom", "Delete script command - wrong leaf component",
95                    substrs=["'welcom' not found"], error=True)
96        self.check_command_tree_exists()
97
98        self.expect("command script delete test-multi test-multi-sub", "Delete script command - no leaf component",
99                    substrs=["subcommand 'test-multi-sub' is not a user command"], error=True)
100        self.check_command_tree_exists()
101
102        # You can't use command script delete to delete container commands:
103        self.expect("command script delete test-multi", "Delete script - can't delete container",
104                    substrs=["command 'test-multi' is a multi-word command."], error=True)
105        self.expect("command script delete test-multi test-multi-sub", "Delete script - can't delete container",
106                    substrs=["subcommand 'test-multi-sub' is not a user command"], error = True)
107
108        # You can't use command container delete to delete scripted commands:
109        self.expect("command container delete test-multi test-multi-sub welcome", "command container can't delete user commands",
110                    substrs=["subcommand 'welcome' is not a container command"], error = True)
111
112        # Also make sure you can't alias on top of container commands:
113        self.expect("command alias test-multi process launch", "Tried to alias on top of a container command",
114                    substrs=["'test-multi' is a user container command and cannot be overwritten."], error=True)
115        self.check_command_tree_exists()
116
117        # Also assert that we can't delete builtin commands:
118        self.expect("command script delete process launch", "Delete builtin command fails", substrs=["command 'process' is not a user command"], error=True)
119        # Now let's do the version that works
120        self.expect("command script delete test-multi test-multi-sub welcome", "Delete script command by path", substrs=["Deleted command: test-multi test-multi-sub welcome"])
121
122        # Now overwrite the sub-command, it should end up empty:
123        self.runCmd("command container add -h 'A different help string' -o test-multi test-multi-sub")
124        # welcome should be gone:
125        self.expect("test-multi test-multi-sub welcome friend", "did remove subcommand",
126                    substrs=["'test-multi-sub' does not have any subcommands."], error=True)
127        # We should have the new help:
128        self.expect("help test-multi test-multi-sub", "help changed",
129                    substrs=["A different help string"])
130
131        # Now try deleting commands.
132        self.runCmd("command container delete test-multi test-multi-sub")
133        self.expect("test-multi test-multi-sub", "Command is not active", error=True,
134                    substrs = ["'test-multi' does not have any subcommands"])
135        self.expect("help test-multi", matching=False, substrs=["test-multi-sub"])
136
137
138        # Next the root command:
139        self.runCmd("command container delete test-multi")
140        self.expect("test-multi", "Root command gone", substrs=["'test-multi' is not a valid command."], error=True)
141