gpt4 book ai didi

c++ - 用 C++ 编写 Gameboy 模拟器,如何测试操作码(谷歌测试框架)?

转载 作者:太空狗 更新时间:2023-10-29 20:58:35 25 4
gpt4 key购买 nike

我正在尝试编写 GameBoy 模拟器,但我不确定应该如何测试我的 CPU_LR39502 类。为了避免大量的 if-else-if/switch-case 语句,我想到了将操作码仿函数放入映射中的想法,它以操作码为键:

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 时立即编写操作码的实现,但为了使其可测试,我将实现编写为成员函数(这里以 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 的私有(private)成员,我必须添加

FRIEND_TEST(CPUTest, test_name);

在 CPU_LR35902 类中 - 之后我可以在 TEST_F 中访问测试类的私有(private)成员,但我无法在 CPUTest 类中访问它们(用于 SetUp/TearDown)。考虑到我已经进行了更多的测试并且我将进行大量测试这一事实,我认为为每个测试添加 FRIEND_TEST 会使一切都变得难看。我接触 C++ 有一段时间了,但我在使用 Google Test Framework 方面的经验完全为零,我的直觉告诉我必须有更好的方法来做到这一点。任何线索将不胜感激:)

最佳答案

How do I test private class members without writing FRIEND_TEST()s?

Write the tests as members of the fixture class:

class Foo {
friend class FooTest;
...
};

class FooTest : public ::testing::Test {
protected:
...
void Test1() {...} // This accesses private members of class Foo.
void Test2() {...} // So does this one.
};

TEST_F(FooTest, Test1) {
Test1();
}

TEST_F(FooTest, Test2) {
Test2();
}

这样一来,您只需为每个测试夹具添加一个类,而无需在您的 header (或您的项目)中包含 gtest。

您也可以创建一个普通类,它是主类的友元类,仅供测试用来访问私有(private)成员。

class Foo {
friend class FooTesting;
...
};

class FooTesting {
public:

static int read_private_variable1( Foo& );
};

TEST_F(FooTest, Test1) {
Foo bar;
EXPECT_EQ( FooTesting::read_private_variable1( bar ), 5 );
}

关于c++ - 用 C++ 编写 Gameboy 模拟器,如何测试操作码(谷歌测试框架)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27337760/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com