Home | History | Annotate | Download | only in tests
      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