mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 12:34:35 +03:00
Merged asmjit:next branch (#149)
This commit is contained in:
278
test/broken.cpp
Normal file
278
test/broken.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
// [Broken]
|
||||
// Lightweight Unit Testing for C++.
|
||||
//
|
||||
// [License]
|
||||
// Public Domain (Unlicense)
|
||||
|
||||
// [Dependencies]
|
||||
#include "./broken.h"
|
||||
|
||||
// ============================================================================
|
||||
// [Broken - Global]
|
||||
// ============================================================================
|
||||
|
||||
// Zero initialized globals.
|
||||
struct BrokenGlobal {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
bool hasArg(const char* a) const {
|
||||
int argc = _argc;
|
||||
const char** argv = _argv;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (::strcmp(argv[i], a) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* getFile() const {
|
||||
return _file ? _file : stdout;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Application arguments.
|
||||
int _argc;
|
||||
const char** _argv;
|
||||
|
||||
// Output file.
|
||||
FILE* _file;
|
||||
|
||||
// Current context.
|
||||
const char* _currentFile;
|
||||
int _currentLine;
|
||||
|
||||
// Unit tests.
|
||||
BrokenAPI::Unit* _unitList;
|
||||
BrokenAPI::Unit* _unitRunning;
|
||||
};
|
||||
static BrokenGlobal _brokenGlobal;
|
||||
|
||||
// ============================================================================
|
||||
// [Broken - API]
|
||||
// ============================================================================
|
||||
|
||||
// Get whether the string `a` starts with string `b`.
|
||||
static bool BrokenAPI_startsWith(const char* a, const char* b) {
|
||||
for (size_t i = 0; ; i++) {
|
||||
if (b[i] == '\0') return true;
|
||||
if (a[i] != b[i]) return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get whether the strings `a` and `b` are equal, ignoring case and treating
|
||||
// `-` as `_`.
|
||||
static bool BrokenAPI_matchesFilter(const char* a, const char* b) {
|
||||
for (size_t i = 0; ; i++) {
|
||||
unsigned char ca = static_cast<unsigned char>(a[i]);
|
||||
unsigned char cb = static_cast<unsigned char>(b[i]);
|
||||
|
||||
// If filter is defined as wildcard the rest automatically matches.
|
||||
if (cb == '*')
|
||||
return true;
|
||||
|
||||
if (ca == '-') ca = '_';
|
||||
if (cb == '-') cb = '_';
|
||||
|
||||
if (ca >= 'A' && ca <= 'Z') ca += 'a' - 'A';
|
||||
if (cb >= 'A' && cb <= 'Z') cb += 'a' - 'A';
|
||||
|
||||
if (ca != cb)
|
||||
return false;
|
||||
|
||||
if (ca == '\0')
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool BrokenAPI_canRun(BrokenAPI::Unit* unit) {
|
||||
BrokenGlobal& global = _brokenGlobal;
|
||||
|
||||
int i, argc = global._argc;
|
||||
const char** argv = global._argv;
|
||||
|
||||
const char* unitName = unit->name;
|
||||
bool hasFilter = false;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char* arg = argv[i];
|
||||
|
||||
if (BrokenAPI_startsWith(arg, "--run-") && ::strcmp(arg, "--run-all") != 0) {
|
||||
hasFilter = true;
|
||||
|
||||
if (BrokenAPI_matchesFilter(unitName, arg + 6))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If no filter has been specified the default is to run.
|
||||
return !hasFilter;
|
||||
}
|
||||
|
||||
static void BrokenAPI_runUnit(BrokenAPI::Unit* unit) {
|
||||
BrokenAPI::info("Running %s", unit->name);
|
||||
|
||||
_brokenGlobal._unitRunning = unit;
|
||||
unit->entry();
|
||||
_brokenGlobal._unitRunning = NULL;
|
||||
}
|
||||
|
||||
static void BrokenAPI_runAll() {
|
||||
BrokenAPI::Unit* unit = _brokenGlobal._unitList;
|
||||
|
||||
bool hasUnits = unit != NULL;
|
||||
size_t count = 0;
|
||||
|
||||
while (unit != NULL) {
|
||||
if (BrokenAPI_canRun(unit)) {
|
||||
BrokenAPI_runUnit(unit);
|
||||
count++;
|
||||
}
|
||||
unit = unit->next;
|
||||
}
|
||||
|
||||
if (count) {
|
||||
INFO("\nSuccess:");
|
||||
INFO(" All tests passed!");
|
||||
}
|
||||
else {
|
||||
INFO("\nWarning:");
|
||||
INFO(" No units %s!", hasUnits ? "matched the filter" : "defined");
|
||||
}
|
||||
}
|
||||
|
||||
static void BrokenAPI_listAll() {
|
||||
BrokenAPI::Unit* unit = _brokenGlobal._unitList;
|
||||
|
||||
if (unit != NULL) {
|
||||
INFO("Units:");
|
||||
do {
|
||||
INFO(" %s", unit->name);
|
||||
unit = unit->next;
|
||||
} while (unit != NULL);
|
||||
}
|
||||
else {
|
||||
INFO("Warning:");
|
||||
INFO(" No units defined!");
|
||||
}
|
||||
}
|
||||
|
||||
void BrokenAPI::add(Unit* unit) {
|
||||
Unit** pPrev = &_brokenGlobal._unitList;
|
||||
Unit* current = *pPrev;
|
||||
|
||||
// C++ static initialization doesn't guarantee anything. We sort all units by
|
||||
// name so the execution will always happen in deterministic order.
|
||||
while (current != NULL) {
|
||||
if (::strcmp(current->name, unit->name) >= 0)
|
||||
break;
|
||||
|
||||
pPrev = ¤t->next;
|
||||
current = *pPrev;
|
||||
}
|
||||
|
||||
*pPrev = unit;
|
||||
unit->next = current;
|
||||
}
|
||||
|
||||
void BrokenAPI::setOutputFile(FILE* file) {
|
||||
BrokenGlobal& global = _brokenGlobal;
|
||||
|
||||
global._file = file;
|
||||
}
|
||||
|
||||
int BrokenAPI::setContext(const char* file, int line) {
|
||||
BrokenGlobal& global = _brokenGlobal;
|
||||
|
||||
global._currentFile = file;
|
||||
global._currentLine = line;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BrokenAPI::run(int argc, const char* argv[],
|
||||
Entry onBeforeRun,
|
||||
Entry onAfterRun) {
|
||||
|
||||
BrokenGlobal& global = _brokenGlobal;
|
||||
|
||||
global._argc = argc;
|
||||
global._argv = argv;
|
||||
|
||||
if (global.hasArg("--help")) {
|
||||
INFO("Options:");
|
||||
INFO(" --help - print this usage");
|
||||
INFO(" --list - list all tests");
|
||||
INFO(" --run-... - run a test(s), trailing wildcards supported");
|
||||
INFO(" --run-all - run all tests");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (global.hasArg("--list")) {
|
||||
BrokenAPI_listAll();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (onBeforeRun)
|
||||
onBeforeRun();
|
||||
|
||||
// We don't care about filters here, it's implemented by `runAll`.
|
||||
BrokenAPI_runAll();
|
||||
|
||||
if (onAfterRun)
|
||||
onAfterRun();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BrokenAPI::info(const char* fmt, ...) {
|
||||
BrokenGlobal& global = _brokenGlobal;
|
||||
FILE* dst = global.getFile();
|
||||
|
||||
const char* prefix = global._unitRunning ? " " : "";
|
||||
size_t len = ::strlen(fmt);
|
||||
|
||||
if (len != 0) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
::fputs(prefix, dst);
|
||||
::vfprintf(dst, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
if (len == 0 || fmt[len - 1] != '\n')
|
||||
::fputs("\n", dst);
|
||||
|
||||
::fflush(dst);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BrokenAPI::fail(const char* fmt, va_list ap) {
|
||||
BrokenGlobal& global = _brokenGlobal;
|
||||
FILE* dst = global.getFile();
|
||||
|
||||
::fputs(" Failed!", dst);
|
||||
if (fmt == NULL)
|
||||
fmt = "";
|
||||
|
||||
size_t len = ::strlen(fmt);
|
||||
if (len != 0) {
|
||||
::fputs(" ", dst);
|
||||
::vfprintf(dst, fmt, ap);
|
||||
}
|
||||
|
||||
if (len > 0 && fmt[len - 1] != '\n')
|
||||
::fputs("\n", dst);
|
||||
|
||||
::fprintf(dst, " File: %s (Line: %d)\n", global._currentFile, global._currentLine);
|
||||
::fflush(dst);
|
||||
|
||||
::exit(1);
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user