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