Added event system to push reporting back to the parent process
This commit is contained in:
parent
6babf0e295
commit
7db8b3f413
14 changed files with 244 additions and 48 deletions
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
CC = gcc
|
||||
CFLAGS = -Wall -Wextra -std=gnu99 -Isrc/ -Iinclude/ -g
|
||||
|
||||
SRCS = runner.c report.c
|
||||
SRCS = runner.c report.c event.c
|
||||
OBJS = $(addprefix src/,$(subst .c,.o,$(SRCS)))
|
||||
|
||||
sample: samples/simple.o libcriterion.a
|
||||
|
|
|
@ -27,49 +27,24 @@
|
|||
# include <stdlib.h>
|
||||
# include <stdbool.h>
|
||||
# include "criterion.h"
|
||||
# include "event.h"
|
||||
|
||||
enum criterion_assert_kind {
|
||||
NORMAL,
|
||||
FATAL
|
||||
};
|
||||
|
||||
struct criterion_assert_stat {
|
||||
enum criterion_assert_kind kind;
|
||||
const char *condition;
|
||||
const char *message;
|
||||
bool passed;
|
||||
unsigned line;
|
||||
|
||||
struct criterion_assert_stat *next;
|
||||
};
|
||||
|
||||
struct criterion_test_stats {
|
||||
struct criterion_test *test;
|
||||
struct criterion_assert_stat *asserts;
|
||||
unsigned failed;
|
||||
unsigned passed;
|
||||
};
|
||||
|
||||
extern struct criterion_test_stats g_current_test_stats;
|
||||
|
||||
# define assertImpl(Kind, Condition, ...) \
|
||||
do { \
|
||||
int passed = !!(Condition); \
|
||||
struct criterion_assert_stat *stat = \
|
||||
malloc(sizeof (struct criterion_assert_stat)); \
|
||||
*stat = (struct criterion_assert_stat) { \
|
||||
struct criterion_assert_stat stat = { \
|
||||
.kind = Kind, \
|
||||
.condition = #Condition, \
|
||||
.message = "" __VA_ARGS__, \
|
||||
.passed = passed, \
|
||||
.line = __LINE__, \
|
||||
.next = g_current_test_stats.asserts, \
|
||||
}; \
|
||||
g_current_test_stats.asserts = stat; \
|
||||
if (passed) \
|
||||
++g_current_test_stats.passed; \
|
||||
else \
|
||||
++g_current_test_stats.failed; \
|
||||
send_event(ASSERT, &stat, sizeof (stat)); \
|
||||
if (!passed && Kind == FATAL) \
|
||||
return; \
|
||||
} while (0)
|
31
include/criterion/event.h
Normal file
31
include/criterion/event.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef CRITERION_EVENT_H_
|
||||
# define CRITERION_EVENT_H_
|
||||
|
||||
extern const int EVENT_PIPE;
|
||||
|
||||
void send_event(int kind, void *data, size_t size);
|
||||
|
||||
#endif /* !CRITERION_EVENT_H_ */
|
|
@ -30,6 +30,8 @@ typedef enum {
|
|||
PRE_EVERYTHING,
|
||||
PRE_INIT,
|
||||
PRE_TEST,
|
||||
ASSERT,
|
||||
TEST_CRASH,
|
||||
POST_TEST,
|
||||
POST_FINI,
|
||||
POST_EVERYTHING,
|
43
include/criterion/stats.h
Normal file
43
include/criterion/stats.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef CRITERION_STATS_H_
|
||||
# define CRITERION_STATS_H_
|
||||
|
||||
# include "criterion.h"
|
||||
|
||||
struct criterion_assert_stat {
|
||||
int kind;
|
||||
const char *condition;
|
||||
const char *message;
|
||||
bool passed;
|
||||
unsigned line;
|
||||
};
|
||||
|
||||
struct criterion_test_stats {
|
||||
struct criterion_test *test;
|
||||
int passed;
|
||||
int failed;
|
||||
};
|
||||
|
||||
#endif /* !CRITERION_STATS_H_ */
|
|
@ -1,8 +1,9 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "criterion.h"
|
||||
#include "report.h"
|
||||
#include "assert.h"
|
||||
#include <criterion/criterion.h>
|
||||
#include <criterion/assert.h>
|
||||
#include <criterion/hooks.h>
|
||||
#include <criterion/stats.h>
|
||||
|
||||
Test(misc, failing) {
|
||||
assert(1);
|
||||
|
@ -13,6 +14,19 @@ Test(misc, simple) {
|
|||
expect(1);
|
||||
}
|
||||
|
||||
Test(aziezdcjn, simple) {
|
||||
expect(1);
|
||||
}
|
||||
Test(aziezdcjn, abcd) {
|
||||
expect(1);
|
||||
}
|
||||
Test(aziezdcjn, simplez) {
|
||||
expect(1);
|
||||
}
|
||||
Test(aziezdcjn, simpl) {
|
||||
expect(1);
|
||||
}
|
||||
|
||||
ReportHook(PRE_INIT)(struct criterion_test *test) {
|
||||
printf("testing %s in category %s\n", test->name, test->category);
|
||||
}
|
||||
|
|
64
src/event.c
Normal file
64
src/event.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "criterion/assert.h"
|
||||
#undef assert
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <csptr/smart_ptr.h>
|
||||
#include "criterion/criterion.h"
|
||||
#include "criterion/stats.h"
|
||||
#include "criterion/hooks.h"
|
||||
#include "event.h"
|
||||
|
||||
const int EVENT_PIPE = 3;
|
||||
|
||||
void destroy_event(void *ptr, UNUSED void *meta) {
|
||||
struct event *ev = ptr;
|
||||
free(ev->data);
|
||||
}
|
||||
|
||||
struct event *read_event(int fd) {
|
||||
unsigned kind;
|
||||
if (read(fd, &kind, sizeof (unsigned)) < (ssize_t) sizeof (unsigned))
|
||||
return NULL;
|
||||
|
||||
if (kind != ASSERT)
|
||||
return unique_ptr(struct event, ({ .kind = kind, .data = NULL }));
|
||||
|
||||
const size_t assert_size = sizeof (struct criterion_assert_stat);
|
||||
unsigned char *buf = malloc(assert_size);
|
||||
if (read(fd, buf, assert_size) < (ssize_t) assert_size)
|
||||
return NULL;
|
||||
|
||||
return unique_ptr(struct event, ({ .kind = kind, .data = buf }), destroy_event);
|
||||
}
|
||||
|
||||
void send_event(int kind, void *data, size_t size) {
|
||||
unsigned char buf[sizeof (int) + size];
|
||||
memcpy(buf, &kind, sizeof (int));
|
||||
memcpy(buf + sizeof (int), data, size);
|
||||
write(EVENT_PIPE, buf, sizeof (buf));
|
||||
}
|
36
src/event.h
Normal file
36
src/event.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2015 Franklin "Snaipe" Mathieu <http://snai.pe/>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef EVENT_H_
|
||||
# define EVENT_H_
|
||||
|
||||
# include "criterion/event.h"
|
||||
|
||||
struct event {
|
||||
int kind;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct event *read_event(int fd);
|
||||
|
||||
#endif /* !EVENT_H_ */
|
|
@ -22,7 +22,8 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "criterion.h"
|
||||
#include "criterion/criterion.h"
|
||||
#include "criterion/stats.h"
|
||||
#include "report.h"
|
||||
|
||||
#define IMPL_CALL_REPORT_HOOKS(Kind) \
|
||||
|
@ -60,3 +61,5 @@ ReportHook(POST_FINI)() {}
|
|||
|
||||
ReportHook(PRE_EVERYTHING)() {}
|
||||
ReportHook(POST_EVERYTHING)() {}
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#ifndef REPORT_H_
|
||||
# define REPORT_H_
|
||||
|
||||
# include "hooks.h"
|
||||
# include "criterion/hooks.h"
|
||||
|
||||
# define report(Kind, Data) call_report_hooks_##Kind(Data)
|
||||
|
||||
|
|
54
src/runner.c
54
src/runner.c
|
@ -22,13 +22,15 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <csptr/smart_ptr.h>
|
||||
#include "criterion/assert.h"
|
||||
#include "criterion/stats.h"
|
||||
#include "runner.h"
|
||||
#include "report.h"
|
||||
#include "assert.h"
|
||||
#include "event.h"
|
||||
|
||||
static struct criterion_test * const g_section_start = &__start_criterion_tests;
|
||||
static struct criterion_test * const g_section_end = &__stop_criterion_tests;
|
||||
|
@ -92,31 +94,57 @@ static void map_tests(struct test_set *set, void (*fun)(struct criterion_test *)
|
|||
__attribute__ ((always_inline))
|
||||
static inline void nothing() {}
|
||||
|
||||
struct criterion_test_stats g_current_test_stats;
|
||||
|
||||
static void run_test_nofork(struct criterion_test *test) {
|
||||
report(PRE_INIT, test);
|
||||
static void run_test_child(struct criterion_test *test) {
|
||||
send_event(PRE_INIT, NULL, 0);
|
||||
(test->data->init ?: nothing)();
|
||||
report(PRE_TEST, test);
|
||||
|
||||
g_current_test_stats = (struct criterion_test_stats) { .test = test };
|
||||
send_event(PRE_TEST, NULL, 0);
|
||||
(test->test ?: nothing)();
|
||||
|
||||
report(POST_TEST, &g_current_test_stats);
|
||||
send_event(POST_TEST, NULL, 0);
|
||||
(test->data->fini ?: nothing)();
|
||||
report(POST_FINI, test);
|
||||
send_event(POST_FINI, NULL, 0);
|
||||
}
|
||||
|
||||
struct pipefds {
|
||||
int in, out;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static void setup_child(struct pipefds *fds) {
|
||||
close(STDIN_FILENO);
|
||||
close(fds->in);
|
||||
dup2(fds->out, EVENT_PIPE);
|
||||
close(fds->out);
|
||||
}
|
||||
|
||||
static void run_test(struct criterion_test *test) {
|
||||
struct pipefds fds;
|
||||
if (pipe((int*) &fds) == -1)
|
||||
abort();
|
||||
|
||||
pid_t pid;
|
||||
if (!(pid = fork())) {
|
||||
run_test_nofork(test);
|
||||
setup_child(&fds);
|
||||
|
||||
run_test_child(test);
|
||||
exit(0);
|
||||
} else {
|
||||
struct criterion_test_stats stats = { .test = test };
|
||||
close(fds.out);
|
||||
struct event *ev;
|
||||
while ((ev = read_event(fds.in)) != NULL) {
|
||||
switch (ev->kind) {
|
||||
case PRE_INIT: report(PRE_INIT, test); break;
|
||||
case PRE_TEST: report(PRE_TEST, test); break;
|
||||
case ASSERT: report(PRE_TEST, ev->data); break;
|
||||
case POST_TEST: report(POST_TEST, &stats); break;
|
||||
case POST_FINI: report(POST_FINI, test); break;
|
||||
}
|
||||
sfree(ev);
|
||||
}
|
||||
waitpid(pid, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: disable & change tests at runtime
|
||||
void run_all(void) {
|
||||
report(PRE_EVERYTHING, NULL);
|
||||
smart struct test_set *set = read_all_tests();
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#ifndef CRITERION_RUNNER_H_
|
||||
# define CRITERION_RUNNER_H_
|
||||
|
||||
# include "criterion.h"
|
||||
# include "criterion/criterion.h"
|
||||
|
||||
extern struct criterion_test __start_criterion_tests;
|
||||
extern struct criterion_test __stop_criterion_tests;
|
||||
|
|
Loading…
Add table
Reference in a new issue