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

#ifndef TOOLS_FIDLCAT_INTERCEPTION_TESTS_INTERCEPTION_WORKFLOW_TEST_H_
#define TOOLS_FIDLCAT_INTERCEPTION_TESTS_INTERCEPTION_WORKFLOW_TEST_H_

#include <zircon/fidl.h>

#include <algorithm>
#include <cstdint>
#include <memory>
#include <sstream>
#include <thread>
#include <utility>
#include <vector>

#include "src/developer/debug/ipc/records.h"
#include "src/developer/debug/shared/arch.h"
#include "src/developer/debug/zxdb/client/frame_impl.h"
#include "src/developer/debug/zxdb/client/mock_remote_api.h"
#include "src/developer/debug/zxdb/client/remote_api_test.h"
#include "src/developer/debug/zxdb/client/target_impl.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/symbols/mock_module_symbols.h"
#include "tools/fidlcat/lib/interception_workflow.h"
#include "tools/fidlcat/lib/replay.h"

namespace fidlcat {

class ProcessController;
class SyscallDecoderDispatcherTest;

constexpr uint64_t kFirstPid = 3141;
constexpr uint64_t kSecondPid = 2718;

constexpr uint64_t kFirstThreadKoid = 8764;
constexpr uint64_t kSecondThreadKoid = 8765;

constexpr uint32_t kHandle = 0xcefa1db0;
constexpr uint64_t kHandleKoid = 1000828;
constexpr uint32_t kHandle2 = 0xcefa1222;
constexpr uint64_t kHandle2Koid = 1000829;
constexpr uint32_t kHandle3 = 0xcefa1333;
constexpr uint32_t kHandleOut = 0xbde90caf;
constexpr uint32_t kHandleOut2 = 0xbde90222;
constexpr uint32_t kPort = 0xdf0b2ec1;
constexpr uint64_t kKey = 1234;
constexpr uint64_t kKoid = 4252;
constexpr uint64_t kKoid2 = 5242;
constexpr zx_futex_t kFutex = 56789;
constexpr zx_futex_t kFutex2 = 98765;

extern SyscallDecoderDispatcher* global_dispatcher;

class SystemCallTest {
 public:
  SystemCallTest(const char* name, int64_t result, std::string_view result_name)
      : name_(name),
        result_({.first_word = result, .second_word = 0}),
        enable_overflow_(false),
        result_name_(result_name) {}

  SystemCallTest(const char* name, result128_t result, std::string_view result_name)
      : name_(name), result_(result), enable_overflow_(true), result_name_(result_name) {}

  const std::string& name() const { return name_; }
  int64_t result() const { return result_.first_word; }
  const std::string& result_name() const { return result_name_; }
  const std::vector<uint64_t>& inputs() const { return inputs_; }

  void AddInput(uint64_t input) { inputs_.push_back(input); }

  bool HasOverflow() const { return enable_overflow_; }
  uint64_t overflow_result() const { return result_.second_word; }

 private:
  const std::string name_;
  const result128_t result_;
  const bool enable_overflow_;
  const std::string result_name_;
  std::vector<uint64_t> inputs_;
};

// Data for syscall tests.
class DataForSyscallTest {
 public:
  explicit DataForSyscallTest(debug::Arch arch);

  const SystemCallTest* syscall() const { return syscall_.get(); }

  void set_syscall(std::unique_ptr<SystemCallTest> syscall) { syscall_ = std::move(syscall); }

  bool use_alternate_data() const { return use_alternate_data_; }

  void set_use_alternate_data() { use_alternate_data_ = true; }

  void load_syscall_data() {
    size_t argument_count = syscall_->inputs().size();
    if (argument_count > param_regs_->size()) {
      argument_count -= param_regs_->size();
      for (auto input = syscall_->inputs().crbegin();
           (input != syscall_->inputs().crend()) && (argument_count > 0);
           ++input, --argument_count) {
        *(--sp_) = *input;
      }
    }
    if (arch_ == debug::Arch::kX64) {
      *(--sp_) = kReturnAddress;
    }
    stepped_processes_.clear();
  }

  uint64_t* sp() const { return sp_; }

  void set_check_bytes() { check_bytes_ = true; }
  void set_check_handles() { check_handles_ = true; }

