| // 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 |