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