blob: 550e622f1742e8f865d805e84a6c849337cc2140 [file] [log] [blame]
// Copyright 2019 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/mock_console.h"
#include <lib/syslog/cpp/macros.h>
#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/command_parser.h"
namespace zxdb {
void MockConsole::Write(const OutputBuffer& output, bool add_newline) {
output_queue_.push_back({MockConsole::OutputEvent::Type::kOutput, output});
output_buffer_.Append(output);
if (waiting_for_output_) {
waiting_for_output_ = false;
debug::MessageLoop::Current()->QuitNow();
}
for (auto& observer : output_observers_) {
observer.OnOutput(output);
}
}
void MockConsole::Clear() {
output_queue_.push_back({MockConsole::OutputEvent::Type::kClear, OutputBuffer()});
output_buffer_.Clear();
if (waiting_for_output_) {
waiting_for_output_ = false;
debug::MessageLoop::Current()->QuitNow();
}
}
MockConsole::OutputEvent MockConsole::GetOutputEvent() {
FX_DCHECK(!waiting_for_output_);
if (output_queue_.empty() && debug::MessageLoop::Current()) {
waiting_for_output_ = true;
debug::MessageLoop::Current()->Run();
}
waiting_for_output_ = false;
if (output_queue_.empty()) {
return {MockConsole::OutputEvent::Type::kQuitEarly, OutputBuffer()};
}
auto ret = std::move(output_queue_.front());
output_queue_.erase(output_queue_.begin());
return ret;
}
void MockConsole::FlushOutputEvents() { output_queue_.clear(); }
bool MockConsole::SendModalReply(const std::string& line) {
if (!last_modal_cb_)
return false;
// Clear callback before issuing the callback so it can issue more if necessary.
auto cb = std::move(last_modal_cb_);
cb(line);
return true;
}
void MockConsole::ModalGetOption(const line_input::ModalPromptOptions& options,
OutputBuffer message, const std::string& prompt,
line_input::ModalLineInput::ModalCompletionCallback cb) {
// Only one modal prompt is supported at a time by this mock. Otherwise things will get confused
// when sending the mock reply.
FX_DCHECK(!last_modal_cb_);
last_modal_cb_ = std::move(cb);
// Add the message to the output queue so tests can see what as printed for this prompt.
GetWeakPtr()->Output(message);
}
void MockConsole::ProcessInputLine(const std::string& line, fxl::RefPtr<CommandContext> cmd_context,
bool add_to_history) {
if (!cmd_context)
cmd_context = fxl::MakeRefCounted<ConsoleCommandContext>(this);
FX_DCHECK(!line.empty());
Command cmd;
if (Err err = ParseCommand(line, &cmd); err.has_error())
return cmd_context->ReportError(err);
cmd_context->SetCommandReport(cmd.BuildReport());
if (Err err = context_.FillOutCommand(&cmd); err.has_error())
return cmd_context->ReportError(err);
DispatchCommand(cmd, cmd_context);
if (cmd.thread() && cmd.verb() != Verb::kNone) {
// Show the right source/disassembly for the next listing.
context_.SetSourceAffinityForThread(cmd.thread(), GetVerbRecord(cmd.verb())->source_affinity);
}
}
void MockConsole::ProcessInputLine(const std::string& line,
OfflineCommandContext::CompletionCallback cb) {
return ProcessInputLine(line, fxl::MakeRefCounted<OfflineCommandContext>(this, std::move(cb)));
}
} // namespace zxdb