mirror of https://github.com/yshui/picom.git
Run run_tests automatically
Make unittest facility less visible. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
cf253e12f3
commit
a84877df68
23
README.md
23
README.md
|
@ -3,12 +3,13 @@ test.h
|
||||||
|
|
||||||
A very simple, light weight, header only C unit test framework.
|
A very simple, light weight, header only C unit test framework.
|
||||||
|
|
||||||
## Features
|
# Features
|
||||||
|
|
||||||
* Easy to use, no dependencies, no setup needed.
|
* Easy to use, no dependencies, no setup needed.
|
||||||
* Keep test cases close to the code they test.
|
* Keep test cases close to the code they test.
|
||||||
* Automatic registration of the test cases.
|
* Automatic registration of the test cases.
|
||||||
|
|
||||||
|
# Usage
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
Just include the header
|
Just include the header
|
||||||
|
@ -17,8 +18,6 @@ Just include the header
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
```
|
```
|
||||||
|
|
||||||
To enable the test cases in your code, compile your program with `-DUNIT_TEST`.
|
|
||||||
|
|
||||||
## Defining test cases
|
## Defining test cases
|
||||||
|
|
||||||
```c
|
```c
|
||||||
|
@ -31,20 +30,8 @@ TEST_CASE(test_case_name) {
|
||||||
|
|
||||||
## Run the test cases
|
## Run the test cases
|
||||||
|
|
||||||
In your main function, call `run_tests`:
|
Build your program with `-DUNIT_TEST`, then run your program with `./program --unittest`.
|
||||||
|
|
||||||
```c
|
# Hooks
|
||||||
int main(int argc, char *const *argv) {
|
|
||||||
// necessary setup code
|
|
||||||
// ...
|
|
||||||
if (!run_tests(argc, argv, NULL)) {
|
|
||||||
// test failed
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
// cleanup
|
|
||||||
// usual code
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
If you define a function `test_h_unittest_setup`, it will be called before any test cases are run.
|
||||||
|
|
||||||
Then, run your program with `./program --unittest`.
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
int main(int argc, char *const *argv) {
|
int main(int argc, char *const *argv) {
|
||||||
run_tests(argc, argv, NULL);
|
printf("Hello World!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(test1) {
|
TEST_CASE(test1) {
|
||||||
|
|
74
test.h
74
test.h
|
@ -60,50 +60,55 @@ struct test_file_metadata __attribute__((weak)) * test_file_head;
|
||||||
SET_FAILURE(#a " != " #b); \
|
SET_FAILURE(#a " != " #b); \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while (0)
|
||||||
|
|
||||||
#define TEST_CASE(_name) \
|
#define TEST_CASE(_name) \
|
||||||
static void __test_h_##_name(struct test_case_metadata *, \
|
static void __test_h_##_name(struct test_case_metadata *, \
|
||||||
struct test_file_metadata *); \
|
struct test_file_metadata *); \
|
||||||
static struct test_file_metadata __test_h_file; \
|
static struct test_file_metadata __test_h_file; \
|
||||||
static struct test_case_metadata __test_h_meta_##_name = { \
|
static struct test_case_metadata __test_h_meta_##_name = { \
|
||||||
.name = #_name, \
|
.name = #_name, \
|
||||||
.fn = __test_h_##_name, \
|
.fn = __test_h_##_name, \
|
||||||
}; \
|
}; \
|
||||||
static void __attribute__((constructor)) __test_h_##_name##_register(void) { \
|
static void __attribute__((constructor(101))) __test_h_##_name##_register(void) { \
|
||||||
__test_h_meta_##_name.next = __test_h_file.tests; \
|
__test_h_meta_##_name.next = __test_h_file.tests; \
|
||||||
__test_h_file.tests = &__test_h_meta_##_name; \
|
__test_h_file.tests = &__test_h_meta_##_name; \
|
||||||
if (!__test_h_file.registered) { \
|
if (!__test_h_file.registered) { \
|
||||||
__test_h_file.name = __FILE__; \
|
__test_h_file.name = __FILE__; \
|
||||||
__test_h_file.next = test_file_head; \
|
__test_h_file.next = test_file_head; \
|
||||||
test_file_head = &__test_h_file; \
|
test_file_head = &__test_h_file; \
|
||||||
__test_h_file.registered = true; \
|
__test_h_file.registered = true; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
static void __test_h_##_name(struct test_case_metadata *metadata, \
|
static void __test_h_##_name(struct test_case_metadata *metadata, \
|
||||||
struct test_file_metadata *file_metadata)
|
struct test_file_metadata *file_metadata)
|
||||||
|
|
||||||
|
extern void __attribute__((weak)) (*test_h_unittest_setup)(void);
|
||||||
/// Run defined tests, return true if all tests succeeds
|
/// Run defined tests, return true if all tests succeeds
|
||||||
/// @param[out] tests_run if not NULL, set to whether tests were run
|
/// @param[out] tests_run if not NULL, set to whether tests were run
|
||||||
static inline bool __attribute__((unused))
|
static inline void __attribute__((constructor(102))) run_tests(void) {
|
||||||
run_tests(int argc, char *const *argv, bool *tests_run) {
|
|
||||||
bool should_run = false;
|
bool should_run = false;
|
||||||
if (tests_run) {
|
FILE *cmdlinef = fopen("/proc/self/cmdline", "r");
|
||||||
*tests_run = false;
|
char *arg = NULL;
|
||||||
}
|
int arglen;
|
||||||
for (int i = 0; i < argc; i++) {
|
fscanf(cmdlinef, "%ms%n", &arg, &arglen);
|
||||||
if (strcmp(argv[i], "--unittest") == 0) {
|
fclose(cmdlinef);
|
||||||
|
for (char *pos = arg; pos < arg + arglen; pos += strlen(pos) + 1) {
|
||||||
|
if (strcmp(pos, "--unittest") == 0) {
|
||||||
should_run = true;
|
should_run = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(arg);
|
||||||
|
|
||||||
if (!should_run) {
|
if (!should_run) {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tests_run) {
|
if (&test_h_unittest_setup) {
|
||||||
*tests_run = true;
|
test_h_unittest_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct test_file_metadata *i = test_file_head;
|
struct test_file_metadata *i = test_file_head;
|
||||||
int failed = 0, success = 0;
|
int failed = 0, success = 0;
|
||||||
while (i) {
|
while (i) {
|
||||||
|
@ -129,7 +134,7 @@ run_tests(int argc, char *const *argv, bool *tests_run) {
|
||||||
int total = failed + success;
|
int total = failed + success;
|
||||||
fprintf(stderr, "Test results: passed %d/%d, failed %d/%d\n", success, total,
|
fprintf(stderr, "Test results: passed %d/%d, failed %d/%d\n", success, total,
|
||||||
failed, total);
|
failed, total);
|
||||||
return failed == 0;
|
exit(failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -146,11 +151,4 @@ run_tests(int argc, char *const *argv, bool *tests_run) {
|
||||||
(void)(a); \
|
(void)(a); \
|
||||||
(void)(b)
|
(void)(b)
|
||||||
|
|
||||||
static inline bool __attribute__((unused))
|
|
||||||
run_tests(int argc, char *const *argv, bool *tests_run) {
|
|
||||||
if (tests_run) {
|
|
||||||
*tests_run = false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue