1//===-- ProcessEventDataTest.cpp ------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Plugins/Platform/MacOSX/PlatformMacOSX.h"
10#include "Plugins/Platform/MacOSX/PlatformRemoteMacOSX.h"
11#include "lldb/Core/Debugger.h"
12#include "lldb/Host/FileSystem.h"
13#include "lldb/Host/HostInfo.h"
14#include "lldb/Interpreter/CommandInterpreter.h"
15#include "lldb/Interpreter/CommandObject.h"
16#include "lldb/Interpreter/CommandObjectMultiword.h"
17#include "lldb/Interpreter/CommandReturnObject.h"
18#include "lldb/Utility/Args.h"
19#include "lldb/Utility/Status.h"
20
21#include "gtest/gtest.h"
22
23using namespace lldb_private;
24using namespace lldb_private::repro;
25using namespace lldb;
26
27namespace {
28class VerifyUserMultiwordCmdPathTest : public ::testing::Test {
29 void SetUp() override {
30 FileSystem::Initialize();
31 HostInfo::Initialize();
32 PlatformMacOSX::Initialize();
33 }
34 void TearDown() override {
35 PlatformMacOSX::Terminate();
36 HostInfo::Terminate();
37 FileSystem::Terminate();
38 }
39};
40} // namespace
41
42class CommandObjectLeaf : public CommandObjectParsed {
43public:
44 CommandObjectLeaf(CommandInterpreter &interpreter)
45 : CommandObjectParsed(interpreter, "dummy subcommand leaf",
46 "Does nothing", "dummy subcommand leaf") {
47 SetIsUserCommand(true);
48 }
49
50protected:
51 void DoExecute(Args &command, CommandReturnObject &result) override {
52 result.SetStatus(eReturnStatusSuccessFinishResult);
53 result.AppendMessage(in_string: "I did nothing");
54 }
55};
56
57class CommandObjectMultiwordSubDummy : public CommandObjectMultiword {
58public:
59 CommandObjectMultiwordSubDummy(CommandInterpreter &interpreter)
60 : CommandObjectMultiword(interpreter, "dummy subcommand", "Does nothing",
61 "dummy subcommand") {
62 SetIsUserCommand(true);
63 LoadSubCommand(cmd_name: "leaf", command_obj: CommandObjectSP(new CommandObjectLeaf(interpreter)));
64 }
65
66 ~CommandObjectMultiwordSubDummy() override = default;
67};
68
69class CommandObjectMultiwordDummy : public CommandObjectMultiword {
70public:
71 CommandObjectMultiwordDummy(CommandInterpreter &interpreter)
72 : CommandObjectMultiword(interpreter, "dummy", "Does nothing", "dummy") {
73 SetIsUserCommand(true);
74 LoadSubCommand(
75 cmd_name: "subcommand",
76 command_obj: CommandObjectSP(new CommandObjectMultiwordSubDummy(interpreter)));
77 }
78
79 ~CommandObjectMultiwordDummy() override = default;
80};
81
82// Pass in the command path to args. If success is true, we make sure the MWC
83// returned matches the test string. If success is false, we make sure the
84// lookup error matches test_str.
85void RunTest(CommandInterpreter &interp, const char *args, bool is_leaf,
86 bool success, const char *test_str) {
87 CommandObjectMultiword *multi_word_cmd = nullptr;
88 Args test_args(args);
89 Status error;
90 multi_word_cmd =
91 interp.VerifyUserMultiwordCmdPath(path&: test_args, leaf_is_command: is_leaf, result&: error);
92 if (success) {
93 ASSERT_NE(multi_word_cmd, nullptr);
94 ASSERT_TRUE(error.Success());
95 ASSERT_STREQ(multi_word_cmd->GetCommandName().str().c_str(), test_str);
96 } else {
97 ASSERT_EQ(multi_word_cmd, nullptr);
98 ASSERT_TRUE(error.Fail());
99 ASSERT_STREQ(error.AsCString(), test_str);
100 }
101}
102
103TEST_F(VerifyUserMultiwordCmdPathTest, TestErrors) {
104 ArchSpec arch("x86_64-apple-macosx-");
105
106 Platform::SetHostPlatform(PlatformRemoteMacOSX::CreateInstance(force: true, arch: &arch));
107
108 DebuggerSP debugger_sp = Debugger::CreateInstance();
109 ASSERT_TRUE(debugger_sp);
110
111 CommandInterpreter &interp = debugger_sp->GetCommandInterpreter();
112
113 Status error;
114 bool success;
115 bool is_leaf;
116
117 // Test that we reject non-user path components:
118 success = false;
119 is_leaf = true;
120 RunTest(interp, args: "process launch", is_leaf, success,
121 test_str: "Path component: 'process' is not a user command");
122
123 // Test that we reject non-existent commands:
124 is_leaf = true;
125 success = false;
126 RunTest(interp, args: "wewouldnevernameacommandthis subcommand", is_leaf, success,
127 test_str: "Path component: 'wewouldnevernameacommandthis' not found");
128
129 // Now we have to add a multiword command, and then probe it.
130 error = interp.AddUserCommand(
131 name: "dummy", cmd_sp: CommandObjectSP(new CommandObjectMultiwordDummy(interp)), can_replace: true);
132 ASSERT_TRUE(error.Success());
133
134 // Now pass the correct path, and make sure we get back the right MWC.
135 is_leaf = false;
136 success = true;
137 RunTest(interp, args: "dummy subcommand", is_leaf, success, test_str: "dummy subcommand");
138
139 is_leaf = true;
140 RunTest(interp, args: "dummy subcommand", is_leaf, success, test_str: "dummy");
141
142 // If you tell us the last node is a leaf, we don't check that. Make sure
143 // that is true:
144 is_leaf = true;
145 success = true;
146 RunTest(interp, args: "dummy subcommand leaf", is_leaf, success,
147 test_str: "dummy subcommand");
148 // But we should fail if we say the last component is a multiword:
149
150 is_leaf = false;
151 success = false;
152 RunTest(interp, args: "dummy subcommand leaf", is_leaf, success,
153 test_str: "Path component: 'leaf' is not a container command");
154
155 // We should fail if we get the second path component wrong:
156 is_leaf = false;
157 success = false;
158 RunTest(interp, args: "dummy not-subcommand", is_leaf, success,
159 test_str: "Path component: 'not-subcommand' not found");
160}
161

source code of lldb/unittests/Interpreter/TestCommandPaths.cpp