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