  uint8_t* bytes() { return reinterpret_cast<uint8_t*>(&header_); }

  size_t num_bytes() const { return sizeof(header_); }

  uint8_t* large_bytes() { return large_bytes_.data(); }

  size_t num_large_bytes() const { return large_bytes_.size(); }

  zx_handle_t* handles() { return handles_; }

  size_t num_handles() const { return sizeof(handles_) / sizeof(handles_[0]); }

  zx_handle_info_t* handle_infos() { return handle_infos_; }

  size_t num_handle_infos() const { return sizeof(handle_infos_) / sizeof(handle_infos_[0]); }

  uint8_t* bytes2() { return reinterpret_cast<uint8_t*>(&header2_); }

  size_t num_bytes2() const { return sizeof(header2_); }

  zx_handle_t* handles2() { return handles2_; }

  size_t num_handles2() const { return sizeof(handles2_) / sizeof(handles2_[0]); }

  void PopulateModules(std::vector<debug_ipc::Module>& modules) {
    const uint64_t kModuleBase = 0x1000000;
    debug_ipc::Module load;
    load.name = "test";
    load.base = kModuleBase;
    load.build_id = kElfSymbolBuildID;
    modules.push_back(load);
  }

  void PopulateMemoryBlockForAddress(uint64_t address, uint64_t size,
                                     debug_ipc::MemoryBlock& block) {
    block.address = address;
    block.size = size;
    block.valid = true;
    std::copy(reinterpret_cast<uint8_t*>(address), reinterpret_cast<uint8_t*>(address + size),
              std::back_inserter(block.data));
    FX_DCHECK(size == block.data.size())
        << "expected size: " << size << " and actual size: " << block.data.size();
  }

  void PopulateRegister(debug::RegisterID register_id, uint64_t value,
                        std::vector<debug::RegisterValue>* registers) {
    debug::RegisterValue& reg = registers->emplace_back();
    reg.id = register_id;
    for (int i = 0; i < 64; i += 8) {
      reg.data.push_back((value >> i) & 0xff);
    }
  }

  void PopulateRegisters(uint64_t process_koid, std::vector<debug::RegisterValue>* registers) {
    if (syscall_ != nullptr) {
      if (stepped_processes_.find(process_koid) == stepped_processes_.end()) {
        size_t count = std::min(param_regs_->size(), syscall_->inputs().size());
        for (size_t i = 0; i < count; ++i) {
          PopulateRegister((*param_regs_)[i], syscall_->inputs()[i], registers);
        }
      } else {
        if (arch_ == debug::Arch::kArm64) {
          PopulateRegister(debug::RegisterID::kARMv8_x0, syscall_->result(), registers);
          if (syscall_->HasOverflow()) {
            PopulateRegister(debug::RegisterID::kARMv8_x1, syscall_->overflow_result(), registers);
          }
        } else {
          PopulateRegister(debug::RegisterID::kX64_rax, syscall_->result(), registers);
          if (syscall_->HasOverflow()) {
            PopulateRegister(debug::RegisterID::kX64_rdx, syscall_->overflow_result(), registers);
          }
        }
      }
    }

    if (arch_ == debug::Arch::kArm64) {
      // stack pointer
      PopulateRegister(debug::RegisterID::kARMv8_sp, reinterpret_cast<uint64_t>(sp_), registers);
      // link register
      PopulateRegister(debug::RegisterID::kARMv8_lr, kReturnAddress, registers);
    } else if (arch_ == debug::Arch::kX64) {
      // stack pointer
      PopulateRegister(debug::RegisterID::kX64_rsp, reinterpret_cast<uint64_t>(sp_), registers);
    }
  }

  void Step(uint64_t process_koid) {
    // Increment the stack pointer to make it look as if we've stepped out of
    // the zx_channel function.
    sp_ = stack_ + kMaxStackSizeInWords;
    stepped_processes_.insert(process_koid);
  }

  template <typename T>
  void AppendElements(std::string& result, size_t num, const T* a, const T* b) {
    std::ostringstream os;
    os << "actual      expected\n";
    for (size_t i = 0; i < num; i++) {
      os << std::left << std::setw(11) << static_cast<uint32_t>(a[i]);
      os << " ";
      os << std::left << std::setw(11) << static_cast<uint32_t>(b[i]);
      os << std::endl;
    }
    result.append(os.str());
  }

