xref: /llvm-project/lldb/unittests/Interpreter/TestCommandPaths.cpp (revision 92d8a28cc665d73d9d679b8c014dd04f95d1df18)
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 
23 using namespace lldb_private;
24 using namespace lldb_private::repro;
25 using namespace lldb;
26 
27 namespace {
28 class VerifyUserMultiwordCmdPathTest : public ::testing::Test {
SetUp()29   void SetUp() override {
30     FileSystem::Initialize();
31     HostInfo::Initialize();
32     PlatformMacOSX::Initialize();
33   }
TearDown()34   void TearDown() override {
35     PlatformMacOSX::Terminate();
36     HostInfo::Terminate();
37     FileSystem::Terminate();
38   }
39 };
40 } // namespace
41 
42 class CommandObjectLeaf : public CommandObjectParsed {
43 public:
CommandObjectLeaf(CommandInterpreter & interpreter)44   CommandObjectLeaf(CommandInterpreter &interpreter)
45       : CommandObjectParsed(interpreter, "dummy subcommand leaf",
46                             "Does nothing", "dummy subcommand leaf") {
47     SetIsUserCommand(true);
48   }
49 
50 protected:
DoExecute(Args & command,CommandReturnObject & result)51   void DoExecute(Args &command, CommandReturnObject &result) override {
52     result.SetStatus(eReturnStatusSuccessFinishResult);
53     result.AppendMessage("I did nothing");
54   }
55 };
56 
57 class CommandObjectMultiwordSubDummy : public CommandObjectMultiword {
58 public:
CommandObjectMultiwordSubDummy(CommandInterpreter & interpreter)59   CommandObjectMultiwordSubDummy(CommandInterpreter &interpreter)
60       : CommandObjectMultiword(interpreter, "dummy subcommand", "Does nothing",
61                                "dummy subcommand") {
62     SetIsUserCommand(true);
63     LoadSubCommand("leaf", CommandObjectSP(new CommandObjectLeaf(interpreter)));
64   }
65 
66   ~CommandObjectMultiwordSubDummy() override = default;
67 };
68 
69 class CommandObjectMultiwordDummy : public CommandObjectMultiword {
70 public:
CommandObjectMultiwordDummy(CommandInterpreter & interpreter)71   CommandObjectMultiwordDummy(CommandInterpreter &interpreter)
72       : CommandObjectMultiword(interpreter, "dummy", "Does nothing", "dummy") {
73     SetIsUserCommand(true);
74     LoadSubCommand(
75         "subcommand",
76         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.
RunTest(CommandInterpreter & interp,const char * args,bool is_leaf,bool success,const char * test_str)85 void 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(test_args, is_leaf, 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 
TEST_F(VerifyUserMultiwordCmdPathTest,TestErrors)103 TEST_F(VerifyUserMultiwordCmdPathTest, TestErrors) {
104   ArchSpec arch("x86_64-apple-macosx-");
105 
106   Platform::SetHostPlatform(PlatformRemoteMacOSX::CreateInstance(true, &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, "process launch", is_leaf, success,
121           "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, "wewouldnevernameacommandthis subcommand", is_leaf, success,
127           "Path component: 'wewouldnevernameacommandthis' not found");
128 
129   // Now we have to add a multiword command, and then probe it.
130   error = interp.AddUserCommand(
131       "dummy", CommandObjectSP(new CommandObjectMultiwordDummy(interp)), 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, "dummy subcommand", is_leaf, success, "dummy subcommand");
138 
139   is_leaf = true;
140   RunTest(interp, "dummy subcommand", is_leaf, success, "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, "dummy subcommand leaf", is_leaf, success,
147           "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, "dummy subcommand leaf", is_leaf, success,
153           "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, "dummy not-subcommand", is_leaf, success,
159           "Path component: 'not-subcommand' not found");
160 }
161