diff options
Diffstat (limited to '3rdparty/asmjit/test/broken.h')
-rw-r--r-- | 3rdparty/asmjit/test/broken.h | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/3rdparty/asmjit/test/broken.h b/3rdparty/asmjit/test/broken.h new file mode 100644 index 00000000000..74b901c3699 --- /dev/null +++ b/3rdparty/asmjit/test/broken.h @@ -0,0 +1,200 @@ +// Broken - Lightweight unit testing for C++ +// +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. +// +// In jurisdictions that recognize copyright laws, the author or authors +// of this software dedicate any and all copyright interest in the +// software to the public domain. We make this dedication for the benefit +// of the public at large and to the detriment of our heirs and +// successors. We intend this dedication to be an overt act of +// relinquishment in perpetuity of all present and future rights to this +// software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// For more information, please refer to <http://unlicense.org> + +#ifndef BROKEN_H_INCLUDED +#define BROKEN_H_INCLUDED + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <utility> + +// Hide everything when using Doxygen. Ideally this can be protected by a macro, +// but there is not globally and widely used one across multiple projects. + +//! \cond + +// Broken - API +// ============ + +namespace BrokenAPI { + +//! Entry point of a unit test defined by `UNIT` macro. +typedef void (*Entry)(void); + +enum Flags : unsigned { + kFlagFinished = 0x1 +}; + +struct Unit; + +bool hasArg(const char* name) noexcept; + +//! Register a new unit test (called automatically by `AutoUnit` and `UNIT`). +void addUnit(Unit* unit) noexcept; + +//! Set output file to a `file`. +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); + +//! Log message, adds automatically new line if not present. +void info(const char* fmt, ...) noexcept; + +//! Called on `EXPECT()` failure. +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; +}; + +//! 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_; + + this->entry = entry_; + this->name = name_; + this->priority = priority_; + this->flags = 0; + this->next = nullptr; + addUnit(this); + } +}; + +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) \ + static void unit_##NAME##_entry(void); \ + static ::BrokenAPI::AutoUnit unit_##NAME##_autoinit(unit_##NAME##_entry, #NAME, PRIORITY); \ + static void unit_##NAME##_entry(void) + +//! \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++. +//! +//! `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 [, ...]) +//! +//! Informative message printed to `stdout`. +#define INFO(...) ::BrokenAPI::info(__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 + +#endif // BROKEN_H_INCLUDED |