  static constexpr uint64_t kReturnAddress = 0x123456798;
  static constexpr uint64_t kMaxStackSizeInWords = 0x100;
  static constexpr zx_txid_t kTxId = 0xaaaaaaaa;
  static constexpr zx_txid_t kTxId2 = 0x88888888;
  static constexpr uint32_t kFidlWireFormatMagicNumberInitial = 0x1;
  static constexpr uint64_t kOrdinal = 0x77e4cceb00000000lu;
  static constexpr uint64_t kOrdinal2 = 1234567890123456789lu;
  static constexpr char kElfSymbolBuildID[] = "123412341234";

 private:
  const std::vector<debug::RegisterID>* param_regs_;
  std::unique_ptr<SystemCallTest> syscall_;
  bool use_alternate_data_ = false;
  uint64_t stack_[kMaxStackSizeInWords];
  uint64_t* sp_;
  bool check_bytes_ = false;
  bool check_handles_ = false;
  fidl_message_header_t header_;
  fidl_message_header_t header2_;
  std::vector<uint8_t> large_bytes_;
  zx_handle_t handles_[2] = {0x01234567, 0x89abcdef};
  zx_handle_info_t handle_infos_[2] = {
      {0x01234567, ZX_OBJ_TYPE_CHANNEL,
       ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_SIGNAL | ZX_RIGHT_SIGNAL_PEER |
           ZX_RIGHT_WAIT | ZX_RIGHT_INSPECT,
       0},
      {0x89abcdef, ZX_OBJ_TYPE_LOG,
       ZX_RIGHT_DUPLICATE | ZX_RIGHT_TRANSFER | ZX_RIGHT_WRITE | ZX_RIGHT_SIGNAL | ZX_RIGHT_WAIT |
           ZX_RIGHT_INSPECT,
       0}};
  zx_handle_t handles2_[2] = {0x76543210, 0xfedcba98};
  debug::Arch arch_;
  std::set<uint64_t> stepped_processes_;
};

// Provides the infrastructure needed to provide the data above.
class InterceptionRemoteAPI : public zxdb::MockRemoteAPI {
 public:
  InterceptionRemoteAPI(DataForSyscallTest& data, bool aborted) : data_(data), aborted_(aborted) {}

  void AddOrChangeBreakpoint(
      const debug_ipc::AddOrChangeBreakpointRequest& request,
      fit::callback<void(const zxdb::Err&, debug_ipc::AddOrChangeBreakpointReply)> cb) override {
    breakpoints_[request.breakpoint.id] = request.breakpoint;
    MockRemoteAPI::AddOrChangeBreakpoint(request, std::move(cb));
  }

  void Attach(const debug_ipc::AttachRequest& request,
              fit::callback<void(const zxdb::Err&, debug_ipc::AttachReply)> cb) override {
    debug::MessageLoop::Current()->PostTask(
        FROM_HERE, [cb = std::move(cb)]() mutable { cb(zxdb::Err(), debug_ipc::AttachReply()); });
  }

  void Modules(const debug_ipc::ModulesRequest& request,
               fit::callback<void(const zxdb::Err&, debug_ipc::ModulesReply)> cb) override {
    debug_ipc::ModulesReply reply;
    data_.PopulateModules(reply.modules);
    debug::MessageLoop::Current()->PostTask(
        FROM_HERE, [cb = std::move(cb), reply]() mutable { cb(zxdb::Err(), reply); });
  }

  void ReadMemory(const debug_ipc::ReadMemoryRequest& request,
                  fit::callback<void(const zxdb::Err&, debug_ipc::ReadMemoryReply)> cb) override {
    if (aborted_) {
      aborted_ = false;
      Process* process = global_dispatcher->SearchProcess(kFirstPid);
      FX_DCHECK(process != nullptr);
      constexpr int64_t kReadFailTimestamp = 1000000000;
      global_dispatcher->AddStopMonitoringEvent(
          std::make_shared<StopMonitoringEvent>(kReadFailTimestamp, process));
    }
    debug_ipc::ReadMemoryReply reply;
    data_.PopulateMemoryBlockForAddress(request.address, request.size, reply.blocks.emplace_back());
    debug::MessageLoop::Current()->PostTask(
        FROM_HERE, [cb = std::move(cb), reply]() mutable { cb(zxdb::Err(), reply); });
  }

