• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TestFail(const char * expval,const char * val,const char * exp,const char * file,int line,const char * func)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 
TestEqStr(const char * expval,const char * val,const char * exp,const char * file,int line)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 
InitTestEngine(TestFailEventListener listener)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 
CloseTestEngine(bool force_report)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