68# ifndef WIN32_LEAN_AND_MEAN
69# define WIN32_LEAN_AND_MEAN
86 virtual void SetUp() {}
87 virtual void TearDown() {}
88 virtual void TestBody() = 0;
95static bool FLAGS_gtest_catch_exceptions =
true;
97#define GTEST_FLAG(name) FLAGS_gtest_##name
114 bool is_console =
false;
115 HANDLE handle = INVALID_HANDLE_VALUE;
118inline const ConsoleInfo& console_info() {
119 static ConsoleInfo info = []() -> ConsoleInfo {
121 ci.handle = GetStdHandle(STD_OUTPUT_HANDLE);
123 CONSOLE_SCREEN_BUFFER_INFO csi;
124 if (ci.handle != INVALID_HANDLE_VALUE &&
125 GetConsoleMode(ci.handle, &mode) &&
126 GetConsoleScreenBufferInfo(ci.handle, &csi)) {
127 ci.is_console =
true;
128 ci.saved = csi.wAttributes;
142 const ConsoleInfo& ci = console_info();
143 if (!ci.is_console)
return;
144 WORD attr = ci.saved;
146 case TagColor::kGreen: attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
break;
147 case TagColor::kRed: attr = FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
148 case TagColor::kYellow: attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
break;
149 case TagColor::kCyan: attr = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
break;
150 case TagColor::kMagenta: attr = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
break;
151 case TagColor::kDefault:
break;
153 SetConsoleTextAttribute(ci.handle, attr);
157 case TagColor::kGreen: std::fputs(
"\033[32m", stdout);
break;
158 case TagColor::kRed: std::fputs(
"\033[31m", stdout);
break;
159 case TagColor::kYellow: std::fputs(
"\033[33m", stdout);
break;
160 case TagColor::kCyan: std::fputs(
"\033[36m", stdout);
break;
161 case TagColor::kMagenta: std::fputs(
"\033[35m", stdout);
break;
162 case TagColor::kDefault:
break;
170 const ConsoleInfo& ci = console_info();
171 if (!ci.is_console)
return;
172 SetConsoleTextAttribute(ci.handle, ci.saved);
175 std::fputs(
"\033[0m", stdout);
183 std::fputs(tag, stdout);
192 std::function<void()> run;
194 bool skipped =
false;
200 static std::vector<TestCase> list;
212 TestRegistrar(
const char* suite,
const char* name, std::function<
void()> run) {
216 t.run = std::move(run);
231 for (
size_t i = 0; i < t->trace.size(); ++i) {
232 std::fprintf(stderr,
" %s\n", t->trace[i].c_str());
235 std::fputs(msg.c_str(), stderr);
236 std::fputc(
'\n', stderr);
249auto stream_value(std::ostream& os,
const T& v,
int) ->
decltype(os << v, void()) {
253void stream_value(std::ostream&,
const T&,
long) {}
258 ScopedTrace(
const char* file,
int line,
const std::string& msg) {
260 t->trace.push_back(std::string(file) +
":" + std::to_string(line) +
": " + msg);
265 if (!t->trace.empty()) t->trace.pop_back();
274 template <
typename T>
276 stream_value(stream_, v, 0);
287 std::ostringstream stream_;
294 FailHelper(
const char* file,
int line) : file_(file), line_(line) {}
296 template <
typename T>
298 stream_value(stream_, v, 0);
303 std::ostringstream os;
304 os << file_ <<
':' << line_ <<
": Failure\n FAIL()";
305 const std::string extra = stream_.str();
306 if (!extra.empty()) {
307 os <<
"\n Extra: " << extra;
316 std::ostringstream stream_;
324 AssertionHelper(
bool ok,
const char* file,
int line,
const char* expr,
bool fatal)
325 : ok_(ok), file_(file), line_(line), expr_(expr), fatal_(fatal) {}
327 template <
typename T>
330 stream_value(stream_, v, 0);
335 explicit operator bool()
const {
return ok_; }
340 std::ostringstream os;
341 os << file_ <<
':' << line_ <<
": Failure\n Expression: " << expr_;
342 const std::string extra = stream_.str();
343 if (!extra.empty()) {
344 os <<
"\n Extra: " << extra;
358 std::ostringstream stream_;
363inline bool streq(
const char* a,
const char* b) {
364 if (!a || !b)
return a == b;
365 return std::strcmp(a, b) == 0;
367template <
typename A,
typename B>
368inline bool streq(
const A& a,
const B& b) {
369 return std::string(a) == std::string(b);
372inline bool double_eq(
double a,
double b) {
373 if (a == b)
return true;
374 if (std::isnan(a) || std::isnan(b))
return std::isnan(a) && std::isnan(b);
375 double scale = std::fabs(a);
376 if (std::fabs(b) > scale) scale = std::fabs(b);
377 if (scale < 1.0) scale = 1.0;
378 return std::fabs(a - b) <= scale * 4.0 * std::numeric_limits<double>::epsilon();
381inline bool is_near(
double a,
double b,
double eps) {
382 return std::fabs(a - b) <= std::fabs(eps);
387 std::vector<TestCase>& list =
registry();
388 int total = 0, failed = 0, skipped = 0;
390 for (
size_t i = 0; i < list.size(); ++i) {
397 emit_tag(TagColor::kGreen,
"[ RUN ]");
398 std::printf(
" %s.%s\n", tc.suite.c_str(), tc.name.c_str());
399 const bool caught = FLAGS_gtest_catch_exceptions;
407 }
catch (
const std::exception& e) {
424 emit_tag(TagColor::kYellow,
"[ SKIPPED ]");
425 std::printf(
" %s.%s\n", tc.suite.c_str(), tc.name.c_str());
426 }
else if (tc.failures > 0) {
428 emit_tag(TagColor::kRed,
"[ FAILED ]");
429 std::printf(
" %s.%s\n", tc.suite.c_str(), tc.name.c_str());
431 emit_tag(TagColor::kGreen,
"[ OK ]");
432 std::printf(
" %s.%s\n", tc.suite.c_str(), tc.name.c_str());
436 emit_tag(TagColor::kGreen,
"\n[==========]");
437 std::printf(
" %d test(s) ran.\n", total);
438 emit_tag(TagColor::kGreen,
"[ PASSED ]");
439 std::printf(
" %d test(s).\n", total - failed - skipped);
441 emit_tag(TagColor::kYellow,
"[ SKIPPED ]");
442 std::printf(
" %d test(s).\n", skipped);
445 emit_tag(TagColor::kRed,
"[ FAILED ]");
446 std::printf(
" %d test(s).\n", failed);
457namespace testing = ast::testing;
467#define GTEST_SKIP() (::testing::internal::SkipHelper())
472#define AST_TRACE_CONCAT_(a, b) a##b
473#define AST_TRACE_CONCAT(a, b) AST_TRACE_CONCAT_(a, b)
474#define SCOPED_TRACE(message) \
475 ::testing::internal::ScopedTrace AST_TRACE_CONCAT(_gtest_scoped_trace_, __LINE__)(__FILE__, __LINE__, (message))
478#define SUCCEED() do { } while (0)
481#define FAIL() (::testing::internal::FailHelper(__FILE__, __LINE__))
484#define AST_GTEST_ASSERT_(expr, exprtext, fatal) \
485 (::testing::internal::AssertionHelper((expr), __FILE__, __LINE__, (exprtext), (fatal)))
487#define EXPECT_EQ(a, b) AST_GTEST_ASSERT_((a) == (b), #a " == " #b, false)
488#define ASSERT_EQ(a, b) AST_GTEST_ASSERT_((a) == (b), #a " == " #b, true)
489#define EXPECT_NE(a, b) AST_GTEST_ASSERT_((a) != (b), #a " != " #b, false)
490#define ASSERT_NE(a, b) AST_GTEST_ASSERT_((a) != (b), #a " != " #b, true)
491#define EXPECT_LT(a, b) AST_GTEST_ASSERT_((a) < (b), #a " < " #b, false)
492#define ASSERT_LT(a, b) AST_GTEST_ASSERT_((a) < (b), #a " < " #b, true)
493#define EXPECT_GT(a, b) AST_GTEST_ASSERT_((a) > (b), #a " > " #b, false)
494#define ASSERT_GT(a, b) AST_GTEST_ASSERT_((a) > (b), #a " > " #b, true)
495#define EXPECT_LE(a, b) AST_GTEST_ASSERT_((a) <= (b), #a " <= " #b, false)
496#define ASSERT_LE(a, b) AST_GTEST_ASSERT_((a) <= (b), #a " <= " #b, true)
497#define EXPECT_GE(a, b) AST_GTEST_ASSERT_((a) >= (b), #a " >= " #b, false)
498#define ASSERT_GE(a, b) AST_GTEST_ASSERT_((a) >= (b), #a " >= " #b, true)
500#define EXPECT_TRUE(v) AST_GTEST_ASSERT_(static_cast<bool>(v), #v, false)
501#define ASSERT_TRUE(v) AST_GTEST_ASSERT_(static_cast<bool>(v), #v, true)
502#define EXPECT_FALSE(v) AST_GTEST_ASSERT_(!static_cast<bool>(v), #v, false)
503#define ASSERT_FALSE(v) AST_GTEST_ASSERT_(!static_cast<bool>(v), #v, true)
505#define EXPECT_NEAR(a, b, eps) AST_GTEST_ASSERT_(::testing::internal::is_near((a), (b), (eps)), #a " near " #b, false)
506#define ASSERT_NEAR(a, b, eps) AST_GTEST_ASSERT_(::testing::internal::is_near((a), (b), (eps)), #a " near " #b, true)
507#define EXPECT_DOUBLE_EQ(a, b) AST_GTEST_ASSERT_(::testing::internal::double_eq((a), (b)), #a " == " #b, false)
508#define ASSERT_DOUBLE_EQ(a, b) AST_GTEST_ASSERT_(::testing::internal::double_eq((a), (b)), #a " == " #b, true)
509#define EXPECT_FLOAT_EQ(a, b) AST_GTEST_ASSERT_(::testing::internal::double_eq((double)(a), (double)(b)), #a " == " #b, false)
510#define ASSERT_FLOAT_EQ(a, b) AST_GTEST_ASSERT_(::testing::internal::double_eq((double)(a), (double)(b)), #a " == " #b, true)
511#define EXPECT_STREQ(a, b) AST_GTEST_ASSERT_(::testing::internal::streq((a), (b)), #a " == " #b, false)
512#define ASSERT_STREQ(a, b) AST_GTEST_ASSERT_(::testing::internal::streq((a), (b)), #a " == " #b, true)
515#define AST_GTEST_EXPECT_THROW_(stmt, ex, fatal) \
518 try { (void)(stmt); } \
519 catch (const ex&) { ok_ = true; } \
522 ::testing::internal::report_current_failure( \
523 std::string("Expected exception ") + #ex + " from: " + #stmt); \
527#define EXPECT_THROW(stmt, ex) AST_GTEST_EXPECT_THROW_(stmt, ex, false)
528#define ASSERT_THROW(stmt, ex) AST_GTEST_EXPECT_THROW_(stmt, ex, true)
530#define AST_GTEST_EXPECT_NO_THROW_(stmt, fatal) \
532 try { (void)(stmt); } \
534 ::testing::internal::report_current_failure( \
535 std::string("Unexpected exception from: ") + #stmt); \
539#define EXPECT_NO_THROW(stmt) AST_GTEST_EXPECT_NO_THROW_(stmt, false)
540#define ASSERT_NO_THROW(stmt) AST_GTEST_EXPECT_NO_THROW_(stmt, true)
543#define TEST(suite, name) \
544 static void suite##_##name##_TestBody(); \
545 static ::testing::internal::TestRegistrar suite##_##name##_Reg( \
546 #suite, #name, [] { suite##_##name##_TestBody(); }); \
547 static void suite##_##name##_TestBody()
551#define TEST_F(fixture, name) \
552 class fixture##_##name##_Test : public fixture { \
554 void TestBody() override; \
556 static ::testing::internal::TestRegistrar fixture##_##name##_Reg( \
557 #fixture, #name, [] { \
558 std::unique_ptr<::testing::Test> obj_(new fixture##_##name##_Test()); \
563 catch (const ::testing::internal::FatalTestException&) {} \
564 catch (const ::testing::internal::SkippedTestException&) {} \
567 void fixture##_##name##_Test::TestBody()
void end_color()
结束一段彩色输出,恢复默认颜色;若不支持颜色则为空操作。
定义 TestFramework.hpp:168
void emit_tag(TagColor c, const char *tag)
打印带颜色的标签(如 "[ OK ]")。写完标签后立即刷新,确保在 Windows 控制台颜色属性在下一次 SetConsoleTextAttribute 之前已生效。
定义 TestFramework.hpp:181
TestCase *& current_test()
当前正在执行的测试(用于归因失败)。
定义 TestFramework.hpp:205
void InitGoogleTest(int *argc, char **argv)
初始化(极简的)测试运行器。参数被忽略。
定义 TestFramework.hpp:100
bool stdout_is_tty()
判断标准输出是否为终端(仅 POSIX 需要)。
定义 TestFramework.hpp:136
void begin_color(TagColor c)
开启一段彩色输出;若当前输出流不支持颜色则为空操作。
定义 TestFramework.hpp:140
int RUN_ALL_TESTS()
运行全部已注册测试(返回失败数量)。
定义 TestFramework.hpp:460
void report_current_failure(const std::string &msg)
在当前测试上记录一次失败并打印消息(含 SCOPED_TRACE 栈)。
定义 TestFramework.hpp:228
int run_all_tests()
运行全部已注册测试,并返回失败数量。
定义 TestFramework.hpp:386
std::vector< TestCase > & registry()
全局测试注册表(整个程序仅一份)。
定义 TestFramework.hpp:199
void mark_skipped()
将当前测试标记为跳过。
定义 TestFramework.hpp:240
TagColor
标签颜色。Windows(含 Win7)用经典控制台 API;POSIX 用 ANSI 转义 序列,仅当输出为终端时启用。实现全部内联,不额外增加编译单元。
定义 TestFramework.hpp:109
TEST_F 夹具的基类。按需覆写 SetUp()/TearDown()。
定义 TestFramework.hpp:83
由 EXPECT_*/ASSERT_* 返回的临时对象;累加可选的 "<<" 消息;其析构 函数负责上报结果,并在致命断言时抛出 FatalTestException 以终止 包围的测试体。
定义 TestFramework.hpp:322
FAIL() << "msg" 的临时对象:支持 "<<" 流式输出,其析构函数上报一次 致命失败并抛出 FatalTestException 以终止测试体。
定义 TestFramework.hpp:292
SCOPED_TRACE 的 RAII 辅助类:构造时压入一条跟踪信息,析构时弹出。
定义 TestFramework.hpp:256
GTEST_SKIP() << "msg" 的临时对象:支持 "<<" 流式输出,其析构函数将 当前测试标记为跳过并抛出 SkippedTestException 以终止测试体。
定义 TestFramework.hpp:272
constexpr char kCyan[]
青色
定义 Escape.hpp:45
constexpr char kYellow[]
黄色
定义 Escape.hpp:47
Unit B
贝尔(无量纲)
定义 Unit.cpp:506
@fixme 头文件依赖倒置
定义 AgentInit.hpp:26
由致命断言(ASSERT_*)抛出,用于终止测试体。
定义 TestFramework.hpp:222
由 GTEST_SKIP 抛出,用于跳过当前测试。
定义 TestFramework.hpp:225
一个已注册的测试用例。
定义 TestFramework.hpp:189
std::vector< std::string > trace
SCOPED_TRACE 栈
定义 TestFramework.hpp:195
在静态初始化阶段注册一个测试。
定义 TestFramework.hpp:211