  void ReadRegisters(
      const debug_ipc::ReadRegistersRequest& request,
      fit::callback<void(const zxdb::Err&, debug_ipc::ReadRegistersReply)> cb) override {
    // TODO: Parameterize this so we can have more than one test.
    debug_ipc::ReadRegistersReply reply;
    data_.PopulateRegisters(request.id.process, &reply.registers);
    debug::MessageLoop::Current()->PostTask(
        FROM_HERE, [cb = std::move(cb), reply]() mutable { cb(zxdb::Err(), reply); });
  }

  void Resume(const debug_ipc::ResumeRequest& request,
              fit::callback<void(const zxdb::Err&, debug_ipc::ResumeReply)> cb) override {
    debug_ipc::ResumeReply reply;
    data_.Step(request.ids[0].process);
    debug::MessageLoop::Current()->PostTask(FROM_HERE, [cb = std::move(cb), reply]() mutable {
      cb(zxdb::Err(), reply);
      // This is so that the test can inject the next exception.
      debug::MessageLoop::Current()->QuitNow();
    });
  }

  void PopulateBreakpointIds(uint64_t address, debug_ipc::NotifyException& notification) {
    for (auto& breakpoint : breakpoints_) {
      if (address == breakpoint.second.locations[0].address) {
        notification.hit_breakpoints.emplace_back();
        notification.hit_breakpoints.back().id = breakpoint.first;
      }
    }
  }

  void LoadInfoHandleTable(
      const debug_ipc::LoadInfoHandleTableRequest& request,
      fit::callback<void(const zxdb::Err&, debug_ipc::LoadInfoHandleTableReply)> cb) override {
    debug_ipc::LoadInfoHandleTableReply reply;

    debug_ipc::InfoHandle info;
    info.type = ZX_OBJ_TYPE_CHANNEL;
    info.handle_value = kHandle;
    info.rights = ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_SIGNAL |
                  ZX_RIGHT_SIGNAL_PEER | ZX_RIGHT_WAIT | ZX_RIGHT_INSPECT;
    info.koid = kHandleKoid;
    info.related_koid = kHandle2Koid;
    info.peer_owner_koid = 0;
    reply.handles.push_back(info);

    info.type = ZX_OBJ_TYPE_CHANNEL;
    info.handle_value = kHandle2;
    info.rights = ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_SIGNAL |
                  ZX_RIGHT_SIGNAL_PEER | ZX_RIGHT_WAIT | ZX_RIGHT_INSPECT;
    info.koid = kHandle2Koid;
    info.related_koid = kHandleKoid;
    info.peer_owner_koid = 0;
    reply.handles.push_back(info);

    cb(zxdb::Err(), std::move(reply));
  }

 private:
  std::map<uint32_t, debug_ipc::BreakpointSettings> breakpoints_;
  DataForSyscallTest& data_;
  bool aborted_;
};

class InterceptionWorkflowTest : public zxdb::RemoteAPITest {
 public:
  InterceptionWorkflowTest(debug::Arch arch, bool aborted) : data_(arch), aborted_(aborted) {
    decode_options_.output_mode = OutputMode::kStandard;
    display_options_.pretty_print = true;
    display_options_.columns = 132;
    display_options_.needs_colors = true;
  }
  ~InterceptionWorkflowTest() override = default;

  InterceptionRemoteAPI& mock_remote_api() { return *mock_remote_api_; }

  std::unique_ptr<zxdb::RemoteAPI> GetRemoteAPIImpl() override {
    auto remote_api = std::make_unique<InterceptionRemoteAPI>(data_, aborted_);
    mock_remote_api_ = remote_api.get();
    return std::move(remote_api);
  }

  DataForSyscallTest& data() { return data_; }

  void set_with_process_info() { display_options_.with_process_info = true; }
  void set_dump_messages(bool dump_messages) { display_options_.dump_messages = dump_messages; }

  void set_bad_stack() { bad_stack_ = true; }

  void AddThread(zxdb::Thread* thread) { threads_[thread->GetKoid()] = thread; }

