blob: 84b6e27005fc02d3fd948c9c742a8a63cf2701a6 [file] [log] [blame]
// 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