1 #include "test_assert.h" 2 3 #include <assert.h> 4 5 #ifdef _MSC_VER 6 # include <crtdbg.h> 7 #endif 8 9 int testing_fails = 0; 10 static TestFailEventListener fail_listener_ = nullptr; 11 12 void TestFail(const char *expval, const char *val, const char *exp, 13 const char *file, int line, const char *func) { 14 TEST_OUTPUT_LINE("VALUE: \"%s\"", expval); 15 TEST_OUTPUT_LINE("EXPECTED: \"%s\"", val); 16 TEST_OUTPUT_LINE("TEST FAILED: %s:%d, %s in %s", file, line, exp, 17 func ? func : ""); 18 testing_fails++; 19 20 // Notify, emulate 'gtest::OnTestPartResult' event handler. 21 if (fail_listener_) (*fail_listener_)(expval, val, exp, file, line, func); 22 23 assert(0); // ignored in Release if NDEBUG defined 24 } 25 26 void TestEqStr(const char *expval, const char *val, const char *exp, 27 const char *file, int line) { 28 if (strcmp(expval, val) != 0) { TestFail(expval, val, exp, file, line); } 29 } 30 31 #if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && defined(_MSC_VER) && \ 32 defined(_DEBUG) 33 #define FLATBUFFERS_MEMORY_LEAK_TRACKING_MSVC 34 #endif 35 36 void InitTestEngine(TestFailEventListener listener) { 37 testing_fails = 0; 38 // Disable stdout buffering to prevent information lost on assertion or core 39 // dump. 40 setvbuf(stdout, NULL, _IONBF, 0); 41 setvbuf(stderr, NULL, _IONBF, 0); 42 43 // clang-format off 44 45 #ifdef _MSC_VER 46 // Send all reports to STDOUT. 47 // CrtDebug reports to _CRT_WARN channel. 48 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 49 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); 50 // The assert from <assert.h> reports to _CRT_ERROR channel 51 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 52 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT); 53 // Internal CRT assert channel? 54 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 55 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT); 56 #endif 57 58 #if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING_MSVC) 59 // For more thorough checking: 60 // _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF 61 auto flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 62 _CrtSetDbgFlag(flags | _CRTDBG_ALLOC_MEM_DF); 63 #endif 64 // clang-format on 65 66 fail_listener_ = listener; 67 } 68 69 int CloseTestEngine(bool force_report) { 70 if (!testing_fails || force_report) { 71 #if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING_MSVC) 72 auto flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 73 flags &= ~_CRTDBG_DELAY_FREE_MEM_DF; 74 flags |= _CRTDBG_LEAK_CHECK_DF; 75 _CrtSetDbgFlag(flags); 76 #endif 77 } 78 return (0 != testing_fails); 79 } 80