  void PerformDisplayTest(const char* syscall_name, std::unique_ptr<SystemCallTest> syscall,
                          const char* expected, fidl_codec::LibraryLoader* loader = nullptr);
  void PerformDisplayTest(ProcessController* controller, const char* syscall_name,
                          std::unique_ptr<SystemCallTest> syscall, const char* expected,
                          fidl_codec::LibraryLoader* loader = nullptr);

  void PerformOneThreadDisplayTest(const char* syscall_name,
                                   std::unique_ptr<SystemCallTest> syscall, const char* expected);

  void PerformInterleavedDisplayTest(const char* syscall_name,
                                     std::unique_ptr<SystemCallTest> syscall, const char* expected);
  void PerformInterleavedDisplayTest(ProcessController* controller, const char* syscall_name,
                                     std::unique_ptr<SystemCallTest> syscall, const char* expected);

  void PerformNoReturnDisplayTest(const char* syscall_name, std::unique_ptr<SystemCallTest> syscall,
                                  const char* expected);

  void PerformTest(const char* syscall_name, std::unique_ptr<SystemCallTest> syscall1,
                   std::unique_ptr<SystemCallTest> syscall2, ProcessController* controller,
                   std::unique_ptr<SyscallDecoderDispatcher> dispatcher, bool interleaved_test,
                   bool multi_thread);

  void PerformAbortedTest(const char* syscall_name, std::unique_ptr<SystemCallTest> syscall,
                          const char* expected);

  void SimulateSyscall(std::unique_ptr<SystemCallTest> syscall, ProcessController* controller,
                       bool interleaved_test, bool multi_thread);
  std::vector<std::unique_ptr<zxdb::Frame>> FillBreakpoint(debug_ipc::NotifyException* notification,
                                                           uint64_t process_koid,
                                                           uint64_t thread_koid);
  void TriggerSyscallBreakpoint(uint64_t process_koid, uint64_t thread_koid);
  void TriggerCallerBreakpoint(uint64_t process_koid, uint64_t thread_koid);

  void PerformExceptionDisplayTest(debug_ipc::ExceptionType type, const char* expected);
  void PerformExceptionTest(ProcessController* controller,
                            std::unique_ptr<SyscallDecoderDispatcher> dispatcher,
                            debug_ipc::ExceptionType type);
  void TriggerException(uint64_t process_koid, uint64_t thread_koid, debug_ipc::ExceptionType type);
  void PerformFunctionTest(ProcessController* controller, const char* syscall_name,
                           std::unique_ptr<SystemCallTest> syscall, uint64_t pid, uint64_t tid);

 protected:
  DataForSyscallTest data_;
  bool aborted_;
  InterceptionRemoteAPI* mock_remote_api_;  // Owned by the session.
  DecodeOptions decode_options_;
  DisplayOptions display_options_;
  std::stringstream result_;
  std::map<uint64_t, zxdb::Thread*> threads_;
  // Function which can simulate the fact that the syscall can modify some data.
  std::function<void()> update_data_;
  bool bad_stack_ = false;
  std::unique_ptr<SyscallDecoderDispatcher> last_decoder_dispatcher_;
};

class InterceptionWorkflowTestX64 : public InterceptionWorkflowTest {
 public:
  InterceptionWorkflowTestX64() : InterceptionWorkflowTest(GetArch(), false) {}
  ~InterceptionWorkflowTestX64() override = default;

  debug::Arch GetArch() const override { return debug::Arch::kX64; }
};

class InterceptionWorkflowTestArm : public InterceptionWorkflowTest {
 public:
  InterceptionWorkflowTestArm() : InterceptionWorkflowTest(GetArch(), false) {}
  ~InterceptionWorkflowTestArm() override = default;

  debug::Arch GetArch() const override { return debug::Arch::kArm64; }
};

class InterceptionWorkflowTestX64Aborted : public InterceptionWorkflowTest {
 public:
  InterceptionWorkflowTestX64Aborted() : InterceptionWorkflowTest(GetArch(), true) {}
  ~InterceptionWorkflowTestX64Aborted() override = default;

  debug::Arch GetArch() const override { return debug::Arch::kX64; }
};

class InterceptionWorkflowTestArmAborted : public InterceptionWorkflowTest {
 public:
  InterceptionWorkflowTestArmAborted() : InterceptionWorkflowTest(GetArch(), true) {}
  ~InterceptionWorkflowTestArmAborted() override = default;

