Switched to a newer testing framework, fixed warnings on AArch64

This commit is contained in:
kobalicek
2023-03-05 15:27:51 +01:00
parent 76520a513d
commit d38b12a2b5
19 changed files with 971 additions and 895 deletions

View File

@@ -38,79 +38,125 @@
//! \cond
// ============================================================================
// [Broken - API]
// ============================================================================
// Broken - API
// ============
struct BrokenAPI {
//! Entry point of a unit test defined by `UNIT` macro.
typedef void (*Entry)(void);
namespace BrokenAPI {
enum Flags : unsigned {
kFlagFinished = 0x1
};
//! Entry point of a unit test defined by `UNIT` macro.
typedef void (*Entry)(void);
//! Test defined by `UNIT` macro.
struct Unit {
Entry entry;
const char* name;
int priority;
unsigned flags;
Unit* next;
};
enum Flags : unsigned {
kFlagFinished = 0x1
};
//! Automatic unit registration by using static initialization.
struct AutoUnit : Unit {
inline AutoUnit(Entry entry_, const char* name_, int priority_ = 0, int dummy_ = 0) noexcept {
// Not used, only to trick `UNIT()` macro.
(void)dummy_;
struct Unit;
this->entry = entry_;
this->name = name_;
this->priority = priority_;
this->flags = 0;
this->next = nullptr;
BrokenAPI::add(this);
}
};
bool hasArg(const char* name) noexcept;
static bool hasArg(const char* name) noexcept;
//! Register a new unit test (called automatically by `AutoUnit` and `UNIT`).
void addUnit(Unit* unit) noexcept;
//! Register a new unit test (called automatically by `AutoUnit` and `UNIT`).
static void add(Unit* unit) noexcept;
//! Set output file to a `file`.
void setOutputFile(FILE* file) noexcept;
//! Set output file to a `file`.
static void setOutputFile(FILE* file) noexcept;
//! Initialize `Broken` framework.
//!
//! Returns `true` if `run()` should be called.
int run(int argc, const char* argv[], Entry onBeforeRun = nullptr, Entry onAfterRun = nullptr);
//! Initialize `Broken` framework.
//!
//! Returns `true` if `run()` should be called.
static int run(int argc, const char* argv[], Entry onBeforeRun = nullptr, Entry onAfterRun = nullptr);
//! Log message, adds automatically new line if not present.
void info(const char* fmt, ...) noexcept;
//! Log message, adds automatically new line if not present.
static void info(const char* fmt, ...) noexcept;
//! Called on `EXPECT()` failure.
void fail(const char* file, int line, const char* expression, const char* fmt, ...) noexcept;
//! Called on `EXPECT()` failure.
static void fail(const char* file, int line, const char* expression, const char* fmt, ...) noexcept;
//! Test defined by `UNIT` macro.
struct Unit {
Entry entry;
const char* name;
int priority;
unsigned flags;
Unit* next;
};
//! Used internally by `EXPECT` macro.
template<typename T>
static inline void expect(const char* file, int line, const char* expression, const T& result) noexcept {
if (!result)
fail(file, line, expression, nullptr);
}
//! Automatic unit registration by using static initialization.
class AutoUnit : public Unit {
public:
inline AutoUnit(Entry entry_, const char* name_, int priority_ = 0, int dummy_ = 0) noexcept {
// Not used, only to trick `UNIT()` macro.
(void)dummy_;
//! Used internally by `EXPECT` macro.
template<typename T, typename... Args>
static inline void expect(const char* file, int line, const char* expression, const T& result, const char* fmt, Args&&... args) noexcept {
if (!result)
fail(file, line, expression, fmt, std::forward<Args>(args)...);
this->entry = entry_;
this->name = name_;
this->priority = priority_;
this->flags = 0;
this->next = nullptr;
addUnit(this);
}
};
// ============================================================================
// [Broken - Macros]
// ============================================================================
class Failure {
public:
const char* _file = nullptr;
const char* _expression = nullptr;
int _line = 0;
bool _handled = false;
inline Failure(const char* file, int line, const char* expression) noexcept
: _file(file),
_expression(expression),
_line(line) {}
inline ~Failure() noexcept {
if (!_handled)
fail(_file, _line, _expression, nullptr);
}
template<typename... Args>
inline void message(const char* fmt, Args&&... args) noexcept {
fail(_file, _line, _expression, fmt, std::forward<Args>(args)...);
_handled = true;
}
};
template<typename Result>
static inline bool check(Result&& result) noexcept { return !!result; }
template<typename LHS, typename RHS>
static inline bool checkEq(LHS&& lhs, RHS&& rhs) noexcept { return lhs == rhs; }
template<typename LHS, typename RHS>
static inline bool checkNe(LHS&& lhs, RHS&& rhs) noexcept { return lhs != rhs; }
template<typename LHS, typename RHS>
static inline bool checkGt(LHS&& lhs, RHS&& rhs) noexcept { return lhs > rhs; }
template<typename LHS, typename RHS>
static inline bool checkGe(LHS&& lhs, RHS&& rhs) noexcept { return lhs >= rhs; }
template<typename LHS, typename RHS>
static inline bool checkLt(LHS&& lhs, RHS&& rhs) noexcept { return lhs < rhs; }
template<typename LHS, typename RHS>
static inline bool checkLe(LHS&& lhs, RHS&& rhs) noexcept { return lhs <= rhs; }
template<typename Result>
static inline bool checkTrue(Result&& result) noexcept { return !!result; }
template<typename Result>
static inline bool checkFalse(Result&& result) noexcept { return !result; }
template<typename Result>
static inline bool checkNull(Result&& result) noexcept { return result == nullptr; }
template<typename Result>
static inline bool checkNotNull(Result&& result) noexcept { return result != nullptr; }
} // {BrokenAPI}
// Broken - Macros
// ===============
//! Internal macro used by `UNIT()`.
#define BROKEN_UNIT_INTERNAL(NAME, PRIORITY) \
@@ -118,19 +164,14 @@ struct BrokenAPI {
static ::BrokenAPI::AutoUnit unit_##NAME##_autoinit(unit_##NAME##_entry, #NAME, PRIORITY); \
static void unit_##NAME##_entry(void)
//! Stringifies the expression used by EXPECT().
#define BROKEN_STRINFIGY_EXPRESSION_INTERNAL(EXP, ...) #EXP
//! \def UNIT(NAME [, PRIORITY])
//!
//! Define a unit test with an optional priority.
//!
//! `NAME` can only contain ASCII characters, numbers and underscore. It has
//! the same rules as identifiers in C and C++.
//! `NAME` can only contain ASCII characters, numbers and underscore. It has the same rules as identifiers in C and C++.
//!
//! `PRIORITY` specifies the order in which unit tests are run. Lesses value
//! increases the priority. At the moment all units are first sorted by
//! priority and then by name - this makes the run always deterministic.
//! `PRIORITY` specifies the order in which unit tests are run. Lesses value increases the priority. At the moment all
//!units are first sorted by priority and then by name - this makes the run always deterministic.
#define UNIT(NAME, ...) BROKEN_UNIT_INTERNAL(NAME, __VA_ARGS__ + 0)
//! #define INFO(FORMAT [, ...])
@@ -138,10 +179,21 @@ struct BrokenAPI {
//! Informative message printed to `stdout`.
#define INFO(...) ::BrokenAPI::info(__VA_ARGS__)
//! #define INFO(EXP [, FORMAT [, ...]])
//!
//! Expect `EXP` to be true or evaluates to true, fail otherwise.
#define EXPECT(...) ::BrokenAPI::expect(__FILE__, __LINE__, BROKEN_STRINFIGY_EXPRESSION_INTERNAL(__VA_ARGS__), __VA_ARGS__)
#define BROKEN_EXPECT_INTERNAL(file, line, expression, result) \
for (bool _testInternalResult = (result); !_testInternalResult; _testInternalResult = true) \
::BrokenAPI::Failure(file, line, expression)
#define EXPECT(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT(" #__VA_ARGS__ ")", !!(__VA_ARGS__))
#define EXPECT_EQ(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_EQ(" #__VA_ARGS__ ")", ::BrokenAPI::checkEq(__VA_ARGS__))
#define EXPECT_NE(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_NE(" #__VA_ARGS__ ")", ::BrokenAPI::checkNe(__VA_ARGS__))
#define EXPECT_GT(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_GT(" #__VA_ARGS__ ")", ::BrokenAPI::checkGt(__VA_ARGS__))
#define EXPECT_GE(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_GE(" #__VA_ARGS__ ")", ::BrokenAPI::checkGe(__VA_ARGS__))
#define EXPECT_LT(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_LT(" #__VA_ARGS__ ")", ::BrokenAPI::checkLt(__VA_ARGS__))
#define EXPECT_LE(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_LE(" #__VA_ARGS__ ")", ::BrokenAPI::checkLe(__VA_ARGS__))
#define EXPECT_TRUE(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_TRUE(" #__VA_ARGS__ ")", ::BrokenAPI::checkTrue(__VA_ARGS__))
#define EXPECT_FALSE(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_FALSE(" #__VA_ARGS__ ")", ::BrokenAPI::checkFalse(__VA_ARGS__))
#define EXPECT_NULL(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_NULL(" #__VA_ARGS__ ")", ::BrokenAPI::checkNull(__VA_ARGS__))
#define EXPECT_NOT_NULL(...) BROKEN_EXPECT_INTERNAL(__FILE__, __LINE__, "EXPECT_NOT_NULL(" #__VA_ARGS__ ")", ::BrokenAPI::checkNotNull(__VA_ARGS__))
//! \endcond