| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/developer/debug/zxdb/console/actions.h" |
| |
| #include <gtest/gtest.h> |
| |
| #include "src/developer/debug/shared/platform_message_loop.h" |
| #include "src/developer/debug/zxdb/client/session.h" |
| #include "src/developer/debug/zxdb/common/test_with_loop.h" |
| #include "src/developer/debug/zxdb/console/console_impl.h" |
| #include "src/lib/fxl/strings/string_printf.h" |
| |
| namespace zxdb { |
| |
| namespace { |
| |
| using debug::MessageLoop; |
| |
| #define STOP_MESSAGE_LOOP() \ |
| MessageLoop::Current()->PostTask(FROM_HERE, []() { MessageLoop::Current()->QuitNow(); }) |
| |
| // We override the Console in order to be able to override the dispatch |
| // function |
| class ConsoleTest : public ConsoleImpl { |
| public: |
| ConsoleTest(Session* session) : ConsoleImpl(session) {} |
| |
| void ProcessInputLine(const std::string& line, CommandCallback callback, |
| bool add_to_history) override { |
| // We update the info |
| calls.push_back(line); |
| if (callback) { |
| callback(errors_to_run[call_count]); |
| } |
| call_count++; |
| } |
| |
| std::vector<std::string> calls; |
| std::vector<Err> errors_to_run; |
| size_t call_count = 0; |
| }; |
| |
| class ActionsTest : public TestWithLoop { |
| protected: |
| ActionsTest() { |
| session = std::make_unique<Session>(); |
| console = std::make_unique<ConsoleTest>(session.get()); |
| } |
| |
| std::unique_ptr<Session> session; |
| std::unique_ptr<ConsoleTest> console; |
| }; |
| |
| } // namespace |
| |
| using debug::MessageLoop; |
| |
| TEST_F(ActionsTest, ScriptFile) { |
| // We expect 3 calls |
| console->errors_to_run = {Err(), Err(), Err()}; |
| // Setup the mock contents |
| std::vector<std::string> mock_commands = {"help", "connect 192.168.0.1 2345", "break main", |
| "run /path/to/binary"}; |
| std::stringstream ss; |
| ss << mock_commands[0] << "\n" << mock_commands[1] << "\n" << mock_commands[2]; |
| std::string mock_contents = ss.str(); |
| |
| auto actions = CommandsToActions(mock_contents); |
| |
| ASSERT_EQ(actions.size(), 3u); |
| EXPECT_EQ(actions[0].name(), mock_commands[0]); |
| EXPECT_EQ(actions[1].name(), mock_commands[1]); |
| EXPECT_EQ(actions[2].name(), mock_commands[2]); |
| |
| Err callback_err("FAIL"); |
| auto callback = [&](Err err) { |
| callback_err = err; |
| STOP_MESSAGE_LOOP(); |
| }; |
| // The callback mechanism depends on a global ActionFlow |
| ActionFlow& flow = ActionFlow::Singleton(); |
| flow.Clear(); |
| flow.ScheduleActions(std::move(actions), session.get(), console.get(), callback); |
| loop().Run(); |
| |
| EXPECT_FALSE(callback_err.has_error()) << callback_err.msg(); |
| |
| ASSERT_EQ(console->calls.size(), 3u); |
| EXPECT_EQ(console->calls[0], mock_commands[0]); |
| EXPECT_EQ(console->calls[1], mock_commands[1]); |
| EXPECT_EQ(console->calls[2], mock_commands[2]); |
| |
| ASSERT_EQ(flow.callbacks().size(), 3u); |
| EXPECT_FALSE(flow.callbacks()[0].has_error()); |
| EXPECT_FALSE(flow.callbacks()[1].has_error()); |
| EXPECT_FALSE(flow.callbacks()[2].has_error()); |
| } |
| |
| TEST_F(ActionsTest, ScriptFileWithFailure) { |
| // We expect an error |
| console->errors_to_run = {Err(), Err("ERROR"), Err()}; |
| // Setup the mock contents |
| std::vector<std::string> mock_commands = {"help", "connect 192.168.0.1 2345", |
| "run /path/to/binary"}; |
| std::stringstream ss; |
| ss << mock_commands[0] << "\n" << mock_commands[1] << "\n" << mock_commands[2]; |
| std::string mock_contents = ss.str(); |
| |
| auto actions = CommandsToActions(mock_contents); |
| |
| ASSERT_EQ(actions.size(), 3u); |
| EXPECT_EQ(actions[0].name(), mock_commands[0]); |
| EXPECT_EQ(actions[1].name(), mock_commands[1]); |
| EXPECT_EQ(actions[2].name(), mock_commands[2]); |
| |
| Err callback_err("FAIL"); |
| auto callback = [&](Err err) { |
| callback_err = err; |
| STOP_MESSAGE_LOOP(); |
| }; |
| |
| // The callback mechanism depends on a global ActionFlow |
| ActionFlow& flow = ActionFlow::Singleton(); |
| flow.Clear(); |
| flow.ScheduleActions(std::move(actions), session.get(), console.get(), callback); |
| loop().Run(); |
| |
| // The error callback was called |
| EXPECT_TRUE(callback_err.has_error()); |
| |
| // The second call fails |
| ASSERT_EQ(console->calls.size(), 2u); |
| EXPECT_EQ(console->calls[0], mock_commands[0]); |
| EXPECT_EQ(console->calls[1], mock_commands[1]); |
| |
| ASSERT_EQ(flow.callbacks().size(), 2u); |
| EXPECT_FALSE(flow.callbacks()[0].has_error()); |
| EXPECT_TRUE(flow.callbacks()[1].has_error()); |
| } |
| |
| } // namespace zxdb |