141 lines
4.2 KiB
C
141 lines
4.2 KiB
C
|
|
#pragma once
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @file test_framework.h
|
||
|
|
* @brief 轻量级测试框架
|
||
|
|
*
|
||
|
|
* 提供简单的测试断言和测试注册机制。
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <extra2d/core/types.h>
|
||
|
|
#include <chrono>
|
||
|
|
#include <cstdio>
|
||
|
|
#include <functional>
|
||
|
|
#include <iostream>
|
||
|
|
#include <sstream>
|
||
|
|
#include <string>
|
||
|
|
#include <vector>
|
||
|
|
|
||
|
|
namespace extra2d {
|
||
|
|
namespace test {
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// 测试结果统计
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
struct TestStats {
|
||
|
|
int passed = 0;
|
||
|
|
int failed = 0;
|
||
|
|
int skipped = 0;
|
||
|
|
|
||
|
|
int total() const { return passed + failed + skipped; }
|
||
|
|
};
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// 测试断言
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
#define TEST_ASSERT(condition) \
|
||
|
|
do { \
|
||
|
|
if (!(condition)) { \
|
||
|
|
std::ostringstream _ss; \
|
||
|
|
_ss << "Assertion failed: " << #condition \
|
||
|
|
<< " at " << __FILE__ << ":" << __LINE__; \
|
||
|
|
throw std::runtime_error(_ss.str()); \
|
||
|
|
} \
|
||
|
|
} while (0)
|
||
|
|
|
||
|
|
#define TEST_ASSERT_EQ(expected, actual) \
|
||
|
|
do { \
|
||
|
|
if (!((expected) == (actual))) { \
|
||
|
|
std::ostringstream _ss; \
|
||
|
|
_ss << "Assertion failed: expected " << (expected) \
|
||
|
|
<< " but got " << (actual) \
|
||
|
|
<< " at " << __FILE__ << ":" << __LINE__; \
|
||
|
|
throw std::runtime_error(_ss.str()); \
|
||
|
|
} \
|
||
|
|
} while (0)
|
||
|
|
|
||
|
|
#define TEST_ASSERT_NE(val1, val2) \
|
||
|
|
do { \
|
||
|
|
if ((val1) == (val2)) { \
|
||
|
|
std::ostringstream _ss; \
|
||
|
|
_ss << "Assertion failed: " << (val1) \
|
||
|
|
<< " should not equal " << (val2) \
|
||
|
|
<< " at " << __FILE__ << ":" << __LINE__; \
|
||
|
|
throw std::runtime_error(_ss.str()); \
|
||
|
|
} \
|
||
|
|
} while (0)
|
||
|
|
|
||
|
|
#define TEST_ASSERT_TRUE(condition) TEST_ASSERT(condition)
|
||
|
|
#define TEST_ASSERT_FALSE(condition) TEST_ASSERT(!(condition))
|
||
|
|
#define TEST_ASSERT_NULL(ptr) TEST_ASSERT((ptr) == nullptr)
|
||
|
|
#define TEST_ASSERT_NOT_NULL(ptr) TEST_ASSERT((ptr) != nullptr)
|
||
|
|
#define TEST_ASSERT_GT(val1, val2) TEST_ASSERT((val1) > (val2))
|
||
|
|
#define TEST_ASSERT_GE(val1, val2) TEST_ASSERT((val1) >= (val2))
|
||
|
|
#define TEST_ASSERT_LT(val1, val2) TEST_ASSERT((val1) < (val2))
|
||
|
|
#define TEST_ASSERT_LE(val1, val2) TEST_ASSERT((val1) <= (val2))
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// 测试用例
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
using TestFunc = std::function<void()>;
|
||
|
|
|
||
|
|
struct TestCase {
|
||
|
|
std::string name;
|
||
|
|
std::string suite;
|
||
|
|
TestFunc func;
|
||
|
|
};
|
||
|
|
|
||
|
|
std::vector<TestCase>& getTestCases();
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// 测试注册器
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
class TestRegistrar {
|
||
|
|
public:
|
||
|
|
TestRegistrar(const std::string& suite, const std::string& name, TestFunc func);
|
||
|
|
};
|
||
|
|
|
||
|
|
#define TEST(suite, name) \
|
||
|
|
static void test_##suite##_##name(); \
|
||
|
|
static extra2d::test::TestRegistrar registrar_##suite##_##name(#suite, #name, test_##suite##_##name); \
|
||
|
|
static void test_##suite##_##name()
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// 测试运行器
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
int runAllTests();
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// 测试工具函数
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief 创建测试数据
|
||
|
|
* @param size 数据大小
|
||
|
|
* @param seed 随机种子
|
||
|
|
* @return 测试数据
|
||
|
|
*/
|
||
|
|
inline std::vector<u8> createTestData(size_t size, u32 seed = 42) {
|
||
|
|
std::vector<u8> data(size);
|
||
|
|
for (size_t i = 0; i < size; ++i) {
|
||
|
|
data[i] = static_cast<u8>((seed + i) % 256);
|
||
|
|
}
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief 比较两个数据是否相等
|
||
|
|
*/
|
||
|
|
inline bool dataEquals(const std::vector<u8>& a, const std::vector<u8>& b) {
|
||
|
|
if (a.size() != b.size()) return false;
|
||
|
|
return std::equal(a.begin(), a.end(), b.begin());
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace test
|
||
|
|
} // namespace extra2d
|