1"""
2Test the lldb command line completion mechanism.
3"""
4
5
6
7import os
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbplatform
12from lldbsuite.test import lldbutil
13
14
15class CommandLineCompletionTestCase(TestBase):
16
17    mydir = TestBase.compute_mydir(__file__)
18
19    NO_DEBUG_INFO_TESTCASE = True
20
21    @classmethod
22    def classCleanup(cls):
23        """Cleanup the test byproducts."""
24        try:
25            os.remove("child_send.txt")
26            os.remove("child_read.txt")
27        except:
28            pass
29
30    def test_at(self):
31        """Test that 'at' completes to 'attach '."""
32        self.complete_from_to('at', 'attach ')
33
34    def test_de(self):
35        """Test that 'de' completes to 'detach '."""
36        self.complete_from_to('de', 'detach ')
37
38    def test_frame_variable(self):
39        self.build()
40        self.main_source = "main.cpp"
41        self.main_source_spec = lldb.SBFileSpec(self.main_source)
42
43        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
44                                          '// Break here', self.main_source_spec)
45        self.assertEquals(process.GetState(), lldb.eStateStopped)
46        # FIXME: This pulls in the debug information to make the completions work,
47        # but the completions should also work without.
48        self.runCmd("frame variable fooo")
49
50        self.complete_from_to('frame variable fo',
51                              'frame variable fooo')
52        self.complete_from_to('frame variable fooo.',
53                              'frame variable fooo.')
54        self.complete_from_to('frame variable fooo.dd',
55                              'frame variable fooo.dd')
56
57        self.complete_from_to('frame variable ptr_fooo->',
58                              'frame variable ptr_fooo->')
59        self.complete_from_to('frame variable ptr_fooo->dd',
60                              'frame variable ptr_fooo->dd')
61
62        self.complete_from_to('frame variable cont',
63                              'frame variable container')
64        self.complete_from_to('frame variable container.',
65                              'frame variable container.MemberVar')
66        self.complete_from_to('frame variable container.Mem',
67                              'frame variable container.MemberVar')
68
69        self.complete_from_to('frame variable ptr_cont',
70                              'frame variable ptr_container')
71        self.complete_from_to('frame variable ptr_container->',
72                              'frame variable ptr_container->MemberVar')
73        self.complete_from_to('frame variable ptr_container->Mem',
74                              'frame variable ptr_container->MemberVar')
75
76    def test_process_attach_dash_dash_con(self):
77        """Test that 'process attach --con' completes to 'process attach --continue '."""
78        self.complete_from_to(
79            'process attach --con',
80            'process attach --continue ')
81
82    def test_process_launch_arch(self):
83        self.complete_from_to('process launch --arch ',
84                              ['mips',
85                               'arm64'])
86
87    def test_ambiguous_long_opt(self):
88        self.completions_match('breakpoint modify --th',
89                               ['--thread-id',
90                                '--thread-index',
91                                '--thread-name'])
92
93    def test_plugin_load(self):
94        self.complete_from_to('plugin load ', [])
95
96    def test_log_enable(self):
97        self.complete_from_to('log enable ll', ['lldb'])
98        self.complete_from_to('log enable dw', ['dwarf'])
99        self.complete_from_to('log enable lldb al', ['all'])
100        self.complete_from_to('log enable lldb sym', ['symbol'])
101
102    def test_log_enable(self):
103        self.complete_from_to('log disable ll', ['lldb'])
104        self.complete_from_to('log disable dw', ['dwarf'])
105        self.complete_from_to('log disable lldb al', ['all'])
106        self.complete_from_to('log disable lldb sym', ['symbol'])
107
108    def test_log_list(self):
109        self.complete_from_to('log list ll', ['lldb'])
110        self.complete_from_to('log list dw', ['dwarf'])
111        self.complete_from_to('log list ll', ['lldb'])
112        self.complete_from_to('log list lldb dwa', ['dwarf'])
113
114    def test_quoted_command(self):
115        self.complete_from_to('"set',
116                              ['"settings" '])
117
118    def test_quoted_arg_with_quoted_command(self):
119        self.complete_from_to('"settings" "repl',
120                              ['"replace" '])
121
122    def test_quoted_arg_without_quoted_command(self):
123        self.complete_from_to('settings "repl',
124                              ['"replace" '])
125
126    def test_single_quote_command(self):
127        self.complete_from_to("'set",
128                              ["'settings' "])
129
130    def test_terminated_quote_command(self):
131        # This should not crash, but we don't get any
132        # reasonable completions from this.
133        self.complete_from_to("'settings'", [])
134
135    def test_process_launch_arch_arm(self):
136        self.complete_from_to('process launch --arch arm',
137                              ['arm64'])
138
139    def test_target_symbols_add_shlib(self):
140        # Doesn't seem to work, but at least it shouldn't crash.
141        self.complete_from_to('target symbols add --shlib ', [])
142
143    def test_log_file(self):
144        # Complete in our source directory which contains a 'main.cpp' file.
145        src_dir =  os.path.dirname(os.path.realpath(__file__)) + '/'
146        self.complete_from_to('log enable lldb expr -f ' + src_dir,
147                              ['main.cpp'])
148
149    def test_log_dir(self):
150        # Complete our source directory.
151        src_dir =  os.path.dirname(os.path.realpath(__file__))
152        self.complete_from_to('log enable lldb expr -f ' + src_dir,
153                              [src_dir + os.sep], turn_off_re_match=True)
154
155    # <rdar://problem/11052829>
156    def test_infinite_loop_while_completing(self):
157        """Test that 'process print hello\' completes to itself and does not infinite loop."""
158        self.complete_from_to('process print hello\\', 'process print hello\\',
159                              turn_off_re_match=True)
160
161    def test_watchpoint_co(self):
162        """Test that 'watchpoint co' completes to 'watchpoint command '."""
163        self.complete_from_to('watchpoint co', 'watchpoint command ')
164
165    def test_watchpoint_command_space(self):
166        """Test that 'watchpoint command ' completes to ['add', 'delete', 'list']."""
167        self.complete_from_to(
168            'watchpoint command ', [
169                'add', 'delete', 'list'])
170
171    def test_watchpoint_command_a(self):
172        """Test that 'watchpoint command a' completes to 'watchpoint command add '."""
173        self.complete_from_to(
174            'watchpoint command a',
175            'watchpoint command add ')
176
177    def test_watchpoint_set_ex(self):
178        """Test that 'watchpoint set ex' completes to 'watchpoint set expression '."""
179        self.complete_from_to(
180            'watchpoint set ex',
181            'watchpoint set expression ')
182
183    def test_watchpoint_set_var(self):
184        """Test that 'watchpoint set var' completes to 'watchpoint set variable '."""
185        self.complete_from_to('watchpoint set var', 'watchpoint set variable ')
186
187    def test_help_fi(self):
188        """Test that 'help fi' completes to ['file', 'finish']."""
189        self.complete_from_to(
190            'help fi', [
191                'file', 'finish'])
192
193    def test_help_watchpoint_s(self):
194        """Test that 'help watchpoint s' completes to 'help watchpoint set '."""
195        self.complete_from_to('help watchpoint s', 'help watchpoint set ')
196
197    def test_settings_append_target_er(self):
198        """Test that 'settings append target.er' completes to 'settings append target.error-path'."""
199        self.complete_from_to(
200            'settings append target.er',
201            'settings append target.error-path')
202
203    def test_settings_insert_after_target_en(self):
204        """Test that 'settings insert-after target.env' completes to 'settings insert-after target.env-vars'."""
205        self.complete_from_to(
206            'settings insert-after target.env',
207            'settings insert-after target.env-vars')
208
209    def test_settings_insert_before_target_en(self):
210        """Test that 'settings insert-before target.env' completes to 'settings insert-before target.env-vars'."""
211        self.complete_from_to(
212            'settings insert-before target.env',
213            'settings insert-before target.env-vars')
214
215    def test_settings_replace_target_ru(self):
216        """Test that 'settings replace target.ru' completes to 'settings replace target.run-args'."""
217        self.complete_from_to(
218            'settings replace target.ru',
219            'settings replace target.run-args')
220
221    def test_settings_show_term(self):
222        self.complete_from_to(
223            'settings show term-',
224            'settings show term-width')
225
226    def test_settings_list_term(self):
227        self.complete_from_to(
228            'settings list term-',
229            'settings list term-width')
230
231    def test_settings_remove_term(self):
232        self.complete_from_to(
233            'settings remove term-',
234            'settings remove term-width')
235
236    def test_settings_s(self):
237        """Test that 'settings s' completes to ['set', 'show']."""
238        self.complete_from_to(
239            'settings s', [
240                'set', 'show'])
241
242    def test_settings_set_th(self):
243        """Test that 'settings set thread-f' completes to 'settings set thread-format'."""
244        self.complete_from_to('settings set thread-f', 'settings set thread-format')
245
246    def test_settings_s_dash(self):
247        """Test that 'settings set --g' completes to 'settings set --global'."""
248        self.complete_from_to('settings set --g', 'settings set --global')
249
250    def test_settings_clear_th(self):
251        """Test that 'settings clear thread-f' completes to 'settings clear thread-format'."""
252        self.complete_from_to(
253            'settings clear thread-f',
254            'settings clear thread-format')
255
256    def test_settings_set_ta(self):
257        """Test that 'settings set ta' completes to 'settings set target.'."""
258        self.complete_from_to(
259            'settings set target.ma',
260            'settings set target.max-')
261
262    def test_settings_set_target_exec(self):
263        """Test that 'settings set target.exec' completes to 'settings set target.exec-search-paths '."""
264        self.complete_from_to(
265            'settings set target.exec',
266            'settings set target.exec-search-paths')
267
268    def test_settings_set_target_pr(self):
269        """Test that 'settings set target.pr' completes to [
270        'target.prefer-dynamic-value', 'target.process.']."""
271        self.complete_from_to('settings set target.pr',
272                              ['target.prefer-dynamic-value',
273                               'target.process.'])
274
275    def test_settings_set_target_process(self):
276        """Test that 'settings set target.process' completes to 'settings set target.process.'."""
277        self.complete_from_to(
278            'settings set target.process',
279            'settings set target.process.')
280
281    def test_settings_set_target_process_dot(self):
282        """Test that 'settings set target.process.t' completes to 'settings set target.process.thread.'."""
283        self.complete_from_to(
284            'settings set target.process.t',
285            'settings set target.process.thread.')
286
287    def test_settings_set_target_process_thread_dot(self):
288        """Test that 'settings set target.process.thread.' completes to [
289        'target.process.thread.step-avoid-regexp', 'target.process.thread.trace-thread']."""
290        self.complete_from_to('settings set target.process.thread.',
291                              ['target.process.thread.step-avoid-regexp',
292                               'target.process.thread.trace-thread'])
293
294    def test_target_space(self):
295        """Test that 'target ' completes to ['create', 'delete', 'list',
296        'modules', 'select', 'stop-hook', 'variable']."""
297        self.complete_from_to('target ',
298                              ['create',
299                               'delete',
300                               'list',
301                               'modules',
302                               'select',
303                               'stop-hook',
304                               'variable'])
305
306    def test_target_modules_dump_line_table(self):
307        """Tests source file completion by completing the line-table argument."""
308        self.build()
309        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
310        self.complete_from_to('target modules dump line-table main.cp',
311                              ['main.cpp'])
312
313    def test_target_modules_load_aout(self):
314        """Tests modules completion by completing the target modules load argument."""
315        self.build()
316        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
317        self.complete_from_to('target modules load a.ou',
318                              ['a.out'])
319
320    def test_target_create_dash_co(self):
321        """Test that 'target create --co' completes to 'target variable --core '."""
322        self.complete_from_to('target create --co', 'target create --core ')
323
324    def test_target_va(self):
325        """Test that 'target va' completes to 'target variable '."""
326        self.complete_from_to('target va', 'target variable ')
327
328    def test_command_argument_completion(self):
329        """Test completion of command arguments"""
330        self.complete_from_to("watchpoint set variable -", ["-w", "-s"])
331        self.complete_from_to('watchpoint set variable -w', 'watchpoint set variable -w ')
332        self.complete_from_to("watchpoint set variable --", ["--watch", "--size"])
333        self.complete_from_to("watchpoint set variable --w", "watchpoint set variable --watch")
334        self.complete_from_to('watchpoint set variable -w ', ['read', 'write', 'read_write'])
335        self.complete_from_to("watchpoint set variable --watch ", ["read", "write", "read_write"])
336        self.complete_from_to("watchpoint set variable --watch w", "watchpoint set variable --watch write")
337        self.complete_from_to('watchpoint set variable -w read_', 'watchpoint set variable -w read_write')
338        # Now try the same thing with a variable name (non-option argument) to
339        # test that getopts arg reshuffling doesn't confuse us.
340        self.complete_from_to("watchpoint set variable foo -", ["-w", "-s"])
341        self.complete_from_to('watchpoint set variable foo -w', 'watchpoint set variable foo -w ')
342        self.complete_from_to("watchpoint set variable foo --", ["--watch", "--size"])
343        self.complete_from_to("watchpoint set variable foo --w", "watchpoint set variable foo --watch")
344        self.complete_from_to('watchpoint set variable foo -w ', ['read', 'write', 'read_write'])
345        self.complete_from_to("watchpoint set variable foo --watch ", ["read", "write", "read_write"])
346        self.complete_from_to("watchpoint set variable foo --watch w", "watchpoint set variable foo --watch write")
347        self.complete_from_to('watchpoint set variable foo -w read_', 'watchpoint set variable foo -w read_write')
348
349    def test_completion_description_commands(self):
350        """Test descriptions of top-level command completions"""
351        self.check_completion_with_desc("", [
352            ["command", "Commands for managing custom LLDB commands."],
353            ["breakpoint", "Commands for operating on breakpoints (see 'help b' for shorthand.)"]
354        ])
355
356        self.check_completion_with_desc("pl", [
357            ["platform", "Commands to manage and create platforms."],
358            ["plugin", "Commands for managing LLDB plugins."]
359        ])
360
361        # Just check that this doesn't crash.
362        self.check_completion_with_desc("comman", [])
363        self.check_completion_with_desc("non-existent-command", [])
364
365    def test_completion_description_command_options(self):
366        """Test descriptions of command options"""
367        # Short options
368        self.check_completion_with_desc("breakpoint set -", [
369            ["-h", "Set the breakpoint on exception catcH."],
370            ["-w", "Set the breakpoint on exception throW."]
371        ])
372
373        # Long options.
374        self.check_completion_with_desc("breakpoint set --", [
375            ["--on-catch", "Set the breakpoint on exception catcH."],
376            ["--on-throw", "Set the breakpoint on exception throW."]
377        ])
378
379        # Ambiguous long options.
380        self.check_completion_with_desc("breakpoint set --on-", [
381            ["--on-catch", "Set the breakpoint on exception catcH."],
382            ["--on-throw", "Set the breakpoint on exception throW."]
383        ])
384
385        # Unknown long option.
386        self.check_completion_with_desc("breakpoint set --Z", [
387        ])
388
389    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
390    def test_symbol_name(self):
391        self.build()
392        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
393        self.complete_from_to('breakpoint set -n Fo',
394                              'breakpoint set -n Foo::Bar(int,\\ int)',
395                              turn_off_re_match=True)
396        # No completion for Qu because the candidate is
397        # (anonymous namespace)::Quux().
398        self.complete_from_to('breakpoint set -n Qu', '')
399