Added file assertions for redirection
This commit is contained in:
parent
3744d67b0c
commit
3dc9d47c0b
7 changed files with 144 additions and 11 deletions
|
@ -61,6 +61,7 @@ enum criterion_assert_messages {
|
|||
CRITERION_ASSERT_MSG_IS_NOT_NULL,
|
||||
CRITERION_ASSERT_MSG_IS_EMPTY,
|
||||
CRITERION_ASSERT_MSG_IS_NOT_EMPTY,
|
||||
CRITERION_ASSERT_MSG_FILE_STR_MATCH,
|
||||
};
|
||||
|
||||
CR_BEGIN_C_API
|
||||
|
@ -80,7 +81,7 @@ CR_END_C_API
|
|||
# endif
|
||||
|
||||
# define CR_TRANSLATE_DEF_MSG__(Arg) \
|
||||
CR_EXPAND Arg
|
||||
CR_IDENTITY Arg
|
||||
|
||||
# define CR_TRANSLATE_DEF_MSG_(...) \
|
||||
CR_EXPAND(translate_assert_msg( \
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
# endif
|
||||
|
||||
# define CR_EXPAND(x) x
|
||||
# define CR_IDENTITY(...) __VA_ARGS__
|
||||
|
||||
# define CR_STR(x) CR_EXPAND(CR_STR_(x))
|
||||
# define CR_STR_(x) #x
|
||||
|
|
|
@ -25,6 +25,13 @@
|
|||
# define CRITERION_REDIRECT_H_
|
||||
|
||||
# include "common.h"
|
||||
# include "assert.h"
|
||||
|
||||
# ifdef __cplusplus
|
||||
# include <cstdio>
|
||||
# else
|
||||
# include <stdio.h>
|
||||
# endif
|
||||
|
||||
CR_BEGIN_C_API
|
||||
|
||||
|
@ -32,10 +39,38 @@ CR_API void cr_redirect_stdout(void);
|
|||
CR_API void cr_redirect_stderr(void);
|
||||
CR_API void cr_redirect_stdin(void);
|
||||
|
||||
CR_API FILE* cr_get_redirected_stdout(void);
|
||||
CR_API FILE* cr_get_redirected_stderr(void);
|
||||
CR_API FILE* cr_get_redirected_stdin(void);
|
||||
CR_API CR_STDN FILE* cr_get_redirected_stdout(void);
|
||||
CR_API CR_STDN FILE* cr_get_redirected_stderr(void);
|
||||
CR_API CR_STDN FILE* cr_get_redirected_stdin(void);
|
||||
|
||||
CR_API int cr_file_match_str(CR_STDN FILE* f, const char *str);
|
||||
|
||||
CR_END_C_API
|
||||
|
||||
# define cr_assert_redir_op_(Fail, Fun, Op, File, Str, ...) \
|
||||
CR_EXPAND(cr_assert_impl( \
|
||||
Fail, \
|
||||
!(Fun((File), (Str)) Op 0), \
|
||||
dummy, \
|
||||
CRITERION_ASSERT_MSG_FILE_STR_MATCH, \
|
||||
(CR_STR(File), Str), \
|
||||
__VA_ARGS__ \
|
||||
))
|
||||
|
||||
# define cr_assert_redir_op_va_(Fail, Fun, Op, ...) \
|
||||
CR_EXPAND(cr_assert_redir_op_( \
|
||||
Fail, \
|
||||
Fun, \
|
||||
Op, \
|
||||
CR_VA_HEAD(__VA_ARGS__), \
|
||||
CR_VA_HEAD(CR_VA_TAIL(__VA_ARGS__)), \
|
||||
CR_VA_TAIL(CR_VA_TAIL(__VA_ARGS__)) \
|
||||
))
|
||||
|
||||
# define cr_assert_file_contents_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, ==, __VA_ARGS__))
|
||||
# define cr_expect_file_contents_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, ==, __VA_ARGS__))
|
||||
|
||||
# define cr_assert_file_contents_not_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_ABORT_, cr_file_match_str, !=, __VA_ARGS__))
|
||||
# define cr_expect_file_contents_not_match_str(...) CR_EXPAND(cr_assert_redir_op_va_(CR_FAIL_CONTINUES_, cr_file_match_str, !=, __VA_ARGS__))
|
||||
|
||||
#endif /* !CRITERION_REDIRECT_H_ */
|
||||
|
|
|
@ -15,6 +15,7 @@ set(SAMPLES
|
|||
description.c
|
||||
simple.c
|
||||
theories.c
|
||||
redirect.c
|
||||
|
||||
signal.cc
|
||||
report.cc
|
||||
|
|
|
@ -17,6 +17,12 @@ char *translate_assert_msg(int msg_index, ...) {
|
|||
[CRITERION_ASSERT_MSG_IS_NOT_NULL] = N_("%s is not null."),
|
||||
[CRITERION_ASSERT_MSG_IS_EMPTY] = N_("%s is empty."),
|
||||
[CRITERION_ASSERT_MSG_IS_NOT_EMPTY] = N_("%s is not empty."),
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
[CRITERION_ASSERT_MSG_FILE_STR_MATCH] = N_("The file contents of %1$s does not match the string \"%2$s\"."),
|
||||
#else
|
||||
[CRITERION_ASSERT_MSG_FILE_STR_MATCH] = "The file contents of %s does not match the string \"%s\".",
|
||||
#endif
|
||||
};
|
||||
|
||||
va_list vl;
|
||||
|
|
|
@ -453,8 +453,72 @@ cr_std_fd get_std_fd(int fd_kind) {
|
|||
return kinds[fd_kind];
|
||||
}
|
||||
|
||||
void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index) {
|
||||
if (stdpipe_stack(pipe) < 0)
|
||||
FILE* get_std_file(int fd_kind) {
|
||||
switch (fd_kind) {
|
||||
case CR_STDIN: return stdin;
|
||||
case CR_STDOUT: return stdout;
|
||||
case CR_STDERR: return stderr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int make_redirect_pipe(s_pipe_handle *handle, int noblock) {
|
||||
#ifdef VANILLA_WIN32
|
||||
static char pipe_name[256] = {0};
|
||||
|
||||
HANDLE fhs[2];
|
||||
SECURITY_ATTRIBUTES attr = {
|
||||
.nLength = sizeof (SECURITY_ATTRIBUTES),
|
||||
.bInheritHandle = TRUE
|
||||
};
|
||||
if (!pipe_name[0]) {
|
||||
snprintf(pipe_name, sizeof (pipe_name),
|
||||
"\\\\.\\pipe\\criterion_%d", GetCurrentProcessId());
|
||||
}
|
||||
fhs[0] = CreateNamedPipe(pipe_name,
|
||||
PIPE_ACCESS_DUPLEX,
|
||||
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE
|
||||
| (noblock ? PIPE_NOWAIT : PIPE_WAIT),
|
||||
PIPE_UNLIMITED_INSTANCES
|
||||
4096 * 4,
|
||||
4096 * 4,
|
||||
0,
|
||||
attr);
|
||||
|
||||
if (fds[0] == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
fhs[1] = CreateFile(pipe_name,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
attr,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (fds[1] == INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(fds[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*handle = (s_pipe_handle) {{ fhs[0], fhs[1] }};
|
||||
#else
|
||||
int fds[2] = { -1, -1 };
|
||||
if (pipe(fds) == -1)
|
||||
return 0;
|
||||
|
||||
if (noblock)
|
||||
for (int i = 0; i < 2; ++i)
|
||||
fcntl(fds[i], F_SETFL, fcntl(fds[i], F_GETFL) | O_NONBLOCK);
|
||||
|
||||
*handle = (s_pipe_handle) {{ fds[0], fds[1] }};
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index, int noblock) {
|
||||
fflush(get_std_file(fd_kind));
|
||||
if (make_redirect_pipe(pipe, noblock) < 0)
|
||||
cr_assert_fail("Could not redirect standard file descriptor.");
|
||||
|
||||
cr_std_fd fd = get_std_fd(fd_kind);
|
||||
|
@ -463,21 +527,21 @@ void cr_redirect(int fd_kind, s_pipe_handle *pipe, int fd_index) {
|
|||
SetStdHandle(fd, pipe->fhs[fd_index]);
|
||||
#else
|
||||
close(fd);
|
||||
dup2(fd, pipe->fds[fd_index]);
|
||||
dup2(pipe->fds[fd_index], fd);
|
||||
close(pipe->fds[fd_index]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cr_redirect_stdout(void) {
|
||||
cr_redirect(CR_STDOUT, &stdout_redir, PIPE_WRITE);
|
||||
cr_redirect(CR_STDOUT, &stdout_redir, PIPE_WRITE, 1);
|
||||
}
|
||||
|
||||
void cr_redirect_stderr(void) {
|
||||
cr_redirect(CR_STDERR, &stderr_redir, PIPE_WRITE);
|
||||
cr_redirect(CR_STDERR, &stderr_redir, PIPE_WRITE, 1);
|
||||
}
|
||||
|
||||
void cr_redirect_stdin(void) {
|
||||
cr_redirect(CR_STDIN, &stdin_redir, PIPE_READ);
|
||||
cr_redirect(CR_STDIN, &stdin_redir, PIPE_READ, 0);
|
||||
}
|
||||
|
||||
FILE* cr_get_redirected_stdout(void) {
|
||||
|
@ -509,3 +573,27 @@ FILE* cr_get_redirected_stdin(void) {
|
|||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
int cr_file_match_str(FILE* f, const char *str) {
|
||||
size_t len = strlen(str);
|
||||
|
||||
fputs(str, stderr);
|
||||
char buf[512];
|
||||
size_t read;
|
||||
int matches = 0;
|
||||
while ((read = fread(buf, 1, sizeof (buf), f)) > 0) {
|
||||
matches = !strncmp(buf, str, read);
|
||||
if (!matches || read > len) {
|
||||
matches = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
len -= read;
|
||||
str += read;
|
||||
}
|
||||
|
||||
// consume the rest of what's available
|
||||
while (fread(buf, 1, sizeof (buf), f) > 0);
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "criterion/types.h"
|
||||
#include "criterion/options.h"
|
||||
#include "criterion/redirect.h"
|
||||
#include "process.h"
|
||||
#include "event.h"
|
||||
#include "posix-compat.h"
|
||||
|
@ -61,7 +62,7 @@ struct event *worker_read_event(struct process *proc) {
|
|||
}
|
||||
|
||||
void run_worker(struct worker_context *ctx) {
|
||||
fclose(stdin);
|
||||
cr_redirect_stdin();
|
||||
g_event_pipe = pipe_out(ctx->pipe, 1);
|
||||
|
||||
ctx->func(ctx->test, ctx->suite);
|
||||
|
|
Loading…
Add table
Reference in a new issue