Added statistics gathering mechanism

This commit is contained in:
Snaipe 2015-02-05 19:52:41 +01:00
parent 1d6eccc69e
commit f90a62ecfa
7 changed files with 189 additions and 12 deletions

View file

@ -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

View file

@ -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__, \

View file

@ -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_ */

View file

@ -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);
}

View file

@ -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
View 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
View 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_ */