Skip to content

Instantly share code, notes, and snippets.

@minad
Last active January 10, 2016 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save minad/8c791c7187b0d7ba3561 to your computer and use it in GitHub Desktop.
Save minad/8c791c7187b0d7ba3561 to your computer and use it in GitHub Desktop.
#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