xref: /llvm-project/lldb/test/API/functionalities/completion/TestCompletion.py (revision 3dfc1d9b0bc41eaf63e551ca357b44a71636b152)
1"""
2Test the lldb command line completion mechanism.
3"""
4
5
6import os
7from multiprocessing import Process
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    NO_DEBUG_INFO_TESTCASE = True
17
18    @classmethod
19    def classCleanup(cls):
20        """Cleanup the test byproducts."""
21        try:
22            os.remove("child_send.txt")
23            os.remove("child_read.txt")
24        except:
25            pass
26
27    def test_at(self):
28        """Test that 'at' completes to 'attach '."""
29        self.complete_from_to("at", "attach ")
30
31    def test_de(self):
32        """Test that 'de' completes to 'detach '."""
33        self.complete_from_to("de", "detach ")
34
35    def test_frame_variable(self):
36        self.build()
37
38        _, process, _, _ = lldbutil.run_to_source_breakpoint(
39            self, "// Break here", lldb.SBFileSpec("main.cpp")
40        )
41        self.assertState(process.GetState(), lldb.eStateStopped)
42
43        # Since CommandInterpreter has been corrected to update the current execution
44        # context at the beginning of HandleCompletion, we're here explicitly testing
45        # the scenario where "frame var" is completed without any preceding commands.
46        self.do_test_variable_completion("frame variable")
47
48    def test_dwim_print(self):
49        self.build()
50
51        _, process, _, _ = lldbutil.run_to_source_breakpoint(
52            self, "// Break here", lldb.SBFileSpec("main.cpp")
53        )
54        self.assertState(process.GetState(), lldb.eStateStopped)
55
56        # Since CommandInterpreter has been corrected to update the current execution
57        # context at the beginning of HandleCompletion, we're here explicitly testing
58        # the scenario where "frame var" is completed without any preceding commands.
59        self.do_test_variable_completion("dwim-print")
60
61    def do_test_variable_completion(self, command):
62        self.complete_from_to(f"{command} fo", f"{command} fooo")
63        self.complete_from_to(f"{command} fooo.", f"{command} fooo.t")
64        self.complete_from_to(f"{command} fooo.t.", f"{command} fooo.t.x")
65        self.complete_from_to(f"{command} fooo.dd", f"{command} fooo.dd")
66
67        self.complete_from_to(f"{command} ptr_fooo->", f"{command} ptr_fooo->t")
68        self.complete_from_to(f"{command} ptr_fooo->t.", f"{command} ptr_fooo->t.x")
69        self.complete_from_to(f"{command} ptr_fooo->dd", f"{command} ptr_fooo->dd")
70
71        self.complete_from_to(f"{command} cont", f"{command} container")
72        self.complete_from_to(f"{command} container.", f"{command} container.MemberVar")
73        self.complete_from_to(
74            f"{command} container.Mem", f"{command} container.MemberVar"
75        )
76
77        self.complete_from_to(f"{command} ptr_cont", f"{command} ptr_container")
78        self.complete_from_to(
79            f"{command} ptr_container->", f"{command} ptr_container->MemberVar"
80        )
81        self.complete_from_to(
82            f"{command} ptr_container->Mem", f"{command} ptr_container->MemberVar"
83        )
84
85    def test_process_attach_dash_dash_con(self):
86        """Test that 'process attach --con' completes to 'process attach --continue '."""
87        self.complete_from_to("process attach --con", "process attach --continue ")
88
89    def test_process_launch_arch(self):
90        self.complete_from_to("process launch --arch ", ["mips", "arm64"])
91
92    def test_process_load(self):
93        self.build()
94        lldbutil.run_to_source_breakpoint(
95            self, "// Break here", lldb.SBFileSpec("main.cpp")
96        )
97        self.complete_from_to("process load Makef", "process load Makefile")
98
99    @skipUnlessPlatform(["linux"])
100    def test_process_unload(self):
101        """Test the completion for "process unload <index>" """
102        # This tab completion should not work without a running process.
103        self.complete_from_to("process unload ", "process unload ")
104
105        self.build()
106        lldbutil.run_to_source_breakpoint(
107            self, "// Break here", lldb.SBFileSpec("main.cpp")
108        )
109        err = lldb.SBError()
110        local_spec = lldb.SBFileSpec(self.getBuildArtifact("libshared.so"))
111        if lldb.remote_platform:
112            self.process().LoadImage(
113                local_spec,
114                lldb.SBFileSpec(
115                    lldbutil.append_to_process_working_directory(self, "libshared.so"),
116                    False,
117                ),
118                err,
119            )
120        else:
121            self.process().LoadImage(local_spec, err)
122        self.assertSuccess(err)
123
124        self.complete_from_to("process unload ", "process unload 0")
125
126        self.process().UnloadImage(0)
127        self.complete_from_to("process unload ", "process unload ")
128
129    def test_process_plugin_completion(self):
130        subcommands = ["attach -P", "connect -p", "launch -p"]
131
132        for subcommand in subcommands:
133            self.complete_from_to(
134                "process " + subcommand + " mac",
135                "process " + subcommand + " mach-o-core",
136            )
137
138    def completions_contain_str(self, input, needle):
139        interp = self.dbg.GetCommandInterpreter()
140        match_strings = lldb.SBStringList()
141        num_matches = interp.HandleCompletion(input, len(input), 0, -1, match_strings)
142        found_needle = False
143        for match in match_strings:
144            if needle in match:
145                found_needle = True
146                break
147        self.assertTrue(
148            found_needle, "Returned completions: " + "\n".join(match_strings)
149        )
150
151    @skipIfRemote
152    def test_common_completion_process_pid_and_name(self):
153        # The LLDB process itself and the process already attached to are both
154        # ignored by the process discovery mechanism, thus we need a process known
155        # to us here.
156        self.build()
157        server = self.spawnSubprocess(
158            self.getBuildArtifact("a.out"),
159            [
160                "-x"
161            ],  # Arg "-x" makes the subprocess wait for input thus it won't be terminated too early
162            install_remote=False,
163        )
164        self.assertIsNotNone(server)
165        pid = server.pid
166
167        self.completions_contain("process attach -p ", [str(pid)])
168        self.completions_contain("platform process attach -p ", [str(pid)])
169        self.completions_contain("platform process info ", [str(pid)])
170
171        self.completions_contain_str("process attach -n ", "a.out")
172        self.completions_contain_str("platform process attach -n ", "a.out")
173
174    def test_process_signal(self):
175        # The tab completion for "process signal"  won't work without a running process.
176        self.complete_from_to("process signal ", "process signal ")
177
178        # Test with a running process.
179        self.build()
180        self.main_source = "main.cpp"
181        self.main_source_spec = lldb.SBFileSpec(self.main_source)
182        lldbutil.run_to_source_breakpoint(self, "// Break here", self.main_source_spec)
183
184        self.complete_from_to("process signal ", "process signal SIG")
185        self.complete_from_to("process signal SIGPIP", "process signal SIGPIPE")
186        self.complete_from_to("process signal SIGA", ["SIGABRT", "SIGALRM"])
187
188    def test_ambiguous_long_opt(self):
189        self.completions_match(
190            "breakpoint modify --th", ["--thread-id", "--thread-index", "--thread-name"]
191        )
192
193    def test_disassemble_dash_f(self):
194        self.completions_match("disassemble -F ", ["default", "intel", "att"])
195
196    def test_plugin_load(self):
197        self.complete_from_to("plugin load ", [])
198
199    def test_log_enable(self):
200        self.complete_from_to("log disable ll", ["lldb"])
201        self.complete_from_to("log disable dw", ["dwarf"])
202        self.complete_from_to("log disable lldb al", ["all"])
203        self.complete_from_to("log disable lldb sym", ["symbol"])
204
205    def test_log_list(self):
206        self.complete_from_to("log list ll", ["lldb"])
207        self.complete_from_to("log list dw", ["dwarf"])
208        self.complete_from_to("log list ll", ["lldb"])
209        self.complete_from_to("log list lldb dwa", ["dwarf"])
210
211    def test_quoted_command(self):
212        self.complete_from_to('"set', ['"settings" '])
213
214    def test_quoted_arg_with_quoted_command(self):
215        self.complete_from_to('"settings" "repl', ['"replace" '])
216
217    def test_quoted_arg_without_quoted_command(self):
218        self.complete_from_to('settings "repl', ['"replace" '])
219
220    def test_single_quote_command(self):
221        self.complete_from_to("'set", ["'settings' "])
222
223    def test_terminated_quote_command(self):
224        # This should not crash, but we don't get any
225        # reasonable completions from this.
226        self.complete_from_to("'settings'", [])
227
228    def test_process_launch_arch_arm(self):
229        self.complete_from_to("process launch --arch arm", ["arm64"])
230
231    def test_target_symbols_add_shlib(self):
232        # Doesn't seem to work, but at least it shouldn't crash.
233        self.complete_from_to("target symbols add --shlib ", [])
234
235    def test_log_file(self):
236        # Complete in our source directory which contains a 'main.cpp' file.
237        src_dir = self.getSourceDir() + "/"
238        self.complete_from_to("log enable lldb expr -f " + src_dir, ["main.cpp"])
239
240    def test_log_dir(self):
241        # Complete our source directory.
242        src_dir = os.path.dirname(os.path.realpath(__file__))
243        self.complete_from_to("log enable lldb expr -f " + src_dir, [src_dir + os.sep])
244
245    # <rdar://problem/11052829>
246    def test_infinite_loop_while_completing(self):
247        """Test that 'process print hello\' completes to itself and does not infinite loop."""
248        self.complete_from_to("process print hello\\", "process print hello\\")
249
250    def test_watchpoint_co(self):
251        """Test that 'watchpoint co' completes to 'watchpoint command '."""
252        self.complete_from_to("watchpoint co", "watchpoint command ")
253
254    def test_watchpoint_command_space(self):
255        """Test that 'watchpoint command ' completes to ['add', 'delete', 'list']."""
256        self.complete_from_to("watchpoint command ", ["add", "delete", "list"])
257
258    def test_watchpoint_command_a(self):
259        """Test that 'watchpoint command a' completes to 'watchpoint command add '."""
260        self.complete_from_to("watchpoint command a", "watchpoint command add ")
261
262    def test_watchpoint_set_ex(self):
263        """Test that 'watchpoint set ex' completes to 'watchpoint set expression '."""
264        self.complete_from_to("watchpoint set ex", "watchpoint set expression ")
265
266    def test_watchpoint_set_var(self):
267        """Test that 'watchpoint set var' completes to 'watchpoint set variable '."""
268        self.complete_from_to("watchpoint set var", "watchpoint set variable ")
269
270    def test_watchpoint_set_variable_foo(self):
271        self.build()
272        lldbutil.run_to_source_breakpoint(
273            self, "// Break here", lldb.SBFileSpec("main.cpp")
274        )
275        self.complete_from_to(
276            "watchpoint set variable fo", "watchpoint set variable fooo"
277        )
278        # Only complete the first argument.
279        self.complete_from_to(
280            "watchpoint set variable fooo ", "watchpoint set variable fooo "
281        )
282
283    def test_help_fi(self):
284        """Test that 'help fi' completes to ['file', 'finish']."""
285        self.complete_from_to("help fi", ["file", "finish"])
286
287    def test_help_watchpoint_s(self):
288        """Test that 'help watchpoint s' completes to 'help watchpoint set '."""
289        self.complete_from_to("help watchpoint s", "help watchpoint set ")
290
291    @expectedFailureNetBSD
292    @add_test_categories(["watchpoint"])
293    def test_common_complete_watchpoint_ids(self):
294        subcommands = ["enable", "disable", "delete", "modify", "ignore"]
295
296        # Completion should not work without a target.
297        for subcommand in subcommands:
298            self.complete_from_to(
299                "watchpoint " + subcommand + " ", "watchpoint " + subcommand + " "
300            )
301
302        # Create a process to provide a target and enable watchpoint setting.
303        self.build()
304        lldbutil.run_to_source_breakpoint(
305            self, "// Break here", lldb.SBFileSpec("main.cpp")
306        )
307
308        self.runCmd("watchpoint set variable ptr_fooo")
309        for subcommand in subcommands:
310            self.complete_from_to("watchpoint " + subcommand + " ", ["1"])
311
312    def test_settings_append_target_er(self):
313        """Test that 'settings append target.er' completes to 'settings append target.error-path'."""
314        self.complete_from_to(
315            "settings append target.er", "settings append target.error-path"
316        )
317
318    def test_settings_insert_after_target_en(self):
319        """Test that 'settings insert-after target.env' completes to 'settings insert-after target.env-vars'."""
320        self.complete_from_to(
321            "settings insert-after target.env", "settings insert-after target.env-vars"
322        )
323
324    def test_settings_insert_before_target_en(self):
325        """Test that 'settings insert-before target.env' completes to 'settings insert-before target.env-vars'."""
326        self.complete_from_to(
327            "settings insert-before target.env",
328            "settings insert-before target.env-vars",
329        )
330
331    def test_settings_replace_target_ru(self):
332        """Test that 'settings replace target.ru' completes to 'settings replace target.run-args'."""
333        self.complete_from_to(
334            "settings replace target.ru", "settings replace target.run-args"
335        )
336
337    def test_settings_show_term(self):
338        self.complete_from_to("settings show term-w", "settings show term-width")
339
340    def test_settings_list_term(self):
341        self.complete_from_to("settings list term-w", "settings list term-width")
342
343    def test_settings_show_term(self):
344        self.complete_from_to("settings show term-h", "settings show term-height")
345
346    def test_settings_list_term(self):
347        self.complete_from_to("settings list term-h", "settings list term-height")
348
349    def test_settings_remove_term(self):
350        self.complete_from_to("settings remove term-w", "settings remove term-width")
351
352    def test_settings_remove_term(self):
353        self.complete_from_to("settings remove term-h", "settings remove term-height")
354
355    def test_settings_s(self):
356        """Test that 'settings s' completes to ['set', 'show']."""
357        self.complete_from_to("settings s", ["set", "show"])
358
359    def test_settings_set_th(self):
360        """Test that 'settings set thread-f' completes to 'settings set thread-format'."""
361        self.complete_from_to("settings set thread-f", "settings set thread-format")
362
363    def test_settings_s_dash(self):
364        """Test that 'settings set --g' completes to 'settings set --global'."""
365        self.complete_from_to("settings set --g", "settings set --global")
366
367    def test_settings_clear_th(self):
368        """Test that 'settings clear thread-f' completes to 'settings clear thread-format'."""
369        self.complete_from_to("settings clear thread-f", "settings clear thread-format")
370
371    def test_settings_set_ta(self):
372        """Test that 'settings set ta' completes to 'settings set target.'."""
373        self.complete_from_to("settings set target.ma", "settings set target.max-")
374
375    def test_settings_set_target_exec(self):
376        """Test that 'settings set target.exec' completes to 'settings set target.exec-search-paths '."""
377        self.complete_from_to(
378            "settings set target.exec", "settings set target.exec-search-paths"
379        )
380
381    def test_settings_set_target_pr(self):
382        """Test that 'settings set target.pr' completes to [
383        'target.prefer-dynamic-value', 'target.process.']."""
384        self.complete_from_to(
385            "settings set target.pr", ["target.prefer-dynamic-value", "target.process."]
386        )
387
388    def test_settings_set_target_process(self):
389        """Test that 'settings set target.process' completes to 'settings set target.process.'."""
390        self.complete_from_to(
391            "settings set target.process", "settings set target.process."
392        )
393
394    def test_settings_set_target_process_dot(self):
395        """Test that 'settings set target.process.t' completes to 'settings set target.process.thread.'."""
396        self.complete_from_to(
397            "settings set target.process.thr", "settings set target.process.thread."
398        )
399
400    def test_settings_set_target_process_thread_dot(self):
401        """Test that 'settings set target.process.thread.' completes to [
402        'target.process.thread.step-avoid-regexp', 'target.process.thread.trace-thread'].
403        """
404        self.complete_from_to(
405            "settings set target.process.thread.",
406            [
407                "target.process.thread.step-avoid-regexp",
408                "target.process.thread.trace-thread",
409            ],
410        )
411
412    def test_settings_set_can_complete_setting_enum_values(self):
413        """Checks that we can complete the values of an enum setting."""
414        self.complete_from_to(
415            "settings set stop-disassembly-display ",
416            ["never", "always", "no-debuginfo", "no-source"],
417        )
418
419    def test_thread_plan_discard(self):
420        self.build()
421        (_, _, thread, _) = lldbutil.run_to_source_breakpoint(
422            self, "ptr_foo", lldb.SBFileSpec("main.cpp")
423        )
424        self.assertTrue(thread)
425        self.complete_from_to("thread plan discard ", "thread plan discard ")
426
427        source_path = os.path.join(self.getSourceDir(), "thread_plan_script.py")
428        self.runCmd("command script import '%s'" % (source_path))
429        self.runCmd("thread step-scripted -C thread_plan_script.PushPlanStack")
430        self.complete_from_to("thread plan discard ", "thread plan discard 1")
431        self.runCmd("thread plan discard 1")
432
433    def test_target_space(self):
434        """Test that 'target ' completes to ['create', 'delete', 'list',
435        'modules', 'select', 'stop-hook', 'variable']."""
436        self.complete_from_to(
437            "target ",
438            ["create", "delete", "list", "modules", "select", "stop-hook", "variable"],
439        )
440
441    def test_target_modules_dump_line_table(self):
442        """Tests source file completion by completing the line-table argument."""
443        self.build()
444        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
445        self.complete_from_to("target modules dump line-table main.cp", ["main.cpp"])
446
447    def test_custom_command_completion(self):
448        """Tests completion in custom user provided commands."""
449        completion_types = [
450            "none",
451            "source-file",
452            "disk-file",
453            "disk-directory",
454            "symbol",
455            "module",
456            "settings-name",
457            "platform-plugin",
458            "architecture",
459            "variable-path",
460            "register",
461            "breakpoint",
462            "process-plugin",
463            "disassembly-flavor",
464            "type-language",
465            "frame-index",
466            "module-uuid",
467            "stophook-id",
468            "thread-index",
469            "watchpoint-id",
470            "breakpoint-name",
471            "process-id",
472            "process-name",
473            "remote-disk-file",
474            "remote-disk-directory",
475            "type-category-name",
476            "custom",
477        ]
478        self.completions_contain("command script add -C ", completion_types)
479
480        source_path = os.path.join(self.getSourceDir(), "my_test_cmd.py")
481        self.runCmd("command script import '%s'" % (source_path))
482        self.runCmd(
483            "command script add -C disk-file -f my_test_cmd.my_test_cmd my_test_cmd"
484        )
485        self.complete_from_to("my_test_cmd main.cp", ["main.cpp"])
486        self.expect("my_test_cmd main.cpp", substrs=["main.cpp"])
487
488    @skipIf(hostoslist=["windows"])
489    def test_completion_target_create_from_root_dir(self):
490        """Tests source file completion by completing ."""
491        root_dir = os.path.abspath(os.sep)
492        self.completions_contain(
493            "target create " + root_dir,
494            list(
495                filter(
496                    lambda x: os.path.exists(x) and os.path.isdir(x),
497                    map(lambda x: root_dir + x + os.sep, os.listdir(root_dir)),
498                )
499            ),
500        )
501
502    def test_target_modules_load_aout(self):
503        """Tests modules completion by completing the target modules load argument."""
504        self.build()
505        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
506        self.complete_from_to("target modules load a.ou", ["a.out"])
507
508    def test_target_modules_search_paths_insert(self):
509        # Completion won't work without a valid target.
510        self.complete_from_to(
511            "target modules search-paths insert ", "target modules search-paths insert "
512        )
513        self.build()
514        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
515        self.assertTrue(target, VALID_TARGET)
516        self.complete_from_to(
517            "target modules search-paths insert ", "target modules search-paths insert "
518        )
519        self.runCmd("target modules search-paths add a b")
520        self.complete_from_to(
521            "target modules search-paths insert ",
522            "target modules search-paths insert 0",
523        )
524        # Completion only works for the first arg.
525        self.complete_from_to(
526            "target modules search-paths insert 0 ",
527            "target modules search-paths insert 0 ",
528        )
529
530    def test_target_create_dash_co(self):
531        """Test that 'target create --co' completes to 'target variable --core '."""
532        self.complete_from_to("target create --co", "target create --core ")
533
534    def test_target_va(self):
535        """Test that 'target va' completes to 'target variable '."""
536        self.complete_from_to("target va", "target variable ")
537
538    def test_common_completion_thread_index(self):
539        subcommands = [
540            "continue",
541            "info",
542            "exception",
543            "select",
544            "step-in",
545            "step-inst",
546            "step-inst-over",
547            "step-out",
548            "step-over",
549            "step-script",
550        ]
551
552        # Completion should do nothing without threads.
553        for subcommand in subcommands:
554            self.complete_from_to(
555                "thread " + subcommand + " ", "thread " + subcommand + " "
556            )
557
558        self.build()
559        lldbutil.run_to_source_breakpoint(
560            self, "// Break here", lldb.SBFileSpec("main.cpp")
561        )
562
563        # At least we have the thread at the index of 1 now.
564        for subcommand in subcommands:
565            self.complete_from_to("thread " + subcommand + " ", ["1"])
566
567    def test_common_completion_type_category_name(self):
568        subcommands = ["delete", "list", "enable", "disable", "define"]
569        for subcommand in subcommands:
570            self.complete_from_to("type category " + subcommand + " ", ["default"])
571        self.complete_from_to("type filter add -w ", ["default"])
572
573    def test_command_argument_completion(self):
574        """Test completion of command arguments"""
575        self.complete_from_to("watchpoint set variable -", ["-w", "-s"])
576        self.complete_from_to(
577            "watchpoint set variable -w", "watchpoint set variable -w "
578        )
579        self.complete_from_to("watchpoint set variable --", ["--watch", "--size"])
580        self.complete_from_to(
581            "watchpoint set variable --w", "watchpoint set variable --watch"
582        )
583        self.complete_from_to(
584            "watchpoint set variable -w ", ["read", "write", "read_write"]
585        )
586        self.complete_from_to(
587            "watchpoint set variable --watch ", ["read", "write", "read_write"]
588        )
589        self.complete_from_to(
590            "watchpoint set variable --watch w", "watchpoint set variable --watch write"
591        )
592        self.complete_from_to(
593            "watchpoint set variable -w read_", "watchpoint set variable -w read_write"
594        )
595        # Now try the same thing with a variable name (non-option argument) to
596        # test that getopts arg reshuffling doesn't confuse us.
597        self.complete_from_to("watchpoint set variable foo -", ["-w", "-s"])
598        self.complete_from_to(
599            "watchpoint set variable foo -w", "watchpoint set variable foo -w "
600        )
601        self.complete_from_to("watchpoint set variable foo --", ["--watch", "--size"])
602        self.complete_from_to(
603            "watchpoint set variable foo --w", "watchpoint set variable foo --watch"
604        )
605        self.complete_from_to(
606            "watchpoint set variable foo -w ", ["read", "write", "read_write"]
607        )
608        self.complete_from_to(
609            "watchpoint set variable foo --watch ", ["read", "write", "read_write"]
610        )
611        self.complete_from_to(
612            "watchpoint set variable foo --watch w",
613            "watchpoint set variable foo --watch write",
614        )
615        self.complete_from_to(
616            "watchpoint set variable foo -w read_",
617            "watchpoint set variable foo -w read_write",
618        )
619
620    def test_command_script_delete(self):
621        self.runCmd("command script add -h test_desc -f none -s current usercmd1")
622        self.check_completion_with_desc("command script delete ", [["usercmd1", ""]])
623
624    def test_command_delete(self):
625        self.runCmd(
626            r"command regex test_command s/^$/finish/ 's/([0-9]+)/frame select %1/'"
627        )
628        self.complete_from_to("command delete test_c", "command delete test_command")
629
630    def test_command_unalias(self):
631        self.complete_from_to("command unalias ima", "command unalias image")
632
633    def test_command_aliases(self):
634        self.runCmd("command alias brkpt breakpoint")
635        # Exact matches are chosen if possible, even if there are longer
636        # completions we could use.
637        self.complete_from_to("b", "b ")
638        # Aliases are included in possible completions.
639        self.complete_from_to("br", ["breakpoint", "brkpt"])
640        # An alias can be the chosen completion.
641        self.complete_from_to("brk", "brkpt")
642
643        # The list can contain only aliases if there's no built-ins to match.
644        self.runCmd("command alias test_1 breakpoint")
645        self.runCmd("command alias test_2 breakpoint")
646        self.complete_from_to("test_", ["test_1", "test_2"])
647
648    def test_completion_description_commands(self):
649        """Test descriptions of top-level command completions"""
650        self.check_completion_with_desc(
651            "",
652            [
653                ["command", "Commands for managing custom LLDB commands."],
654                [
655                    "breakpoint",
656                    "Commands for operating on breakpoints (see 'help b' for shorthand.)",
657                ],
658            ],
659        )
660
661        self.check_completion_with_desc(
662            "pl",
663            [
664                ["platform", "Commands to manage and create platforms."],
665                ["plugin", "Commands for managing LLDB plugins."],
666            ],
667        )
668
669        # Just check that this doesn't crash.
670        self.check_completion_with_desc("comman", [])
671        self.check_completion_with_desc("non-existent-command", [])
672
673    def test_completion_description_command_options(self):
674        """Test descriptions of command options"""
675        # Short options
676        self.check_completion_with_desc(
677            "breakpoint set -",
678            [
679                ["-h", "Set the breakpoint on exception catcH."],
680                ["-w", "Set the breakpoint on exception throW."],
681            ],
682        )
683
684        # Long options.
685        self.check_completion_with_desc(
686            "breakpoint set --",
687            [
688                ["--on-catch", "Set the breakpoint on exception catcH."],
689                ["--on-throw", "Set the breakpoint on exception throW."],
690            ],
691        )
692
693        # Ambiguous long options.
694        self.check_completion_with_desc(
695            "breakpoint set --on-",
696            [
697                ["--on-catch", "Set the breakpoint on exception catcH."],
698                ["--on-throw", "Set the breakpoint on exception throW."],
699            ],
700        )
701
702        # Unknown long option.
703        self.check_completion_with_desc("breakpoint set --Z", [])
704
705    def test_common_completion_frame_index(self):
706        self.build()
707        lldbutil.run_to_source_breakpoint(
708            self, "// Break here", lldb.SBFileSpec("main.cpp")
709        )
710
711        self.complete_from_to("frame select ", ["0"])
712        self.complete_from_to("thread backtrace -s ", ["0"])
713
714    def test_frame_recognizer_delete(self):
715        self.runCmd(
716            "frame recognizer add -l py_class -s module_name -n recognizer_name"
717        )
718        self.check_completion_with_desc(
719            "frame recognizer delete ",
720            [["0", "py_class, module module_name, demangled symbol recognizer_name"]],
721        )
722
723    def test_platform_install_local_file(self):
724        self.complete_from_to(
725            "platform target-install main.cp", "platform target-install main.cpp"
726        )
727
728    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
729    def test_symbol_name(self):
730        self.build()
731        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
732        self.complete_from_to(
733            "breakpoint set -n Fo", "breakpoint set -n Foo::Bar(int,\\ int)"
734        )
735        # No completion for Qu because the candidate is
736        # (anonymous namespace)::Quux().
737        self.complete_from_to("breakpoint set -n Qu", "")
738
739    def test_completion_type_formatter_delete(self):
740        self.runCmd("type filter add --child a Aoo")
741        self.complete_from_to("type filter delete ", ["Aoo"])
742        self.runCmd("type filter add --child b -x Boo")
743        self.complete_from_to("type filter delete ", ["Boo"])
744
745        self.runCmd("type format add -f hex Coo")
746        self.complete_from_to("type format delete ", ["Coo"])
747        self.runCmd("type format add -f hex -x Doo")
748        self.complete_from_to("type format delete ", ["Doo"])
749
750        self.runCmd("type summary add -c Eoo")
751        self.complete_from_to("type summary delete ", ["Eoo"])
752        self.runCmd("type summary add -x -c Foo")
753        self.complete_from_to("type summary delete ", ["Foo"])
754
755        self.runCmd("type synthetic add Goo -l test")
756        self.complete_from_to("type synthetic delete ", ["Goo"])
757        self.runCmd("type synthetic add -x Hoo -l test")
758        self.complete_from_to("type synthetic delete ", ["Hoo"])
759
760    def test_register_no_complete(self):
761        # The tab completion for "register read/write"  won't work without a running process.
762        self.complete_from_to("register read ", "register read ")
763        self.complete_from_to("register write ", "register write ")
764        self.complete_from_to("register info ", "register info ")
765
766        self.build()
767        self.runCmd("target create {}".format(self.getBuildArtifact("a.out")))
768        self.runCmd("run")
769
770        # Once a program has finished you have an execution context but no register
771        # context so completion cannot work.
772        self.complete_from_to("register read ", "register read ")
773        self.complete_from_to("register write ", "register write ")
774        self.complete_from_to("register info ", "register info ")
775
776    @skipIf(archs=no_match(["x86_64"]))
777    def test_register_read_and_write_on_x86(self):
778        """Test the completion of the commands register read and write on x86"""
779
780        self.build()
781        self.main_source_spec = lldb.SBFileSpec("main.cpp")
782        lldbutil.run_to_source_breakpoint(self, "// Break here", self.main_source_spec)
783
784        # test cases for register read
785        self.complete_from_to("register read ", ["rax", "rbx", "rcx"])
786        self.complete_from_to("register read r", ["rax", "rbx", "rcx"])
787        self.complete_from_to("register read ra", "register read rax")
788        # register read can take multiple register names as arguments
789        self.complete_from_to("register read rax ", ["rax", "rbx", "rcx"])
790        # complete with prefix '$'
791        self.completions_match("register read $rb", ["$rbx", "$rbp"])
792        self.completions_match("register read $ra", ["$rax"])
793        self.complete_from_to("register read rax $", ["$rax", "$rbx", "$rcx"])
794        self.complete_from_to("register read $rax ", ["rax", "rbx", "rcx"])
795
796        # test cases for register write
797        self.complete_from_to("register write ", ["rax", "rbx", "rcx"])
798        self.complete_from_to("register write r", ["rax", "rbx", "rcx"])
799        self.complete_from_to("register write ra", "register write rax")
800        self.complete_from_to("register write rb", ["rbx", "rbp"])
801        # register write can only take exact one register name as argument
802        self.complete_from_to("register write rbx ", [])
803
804    def test_common_completion_target_stophook_ids(self):
805        subcommands = ["delete", "enable", "disable"]
806
807        for subcommand in subcommands:
808            self.complete_from_to(
809                "target stop-hook " + subcommand + " ",
810                "target stop-hook " + subcommand + " ",
811            )
812
813        self.build()
814        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
815        self.runCmd("target stop-hook add -o test")
816
817        for subcommand in subcommands:
818            self.complete_from_to(
819                "target stop-hook " + subcommand + " ",
820                "target stop-hook " + subcommand + " 1",
821            )
822
823        # Completion should work only on the first argument.
824        for subcommand in subcommands:
825            self.complete_from_to(
826                "target stop-hook " + subcommand + " 1 ",
827                "target stop-hook " + subcommand + " 1 ",
828            )
829
830    def test_common_completion_type_language(self):
831        self.complete_from_to("type category -l ", ["c"])
832
833    def test_target_modules_load_dash_u(self):
834        self.build()
835        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
836        self.complete_from_to(
837            "target modules load -u ", [target.GetModuleAtIndex(0).GetUUIDString()]
838        )
839
840    def test_complete_breakpoint_with_ids(self):
841        """These breakpoint subcommands should be completed with a list of breakpoint ids"""
842
843        subcommands = [
844            "enable",
845            "disable",
846            "delete",
847            "modify",
848            "name add",
849            "name delete",
850            "write",
851        ]
852
853        # The tab completion here is unavailable without a target
854        for subcommand in subcommands:
855            self.complete_from_to(
856                "breakpoint " + subcommand + " ", "breakpoint " + subcommand + " "
857            )
858
859        self.build()
860        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
861        self.assertTrue(target, VALID_TARGET)
862
863        bp = target.BreakpointCreateByName("main", "a.out")
864        self.assertTrue(bp)
865        self.assertEqual(bp.GetNumLocations(), 1)
866
867        for subcommand in subcommands:
868            self.complete_from_to("breakpoint " + subcommand + " ", ["1"])
869
870        bp2 = target.BreakpointCreateByName("Bar", "a.out")
871        self.assertTrue(bp2)
872        self.assertEqual(bp2.GetNumLocations(), 1)
873
874        for subcommand in subcommands:
875            self.complete_from_to("breakpoint " + subcommand + " ", ["1", "2"])
876
877        for subcommand in subcommands:
878            self.complete_from_to("breakpoint " + subcommand + " 1 ", ["1", "2"])
879
880    def test_complete_breakpoint_with_names(self):
881        self.build()
882        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
883        self.assertTrue(target, VALID_TARGET)
884
885        # test breakpoint read dedicated
886        self.complete_from_to("breakpoint read -N ", "breakpoint read -N ")
887        self.complete_from_to("breakpoint read -f breakpoints.json -N ", ["mm"])
888        self.complete_from_to(
889            "breakpoint read -f breakpoints.json -N n",
890            "breakpoint read -f breakpoints.json -N n",
891        )
892        self.complete_from_to(
893            "breakpoint read -f breakpoints_invalid.json -N ",
894            "breakpoint read -f breakpoints_invalid.json -N ",
895        )
896
897        # test common breapoint name completion
898        bp1 = target.BreakpointCreateByName("main", "a.out")
899        self.assertTrue(bp1)
900        self.assertEqual(bp1.GetNumLocations(), 1)
901        self.complete_from_to("breakpoint set -N n", "breakpoint set -N n")
902        self.assertTrue(bp1.AddNameWithErrorHandling("nn"))
903        self.complete_from_to("breakpoint set -N ", "breakpoint set -N nn")
904
905    def test_ambiguous_command(self):
906        """Test completing an ambiguous commands"""
907        self.complete_from_to("settings s", ["set", "show"])
908
909    def test_ambiguous_subcommand(self):
910        """Test completing a subcommand of an ambiguous command"""
911        self.complete_from_to("settings s ta", [])
912
913    def test_shlib_name(self):
914        self.build()
915        error = lldb.SBError()
916        # Create a target, but don't load dependent modules
917        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"), None, None, False, error)
918        self.assertSuccess(error)
919        self.registerSharedLibrariesWithTarget(target, ["shared"])
920
921        basenames = []
922        paths = []
923        for m in target.modules:
924            basenames.append(m.file.basename)
925            paths.append(m.file.fullpath)
926
927        # To see all the diffs
928        self.maxDiff = None
929
930        # An empty string completes to everything
931        self.completions_match("target symbols add -s ", basenames + paths)
932
933        # Base name completion
934        self.completions_match("target symbols add -s a.", ["a.out"])
935
936        # Full path completion
937        prefix = os.path.commonpath(paths)
938        self.completions_match("target symbols add -s '" + prefix, paths)
939
940        # Full path, but ending with a path separator
941        prefix_sep = prefix + os.path.sep
942        self.completions_match("target symbols add -s '" + prefix_sep, paths)
943
944        # The completed path should match the spelling of the input, so if the
945        # input contains a double separator, so should the completions.
946        prefix_sep_sep = prefix_sep + os.path.sep
947        paths_sep = [prefix_sep_sep + p[len(prefix_sep) :] for p in paths]
948        self.completions_match("target symbols add -s '" + prefix_sep_sep, paths_sep)
949