我想寫GameBoy模擬器,但我不知道如何測試我的CPU_LR39502類。爲了避免巨大的if-else-IF /開關case語句,我想出了主意,把操作碼仿成地圖,這需要操作碼的關鍵:在C++中編寫Gameboy模擬器,如何測試操作碼(Google Test Framework)?
class Functor
{
std::function<void()> m_function;
public:
Functor(std::function<void()>&& function)
{
m_function = std::move(function);
}
void operator()()
{
m_function();
}
};
class BaseOpcodeFunctor : public Functor
{
unsigned char m_opcode;
std::string m_disasmString;
public:
BaseOpcodeFunctor(std::function<void()>&& function,
unsigned char opcode,
std::string&& disasmString)
: Functor(std::move(function)),
m_opcode(opcode),
m_disasmString(std::move(disasmString)) {}
std::string disasm()
{
return m_disasmString;
}
unsigned char getAssignedOpcode()
{
return m_opcode;
}
};
和舉例吧:
class CPU_LR35902
{
...
std::map<unsigned char, BaseOpcodeFunctor> m_baseOpcodeMap;
public:
CPU_LR35902()
{
...
initializeBaseOpcodeMap();
}
...
private:
void addFunctorToBaseOpcodeMap(BaseOpcodeFunctor&& functor);
void initializeBaseOpcodeMap()
{
...
addFunctorToBaseOpcodeMap(BaseOpcodeFunctor([this]() {
bitwiseRotationLeft(REGISTER_A);
}, 0x07, "RLCA"));
}
void bitwiseRotationLeft(LR35902_8BIT_REGISTERS reg)
{
resetFlag(FLAG_Z);
resetFlag(FLAG_N);
resetFlag(FLAG_H);
setFlag(FLAG_C, registers_8bit.at(reg) >> 7);
registers_8bit.at(reg) <<= 1;
registers_8bit.at(reg) |= getFlag(FLAG_C);
}
...
};
這讓我想起了兩個問題。我實際上想在將代碼添加到m_baseOpcodeMap中時立即編寫opcode的實現,但爲了使其可測試,我將實現作爲成員函數(此處爲bitwiseRotationLeft,作爲示例)編寫,並且在lambda中將其稱爲 - 我不確定這是否是正確的做法。
目前,測試一些實現,我有這樣的事情(使用谷歌測試框架):
#include "cpu_lr35902.h"
#include <gtest/gtest.h>
class CPUTest : public ::testing::Test
{
protected:
CPU_LR35902 cpu_testable;
};
TEST_F(CPUTest, test_bitwiseRotationLeft)
{
cpu_testable.flags = 0;
cpu_testable.clearRegisters();
//0xA5 = 1010 0101, after: 0100 1011 = 0x4B
cpu_testable.registers_8bit.at(CPU_LR35902::REGISTER_A) = 0xA5;
cpu_testable.bitwiseRotationLeft(CPU_LR35902::REGISTER_A);
ASSERT_EQ(1, cpu_testable.getFlag(CPU_LR35902::FLAG_C));
ASSERT_EQ(0x4B, cpu_testable.registers_8bit.at(CPU_LR35902::REGISTER_A));
}
但以訪問CPU_LR35902的私有成員,我要補充
FRIEND_TEST(CPUTest, test_name);
在CPU_LR35902類 - 之後,我可以在TEST_F到達被測試類的私有成員,但我無法在CPUTest類(用於SetUp/TearDown)訪問它們。考慮到事實,我已經有了更多的測試,並且我將會有很多測試,我認爲每次測試都添加FRIEND_TEST會讓一切都變得不好看。我已經與C++保持了一段時間的聯繫,但是我完全沒有使用Google Test Framework的經驗,而我的直覺告訴我必須有更好的方式來實現它。任何線索將欣然讚賞:)
我錯過了,我喜歡這個解決方案,謝謝:) – pablo432 2014-12-07 11:43:35