Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix detect test functions #52

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 34 additions & 19 deletions ctest.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ union ctest_run_func_union {
};

#define CTEST_IMPL_PRAGMA(x) _Pragma (#x)
#define CTEST_CONTAINER_OF(p, T, m) \
((T*)((char*)(p) + 0*sizeof((p) == &((T*)0)->m) - offsetof(T, m)))

#if defined(__GNUC__)
#if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
Expand All @@ -63,6 +65,8 @@ union ctest_run_func_union {
#endif

struct ctest {
uint32_t magic0, padding;

const char* ssname; // suite name
const char* ttname; // test name
union ctest_run_func_union run;
Expand All @@ -71,9 +75,8 @@ struct ctest {
ctest_setup_func* setup;
ctest_teardown_func* teardown;

int skip;

unsigned int magic;
int32_t skip;
uint32_t magic1;
};

#define CTEST_IMPL_NAME(name) ctest_##name
Expand All @@ -88,7 +91,6 @@ struct ctest {
#define CTEST_IMPL_TEARDOWN_FPNAME(sname) CTEST_IMPL_NAME(sname##_teardown_ptr)
#define CTEST_IMPL_TEARDOWN_TPNAME(sname, tname) CTEST_IMPL_NAME(sname##_##tname##_teardown_ptr)

#define CTEST_IMPL_MAGIC (0xdeadbeef)
#ifdef __APPLE__
#define CTEST_IMPL_SECTION __attribute__ ((used, section ("__DATA, .ctest"), aligned(1)))
#else
Expand All @@ -97,14 +99,15 @@ struct ctest {

#define CTEST_IMPL_STRUCT(sname, tname, tskip, tdata, tsetup, tteardown) \
static struct ctest CTEST_IMPL_TNAME(sname, tname) CTEST_IMPL_SECTION = { \
0xBADFEED0, 0, \
#sname, \
#tname, \
{ (ctest_nullary_run_func) CTEST_IMPL_FNAME(sname, tname) }, \
tdata, \
(ctest_setup_func*) tsetup, \
(ctest_teardown_func*) tteardown, \
tskip, \
CTEST_IMPL_MAGIC, \
0xBADFEED1, \
}

#ifdef __cplusplus
Expand Down Expand Up @@ -528,28 +531,40 @@ __attribute__((no_sanitize_address)) int ctest_main(int argc, const char *argv[]
#endif
clock_t t1 = clock();

struct ctest* ctest_begin = &CTEST_IMPL_TNAME(suite, test);
struct ctest* ctest_end = &CTEST_IMPL_TNAME(suite, test);
// find begin and end of section by comparing magics
while (1) {
struct ctest* t = ctest_begin-1;
if (t->magic != CTEST_IMPL_MAGIC) break;
ctest_begin--;
uint32_t* magic_begin = &CTEST_IMPL_TNAME(suite, test).magic1;
uint32_t* magic_end = &CTEST_IMPL_TNAME(suite, test).magic0, *m;
size_t iskip = sizeof(struct ctest)/sizeof *m;

#if (defined __TINYC__ && defined __unix__)
#define CTEST_PEEK 12 /* search 4*(1+12) bytes outside ctest entry bounds */
#else
#define CTEST_PEEK 0 /* access only 4 bytes outside outer ctest entry bounds */
#endif
for (m = magic_begin; magic_begin - m <= iskip + CTEST_PEEK; --m) {
if (*m == 0xBADFEED1) {
magic_begin = m;
m -= iskip - 1;
}
}
while (1) {
struct ctest* t = ctest_end+1;
if (t->magic != CTEST_IMPL_MAGIC) break;
ctest_end++;
for (m = magic_end; m - magic_end <= iskip + CTEST_PEEK; ++m) {
if (*m == 0xBADFEED0) {
magic_end = m;
m += iskip - 1;
}
}
ctest_end++; // end after last one
magic_begin = &CTEST_CONTAINER_OF(magic_begin, struct ctest, magic1)->magic0;

static struct ctest* test;
for (test = ctest_begin; test != ctest_end; test++) {
for (m = magic_begin; m <= magic_end; m += iskip) {
while (*m != 0xBADFEED0) ++m;
test = CTEST_CONTAINER_OF(m, struct ctest, magic0);
if (test == &CTEST_IMPL_TNAME(suite, test)) continue;
if (filter(test)) total++;
}

for (test = ctest_begin; test != ctest_end; test++) {
for (m = magic_begin; m <= magic_end; m += iskip) {
while (*m != 0xBADFEED0) ++m;
test = CTEST_CONTAINER_OF(m, struct ctest, magic0);
if (test == &CTEST_IMPL_TNAME(suite, test)) continue;
if (filter(test)) {
ctest_errorbuffer[0] = 0;
Expand Down