  debug::Arch GetArch() const override { return debug::Arch::kArm64; }
};

// This does process setup for the test.  It creates fake processes, injects
// modules with the appropriate symbols, attaches to the processes, etc.
class ProcessController {
 public:
  ProcessController(InterceptionWorkflowTest* remote_api, zxdb::Session& session,
                    debug::MessageLoop& loop);
  ~ProcessController();

  InterceptionWorkflowTest* remote_api() const { return remote_api_; }
  InterceptionWorkflow& workflow() { return workflow_; }
  const std::vector<uint64_t>& process_koids() { return process_koids_; }
  uint64_t thread_koid(uint64_t process_koid) { return thread_koids_[process_koid]; }
  bool initialized() const { return initialized_; }

  std::unique_ptr<SyscallDecoderDispatcher> GetBackDispatcher() {
    return workflow_.GetBackDispatcher();
  }

  void InjectProcesses(zxdb::Session& session);

  // The syscall_name can be the empty string if no mock syscall is needed.
  void Initialize(zxdb::Session& session, std::unique_ptr<SyscallDecoderDispatcher> dispatcher,
                  const char* syscall_name);
  void Detach();

 private:
  InterceptionWorkflowTest* remote_api_;
  std::vector<uint64_t> process_koids_;
  std::map<uint64_t, uint64_t> thread_koids_;
  InterceptionWorkflow workflow_;

  std::vector<zxdb::Process*> processes_;
  std::vector<zxdb::Target*> targets_;
  size_t detached_processes_ = 0;
  bool initialized_ = false;
};

class AlwaysQuit {
 public:
  AlwaysQuit(ProcessController* controller) : controller_(controller) {}
  ~AlwaysQuit() { controller_->Detach(); }

 private:
  ProcessController* controller_;
};

template <typename T>
void AppendElements(std::string& result, const T* a, const T* b, size_t num) {
  std::ostringstream os;
  os << "actual      expected\n";
  for (size_t i = 0; i < num; i++) {
    os << std::left << std::setw(11) << static_cast<uint32_t>(a[i]);
    os << " ";
    os << std::left << std::setw(11) << static_cast<uint32_t>(b[i]);
    os << std::endl;
  }
  result.append(os.str());
}

class SyscallDisplayDispatcherTest : public SyscallDisplayDispatcher {
 public:
  SyscallDisplayDispatcherTest(fidl_codec::LibraryLoader* loader,
                               const DecodeOptions& decode_options,
                               const DisplayOptions& display_options, std::ostream& os,
                               ProcessController* controller, bool aborted)
      : SyscallDisplayDispatcher(loader, decode_options, display_options, os),
        controller_(controller),
        aborted_(aborted),
        replay_dispatcher_(std::make_unique<SyscallDisplayDispatcher>(loader, decode_options,
                                                                      display_options, os)),
        replay_(replay_dispatcher_.get()) {}

  ProcessController* controller() const { return controller_; }

  void DeleteDecoder(SyscallDecoder* decoder) override {
    SyscallDisplayDispatcher::DeleteDecoder(decoder);
    AlwaysQuit aq(controller_);
  }

  void DeleteDecoder(ExceptionDecoder* decoder) override {
    SyscallDecoderDispatcher::DeleteDecoder(decoder);
    AlwaysQuit aq(controller_);
  }

  void AddProcessLaunchedEvent(std::shared_ptr<ProcessLaunchedEvent> event) override {}

  void AddProcessMonitoredEvent(std::shared_ptr<ProcessMonitoredEvent> event) override {}

  void AddStopMonitoringEvent(std::shared_ptr<StopMonitoringEvent> event) override {
    if (aborted_) {
      SyscallDisplayDispatcher::AddStopMonitoringEvent(std::move(event));
    }
  }

  // For events, instead of dispatching them using this dispatcher, we dispatch them using the
  // replay dispatcher. This method ensures that the thread/process used by an event which has
  // been created in this dispatcher is also created in the replay dispatcher.
  void CreateReplayThread(Thread* thread) {
    Thread* replay_thread = replay_dispatcher_->SearchThread(thread->koid());
    if (replay_thread == nullptr) {
      Process* process = thread->process();
      Process* replay_process = replay_dispatcher_->SearchProcess(process->koid());
      if (replay_process == nullptr) {
        replay_process =
            replay_dispatcher_->CreateProcess(process->name(), process->koid(), nullptr);
      }
      replay_dispatcher_->CreateThread(thread->koid(), replay_process);
    }
  }

