Last active
January 10, 2016 15:53
-
-
Save minad/8c791c7187b0d7ba3561 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <setjmp.h> | |
#include <signal.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <time.h> | |
#define ASSERT_CHAR(a, cmp, b) _ASSERT_CMP(char, %d, a, cmp, b) | |
#define ASSERT_SHORT(a, cmp, b) _ASSERT_CMP(short, %d, a, cmp, b) | |
#define ASSERT_INT(a, cmp, b) _ASSERT_CMP(int, %d, a, cmp, b) | |
#define ASSERT_LONG(a, cmp, b) _ASSERT_CMP(long, %ld, a, cmp, b) | |
#define ASSERT_UCHAR(a, cmp, b) _ASSERT_CMP(unsigned char, %u, a, cmp, b) | |
#define ASSERT_USHORT(a, cmp, b) _ASSERT_CMP(unsigned short, %u, a, cmp, b) | |
#define ASSERT_UINT(a, cmp, b) _ASSERT_CMP(unsigned int, %u, a, cmp, b) | |
#define ASSERT_ULONG(a, cmp, b) _ASSERT_CMP(unsigned long, %lu, a, cmp, b) | |
#define ASSERT(cond, msg) assert((msg, cond)) | |
#ifdef NDEBUG | |
static inline void runTests() {} | |
#define TEST(name) static inline __attribute__((unused)) void _unused_test_##name() | |
#define _ASSERT_CMP(type, fmt, a, cmp, b) ((void)0) | |
#else | |
typedef void (*TestFunc)(void); | |
extern void runTests(void); | |
#define TEST(name) \ | |
void test_##name(void); \ | |
static TestFunc _register_test_##name \ | |
__attribute__ ((section("test_registry"), used)) = test_##name; \ | |
void test_##name() | |
#define _ASSERT_CMP(type, fmt, a, cmp, b) \ | |
do { \ | |
type _a = (a), _b = (b); \ | |
if (_a cmp _b) break; \ | |
fprintf(stderr, \ | |
"%s:%d: %s: Comparison `%s %s %s' failed (" #fmt " %s " #fmt ").\n", \ | |
__FILE__, __LINE__, __func__, #a, #cmp, #b, _a, #cmp, _b); \ | |
abort(); \ | |
} while (0) | |
#endif | |
#ifndef NDEBUG | |
static sigjmp_buf testBuf; | |
extern TestFunc __start_test_registry[], __stop_test_registry[]; | |
static void handleAbort() { | |
siglongjmp(testBuf, 1); | |
} | |
static void shuffle(TestFunc* a, int n) { | |
for (int i = 0; i < n - 1; i++) { | |
int j = i + rand() / (RAND_MAX / (n - i) + 1); | |
TestFunc t = a[j]; | |
a[j] = a[i]; | |
a[i] = t; | |
} | |
} | |
void runTests() { | |
if (!getenv("TEST")) | |
return; | |
char* s = getenv("TEST_SEED"); | |
unsigned int seed = s ? strtoul(s, 0, 10) : (unsigned int)time(0); | |
srand(seed); | |
fprintf(stderr, "*** Running test suite with TEST_SEED=%d ***\n", seed); | |
struct sigaction sigabrt = { .sa_handler = handleAbort }; | |
sigemptyset(&sigabrt.sa_mask); | |
if (sigaction(SIGABRT, &sigabrt, 0) < 0) | |
return perror("sigaction"); | |
int failed = 0, total = __stop_test_registry - __start_test_registry; | |
shuffle(__start_test_registry, total); | |
for (int i = 0, row = 0; i < total; ++i) { | |
if (sigsetjmp(testBuf, 1)) { | |
++failed; | |
row = 0; | |
} else { | |
__start_test_registry[i](); | |
fprintf(stderr, row > 0 ? "\033[A\033[%dC.\n" : ".\n", row); | |
++row; | |
} | |
fflush(stderr); | |
} | |
fprintf(stderr, "%d succeeded, %d failed.\n", total - failed, failed); | |
exit(failed > 0); | |
} | |
#endif | |
TEST(plus1) { | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
} | |
TEST(fail1) { | |
ASSERT_INT(1 + 1, ==, 3); usleep(100000); | |
ASSERT_INT(1 + 1, ==, 3); usleep(100000); | |
ASSERT_INT(1 + 1, ==, 3); usleep(100000); | |
} | |
TEST(plus2) { | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
} | |
TEST(plus3) { | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
} | |
TEST(plus4) { | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
} | |
TEST(plus5) { | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
} | |
TEST(plus6) { | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
assert(1 + 1 == 2); usleep(100000); | |
} | |
TEST(fail2) { | |
ASSERT_INT(1 + 1, ==, 3); usleep(100000); | |
ASSERT_INT(1 + 1, ==, 3); usleep(100000); | |
ASSERT_INT(1 + 1, ==, 3); usleep(100000); | |
} | |
TEST(fail3) { | |
assert(1 + 1 == 3); usleep(100000); | |
assert(1 + 1 == 3); usleep(100000); | |
assert(1 + 1 == 3); usleep(100000); | |
} | |
int main(int argc, char* argv[]) { | |
runTests(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment