Started to integrate the new message pump into the runner

This commit is contained in:
Snaipe 2015-12-13 17:18:06 +01:00
parent d9fa24276e
commit 43f7d837f0
14 changed files with 689 additions and 213 deletions

View file

@ -30,11 +30,14 @@
# include <stddef.h>
# endif
# include "internal/common.h"
# include "stats.h"
CR_BEGIN_C_API
CR_API void criterion_send_event(int kind, void *data, size_t size);
CR_API void criterion_send_assert(struct criterion_assert_stats *stats);
CR_END_C_API
#endif /* !CRITERION_EVENT_H_ */

294
src/core/client.c Normal file
View file

@ -0,0 +1,294 @@
/*
* 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 <stdio.h>
#include <inttypes.h>
#include "protocol/protocol.h"
#include "criterion/logging.h"
#include "criterion/options.h"
#include "io/event.h"
#include "report.h"
#include "stats.h"
#include "client.h"
void nothing();
enum protocol_version {
PROTOCOL_V1 = 1,
};
KHASH_MAP_INIT_INT(ht_client, struct client_ctx)
static enum client_state msg_to_state[] = {
[criterion_protocol_submessage_birth_tag] = CS_BIRTH,
[criterion_protocol_submessage_pre_init_tag] = CS_PRE_INIT,
[criterion_protocol_submessage_pre_test_tag] = CS_PRE_TEST,
[criterion_protocol_submessage_post_test_tag] = CS_POST_TEST,
[criterion_protocol_submessage_post_fini_tag] = CS_POST_FINI,
[criterion_protocol_submessage_death_tag] = CS_DEATH,
};
static const char *state_to_string[] = {
[CS_BIRTH] = "BIRTH",
[CS_PRE_INIT] = "PRE_INIT",
[CS_PRE_TEST] = "PRE_TEST",
[CS_POST_TEST] = "POST_TEST",
[CS_POST_FINI] = "POST_FINI",
[CS_DEATH] = "DEATH",
};
typedef void message_handler(struct server_ctx *, struct client_ctx *, const criterion_protocol_msg *);
void handle_birth(struct server_ctx *, struct client_ctx *, const criterion_protocol_msg *);
void handle_pre_init(struct server_ctx *, struct client_ctx *, const criterion_protocol_msg *);
void handle_pre_test(struct server_ctx *, struct client_ctx *, const criterion_protocol_msg *);
void handle_post_test(struct server_ctx *, struct client_ctx *, const criterion_protocol_msg *);
void handle_death(struct server_ctx *, struct client_ctx *, const criterion_protocol_msg *);
static message_handler *message_handlers[] = {
[criterion_protocol_submessage_birth_tag] = handle_birth,
[criterion_protocol_submessage_pre_init_tag] = handle_pre_init,
[criterion_protocol_submessage_pre_test_tag] = handle_pre_test,
[criterion_protocol_submessage_post_test_tag] = handle_post_test,
[criterion_protocol_submessage_death_tag] = handle_death,
};
static void get_message_id(char *out, size_t n, const criterion_protocol_msg *msg) {
switch (msg->which_id) {
case criterion_protocol_msg_pid_tag:
snprintf(out, n, "[PID %" PRId64 "]", msg->id.pid); return;
default: break;
}
}
void init_server_context(struct server_ctx *sctx) {
sctx->subprocesses = kh_init(ht_client);
}
void destroy_server_context(struct server_ctx *sctx) {
kh_destroy(ht_client, sctx->subprocesses);
}
struct client_ctx *add_client_from_worker(struct server_ctx *sctx, struct client_ctx *ctx, struct worker *w) {
unsigned long long pid = get_process_id_of(w->proc);
int absent;
khint_t k = kh_put(ht_client, sctx->subprocesses, pid, &absent);
ctx->worker = w;
ctx->kind = WORKER;
kh_value(sctx->subprocesses, k) = *ctx;
return &kh_value(sctx->subprocesses, k);
}
void remove_client_by_pid(struct server_ctx *sctx, int pid) {
khint_t k = kh_get(ht_client, sctx->subprocesses, pid);
if (k != kh_end(sctx->subprocesses))
kh_del(ht_client, sctx->subprocesses, pid);
}
static void process_client_message_impl(struct server_ctx *sctx, struct client_ctx *ctx, const criterion_protocol_msg *msg) {
if (msg->data.which_value >= CS_MAX_CLIENT_STATES
|| msg_to_state[msg->data.which_value] == 0) {
char id[32];
get_message_id(id, sizeof (id), msg);
criterion_perror("%s: Received message with malformed data.value tag '%d'.",
id,
msg->data.which_value);
return;
}
enum client_state new_state = msg_to_state[msg->data.which_value];
if (new_state < CS_DEATH && new_state != ctx->state + 1) {
char id[32];
get_message_id(id, sizeof (id), msg);
criterion_perror("%s: Expected message to change to state '%s', got '%s' instead.",
id,
state_to_string[ctx->state + 1],
state_to_string[new_state]);
return;
}
message_handler *handler = message_handlers[msg->data.which_value];
if (handler)
handler(sctx, ctx, msg);
if (new_state <= CS_DEATH)
ctx->state = new_state;
}
struct client_ctx *process_client_message(struct server_ctx *ctx, const criterion_protocol_msg *msg) {
if (msg->version != PROTOCOL_V1) {
criterion_perror("Received message using invalid protocol version number '%d'.", msg->version);
return NULL;
}
switch (msg->which_id) {
case criterion_protocol_msg_pid_tag: {
khiter_t k = kh_get(ht_client, ctx->subprocesses, msg->id.pid);
if (k != kh_end(ctx->subprocesses)) {
process_client_message_impl(ctx, &kh_value(ctx->subprocesses, k), msg);
return &kh_value(ctx->subprocesses, k);
} else {
char id[32];
get_message_id(id, sizeof (id), msg);
criterion_perror("%s: Received message identified by a PID "
"that is not a child process.",
id);
}
} break;
default: {
criterion_perror("Received message with malformed id tag '%d'.",
criterion_protocol_msg_pid_tag);
} break;
}
return NULL;
}
#define push_event(...) \
do { \
push_event_noreport(__VA_ARGS__); \
report(CR_VA_HEAD(__VA_ARGS__), ctx->tstats); \
} while (0)
#define push_event_noreport(...) \
do { \
stat_push_event(ctx->gstats, \
ctx->sstats, \
ctx->tstats, \
&(struct event) { \
.kind = CR_VA_HEAD(__VA_ARGS__), \
CR_VA_TAIL(__VA_ARGS__) \
}); \
} while (0)
void handle_birth(struct server_ctx *sctx, struct client_ctx *ctx, const criterion_protocol_msg *msg) {
(void) sctx;
(void) ctx;
(void) msg;
}
void handle_pre_init(struct server_ctx *sctx, struct client_ctx *ctx, const criterion_protocol_msg *msg) {
(void) sctx;
(void) msg;
push_event_noreport(PRE_INIT);
report(PRE_INIT, ctx->test);
log(pre_init, ctx->test);
}
void handle_pre_test(struct server_ctx *sctx, struct client_ctx *ctx, const criterion_protocol_msg *msg) {
(void) sctx;
(void) msg;
report(PRE_TEST, ctx->test);
log(pre_test, ctx->test);
}
void handle_post_test(struct server_ctx *sctx, struct client_ctx *ctx, const criterion_protocol_msg *msg) {
(void) sctx;
(void) msg;
double elapsed_time = 0; // TODO: restore elapsed time handling
push_event_noreport(POST_TEST, .data = &elapsed_time);
report(POST_TEST, ctx->tstats);
log(post_test, ctx->tstats);
}
void handle_death(struct server_ctx *sctx, struct client_ctx *ctx, const criterion_protocol_msg *msg) {
(void) sctx;
const criterion_protocol_death *death = &msg->data.value.death;
switch (death->result) {
case criterion_protocol_death_result_type_CRASH: {
if (ctx->state >= CS_POST_TEST || ctx->state < CS_PRE_TEST) {
log(other_crash, ctx->tstats);
if (ctx->state < CS_PRE_TEST) {
stat_push_event(ctx->gstats,
ctx->sstats,
ctx->tstats,
&(struct event) { .kind = TEST_CRASH });
}
} else {
ctx->tstats->signal = death->status;
if (ctx->test->data->signal == 0) {
push_event(TEST_CRASH);
log(test_crash, ctx->tstats);
} else {
double elapsed_time = 0;
push_event(POST_TEST, .data = &elapsed_time);
log(post_test, ctx->tstats);
push_event(POST_FINI);
log(post_fini, ctx->tstats);
}
}
} break;
case criterion_protocol_death_result_type_TIMEOUT: {
ctx->tstats->timed_out = true;
double elapsed_time = ctx->test->data->timeout;
if (elapsed_time == 0 && ctx->suite->data)
elapsed_time = ctx->suite->data->timeout;
push_event(POST_TEST, .data = &elapsed_time);
push_event(POST_FINI);
log(test_timeout, ctx->tstats);
} break;
case criterion_protocol_death_result_type_ABORT: {
if (ctx->state < CS_POST_TEST) {
double elapsed_time = 0;
push_event(POST_TEST, .data = &elapsed_time);
log(post_test, ctx->tstats);
}
if (ctx->state < CS_POST_FINI) {
push_event(POST_FINI);
log(post_fini, ctx->tstats);
}
} break;
case criterion_protocol_death_result_type_NORMAL: {
if ((ctx->state >= CS_POST_TEST && ctx->state < CS_POST_FINI) || ctx->state < CS_PRE_TEST) {
log(abnormal_exit, ctx->tstats);
if (ctx->state < CS_PRE_TEST) {
stat_push_event(ctx->gstats,
ctx->sstats,
ctx->tstats,
&(struct event) { .kind = TEST_CRASH });
}
return;
}
ctx->tstats->exit_code = death->status;
if (ctx->state < CS_POST_TEST) {
if (ctx->test->data->exit_code == 0) {
push_event(TEST_CRASH);
log(abnormal_exit, ctx->tstats);
} else {
double elapsed_time = 0;
push_event(POST_TEST, .data = &elapsed_time);
log(post_test, ctx->tstats);
push_event(POST_FINI);
log(post_fini, ctx->tstats);
}
}
} break;
default: break;
}
}

74
src/core/client.h Normal file
View file

@ -0,0 +1,74 @@
/*
* 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 CLIENT_H_
# define CLIENT_H_
# include <khash.h>
// order matters here
enum client_state {
CS_BIRTH = 1,
CS_PRE_INIT,
CS_PRE_TEST,
CS_POST_TEST,
CS_POST_FINI,
CS_DEATH,
CS_PRE_SUBTEST,
CS_POST_SUBTEST,
CS_MAX_CLIENT_STATES // always leave at the end
};
enum client_kind {
WORKER,
EXTERN,
};
struct client_ctx {
enum client_kind kind;
struct worker *worker;
enum client_state state;
struct criterion_global_stats *gstats;
struct criterion_suite_stats *sstats;
struct criterion_test_stats *tstats;
struct criterion_test *test;
struct criterion_suite *suite;
};
typedef struct kh_ht_client_s khash_t(ht_client);
struct server_ctx {
khash_t(ht_client) *subprocesses;
};
struct client_ctx *process_client_message(struct server_ctx *ctx, const criterion_protocol_msg *msg);
void init_server_context(struct server_ctx *sctx);
void destroy_server_context(struct server_ctx *sctx);
struct client_ctx *add_client_from_worker(struct server_ctx *sctx, struct client_ctx *ctx, struct worker *w);
void remove_client_by_pid(struct server_ctx *sctx, int pid);
#endif /* !CLIENT_H_ */

