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