// Copyright 2020 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/debug_agent/mock_process_handle.h"

#include <string.h>

#include "src/developer/debug/ipc/records.h"

namespace debug_agent {

NativeProcessHandle MockProcessHandle::null_handle_;

MockProcessHandle::MockProcessHandle(zx_koid_t process_koid, std::string name)
    : process_koid_(process_koid), name_(std::move(name)) {
  // Tests could accidentally write to this handle since it's returned as a mutable value in some
  // cases. Catch accidents like that.
  FX_DCHECK(!null_handle_);
}

std::vector<std::unique_ptr<ThreadHandle>> MockProcessHandle::GetChildThreads() const {
  // Need to return a unique set of objects every time so make copies.
  std::vector<std::unique_ptr<ThreadHandle>> result;
  for (auto& thread : threads_)
    result.push_back(std::make_unique<MockThreadHandle>(thread));
  return result;
}

debug::Status MockProcessHandle::Kill() { return kill_status_; }

int64_t MockProcessHandle::GetReturnCode() const { return 0; }

debug::Status MockProcessHandle::Attach(ProcessHandleObserver* observer, AttachConfig config) {
  if (config.claim_exception_channel) {
    is_attached_ = true;
  }
  return debug::Status();
}

void MockProcessHandle::Detach() { is_attached_ = false; }

uint64_t MockProcessHandle::GetLoaderBreakpointAddress() {
  // Not currently implemented in this mock.
  return kLoaderBreakpointAddress;
}

std::vector<debug_ipc::AddressRegion> MockProcessHandle::GetAddressSpace(uint64_t address) const {
  // Not currently implemented in this mock.
  return {};
}

std::optional<debug_ipc::AddressRegion> MockProcessHandle::GetSharedAddressSpace() const {
  // Not currently implemented in this mock.
  return std::nullopt;
}

std::vector<debug_ipc::Module> MockProcessHandle::GetModules() const {
  // Not currently implemented in this mock.
  return {};
}

fit::result<debug::Status, std::vector<debug_ipc::InfoHandle>> MockProcessHandle::GetHandles()
    const {
  // Not currently implemented in this mock.
  return fit::success(std::vector<debug_ipc::InfoHandle>());
}

debug::Status MockProcessHandle::ReadMemory(uintptr_t address, void* buffer, size_t len,
                                            size_t* actual) const {
  auto vect = mock_memory_.ReadMemory(address, len);
  if (!vect.empty())
    memcpy(buffer, vect.data(), vect.size());
  *actual = vect.size();
  return debug::Status();
}

debug::Status MockProcessHandle::WriteMemory(uintptr_t address, const void* buffer, size_t len,
                                             size_t* actual) {
  // This updates the underlying memory object to account for the change. Otherwise some tests
  // become much more complex because they have to manually manage the memory expected by the
  // code under test.
  //
  // The MockMemory object isn't necessarily designed for this and there will be some limitations.
  // Calling AddMemory adds that span to the mapped memory, but does not necessarily combine it with
  // other spans. If a larger region of memory is requested, the results may be invalid, but if the
  // same sized block is always read and written, it will be fine. Since our main test use is for
  // writing breakpoints which always use fixed sizes, this works fine for now. If this limitation
  // is a problem, we should enhance MockMemory.
  const uint8_t* src = static_cast<const uint8_t*>(buffer);
  mock_memory_.AddMemory(address, std::vector<uint8_t>(src, src + len));

  memory_writes_.emplace_back(address, std::vector<uint8_t>(src, &src[len]));
  return debug::Status();
}

std::vector<debug_ipc::MemoryBlock> MockProcessHandle::ReadMemoryBlocks(uint64_t address,
                                                                        uint32_t size) const {
  auto mem_vect = mock_memory_.ReadMemory(address, size);
  debug_ipc::MemoryBlock mem_block;
  mem_block.data = std::move(mem_vect);
  mem_block.size = size;
  mem_block.valid = true;
  mem_block.address = address;
  std::vector<debug_ipc::MemoryBlock> mem_blocks;
  mem_blocks.emplace_back(std::move(mem_block));
  return mem_blocks;
}

debug::Status MockProcessHandle::SaveMinidump(const std::vector<DebuggedThread*>& threads,
                                              std::vector<uint8_t>* core_data) {
  // Not currently implemented.
  return debug::Status();
}

}  // namespace debug_agent
