blob: ba1796cdfccea75fa8b6796226559c0d94148fe1 [file] [log] [blame]
// Copyright 2026 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 SRC_LIB_UNWINDER_TESTING_MOCK_MEMORY_H_
#define SRC_LIB_UNWINDER_TESTING_MOCK_MEMORY_H_
#include <map>
#include <vector>
#include "src/lib/unwinder/memory.h"
namespace unwinder {
// A fake implementation of Memory that stores literal bytes.
// It is called "MockMemory" to align with zxdb naming conventions.
//
// Example usage:
// MockMemory mock_memory;
// uint64_t val = 0xdeadbeef;
// mock_memory.AddMemory(0x1000, std::vector<uint8_t>(
// reinterpret_cast<uint8_t*>(&val),
// reinterpret_cast<uint8_t*>(&val) + sizeof(val)));
class MockMemory : public Memory {
public:
void AddMemory(uint64_t addr, std::vector<uint8_t> data) { regions_[addr] = std::move(data); }
Error ReadBytes(uint64_t addr, uint64_t size, void* dst) override {
for (const auto& [base_addr, data] : regions_) {
if (addr >= base_addr && addr + size <= base_addr + data.size()) {
memcpy(dst, data.data() + (addr - base_addr), size);
return Success();
}
}
return Error("Invalid memory access at 0x%zx", addr);
}
private:
std::map<uint64_t, std::vector<uint8_t>> regions_;
};
// A fake implementation of AsyncMemory::Delegate.
//
// Used to test asynchronous unwinding flows. Automatically executes callbacks
// synchronously to simplify test execution.
class MockAsyncMemoryDelegate : public AsyncMemory::Delegate {
public:
void AddMemory(uint64_t addr, std::vector<uint8_t> data) {
mem_.AddMemory(addr, std::move(data));
}
Error ReadBytes(uint64_t addr, uint64_t size, void* dst) override {
return mem_.ReadBytes(addr, size, dst);
}
void FetchMemoryRanges(std::vector<std::pair<uint64_t, uint32_t>> ranges,
fit::callback<void()> cb) override {
cb();
}
void PostTask(fit::callback<void()> cb) override { cb(); }
private:
MockMemory mem_;
};
} // namespace unwinder
#endif // SRC_LIB_UNWINDER_TESTING_MOCK_MEMORY_H_