  void AddInvokedEvent(std::shared_ptr<InvokedEvent> invoked_event) override {
    // Set the invoked event id (this is usually done by SyscallDisplayDispatcher).
    invoked_event->set_id(GetNextInvokedEventId());
    // Ensure that the thread/process are created for the replay dispatcher.
    CreateReplayThread(invoked_event->thread());
    // Create a proto event.
    proto::Event proto_event;
    invoked_event->Write(&proto_event);
    // Replay the proto event. This will dispatch the event to the replay dispatcher. Because both
    // this dispatcher and the replay dispatcher have the output stream, the output must be
    // unchanged.
    replay_.DecodeAndDispatchEvent(proto_event);
  }

  void AddOutputEvent(std::shared_ptr<OutputEvent> output_event) override {
    // Create a proto event.
    proto::Event proto_event;
    output_event->Write(&proto_event);
    // Replay the proto event. This will dispatch the event to the replay dispatcher. Because both
    // this dispatcher and the replay dispatcher have the output stream, the output must be
    // unchanged.
    replay_.DecodeAndDispatchEvent(proto_event);
  }

  void AddExceptionEvent(std::shared_ptr<ExceptionEvent> exception_event) override {
    // Ensure that the thread/process are created for the replay dispatcher.
    CreateReplayThread(exception_event->thread());
    // Create a proto event.
    proto::Event proto_event;
    exception_event->Write(&proto_event);
    // Replay the proto event. This will dispatch the event to the replay dispatcher. Because both
    // this dispatcher and the replay dispatcher have the output stream, the output must be
    // unchanged.
    replay_.DecodeAndDispatchEvent(proto_event);
  }

 private:
  ProcessController* controller_;
  bool aborted_;
  // Dispatcher used to test the save/replay of events.
  std::unique_ptr<SyscallDisplayDispatcher> replay_dispatcher_;
  // Used to replay saved events.
  Replay replay_;
};

#define AUTOMATION_TEST_CONTENT(syscall_name, errno, expected)                                   \
  ProcessController controller(this, session(), loop());                                         \
  controller.Initialize(                                                                         \
      session(),                                                                                 \
      std::make_unique<SyscallDisplayDispatcherTest>(nullptr, decode_options_, display_options_, \
                                                     result_, &controller, aborted_),            \
      "");                                                                                       \
  SyscallDecoderDispatcher* dispatcher = controller.workflow().syscall_decoder_dispatcher();     \
  Syscall* syscall = dispatcher->SearchSyscall(syscall_name);                                    \
  ASSERT_NE(syscall, nullptr);                                                                   \
  std::stringstream output_stream;                                                               \
  if (syscall->invoked_bp_instructions().size() > 0) {                                           \
    output_stream << "Invoked bp instructions:\n";                                               \
    for (auto instr : syscall->invoked_bp_instructions()) {                                      \
      output_stream << "  " << instr.ToString();                                                 \
    }                                                                                            \
  }                                                                                              \
  if (syscall->exit_bp_instructions().size() > 0) {                                              \
    output_stream << "Exit bp instructions:\n";                                                  \
    for (auto instr : syscall->exit_bp_instructions()) {                                         \
      output_stream << "  " << instr.ToString();                                                 \
    }                                                                                            \
  }                                                                                              \
  ASSERT_EQ(output_stream.str(), expected);

#define CREATE_AUTOMATION_TEST(test_name, syscall_name, errno, expected_x64, expected_arm) \
  TEST_F(InterceptionWorkflowTestX64, test_name) {                                         \
    AUTOMATION_TEST_CONTENT(syscall_name, errno, expected_x64);                            \
  }                                                                                        \
  TEST_F(InterceptionWorkflowTestArm, test_name) {                                         \
    AUTOMATION_TEST_CONTENT(syscall_name, errno, expected_arm);                            \
  }

}  // namespace fidlcat

#endif  // TOOLS_FIDLCAT_INTERCEPTION_TESTS_INTERCEPTION_WORKFLOW_TEST_H_
