#include "gtest/gtest.h" #include "gmock/gmock.h" #include "memory.h" #include <vector> using namespace std; using namespace Retro; using namespace ::testing; struct MemoryOverlayTestParam { MemoryOverlay overlay; vector<uint8_t> in; vector<uint8_t> out; size_t size; size_t offset = 0; }; class MemoryOverlayTest : public TestWithParam<MemoryOverlayTestParam> { }; TEST_P(MemoryOverlayTest, Parse) { const auto& param = GetParam(); ASSERT_EQ(param.in.size(), param.out.size()); size_t offset = param.offset & ~(param.overlay.width - 1); size_t width = min(param.size, param.in.size() - param.offset); vector<uint8_t> parsed(param.out); const void* parseLoc = param.overlay.parse(reinterpret_cast<const void*>(¶m.in[0]), param.offset, reinterpret_cast<void*>(&parsed[offset]), width); EXPECT_EQ(parseLoc, &parsed[param.offset]); EXPECT_THAT(parsed, ElementsAreArray(param.out)); } TEST_P(MemoryOverlayTest, Unparse) { const auto& param = GetParam(); ASSERT_EQ(param.in.size(), param.out.size()); size_t offset = param.offset & ~(param.overlay.width - 1); size_t width = min(param.size, param.out.size() - param.offset); vector<uint8_t> unparsed(param.in); param.overlay.unparse(reinterpret_cast<void*>(&unparsed[0]), param.offset, reinterpret_cast<const void*>(¶m.out[offset]), width); EXPECT_THAT(unparsed, ElementsAreArray(param.in)); } #define INSTANTIATE_OVERLAY_TEST_CASE(NAME, ...) \ INSTANTIATE_TEST_CASE_P(NAME, MemoryOverlayTest, Values(MemoryOverlayTestParam{ __VA_ARGS__ })); INSTANTIATE_OVERLAY_TEST_CASE(NativeNative1, { Endian::NATIVE, Endian::NATIVE, 1 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(NativeNative2, { Endian::NATIVE, Endian::NATIVE, 2 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(NativeNative4, { Endian::NATIVE, Endian::NATIVE, 4 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(LittleLittle1, { Endian::LITTLE, Endian::LITTLE, 1 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(LittleLittle2, { Endian::LITTLE, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(LittleLittle4, { Endian::LITTLE, Endian::LITTLE, 4 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(BigBig1, { Endian::BIG, Endian::BIG, 1 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(BigBig2, { Endian::BIG, Endian::BIG, 2 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(BigBig4, { Endian::BIG, Endian::BIG, 2 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle1, { Endian::BIG, Endian::LITTLE, 1 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 1, 0, 3, 2 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle4, { Endian::BIG, Endian::LITTLE, 4 }, { 0, 1, 2, 3 }, { 3, 2, 1, 0 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(LittleBig1, { Endian::LITTLE, Endian::BIG, 1 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(LittleBig2, { Endian::LITTLE, Endian::BIG, 2 }, { 0, 1, 2, 3 }, { 1, 0, 3, 2 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(LittleBig4, { Endian::LITTLE, Endian::BIG, 4 }, { 0, 1, 2, 3 }, { 3, 2, 1, 0 }, 4 ) INSTANTIATE_OVERLAY_TEST_CASE(LittleLittle2Offset1, { Endian::LITTLE, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4, 1 ) INSTANTIATE_OVERLAY_TEST_CASE(LittleLittle2Offset2, { Endian::LITTLE, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, 4, 2 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2Offset1, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 1, 0, 3, 2 }, 4, 1 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2Offset2, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 1, 0, 3, 2 }, 4, 2 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2Size1, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 1, 0, 2, 3 }, 1 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2Size1Offset1, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 1, 0, 2, 3 }, 1, 1 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2Size1Offset2, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 0, 1, 3, 2 }, 1, 2 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2Size1Offset3, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 0, 1, 3, 2 }, 1, 3 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2Size2, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 1, 0, 2, 3 }, 2 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2Size2Offset1, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 1, 0, 3, 2 }, 2, 1 ) INSTANTIATE_OVERLAY_TEST_CASE(BigLittle2Size2Offset2, { Endian::BIG, Endian::LITTLE, 2 }, { 0, 1, 2, 3 }, { 0, 1, 3, 2 }, 2, 2 )