// 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) {
  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::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
