Added statistics gathering mechanism
This commit is contained in:
parent
1d6eccc69e
commit
f90a62ecfa
7 changed files with 189 additions and 12 deletions
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
CC = gcc
|
||||
CFLAGS = -Wall -Wextra -std=gnu99 -Isrc/ -Iinclude/ -g
|
||||
|
||||
SRCS = runner.c report.c event.c
|
||||
SRCS = runner.c report.c event.c stats.c
|
||||
OBJS = $(addprefix src/,$(subst .c,.o,$(SRCS)))
|
||||
|
||||
sample: samples/simple.o libcriterion.a
|
||||
|
|
|
@ -37,7 +37,7 @@ enum criterion_assert_kind {
|
|||
# define assertImpl(Kind, Condition, ...) \
|
||||
do { \
|
||||
int passed = !!(Condition); \
|
||||
struct criterion_assert_stat stat = { \
|
||||
struct criterion_assert_stats stat = { \
|
||||
.kind = Kind, \
|
||||
.condition = #Condition, \
|
||||
.message = "" __VA_ARGS__, \
|
||||
|
|
|
@ -26,18 +26,34 @@
|
|||
|
||||
# include "criterion.h"
|
||||
|
||||
struct criterion_assert_stat {
|
||||
struct criterion_assert_stats {
|
||||
int kind;
|
||||
const char *condition;
|
||||
const char *message;
|
||||
bool passed;
|
||||
unsigned line;
|
||||
|
||||
struct criterion_assert_stats *next;
|
||||
};
|
||||
|
||||
struct criterion_test_stats {
|
||||
struct criterion_test *test;
|
||||
struct criterion_assert_stats *asserts;
|
||||
int passed;
|
||||
int failed;
|
||||
|
||||
struct criterion_test_stats *next;
|
||||
};
|
||||
|
||||
struct criterion_global_stats {
|
||||
struct criterion_test_stats *tests;
|
||||
size_t nb_tests;
|
||||
size_t nb_asserts;
|
||||
size_t tests_failed;
|
||||
size_t tests_crashed;
|
||||
size_t tests_passed;
|
||||
size_t asserts_failed;
|
||||
size_t asserts_passed;
|
||||
};
|
||||
|
||||
#endif /* !CRITERION_STATS_H_ */
|
||||
|
|
|
@ -48,7 +48,7 @@ struct event *read_event(int fd) {
|
|||
if (kind != ASSERT)
|
||||
return unique_ptr(struct event, ({ .kind = kind, .data = NULL }));
|
||||
|
||||
const size_t assert_size = sizeof (struct criterion_assert_stat);
|
||||
const size_t assert_size = sizeof (struct criterion_assert_stats);
|
||||
unsigned char *buf = malloc(assert_size);
|
||||
if (read(fd, buf, assert_size) < (ssize_t) assert_size)
|
||||
return NULL;
|
||||
|
@ -60,5 +60,5 @@ 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));
|
||||
write(EVENT_PIPE, buf, sizeof (int) + size);
|
||||
}
|
||||
|
|
17
src/runner.c
17
src/runner.c
|
@ -27,7 +27,7 @@
|
|||
#include <sys/wait.h>
|
||||
#include <csptr/smart_ptr.h>
|
||||
#include "criterion/assert.h"
|
||||
#include "criterion/stats.h"
|
||||
#include "stats.h"
|
||||
#include "runner.h"
|
||||
#include "report.h"
|
||||
#include "event.h"
|
||||
|
@ -85,10 +85,10 @@ static struct test_set *read_all_tests(void) {
|
|||
}), destroy_test_set);
|
||||
}
|
||||
|
||||
static void map_tests(struct test_set *set, void (*fun)(struct criterion_test *)) {
|
||||
static void map_tests(struct test_set *set, struct criterion_global_stats *stats, void (*fun)(struct criterion_global_stats *, struct criterion_test *)) {
|
||||
size_t i = 0;
|
||||
for (struct criterion_test **t = set->tests; i < set->nb_tests; ++i, ++t)
|
||||
fun(*t);
|
||||
fun(stats, *t);
|
||||
}
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
|
@ -115,7 +115,9 @@ static void setup_child(struct pipefds *fds) {
|
|||
close(fds->out);
|
||||
}
|
||||
|
||||
static void run_test(struct criterion_test *test) {
|
||||
static void run_test(struct criterion_global_stats *stats, struct criterion_test *test) {
|
||||
smart struct criterion_test_stats *test_stats = test_stats_init(test);
|
||||
|
||||
struct pipefds fds;
|
||||
if (pipe((int*) &fds) == -1)
|
||||
abort();
|
||||
|
@ -127,15 +129,15 @@ static void run_test(struct criterion_test *test) {
|
|||
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) {
|
||||
stat_push_event(stats, test_stats, ev);
|
||||
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_TEST: report(POST_TEST, test_stats); break;
|
||||
case POST_FINI: report(POST_FINI, test); break;
|
||||
}
|
||||
sfree(ev);
|
||||
|
@ -148,9 +150,10 @@ static void run_test(struct criterion_test *test) {
|
|||
void run_all(void) {
|
||||
report(PRE_EVERYTHING, NULL);
|
||||
smart struct test_set *set = read_all_tests();
|
||||
smart struct criterion_global_stats *stats = stats_init();
|
||||
if (!set)
|
||||
abort();
|
||||
map_tests(set, run_test);
|
||||
map_tests(set, stats, run_test);
|
||||
report(POST_EVERYTHING, NULL);
|
||||
}
|
||||
|
||||
|
|
122
src/stats.c
Normal file
122
src/stats.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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 <csptr/smart_ptr.h>
|
||||
#include "criterion/common.h"
|
||||
#include "stats.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static void nothing() {};
|
||||
static void push_pre_test();
|
||||
static void push_assert();
|
||||
static void push_post_test();
|
||||
static void push_test_crash();
|
||||
|
||||
typedef struct criterion_global_stats s_glob_stats;
|
||||
typedef struct criterion_test_stats s_test_stats;
|
||||
typedef struct criterion_assert_stats s_assert_stats;
|
||||
|
||||
static void destroy_stats(void *ptr, UNUSED void *meta) {
|
||||
s_glob_stats *stats = ptr;
|
||||
sfree(stats->tests);
|
||||
}
|
||||
|
||||
s_glob_stats *stats_init(void) {
|
||||
return unique_ptr(s_glob_stats, ({0}), destroy_stats);
|
||||
}
|
||||
|
||||
static void destroy_test_stats(void *ptr, UNUSED void *meta) {
|
||||
s_test_stats *stats = ptr;
|
||||
sfree(stats->asserts);
|
||||
sfree(stats->next);
|
||||
}
|
||||
|
||||
s_test_stats *test_stats_init(struct criterion_test *t) {
|
||||
return shared_ptr(s_test_stats, ({ .test = t }), destroy_test_stats);
|
||||
}
|
||||
|
||||
void stat_push_event(s_glob_stats *stats,
|
||||
s_test_stats *test,
|
||||
struct event *data) {
|
||||
static void (*const handles[])(s_glob_stats *, s_test_stats *, void *) = {
|
||||
nothing, // PRE_EVERYTHING
|
||||
nothing, // PRE_INIT
|
||||
push_pre_test, // PRE_TEST
|
||||
push_assert, // ASSERT
|
||||
push_test_crash, // TEST_CRASH
|
||||
push_post_test, // POST_TEST
|
||||
nothing, // POST_FINI
|
||||
nothing, // POST_EVERYTHING
|
||||
};
|
||||
|
||||
assert(data->kind > 0);
|
||||
assert(data->kind <= (ssize_t) (sizeof (handles) / sizeof (void (*)(void))));
|
||||
|
||||
handles[data->kind](stats, test, data->data);
|
||||
}
|
||||
|
||||
static void push_pre_test(s_glob_stats *stats,
|
||||
s_test_stats *test,
|
||||
UNUSED void *ptr) {
|
||||
test->next = stats->tests;
|
||||
stats->tests = sref(test);
|
||||
++stats->nb_tests;
|
||||
}
|
||||
|
||||
static void destroy_assert(void *ptr, UNUSED void *meta) {
|
||||
s_assert_stats *data = ptr;
|
||||
sfree(data->next);
|
||||
}
|
||||
|
||||
static void push_assert(s_glob_stats *stats,
|
||||
s_test_stats *test,
|
||||
s_assert_stats *data) {
|
||||
s_assert_stats *dup = unique_ptr(s_assert_stats, (*data), destroy_assert);
|
||||
dup->next = test->asserts;
|
||||
test->asserts = dup;
|
||||
|
||||
if (data->passed) {
|
||||
++stats->asserts_passed;
|
||||
++test->passed;
|
||||
} else {
|
||||
++stats->asserts_failed;
|
||||
++test->failed;
|
||||
}
|
||||
}
|
||||
|
||||
static void push_post_test(s_glob_stats *stats,
|
||||
s_test_stats *test,
|
||||
UNUSED void *ptr) {
|
||||
if (test->failed > 0)
|
||||
++stats->tests_failed;
|
||||
else
|
||||
++stats->tests_passed;
|
||||
}
|
||||
|
||||
static void push_test_crash(s_glob_stats *stats,
|
||||
s_test_stats *test,
|
||||
UNUSED void *ptr) {
|
||||
++stats->tests_failed;
|
||||
++stats->tests_crashed;
|
||||
}
|
36
src/stats.h
Normal file
36
src/stats.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 STATS_H_
|
||||
# define STATS_H_
|
||||
|
||||
# include "criterion/stats.h"
|
||||
# include "event.h"
|
||||
|
||||
struct criterion_global_stats *stats_init(void);
|
||||
struct criterion_test_stats *test_stats_init(struct criterion_test *t);
|
||||
void stat_push_event(struct criterion_global_stats *stats,
|
||||
struct criterion_test_stats *test,
|
||||
struct event *data);
|
||||
|
||||
#endif /* !STATS_H_ */
|
Loading…
Add table
Reference in a new issue