blob: 9d5f7801fcf13905d70531c8c1b2a9197341550c [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001#ifndef TEST_ASSERT_H
2#define TEST_ASSERT_H
3
4#include "flatbuffers/base.h"
5#include "flatbuffers/util.h"
6
7// clang-format off
8
9#ifdef __ANDROID__
10 #include <android/log.h>
11 #define TEST_OUTPUT_LINE(...) \
12 __android_log_print(ANDROID_LOG_INFO, "FlatBuffers", __VA_ARGS__)
13 #define FLATBUFFERS_NO_FILE_TESTS
14#else
15 #define TEST_OUTPUT_LINE(...) \
Austin Schuh272c6132020-11-14 16:37:52 -080016 do { printf(__VA_ARGS__); printf("\n"); } while(!IsConstTrue(true))
Austin Schuhe89fa2d2019-08-14 20:24:23 -070017#endif
18
Austin Schuh272c6132020-11-14 16:37:52 -080019#define TEST_EQ(exp, val) TestEq(exp, val, "'" #exp "' != '" #val "'", __FILE__, __LINE__, "")
20#define TEST_ASSERT(val) TestEq(true, !!(val), "'" "true" "' != '" #val "'", __FILE__, __LINE__, "")
21#define TEST_NOTNULL(val) TestEq(true, (val) != nullptr, "'" "nullptr" "' == '" #val "'", __FILE__, __LINE__, "")
22#define TEST_EQ_STR(exp, val) TestEqStr(exp, val, "'" #exp "' != '" #val "'", __FILE__, __LINE__, "")
Austin Schuhe89fa2d2019-08-14 20:24:23 -070023
24#ifdef _WIN32
Austin Schuh272c6132020-11-14 16:37:52 -080025 #define TEST_ASSERT_FUNC(val) TestEq(true, !!(val), "'" "true" "' != '" #val "'", __FILE__, __LINE__, __FUNCTION__)
26 #define TEST_EQ_FUNC(exp, val) TestEq(exp, val, "'" #exp "' != '" #val "'", __FILE__, __LINE__, __FUNCTION__)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070027#else
Austin Schuh272c6132020-11-14 16:37:52 -080028 #define TEST_ASSERT_FUNC(val) TestEq(true, !!(val), "'" "true" "' != '" #val "'", __FILE__, __LINE__, __PRETTY_FUNCTION__)
29 #define TEST_EQ_FUNC(exp, val) TestEq(exp, val, "'" #exp "' != '" #val "'", __FILE__, __LINE__, __PRETTY_FUNCTION__)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070030#endif
31
32// clang-format on
33
34extern int testing_fails;
35
36// Listener of TestFail, like 'gtest::OnTestPartResult' event handler.
37// Called in TestFail after a failed assertion.
38typedef bool (*TestFailEventListener)(const char *expval, const char *val,
39 const char *exp, const char *file,
40 int line, const char *func);
41
42// Prepare test engine (MSVC assertion setup, etc).
43// listener - this function will be notified on each TestFail call.
44void InitTestEngine(TestFailEventListener listener = nullptr);
45
46// Release all test-engine resources.
47// Prints or schedule a debug report if all test passed.
48// Returns 0 if all tests passed or 1 otherwise.
49// Memory leak report: FLATBUFFERS_MEMORY_LEAK_TRACKING && _MSC_VER && _DEBUG.
50int CloseTestEngine(bool force_report = false);
51
52// Write captured state to a log and terminate test run.
53void TestFail(const char *expval, const char *val, const char *exp,
Austin Schuh2dd86a92022-09-14 21:19:23 -070054 const char *file, int line, const char *func = nullptr);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070055
56void TestEqStr(const char *expval, const char *val, const char *exp,
Austin Schuh2dd86a92022-09-14 21:19:23 -070057 const char *file, int line, const char *func = nullptr);
Austin Schuh272c6132020-11-14 16:37:52 -080058
59// Workaround for `enum class` printing.
60// There is an issue with the printing of enums with a fixed underlying type.
61// These enums are generated by `flatc` if `--scoped-enums` is active.
62// All modern compilers have problems with `std::stringstream&<<(T v)` if T is
63// an enum with fixed type. For details see DR1601:
64// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1601
65// https://stackoverflow.com/questions/34336024/ambiguous-overload-when-writing-an-enum-with-an-enum-base-but-only-with-clang
66
67template<typename T, bool is_enum_type = flatbuffers::is_enum<T>::value>
68struct underlying_of_scalar {
69 static_assert(flatbuffers::is_scalar<T>::value, "invalid type T");
70 typedef T type;
71};
72
73template<typename T> struct underlying_of_scalar<T, true> {
74// clang-format off
75 // There are old compilers without full C++11 support (see stl_emulation.h).
James Kuszmaul8e62b022022-03-22 09:33:25 -070076 #if defined(FLATBUFFERS_TEMPLATES_ALIASES)
Austin Schuh272c6132020-11-14 16:37:52 -080077 using type = typename std::underlying_type<T>::type;
78 #else
79 typedef int64_t type;
80 #endif
81 // clang-format on
82};
83
84template<typename T>
85typename underlying_of_scalar<T>::type scalar_as_underlying(T v) {
86 return static_cast<typename underlying_of_scalar<T>::type>(v);
87}
Austin Schuhe89fa2d2019-08-14 20:24:23 -070088
89template<typename T, typename U>
90void TestEq(T expval, U val, const char *exp, const char *file, int line,
Austin Schuh272c6132020-11-14 16:37:52 -080091 const char *func) {
92 if (static_cast<U>(expval) != val) {
93 TestFail(flatbuffers::NumToString(scalar_as_underlying(expval)).c_str(),
94 flatbuffers::NumToString(scalar_as_underlying(val)).c_str(), exp,
95 file, line, func);
96 }
97}
98
99template<>
100inline void TestEq<std::string, std::string>(std::string expval,
101 std::string val, const char *exp,
102 const char *file, int line,
103 const char *func) {
104 if (expval != val) {
105 TestFail(expval.c_str(), val.c_str(), exp, file, line, func);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700106 }
107}
108
109#endif // !TEST_ASSERT_H