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
47        # Since CommandInterpreter has been corrected to update the current execution
48        # context at the beginning of HandleCompletion, we're here explicitly testing
49        # the scenario where "frame var" is completed without any preceding commands.
50
51        self.complete_from_to('frame variable fo',
52                              'frame variable fooo')
53        self.complete_from_to('frame variable fooo.',
54                              'frame variable fooo.')
55        self.complete_from_to('frame variable fooo.dd',
56                              'frame variable fooo.dd')
57
58        self.complete_from_to('frame variable ptr_fooo->',
59                              'frame variable ptr_fooo->')
60        self.complete_from_to('frame variable ptr_fooo->dd',
61                              'frame variable ptr_fooo->dd')
62
63        self.complete_from_to('frame variable cont',
64                              'frame variable container')
65        self.complete_from_to('frame variable container.',
66                              'frame variable container.MemberVar')
67        self.complete_from_to('frame variable container.Mem',
68                              'frame variable container.MemberVar')
69
70        self.complete_from_to('frame variable ptr_cont',
71                              'frame variable ptr_container')
72        self.complete_from_to('frame variable ptr_container->',
73                              'frame variable ptr_container->MemberVar')
74        self.complete_from_to('frame variable ptr_container->Mem',
75                              'frame variable ptr_container->MemberVar')
76
77    def test_process_attach_dash_dash_con(self):
78        """Test that 'process attach --con' completes to 'process attach --continue '."""
79        self.complete_from_to(
80            'process attach --con',
81            'process attach --continue ')
82
83    def test_process_launch_arch(self):
84        self.complete_from_to('process launch --arch ',
85                              ['mips',
86                               'arm64'])
87
88    def test_process_signal(self):
89        # The tab completion for "process signal"  won't work without a running process.
90        self.complete_from_to('process signal ',
91                              'process signal ')
92
93        # Test with a running process.
94        self.build()
95        self.main_source = "main.cpp"
96        self.main_source_spec = lldb.SBFileSpec(self.main_source)
97        lldbutil.run_to_source_breakpoint(self, '// Break here', self.main_source_spec)
98
99        self.complete_from_to('process signal ',
100                              'process signal SIG')
101        self.complete_from_to('process signal SIGA',
102                              ['SIGABRT',
103                               'SIGALRM'])
104
105    def test_ambiguous_long_opt(self):
106        self.completions_match('breakpoint modify --th',
107                               ['--thread-id',
108                                '--thread-index',
109                                '--thread-name'])
110
111    def test_plugin_load(self):
112        self.complete_from_to('plugin load ', [])
113
114    def test_log_enable(self):
115        self.complete_from_to('log enable ll', ['lldb'])
116        self.complete_from_to('log enable dw', ['dwarf'])
117        self.complete_from_to('log enable lldb al', ['all'])
118        self.complete_from_to('log enable lldb sym', ['symbol'])
119
120    def test_log_enable(self):
121        self.complete_from_to('log disable ll', ['lldb'])
122        self.complete_from_to('log disable dw', ['dwarf'])
123        self.complete_from_to('log disable lldb al', ['all'])
124        self.complete_from_to('log disable lldb sym', ['symbol'])
125
126    def test_log_list(self):
127        self.complete_from_to('log list ll', ['lldb'])
128        self.complete_from_to('log list dw', ['dwarf'])
129        self.complete_from_to('log list ll', ['lldb'])
130        self.complete_from_to('log list lldb dwa', ['dwarf'])
131
132    def test_quoted_command(self):
133        self.complete_from_to('"set',
134                              ['"settings" '])
135
136    def test_quoted_arg_with_quoted_command(self):
137        self.complete_from_to('"settings" "repl',
138                              ['"replace" '])
139
140    def test_quoted_arg_without_quoted_command(self):
141        self.complete_from_to('settings "repl',
142                              ['"replace" '])
143
144    def test_single_quote_command(self):
145        self.complete_from_to("'set",
146                              ["'settings' "])
147
148    def test_terminated_quote_command(self):
149        # This should not crash, but we don't get any
150        # reasonable completions from this.
151        self.complete_from_to("'settings'", [])
152
153    def test_process_launch_arch_arm(self):
154        self.complete_from_to('process launch --arch arm',
155                              ['arm64'])
156
157    def test_target_symbols_add_shlib(self):
158        # Doesn't seem to work, but at least it shouldn't crash.
159        self.complete_from_to('target symbols add --shlib ', [])
160
161    def test_log_file(self):
162        # Complete in our source directory which contains a 'main.cpp' file.
163        src_dir =  os.path.dirname(os.path.realpath(__file__)) + '/'
164        self.complete_from_to('log enable lldb expr -f ' + src_dir,
165                              ['main.cpp'])
166
167    def test_log_dir(self):
168        # Complete our source directory.
169        src_dir =  os.path.dirname(os.path.realpath(__file__))
170        self.complete_from_to('log enable lldb expr -f ' + src_dir,
171                              [src_dir + os.sep], turn_off_re_match=True)
172
173    # <rdar://problem/11052829>
174    def test_infinite_loop_while_completing(self):
175        """Test that 'process print hello\' completes to itself and does not infinite loop."""
176        self.complete_from_to('process print hello\\', 'process print hello\\',
177                              turn_off_re_match=True)
178
179    def test_watchpoint_co(self):
180        """Test that 'watchpoint co' completes to 'watchpoint command '."""
181        self.complete_from_to('watchpoint co', 'watchpoint command ')
182
183    def test_watchpoint_command_space(self):
184        """Test that 'watchpoint command ' completes to ['add', 'delete', 'list']."""
185        self.complete_from_to(
186            'watchpoint command ', [
187                'add', 'delete', 'list'])
188
189    def test_watchpoint_command_a(self):
190        """Test that 'watchpoint command a' completes to 'watchpoint command add '."""
191        self.complete_from_to(
192            'watchpoint command a',
193            'watchpoint command add ')
194
195    def test_watchpoint_set_ex(self):
196        """Test that 'watchpoint set ex' completes to 'watchpoint set expression '."""
197        self.complete_from_to(
198            'watchpoint set ex',
199            'watchpoint set expression ')
200
201    def test_watchpoint_set_var(self):
202        """Test that 'watchpoint set var' completes to 'watchpoint set variable '."""
203        self.complete_from_to('watchpoint set var', 'watchpoint set variable ')
204
205    def test_help_fi(self):
206        """Test that 'help fi' completes to ['file', 'finish']."""
207        self.complete_from_to(
208            'help fi', [
209                'file', 'finish'])
210
211    def test_help_watchpoint_s(self):
212        """Test that 'help watchpoint s' completes to 'help watchpoint set '."""
213        self.complete_from_to('help watchpoint s', 'help watchpoint set ')
214
215    def test_settings_append_target_er(self):
216        """Test that 'settings append target.er' completes to 'settings append target.error-path'."""
217        self.complete_from_to(
218            'settings append target.er',
219            'settings append target.error-path')
220
221    def test_settings_insert_after_target_en(self):
222        """Test that 'settings insert-after target.env' completes to 'settings insert-after target.env-vars'."""
223        self.complete_from_to(
224            'settings insert-after target.env',
225            'settings insert-after target.env-vars')
226
227    def test_settings_insert_before_target_en(self):
228        """Test that 'settings insert-before target.env' completes to 'settings insert-before target.env-vars'."""
229        self.complete_from_to(
230            'settings insert-before target.env',
231            'settings insert-before target.env-vars')
232
233    def test_settings_replace_target_ru(self):
234        """Test that 'settings replace target.ru' completes to 'settings replace target.run-args'."""
235        self.complete_from_to(
236            'settings replace target.ru',
237            'settings replace target.run-args')
238
239    def test_settings_show_term(self):
240        self.complete_from_to(
241            'settings show term-',
242            'settings show term-width')
243
244    def test_settings_list_term(self):
245        self.complete_from_to(
246            'settings list term-',
247            'settings list term-width')
248
249    def test_settings_remove_term(self):
250        self.complete_from_to(
251            'settings remove term-',
252            'settings remove term-width')
253
254    def test_settings_s(self):
255        """Test that 'settings s' completes to ['set', 'show']."""
256        self.complete_from_to(
257            'settings s', [
258                'set', 'show'])
259
260    def test_settings_set_th(self):
261        """Test that 'settings set thread-f' completes to 'settings set thread-format'."""
262        self.complete_from_to('settings set thread-f', 'settings set thread-format')
263
264    def test_settings_s_dash(self):
265        """Test that 'settings set --g' completes to 'settings set --global'."""
266        self.complete_from_to('settings set --g', 'settings set --global')
267
268    def test_settings_clear_th(self):
269        """Test that 'settings clear thread-f' completes to 'settings clear thread-format'."""
270        self.complete_from_to(
271            'settings clear thread-f',
272            'settings clear thread-format')
273
274    def test_settings_set_ta(self):
275        """Test that 'settings set ta' completes to 'settings set target.'."""
276        self.complete_from_to(
277            'settings set target.ma',
278            'settings set target.max-')
279
280    def test_settings_set_target_exec(self):
281        """Test that 'settings set target.exec' completes to 'settings set target.exec-search-paths '."""
282        self.complete_from_to(
283            'settings set target.exec',
284            'settings set target.exec-search-paths')
285
286    def test_settings_set_target_pr(self):
287        """Test that 'settings set target.pr' completes to [
288        'target.prefer-dynamic-value', 'target.process.']."""
289        self.complete_from_to('settings set target.pr',
290                              ['target.prefer-dynamic-value',
291                               'target.process.'])
292
293    def test_settings_set_target_process(self):
294        """Test that 'settings set target.process' completes to 'settings set target.process.'."""
295        self.complete_from_to(
296            'settings set target.process',
297            'settings set target.process.')
298
299    def test_settings_set_target_process_dot(self):
300        """Test that 'settings set target.process.t' completes to 'settings set target.process.thread.'."""
301        self.complete_from_to(
302            'settings set target.process.t',
303            'settings set target.process.thread.')
304
305    def test_settings_set_target_process_thread_dot(self):
306        """Test that 'settings set target.process.thread.' completes to [
307        'target.process.thread.step-avoid-regexp', 'target.process.thread.trace-thread']."""
308        self.complete_from_to('settings set target.process.thread.',
309                              ['target.process.thread.step-avoid-regexp',
310                               'target.process.thread.trace-thread'])
311
312    def test_target_space(self):
313        """Test that 'target ' completes to ['create', 'delete', 'list',
314        'modules', 'select', 'stop-hook', 'variable']."""
315        self.complete_from_to('target ',
316                              ['create',
317                               'delete',
318                               'list',
319                               'modules',
320                               'select',
321                               'stop-hook',
322                               'variable'])
323
324    def test_target_modules_dump_line_table(self):
325        """Tests source file completion by completing the line-table argument."""
326        self.build()
327        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
328        self.complete_from_to('target modules dump line-table main.cp',
329                              ['main.cpp'])
330
331    def test_target_modules_load_aout(self):
332        """Tests modules completion by completing the target modules load argument."""
333        self.build()
334        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
335        self.complete_from_to('target modules load a.ou',
336                              ['a.out'])
337
338    def test_target_create_dash_co(self):
339        """Test that 'target create --co' completes to 'target variable --core '."""
340        self.complete_from_to('target create --co', 'target create --core ')
341
342    def test_target_va(self):
343        """Test that 'target va' completes to 'target variable '."""
344        self.complete_from_to('target va', 'target variable ')
345
346    def test_command_argument_completion(self):
347        """Test completion of command arguments"""
348        self.complete_from_to("watchpoint set variable -", ["-w", "-s"])
349        self.complete_from_to('watchpoint set variable -w', 'watchpoint set variable -w ')
350        self.complete_from_to("watchpoint set variable --", ["--watch", "--size"])
351        self.complete_from_to("watchpoint set variable --w", "watchpoint set variable --watch")
352        self.complete_from_to('watchpoint set variable -w ', ['read', 'write', 'read_write'])
353        self.complete_from_to("watchpoint set variable --watch ", ["read", "write", "read_write"])
354        self.complete_from_to("watchpoint set variable --watch w", "watchpoint set variable --watch write")
355        self.complete_from_to('watchpoint set variable -w read_', 'watchpoint set variable -w read_write')
356        # Now try the same thing with a variable name (non-option argument) to
357        # test that getopts arg reshuffling doesn't confuse us.
358        self.complete_from_to("watchpoint set variable foo -", ["-w", "-s"])
359        self.complete_from_to('watchpoint set variable foo -w', 'watchpoint set variable foo -w ')
360        self.complete_from_to("watchpoint set variable foo --", ["--watch", "--size"])
361        self.complete_from_to("watchpoint set variable foo --w", "watchpoint set variable foo --watch")
362        self.complete_from_to('watchpoint set variable foo -w ', ['read', 'write', 'read_write'])
363        self.complete_from_to("watchpoint set variable foo --watch ", ["read", "write", "read_write"])
364        self.complete_from_to("watchpoint set variable foo --watch w", "watchpoint set variable foo --watch write")
365        self.complete_from_to('watchpoint set variable foo -w read_', 'watchpoint set variable foo -w read_write')
366
367    def test_completion_description_commands(self):
368        """Test descriptions of top-level command completions"""
369        self.check_completion_with_desc("", [
370            ["command", "Commands for managing custom LLDB commands."],
371            ["breakpoint", "Commands for operating on breakpoints (see 'help b' for shorthand.)"]
372        ])
373
374        self.check_completion_with_desc("pl", [
375            ["platform", "Commands to manage and create platforms."],
376            ["plugin", "Commands for managing LLDB plugins."]
377        ])
378
379        # Just check that this doesn't crash.
380        self.check_completion_with_desc("comman", [])
381        self.check_completion_with_desc("non-existent-command", [])
382
383    def test_completion_description_command_options(self):
384        """Test descriptions of command options"""
385        # Short options
386        self.check_completion_with_desc("breakpoint set -", [
387            ["-h", "Set the breakpoint on exception catcH."],
388            ["-w", "Set the breakpoint on exception throW."]
389        ])
390
391        # Long options.
392        self.check_completion_with_desc("breakpoint set --", [
393            ["--on-catch", "Set the breakpoint on exception catcH."],
394            ["--on-throw", "Set the breakpoint on exception throW."]
395        ])
396
397        # Ambiguous long options.
398        self.check_completion_with_desc("breakpoint set --on-", [
399            ["--on-catch", "Set the breakpoint on exception catcH."],
400            ["--on-throw", "Set the breakpoint on exception throW."]
401        ])
402
403        # Unknown long option.
404        self.check_completion_with_desc("breakpoint set --Z", [
405        ])
406
407    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
408    def test_symbol_name(self):
409        self.build()
410        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
411        self.complete_from_to('breakpoint set -n Fo',
412                              'breakpoint set -n Foo::Bar(int,\\ int)',
413                              turn_off_re_match=True)
414        # No completion for Qu because the candidate is
415        # (anonymous namespace)::Quux().
416        self.complete_from_to('breakpoint set -n Qu', '')
417
418    @skipIf(archs=no_match(['x86_64']))
419    def test_register_read_and_write_on_x86(self):
420        """Test the completion of the commands register read and write on x86"""
421
422        # The tab completion for "register read/write"  won't work without a running process.
423        self.complete_from_to('register read ',
424                              'register read ')
425        self.complete_from_to('register write ',
426                              'register write ')
427
428        self.build()
429        self.main_source_spec = lldb.SBFileSpec("main.cpp")
430        lldbutil.run_to_source_breakpoint(self, '// Break here', self.main_source_spec)
431
432        # test cases for register read
433        self.complete_from_to('register read ',
434                              ['rax',
435                               'rbx',
436                               'rcx'])
437        self.complete_from_to('register read r',
438                              ['rax',
439                               'rbx',
440                               'rcx'])
441        self.complete_from_to('register read ra',
442                              'register read rax')
443        # register read can take multiple register names as arguments
444        self.complete_from_to('register read rax ',
445                              ['rax',
446                               'rbx',
447                               'rcx'])
448        # complete with prefix '$'
449        self.completions_match('register read $rb',
450                              ['$rbx',
451                               '$rbp'])
452        self.completions_match('register read $ra',
453                              ['$rax'])
454        self.complete_from_to('register read rax $',
455                              ['\$rax',
456                               '\$rbx',
457                               '\$rcx'])
458        self.complete_from_to('register read $rax ',
459                              ['rax',
460                               'rbx',
461                               'rcx'])
462
463        # test cases for register write
464        self.complete_from_to('register write ',
465                              ['rax',
466                               'rbx',
467                               'rcx'])
468        self.complete_from_to('register write r',
469                              ['rax',
470                               'rbx',
471                               'rcx'])
472        self.complete_from_to('register write ra',
473                              'register write rax')
474        self.complete_from_to('register write rb',
475                              ['rbx',
476                               'rbp'])
477        # register write can only take exact one register name as argument
478        self.complete_from_to('register write rbx ',
479                              [])
480
481    def test_complete_breakpoint_with_ids(self):
482        """These breakpoint subcommands should be completed with a list of breakpoint ids"""
483
484        subcommands = ['enable', 'disable', 'delete', 'modify', 'name add', 'name delete', 'write']
485
486        # The tab completion here is unavailable without a target
487        for subcommand in subcommands:
488            self.complete_from_to('breakpoint ' + subcommand + ' ',
489                                  'breakpoint ' + subcommand + ' ')
490
491        self.build()
492        target = self.dbg.CreateTarget(self.getBuildArtifact('a.out'))
493        self.assertTrue(target, VALID_TARGET)
494
495        bp = target.BreakpointCreateByName('main', 'a.out')
496        self.assertTrue(bp)
497        self.assertEqual(bp.GetNumLocations(), 1)
498
499        for subcommand in subcommands:
500            self.complete_from_to('breakpoint ' + subcommand + ' ',
501                                  ['1'])
502
503        bp2 = target.BreakpointCreateByName('Bar', 'a.out')
504        self.assertTrue(bp2)
505        self.assertEqual(bp2.GetNumLocations(), 1)
506
507        for subcommand in subcommands:
508            self.complete_from_to('breakpoint ' + subcommand + ' ',
509                                  ['1',
510                                   '2'])
511
512        for subcommand in subcommands:
513            self.complete_from_to('breakpoint ' + subcommand + ' 1 ',
514                                  ['1',
515                                   '2'])
516
517