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 { 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 42 class CommandObjectLeaf : public CommandObjectParsed { 43 public: 44 CommandObjectLeaf(CommandInterpreter &interpreter) 45 : CommandObjectParsed(interpreter, "dummy subcommand leaf", 46 "Does nothing", "dummy subcommand leaf") { 47 SetIsUserCommand(true); 48 } 49 50 protected: 51 bool DoExecute(Args &command, CommandReturnObject &result) override { 52 result.SetStatus(eReturnStatusSuccessFinishResult); 53 result.AppendMessage("I did nothing"); 54 return true; 55 } 56 }; 57 58 class CommandObjectMultiwordSubDummy : public CommandObjectMultiword { 59 public: 60 CommandObjectMultiwordSubDummy(CommandInterpreter &interpreter) 61 : CommandObjectMultiword(interpreter, "dummy subcommand", "Does nothing", 62 "dummy subcommand") { 63 SetIsUserCommand(true); 64 LoadSubCommand("leaf", CommandObjectSP(new CommandObjectLeaf(interpreter))); 65 } 66 67 ~CommandObjectMultiwordSubDummy() override = default; 68 }; 69 70 class CommandObjectMultiwordDummy : public CommandObjectMultiword { 71 public: 72 CommandObjectMultiwordDummy(CommandInterpreter &interpreter) 73 : CommandObjectMultiword(interpreter, "dummy", "Does nothing", "dummy") { 74 SetIsUserCommand(true); 75 LoadSubCommand( 76 "subcommand", 77 CommandObjectSP(new CommandObjectMultiwordSubDummy(interpreter))); 78 } 79 80 ~CommandObjectMultiwordDummy() override = default; 81 }; 82 83 // Pass in the command path to args. If success is true, we make sure the MWC 84 // returned matches the test string. If success is false, we make sure the 85 // lookup error matches test_str. 86 void RunTest(CommandInterpreter &interp, const char *args, bool is_leaf, 87 bool success, const char *test_str) { 88 CommandObjectMultiword *multi_word_cmd = nullptr; 89 Args test_args(args); 90 Status error; 91 multi_word_cmd = 92 interp.VerifyUserMultiwordCmdPath(test_args, is_leaf, error); 93 if (success) { 94 ASSERT_NE(multi_word_cmd, nullptr); 95 ASSERT_TRUE(error.Success()); 96 ASSERT_STREQ(multi_word_cmd->GetCommandName().str().c_str(), test_str); 97 } else { 98 ASSERT_EQ(multi_word_cmd, nullptr); 99 ASSERT_TRUE(error.Fail()); 100 ASSERT_STREQ(error.AsCString(), test_str); 101 } 102 } 103 104 TEST_F(VerifyUserMultiwordCmdPathTest, TestErrors) { 105 ArchSpec arch("x86_64-apple-macosx-"); 106 107 Platform::SetHostPlatform(PlatformRemoteMacOSX::CreateInstance(true, &arch)); 108 109 DebuggerSP debugger_sp = Debugger::CreateInstance(); 110 ASSERT_TRUE(debugger_sp); 111 112 CommandInterpreter &interp = debugger_sp->GetCommandInterpreter(); 113 114 Status error; 115 bool success; 116 bool is_leaf; 117 118 // Test that we reject non-user path components: 119 success = false; 120 is_leaf = true; 121 RunTest(interp, "process launch", is_leaf, success, 122 "Path component: 'process' is not a user command"); 123 124 // Test that we reject non-existent commands: 125 is_leaf = true; 126 success = false; 127 RunTest(interp, "wewouldnevernameacommandthis subcommand", is_leaf, success, 128 "Path component: 'wewouldnevernameacommandthis' not found"); 129 130 // Now we have to add a multiword command, and then probe it. 131 error = interp.AddUserCommand( 132 "dummy", CommandObjectSP(new CommandObjectMultiwordDummy(interp)), true); 133 ASSERT_TRUE(error.Success()); 134 135 // Now pass the correct path, and make sure we get back the right MWC. 136 is_leaf = false; 137 success = true; 138 RunTest(interp, "dummy subcommand", is_leaf, success, "dummy subcommand"); 139 140 is_leaf = true; 141 RunTest(interp, "dummy subcommand", is_leaf, success, "dummy"); 142 143 // If you tell us the last node is a leaf, we don't check that. Make sure 144 // that is true: 145 is_leaf = true; 146 success = true; 147 RunTest(interp, "dummy subcommand leaf", is_leaf, success, 148 "dummy subcommand"); 149 // But we should fail if we say the last component is a multiword: 150 151 is_leaf = false; 152 success = false; 153 RunTest(interp, "dummy subcommand leaf", is_leaf, success, 154 "Path component: 'leaf' is not a container command"); 155 156 // We should fail if we get the second path component wrong: 157 is_leaf = false; 158 success = false; 159 RunTest(interp, "dummy not-subcommand", is_leaf, success, 160 "Path component: 'not-subcommand' not found"); 161 } 162