I'm trying to write GameBoy emulator, but I'm not sure how should I test my CPU_LR39502 class. To avoid huge if-else-if / switch-case statements, I came up with idea to put opcode functor into map, which takes opcode as key:
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;
}
};
And example of it:
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);
}
...
};
And this somehow makes me think about two problems. I actually wanted to write implementation of opcode immediately when adding it to m_baseOpcodeMap, but to make it testable, I wrote implementation as a member function (here bitwiseRotationLeft as example) and I call it in lambda - and I'm not sure if this is correct approach.
Currently, to test some implementations, I've got something like this (using google test framework):
#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));
}
but to get access to private members of CPU_LR35902, I have to add
FRIEND_TEST(CPUTest, test_name);
in CPU_LR35902 class - after that I can reach private members of tested class in TEST_F, but I can't access them in CPUTest class (for SetUp / TearDown). Considering the fact, that I've got a little bit more of tests and I'm going to have a plenty of them, I think that adding FRIEND_TEST for every test makes everything somehow bad-looking. I'm in touch with C++ for some time, but I've got completely zero experience in using Google Test Framework and my intuition tells me that there must be a better way to do it. Any clues will be gladly appreciated :)
How do I test private class members without writing FRIEND_TEST()s?
This makes it so you only have to friend one class per test fixture, without the need of including gtest in your header (or your project).
You can also just make a normal class that is a friend of the main class that is purely used by tests to access private members.