View file

@ -27,11 +27,14 @@
#include <errno.h>
#include <csptr/smalloc.h>
#include <valgrind/valgrind.h>
#include <nanomsg/nn.h>
#include "criterion/internal/test.h"
#include "criterion/options.h"
#include "criterion/internal/ordered-set.h"
#include "criterion/logging.h"
#include "criterion/internal/preprocess.h"
#include "protocol/protocol.h"
#include "protocol/connect.h"
#include "compat/time.h"
#include "compat/posix.h"
#include "compat/processor.h"
@ -46,6 +49,7 @@
#include "abort.h"
#include "config.h"
#include "common.h"
#include "client.h"
#ifdef HAVE_PCRE
#include "string/extmatch.h"
@ -194,131 +198,6 @@ void run_test_child(struct criterion_test *test,
s_pipe_handle *g_worker_pipe;
static void handle_worker_terminated(struct event *ev,
struct execution_context *ctx) {
struct worker_status *ws = ev->data;
struct process_status status = ws->status;
if (status.kind == SIGNAL) {
if (status.status == SIGPROF) {
ctx->test_stats->timed_out = true;
double elapsed_time = ctx->test->data->timeout;
if (elapsed_time == 0 && ctx->suite->data)
elapsed_time = ctx->suite->data->timeout;
push_event(POST_TEST, .data = &elapsed_time);
push_event(POST_FINI);
log(test_timeout, ctx->test_stats);
return;
}
if (ctx->normal_finish || !ctx->test_started) {
log(other_crash, ctx->test_stats);
if (!ctx->test_started) {
stat_push_event(ctx->stats,
ctx->suite_stats,
ctx->test_stats,
&(struct event) { .kind = TEST_CRASH });
}
return;
}
ctx->test_stats->signal = status.status;
if (ctx->test->data->signal == 0) {
push_event(TEST_CRASH);
log(test_crash, ctx->test_stats);
} else {
double elapsed_time = 0;
push_event(POST_TEST, .data = &elapsed_time);
log(post_test, ctx->test_stats);
push_event(POST_FINI);
log(post_fini, ctx->test_stats);
}
} else {
if (ctx->aborted) {
if (!ctx->normal_finish) {
double elapsed_time = 0;
push_event(POST_TEST, .data = &elapsed_time);
log(post_test, ctx->test_stats);
}
if (!ctx->cleaned_up) {
push_event(POST_FINI);
log(post_fini, ctx->test_stats);
}
return;
}
if ((ctx->normal_finish && !ctx->cleaned_up) || !ctx->test_started) {
log(abnormal_exit, ctx->test_stats);
if (!ctx->test_started) {
stat_push_event(ctx->stats,
ctx->suite_stats,
ctx->test_stats,
&(struct event) { .kind = TEST_CRASH });
}
return;
}
ctx->test_stats->exit_code = status.status;
if (!ctx->normal_finish) {
if (ctx->test->data->exit_code == 0) {
push_event(TEST_CRASH);
log(abnormal_exit, ctx->test_stats);
} else {
double elapsed_time = 0;
push_event(POST_TEST, .data = &elapsed_time);
log(post_test, ctx->test_stats);
push_event(POST_FINI);
log(post_fini, ctx->test_stats);
}
}
}
}
static void handle_event(struct event *ev) {
struct execution_context *ctx = &ev->worker->ctx;
if (ev->kind < WORKER_TERMINATED)
stat_push_event(ctx->stats, ctx->suite_stats, ctx->test_stats, ev);
switch (ev->kind) {
case PRE_INIT:
report(PRE_INIT, ctx->test);
log(pre_init, ctx->test);
break;
case PRE_TEST:
report(PRE_TEST, ctx->test);
log(pre_test, ctx->test);
ctx->test_started = true;
break;
case THEORY_FAIL: {
struct criterion_theory_stats ths = {
.formatted_args = (char*) ev->data,
.stats = ctx->test_stats,
};
report(THEORY_FAIL, &ths);
log(theory_fail, &ths);
} break;
case ASSERT:
report(ASSERT, ev->data);
log(assert, ev->data);
break;
case TEST_ABORT:
log(test_abort, ctx->test_stats, ev->data);
ctx->test_stats->failed = 1;
ctx->aborted = true;
break;
case POST_TEST:
report(POST_TEST, ctx->test_stats);
log(post_test, ctx->test_stats);
ctx->normal_finish = true;
break;
case POST_FINI:
report(POST_FINI, ctx->test_stats);
log(post_fini, ctx->test_stats);
ctx->cleaned_up = true;
break;
case WORKER_TERMINATED:
handle_worker_terminated(ev, ctx);
break;
}
}
#ifdef HAVE_PCRE
void disable_unmatching(struct criterion_test_set *set) {
FOREACH_SET(struct criterion_suite_set *s, set->suites) {
@ -370,31 +249,44 @@ void criterion_finalize(struct criterion_test_set *set) {
criterion_free_output();
}
static struct client_ctx *spawn_next_client(struct server_ctx *sctx, ccrContext *ctx) {
struct worker *w = ctx ? run_next_test(NULL, NULL, ctx) : NULL;
if (!is_runner() || w == NULL)
return NULL;
struct client_ctx new_ctx = (struct client_ctx) {
.test = w->ctx.test,
.tstats = w->ctx.test_stats,
.suite = w->ctx.suite,
.sstats = w->ctx.suite_stats,
.gstats = w->ctx.stats,
};
return add_client_from_worker(sctx, &new_ctx, w);
}
static void run_tests_async(struct criterion_test_set *set,
struct criterion_global_stats *stats) {
struct criterion_global_stats *stats,
int socket) {
ccrContext ctx = 0;
size_t nb_workers = DEF(criterion_options.jobs, get_processor_count());
struct worker_set workers = {
.max_workers = nb_workers,
.workers = calloc(nb_workers, sizeof (struct worker*)),
};
size_t active_workers = 0;
s_pipe_file_handle *event_pipe = pipe_in_handle(g_worker_pipe, PIPE_DUP);
struct event *ev = NULL;
struct server_ctx sctx;
init_server_context(&sctx);
// initialization of coroutine
run_next_test(set, stats, &ctx);
for (size_t i = 0; i < nb_workers; ++i) {
workers.workers[i] = run_next_test(NULL, NULL, &ctx);
struct client_ctx *cctx = spawn_next_client(&sctx, &ctx);
if (!is_runner())
goto cleanup;
if (!ctx)
if (!cctx)
break;
++active_workers;
}
@ -402,31 +294,33 @@ static void run_tests_async(struct criterion_test_set *set,
if (!active_workers)
goto cleanup;
while ((ev = worker_read_event(&workers, event_pipe)) != NULL) {
handle_event(ev);
size_t wi = ev->worker_index;
if (ev->kind == WORKER_TERMINATED) {
sfree(workers.workers[wi]);
workers.workers[wi] = ctx ? run_next_test(NULL, NULL, &ctx) : NULL;
criterion_protocol_msg msg = criterion_protocol_msg_init_zero;
unsigned char *buf = NULL;
int length;
while ((length = nn_recv(socket, &buf, NN_MSG, 0)) > 0) {
pb_istream_t in = pb_istream_from_buffer(buf, length);
if (pb_decode(&in, criterion_protocol_msg_fields, &msg)) {
struct client_ctx *cctx = process_client_message(&sctx, &msg);
if (cctx->state == CS_DEATH && cctx->kind == WORKER) {
remove_client_by_pid(&sctx, get_process_id_of(cctx->worker->proc));
sfree(cctx->worker);
if (!is_runner())
goto cleanup;
cctx = spawn_next_client(&sctx, &ctx);
if (!is_runner())
goto cleanup;
if (workers.workers[wi] == NULL)
--active_workers;
if (cctx == NULL)
--active_workers;
}
}
sfree(ev);
nn_freemsg(buf);
if (!active_workers)
break;
}
ev = NULL;
destroy_server_context(&sctx);
cleanup:
sfree(event_pipe);
sfree(ev);
for (size_t i = 0; i < nb_workers; ++i)
sfree(workers.workers[i]);
free(workers.workers);
ccrAbort(ctx);
}
@ -445,16 +339,17 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) {
fflush(NULL); // flush everything before forking
g_worker_pipe = stdpipe();
if (g_worker_pipe == NULL) {
criterion_perror("Could not initialize the event pipe: %s.\n",
int sock = bind_server();
if (sock < 0) {
criterion_perror("Could not initialize the message server: %s.\n",
strerror(errno));
abort();
}
init_proc_compat();
struct criterion_global_stats *stats = stats_init();
run_tests_async(set, stats);
run_tests_async(set, stats, sock);
int result = is_runner() ? stats->tests_failed == 0 : -1;
@ -467,7 +362,7 @@ static int criterion_run_all_tests_impl(struct criterion_test_set *set) {
cleanup:
free_proc_compat();
sfree(g_worker_pipe);
nn_close(sock);
sfree(stats);
return result;
}

View file

@ -25,6 +25,7 @@
#include <stdbool.h>
#include <errno.h>
#include <csptr/smalloc.h>
#include <nanomsg/nn.h>
#include "criterion/types.h"
#include "criterion/options.h"
@ -32,6 +33,7 @@
#include "io/event.h"
#include "compat/posix.h"
#include "worker.h"
#include "protocol/connect.h"
static s_proc_handle *g_current_proc;
@ -56,33 +58,12 @@ static void close_process(void *ptr, CR_UNUSED void *meta) {
sfree(proc->proc);
}
struct event *worker_read_event(struct worker_set *workers, s_pipe_file_handle *pipe) {
struct event *ev = read_event(pipe);
if (ev) {
ev->worker_index = -1;
for (size_t i = 0; i < workers->max_workers; ++i) {
if (!workers->workers[i])
continue;
if (get_process_id_of(workers->workers[i]->proc) == ev->pid) {
ev->worker = workers->workers[i];
ev->worker_index = i;
return ev;
}
}
criterion_perror("Could not link back the event PID to the active workers.\n");
criterion_perror("The event pipe might have been corrupted.\n");
abort();
}
return NULL;
}
void run_worker(struct worker_context *ctx) {
cr_redirect_stdin();
g_event_pipe = pipe_out_handle(ctx->pipe, PIPE_CLOSE);
g_client_socket = connect_client();
ctx->func(ctx->test, ctx->suite);
sfree(g_event_pipe);
nn_close(g_client_socket);
fflush(NULL); // flush all opened streams
if (criterion_options.no_early_exit)

View file

@ -30,10 +30,14 @@
#include "criterion/hooks.h"
#include "criterion/logging.h"
#include "core/worker.h"
#include "protocol/protocol.h"
#include "event.h"
s_pipe_file_handle *g_event_pipe = NULL;
int g_client_socket = -1;
pb_ostream_t g_event_stream;
void destroy_event(void *ptr, CR_UNUSED void *meta) {
struct event *ev = ptr;
free(ev->data);

View file

@ -27,8 +27,11 @@
# include "criterion/event.h"
# include "core/worker.h"
# include <stdio.h>
# include <pb.h>
extern s_pipe_file_handle *g_event_pipe;
extern pb_ostream_t g_event_stream;
extern int g_client_socket;
struct event {
unsigned long long pid;
@ -44,6 +47,4 @@ enum other_event_kinds {
TEST_ABORT,
};
struct event *read_event(s_pipe_file_handle *f);
#endif /* !EVENT_H_ */

63
src/protocol/connect.c Normal file
View file

@ -0,0 +1,63 @@
/*
* 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 <errno.h>
#include <nanomsg/nn.h>
#include <nanomsg/pubsub.h>
#define URL "ipc://criterion.sock"
#define errno_ignore(Stmt) do { int err = errno; Stmt; errno = err; } while (0)
int bind_server(void) {
int sock = nn_socket(AF_SP, NN_SUB);
if (sock < 0)
return -1;
if (nn_setsockopt(sock, NN_SUB, NN_SUB_SUBSCRIBE, "", 0) < 0)
goto error;
if (nn_bind(sock, URL) < 0)
goto error;
return sock;
error: {}
errno_ignore(nn_close(sock));
return -1;
}
int connect_client(void) {
int sock = nn_socket(AF_SP, NN_PUB);
if (sock < 0)
return -1;
if (nn_connect (sock, URL) < 0)
goto error;
return sock;
error: {}
errno_ignore(nn_close(sock));
return -1;
}

30
src/protocol/connect.h Normal file
View file

@ -0,0 +1,30 @@
/*
* 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 CONNECT_H_
# define CONNECT_H_
int connect_client(void);
int bind_server(void);
#endif /* !CONNECT_H_ */

View file

@ -1,5 +1,5 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.5-dev at Fri Dec 11 17:13:49 2015. */
/* Generated by nanopb-0.3.5-dev at Sun Dec 13 17:07:36 2015. */
#include "criterion.pb.h"
@ -32,6 +32,16 @@ const pb_field_t criterion_protocol_post_fini_fields[1] = {
PB_LAST_FIELD
};
const pb_field_t criterion_protocol_pre_subtest_fields[2] = {
PB_FIELD( 1, STRING , REQUIRED, CALLBACK, FIRST, criterion_protocol_pre_subtest, id, id, 0),
PB_LAST_FIELD
};
const pb_field_t criterion_protocol_post_subtest_fields[2] = {
PB_FIELD( 1, STRING , REQUIRED, CALLBACK, FIRST, criterion_protocol_post_subtest, id, id, 0),
PB_LAST_FIELD
};
const pb_field_t criterion_protocol_death_fields[3] = {
PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, criterion_protocol_death, result, result, 0),
PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, criterion_protocol_death, status, result, 0),
@ -46,14 +56,24 @@ const pb_field_t criterion_protocol_assert_fields[5] = {
PB_LAST_FIELD
};
const pb_field_t criterion_protocol_submessage_fields[8] = {
const pb_field_t criterion_protocol_log_fields[4] = {
PB_FIELD( 1, INT32 , REQUIRED, STATIC , FIRST, criterion_protocol_log, severity, severity, 0),
PB_FIELD( 2, STRING , REQUIRED, POINTER , OTHER, criterion_protocol_log, message, severity, 0),
PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, criterion_protocol_log, prefix, message, 0),
PB_LAST_FIELD
};
const pb_field_t criterion_protocol_submessage_fields[11] = {
PB_ONEOF_FIELD(value, 1, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, birth, birth, &criterion_protocol_birth_fields),
PB_ONEOF_FIELD(value, 2, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, pre_init, pre_init, &criterion_protocol_pre_init_fields),
PB_ONEOF_FIELD(value, 3, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, pre_test, pre_test, &criterion_protocol_pre_test_fields),
PB_ONEOF_FIELD(value, 4, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, post_test, post_test, &criterion_protocol_post_test_fields),
PB_ONEOF_FIELD(value, 5, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, post_fini, post_fini, &criterion_protocol_post_fini_fields),
PB_ONEOF_FIELD(value, 6, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, death, death, &criterion_protocol_death_fields),
PB_ONEOF_FIELD(value, 7, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, assert, assert, &criterion_protocol_assert_fields),
PB_ONEOF_FIELD(value, 7, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, message, message, &criterion_protocol_log_fields),
PB_ONEOF_FIELD(value, 8, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, assert, assert, &criterion_protocol_assert_fields),
PB_ONEOF_FIELD(value, 9, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, pre_subtest, pre_subtest, &criterion_protocol_pre_subtest_fields),
PB_ONEOF_FIELD(value, 10, MESSAGE , ONEOF, STATIC , FIRST, criterion_protocol_submessage, post_subtest, post_subtest, &criterion_protocol_post_subtest_fields),
PB_LAST_FIELD
};
@ -74,7 +94,7 @@ const pb_field_t criterion_protocol_msg_fields[4] = {
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(criterion_protocol_submessage, value.birth) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 65536 && pb_membersize(criterion_protocol_submessage, value.death) < 65536 && pb_membersize(criterion_protocol_submessage, value.assert) < 65536 && pb_membersize(criterion_protocol_submessage, value.birth) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 65536 && pb_membersize(criterion_protocol_submessage, value.death) < 65536 && pb_membersize(criterion_protocol_submessage, value.assert) < 65536 && pb_membersize(criterion_protocol_submessage, value.birth) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 65536 && pb_membersize(criterion_protocol_submessage, value.death) < 65536 && pb_membersize(criterion_protocol_submessage, value.assert) < 65536 && pb_membersize(criterion_protocol_submessage, value.birth) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 65536 && pb_membersize(criterion_protocol_submessage, value.death) < 65536 && pb_membersize(criterion_protocol_submessage, value.assert) < 65536 && pb_membersize(criterion_protocol_msg, data) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_criterion_protocol_birth_criterion_protocol_pre_init_criterion_protocol_pre_test_criterion_protocol_post_test_criterion_protocol_post_fini_criterion_protocol_death_criterion_protocol_assert_criterion_protocol_submessage_criterion_protocol_msg)
PB_STATIC_ASSERT((pb_membersize(criterion_protocol_submessage, value.birth) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 65536 && pb_membersize(criterion_protocol_submessage, value.death) < 65536 && pb_membersize(criterion_protocol_submessage, value.message) < 65536 && pb_membersize(criterion_protocol_submessage, value.assert) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_subtest) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_subtest) < 65536 && pb_membersize(criterion_protocol_submessage, value.birth) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 65536 && pb_membersize(criterion_protocol_submessage, value.death) < 65536 && pb_membersize(criterion_protocol_submessage, value.message) < 65536 && pb_membersize(criterion_protocol_submessage, value.assert) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_subtest) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_subtest) < 65536 && pb_membersize(criterion_protocol_submessage, value.birth) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 65536 && pb_membersize(criterion_protocol_submessage, value.death) < 65536 && pb_membersize(criterion_protocol_submessage, value.message) < 65536 && pb_membersize(criterion_protocol_submessage, value.assert) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_subtest) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_subtest) < 65536 && pb_membersize(criterion_protocol_submessage, value.birth) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_test) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 65536 && pb_membersize(criterion_protocol_submessage, value.death) < 65536 && pb_membersize(criterion_protocol_submessage, value.message) < 65536 && pb_membersize(criterion_protocol_submessage, value.assert) < 65536 && pb_membersize(criterion_protocol_submessage, value.pre_subtest) < 65536 && pb_membersize(criterion_protocol_submessage, value.post_subtest) < 65536 && pb_membersize(criterion_protocol_msg, data) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_criterion_protocol_birth_criterion_protocol_pre_init_criterion_protocol_pre_test_criterion_protocol_post_test_criterion_protocol_post_fini_criterion_protocol_pre_subtest_criterion_protocol_post_subtest_criterion_protocol_death_criterion_protocol_assert_criterion_protocol_log_criterion_protocol_submessage_criterion_protocol_msg)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
@ -85,7 +105,7 @@ PB_STATIC_ASSERT((pb_membersize(criterion_protocol_submessage, value.birth) < 65
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(criterion_protocol_submessage, value.birth) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 256 && pb_membersize(criterion_protocol_submessage, value.death) < 256 && pb_membersize(criterion_protocol_submessage, value.assert) < 256 && pb_membersize(criterion_protocol_submessage, value.birth) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 256 && pb_membersize(criterion_protocol_submessage, value.death) < 256 && pb_membersize(criterion_protocol_submessage, value.assert) < 256 && pb_membersize(criterion_protocol_submessage, value.birth) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 256 && pb_membersize(criterion_protocol_submessage, value.death) < 256 && pb_membersize(criterion_protocol_submessage, value.assert) < 256 && pb_membersize(criterion_protocol_submessage, value.birth) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 256 && pb_membersize(criterion_protocol_submessage, value.death) < 256 && pb_membersize(criterion_protocol_submessage, value.assert) < 256 && pb_membersize(criterion_protocol_msg, data) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_criterion_protocol_birth_criterion_protocol_pre_init_criterion_protocol_pre_test_criterion_protocol_post_test_criterion_protocol_post_fini_criterion_protocol_death_criterion_protocol_assert_criterion_protocol_submessage_criterion_protocol_msg)
PB_STATIC_ASSERT((pb_membersize(criterion_protocol_submessage, value.birth) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 256 && pb_membersize(criterion_protocol_submessage, value.death) < 256 && pb_membersize(criterion_protocol_submessage, value.message) < 256 && pb_membersize(criterion_protocol_submessage, value.assert) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_subtest) < 256 && pb_membersize(criterion_protocol_submessage, value.post_subtest) < 256 && pb_membersize(criterion_protocol_submessage, value.birth) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 256 && pb_membersize(criterion_protocol_submessage, value.death) < 256 && pb_membersize(criterion_protocol_submessage, value.message) < 256 && pb_membersize(criterion_protocol_submessage, value.assert) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_subtest) < 256 && pb_membersize(criterion_protocol_submessage, value.post_subtest) < 256 && pb_membersize(criterion_protocol_submessage, value.birth) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 256 && pb_membersize(criterion_protocol_submessage, value.death) < 256 && pb_membersize(criterion_protocol_submessage, value.message) < 256 && pb_membersize(criterion_protocol_submessage, value.assert) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_subtest) < 256 && pb_membersize(criterion_protocol_submessage, value.post_subtest) < 256 && pb_membersize(criterion_protocol_submessage, value.birth) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_init) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_test) < 256 && pb_membersize(criterion_protocol_submessage, value.post_fini) < 256 && pb_membersize(criterion_protocol_submessage, value.death) < 256 && pb_membersize(criterion_protocol_submessage, value.message) < 256 && pb_membersize(criterion_protocol_submessage, value.assert) < 256 && pb_membersize(criterion_protocol_submessage, value.pre_subtest) < 256 && pb_membersize(criterion_protocol_submessage, value.post_subtest) < 256 && pb_membersize(criterion_protocol_msg, data) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_criterion_protocol_birth_criterion_protocol_pre_init_criterion_protocol_pre_test_criterion_protocol_post_test_criterion_protocol_post_fini_criterion_protocol_pre_subtest_criterion_protocol_post_subtest_criterion_protocol_death_criterion_protocol_assert_criterion_protocol_log_criterion_protocol_submessage_criterion_protocol_msg)
#endif

View file

@ -1,5 +1,5 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.5-dev at Fri Dec 11 17:13:49 2015. */
/* Generated by nanopb-0.3.5-dev at Sun Dec 13 17:07:36 2015. */
#ifndef PB_CRITERION_PB_H_INCLUDED
#define PB_CRITERION_PB_H_INCLUDED
@ -17,7 +17,8 @@ extern "C" {
typedef enum _criterion_protocol_death_result_type {
criterion_protocol_death_result_type_NORMAL = 0,
criterion_protocol_death_result_type_CRASH = 1,
criterion_protocol_death_result_type_TIMEOUT = 2
criterion_protocol_death_result_type_TIMEOUT = 2,
criterion_protocol_death_result_type_ABORT = 3
} criterion_protocol_death_result_type;
/* Struct definitions */
@ -29,10 +30,18 @@ typedef struct _criterion_protocol_post_fini {
uint8_t dummy_field;
} criterion_protocol_post_fini;
typedef struct _criterion_protocol_post_subtest {
pb_callback_t id;
} criterion_protocol_post_subtest;
typedef struct _criterion_protocol_pre_init {
uint8_t dummy_field;
} criterion_protocol_pre_init;
typedef struct _criterion_protocol_pre_subtest {
pb_callback_t id;
} criterion_protocol_pre_subtest;
typedef struct _criterion_protocol_assert {
char *message;
bool passed;
@ -48,6 +57,13 @@ typedef struct _criterion_protocol_death {
int64_t status;
} criterion_protocol_death;
typedef struct _criterion_protocol_log {
int32_t severity;
char *message;
bool has_prefix;
int32_t prefix;
} criterion_protocol_log;
typedef struct _criterion_protocol_post_test {
bool has_timestamp;
int64_t timestamp;
@ -67,7 +83,10 @@ typedef struct _criterion_protocol_submessage {
criterion_protocol_post_test post_test;
criterion_protocol_post_fini post_fini;
criterion_protocol_death death;
criterion_protocol_log message;
criterion_protocol_assert assert;
criterion_protocol_pre_subtest pre_subtest;
criterion_protocol_post_subtest post_subtest;
} value;
} criterion_protocol_submessage;
@ -89,8 +108,11 @@ extern const int32_t criterion_protocol_msg_version_default;
#define criterion_protocol_pre_test_init_default {false, 0}
#define criterion_protocol_post_test_init_default {false, 0}
#define criterion_protocol_post_fini_init_default {0}
#define criterion_protocol_pre_subtest_init_default {{{NULL}, NULL}}
#define criterion_protocol_post_subtest_init_default {{{NULL}, NULL}}
#define criterion_protocol_death_init_default {false, (criterion_protocol_death_result_type)0, false, 0}
#define criterion_protocol_assert_init_default {NULL, 0, NULL, false, 0}
#define criterion_protocol_log_init_default {0, NULL, false, 0}
#define criterion_protocol_submessage_init_default {0, {criterion_protocol_birth_init_default}}
#define criterion_protocol_msg_init_default {1, 0, {0}, criterion_protocol_submessage_init_default}
#define criterion_protocol_birth_init_zero {0}
@ -98,18 +120,26 @@ extern const int32_t criterion_protocol_msg_version_default;
#define criterion_protocol_pre_test_init_zero {false, 0}
#define criterion_protocol_post_test_init_zero {false, 0}
#define criterion_protocol_post_fini_init_zero {0}
#define criterion_protocol_pre_subtest_init_zero {{{NULL}, NULL}}
#define criterion_protocol_post_subtest_init_zero {{{NULL}, NULL}}
#define criterion_protocol_death_init_zero {false, (criterion_protocol_death_result_type)0, false, 0}
#define criterion_protocol_assert_init_zero {NULL, 0, NULL, false, 0}
#define criterion_protocol_log_init_zero {0, NULL, false, 0}
#define criterion_protocol_submessage_init_zero {0, {criterion_protocol_birth_init_zero}}
#define criterion_protocol_msg_init_zero {0, 0, {0}, criterion_protocol_submessage_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define criterion_protocol_post_subtest_id_tag 1
#define criterion_protocol_pre_subtest_id_tag 1
#define criterion_protocol_assert_message_tag 1
#define criterion_protocol_assert_passed_tag 2
#define criterion_protocol_assert_file_tag 3
#define criterion_protocol_assert_line_tag 4
#define criterion_protocol_death_result_tag 1
#define criterion_protocol_death_status_tag 2
#define criterion_protocol_log_severity_tag 1
#define criterion_protocol_log_message_tag 2
#define criterion_protocol_log_prefix_tag 3
#define criterion_protocol_post_test_timestamp_tag 1
#define criterion_protocol_pre_test_timestamp_tag 1
#define criterion_protocol_submessage_birth_tag 1
@ -118,7 +148,10 @@ extern const int32_t criterion_protocol_msg_version_default;
#define criterion_protocol_submessage_post_test_tag 4
#define criterion_protocol_submessage_post_fini_tag 5
#define criterion_protocol_submessage_death_tag 6
#define criterion_protocol_submessage_assert_tag 7
#define criterion_protocol_submessage_message_tag 7
#define criterion_protocol_submessage_assert_tag 8
#define criterion_protocol_submessage_pre_subtest_tag 9
#define criterion_protocol_submessage_post_subtest_tag 10
#define criterion_protocol_msg_pid_tag 2
#define criterion_protocol_msg_version_tag 1
#define criterion_protocol_msg_data_tag 16
@ -129,9 +162,12 @@ extern const pb_field_t criterion_protocol_pre_init_fields[1];
extern const pb_field_t criterion_protocol_pre_test_fields[2];
extern const pb_field_t criterion_protocol_post_test_fields[2];
extern const pb_field_t criterion_protocol_post_fini_fields[1];
extern const pb_field_t criterion_protocol_pre_subtest_fields[2];
extern const pb_field_t criterion_protocol_post_subtest_fields[2];
extern const pb_field_t criterion_protocol_death_fields[3];
extern const pb_field_t criterion_protocol_assert_fields[5];
extern const pb_field_t criterion_protocol_submessage_fields[8];
extern const pb_field_t criterion_protocol_log_fields[4];
extern const pb_field_t criterion_protocol_submessage_fields[11];
extern const pb_field_t criterion_protocol_msg_fields[4];
/* Maximum encoded size of messages (where known) */

View file

@ -18,11 +18,20 @@ message post_test {
message post_fini {
}
message pre_subtest {
required string id = 1;
}
message post_subtest {
required string id = 1;
}
message death {
enum result_type {
NORMAL = 0;
CRASH = 1;
TIMEOUT = 2;
ABORT = 3;
}
optional result_type result = 1;
@ -36,16 +45,26 @@ message assert {
optional int64 line = 4;
}
message log {
required int32 severity = 1;
required string message = 2;
optional int32 prefix = 3;
}
message submessage {
oneof value {
criterion.protocol.birth birth = 1;
criterion.protocol.pre_init pre_init = 2;
criterion.protocol.pre_test pre_test = 3;
criterion.protocol.post_test post_test = 4;
criterion.protocol.post_fini post_fini = 5;
criterion.protocol.death death = 6;
criterion.protocol.assert assert = 7;
criterion.protocol.birth birth = 1;
criterion.protocol.pre_init pre_init = 2;
criterion.protocol.pre_test pre_test = 3;
criterion.protocol.post_test post_test = 4;
criterion.protocol.post_fini post_fini = 5;
criterion.protocol.death death = 6;
criterion.protocol.log message = 7;
criterion.protocol.assert assert = 8;
criterion.protocol.pre_subtest pre_subtest = 9;
criterion.protocol.post_subtest post_subtest = 10;
}
}

View file

@ -2,37 +2,40 @@
#include <pb_decode.h>
#include <nanomsg/nn.h>
#include <nanomsg/pipeline.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count) {
int sock = (intptr_t) stream->state;
int result = nn_send(sock, buf, count, 0);
#include "criterion/internal/common.h"
#include "protocol.h"
static bool write_fd_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count) {
int fd = (intptr_t) stream->state;
ssize_t result = write(fd, buf, count);
if (result < 0)
return false;
return (size_t) result == count;
}
static bool read_callback(pb_istream_t *stream, uint8_t *buf, size_t count) {
int sock = (intptr_t)stream->state;
int result;
result = nn_recv(sock, buf, count, 0);
if (result == 0)
stream->bytes_left = 0; /* EOF */
static bool read_fd_callback(pb_istream_t *stream, uint8_t *buf, size_t count) {
int fd = (intptr_t) stream->state;
ssize_t result = read(fd, buf, count);
if (result < 0)
return false;
if ((size_t) result < count)
stream->bytes_left = result;
return (size_t) result == count;
}
pb_ostream_t pb_ostream_from_nn_socket(int sock) {
pb_ostream_t stream = {&write_callback, (void*)(intptr_t) sock, SIZE_MAX, 0, ""};
pb_ostream_t pb_ostream_from_fd(int fd) {
pb_ostream_t stream = {&write_fd_callback, (void*)(intptr_t) fd, SIZE_MAX, 0, NULL};
return stream;
}
pb_istream_t pb_istream_from_nn_socket(int sock) {
pb_istream_t stream = {&read_callback, (void*)(intptr_t) sock, SIZE_MAX, ""};
pb_istream_t pb_istream_from_fd(int fd) {
pb_istream_t stream = {&read_fd_callback, (void*)(intptr_t) fd, SIZE_MAX, NULL};
return stream;
}

53
src/protocol/protocol.h Normal file
View file

@ -0,0 +1,53 @@
/*
* 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 PROTOCOL_H_
# define PROTOCOL_H_
# include <pb_encode.h>
# include <pb_decode.h>
# include "criterion.pb.h"
# include "criterion/internal/preprocess.h"
bool pb_write_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg);
bool pb_read_string(pb_istream_t *stream, const pb_field_t *field, void **arg);
pb_ostream_t pb_ostream_from_fd(int fd);
pb_istream_t pb_istream_from_fd(int fd);
# define criterion_message(Kind, ...) \
(criterion_protocol_msg) { \
.version = 1, \
.which_id = criterion_protocol_msg_pid_tag, \
.id = { \
.pid = get_process_id(), \
}, \
.data = { \
.which_value = criterion_protocol_submessage_ ## Kind ## _tag, \
.value = { \
.Kind = { CR_EXPAND(__VA_ARGS__) }, \
} \
} \
}
#endif /* !PROTOCOL_H_ */