Skip to content

Commit

Permalink
Added initial support for Windows. stderr capture isn't working.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tordek committed Aug 14, 2012
1 parent 626de02 commit 6b61d2a
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 18 deletions.
97 changes: 84 additions & 13 deletions cheat.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct cheat_test_suite {
char *argv0;
size_t log_size;
int nofork;
FILE *stdout;
FILE *captured_stdout;
};

typedef void cheat_test(struct cheat_test_suite *suite);
Expand Down Expand Up @@ -55,7 +55,7 @@ struct cheat_test_s {
static void cheat_suite_init(struct cheat_test_suite *suite, char *argv0)
{
memset(suite, 0, sizeof(struct cheat_test_suite));
suite->stdout = stdout;
suite->captured_stdout = stdout;
suite->argv0 = argv0;
}

Expand All @@ -64,16 +64,16 @@ static void cheat_suite_summary(struct cheat_test_suite *suite)
if (suite->log) {
size_t i;

fputs("\n", suite->stdout);
fputs("\n", suite->captured_stdout);
for (i = 0; i < suite->log_size; ++i) {
fputs(suite->log[i], suite->stdout);
fputs(suite->log[i], suite->captured_stdout);
free(suite->log[i]);
}

free(suite->log);
}

fprintf(suite->stdout, "\n%d failed tests of %d tests run.\n", suite->test_failures, suite->test_count);
fprintf(suite->captured_stdout, "\n%d failed tests of %d tests run.\n", suite->test_failures, suite->test_count);
}

static void cheat_test_end(struct cheat_test_suite *suite)
Expand All @@ -82,17 +82,17 @@ static void cheat_test_end(struct cheat_test_suite *suite)

switch (suite->last_test_status) {
case CHEAT_SUCCESS:
fputc('.', suite->stdout);
fputc('.', suite->captured_stdout);
break;
case CHEAT_FAILURE:
fputc('F', suite->stdout);
fputc('F', suite->captured_stdout);
suite->test_failures++;
break;
case CHEAT_IGNORE:
fputc('I', suite->stdout);
fputc('I', suite->captured_stdout);
break;
case CHEAT_SEGFAULT:
fputc('S', suite->stdout);
fputc('S', suite->captured_stdout);
suite->test_failures++;
break;
default:
Expand All @@ -102,9 +102,15 @@ static void cheat_test_end(struct cheat_test_suite *suite)

static void cheat_log_append(struct cheat_test_suite *suite, char *message, int len)
{
char * const buf = malloc(len);
if (len == 0) {
return;
}

char * const buf = malloc(len + 1);
memcpy(buf, message, len);

buf[len] = '\0';

suite->log_size++;
suite->log = realloc(suite->log, (suite->log_size + 1) * sizeof(char *));
suite->log[suite->log_size - 1] = buf; /* We give up our buffer! */
Expand All @@ -127,18 +133,18 @@ static void cheat_test_assert(
int bufsize;

do {
bufsize = len;
bufsize = (len + 1);
buffer = realloc(buffer, bufsize);
len = snprintf(buffer, bufsize,
"%s:%d: Assertion failed: '%s'.\n",
filename,
line,
assertion);
} while (bufsize != len);
} while (bufsize != (len + 1));

cheat_log_append(suite, buffer, bufsize);
} else {
fprintf(suite->stdout,
fprintf(suite->captured_stdout,
"%s:%d: Assertion failed: '%s'.\n",
filename,
line,
Expand All @@ -158,8 +164,14 @@ static int run_test(struct cheat_test_s const *test, struct cheat_test_suite *su
}

#ifdef unix

#include <sys/types.h>
#include <sys/wait.h>

#elif defined _WIN32

#include <windows.h>

#endif

static void run_isolated_test(
Expand Down Expand Up @@ -197,8 +209,67 @@ static void run_isolated_test(
suite->last_test_status = WIFEXITED(status) ? WEXITSTATUS(status)
: CHEAT_SEGFAULT;
}

#elif defined _WIN32

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;

HANDLE stdoutPipe_read;
HANDLE stdoutPipe_write;
CreatePipe(&stdoutPipe_read, &stdoutPipe_write, &sa, 0);

STARTUPINFO si = {
.cb = sizeof(STARTUPINFO),
.dwFlags = STARTF_USESTDHANDLES,
.hStdOutput = stdoutPipe_write
};

PROCESS_INFORMATION pi = {0};

CHAR command[255];
snprintf(command, 255, "%s %s", suite->argv0, test->name);

CreateProcess(
NULL,
command,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&si,
&pi);

CloseHandle(stdoutPipe_write);

DWORD len;
DWORD maxlen = 255;
CHAR buffer[255];

do {
ReadFile(stdoutPipe_read, buffer, maxlen, &len, NULL);
buffer[len] = '\0';
cheat_log_append(suite, buffer, len);
} while (len > 0);

WaitForSingleObject(pi.hProcess, INFINITE);

DWORD status;
GetExitCodeProcess(pi.hProcess, &status);

suite->last_test_status = (status & 0x80000000) ? CHEAT_SEGFAULT
: status;

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

#else
fputs("Running isolated tests not supported in this environment. Please use --nofork.\n", stderr);
exit(EXIT_FAILURE);
#endif
}

Expand Down
42 changes: 37 additions & 5 deletions cheat_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,48 @@ int cheat_stream_contains(FILE *stream, char const *contents);

#include <unistd.h>

#elif defined _WIN32

#include <windows.h>
#include <fcntl.h>

#define dup _dup
#define dup2 _dup2

int mkstemp(char * pattern) {
// TODO: Generate a uUnique to avoid using CREATE_ALWAYS.
// Even better: get rid of this, and try to open in a do..while loop
// to match mkstemp.
char tempFileName[MAX_PATH];
GetTempFileName(
".",
pattern,
0,
tempFileName);

HANDLE tempFile = CreateFile(
tempFileName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS, // Bad. Should be _NEW, to avoid races.
0,
NULL);

return _open_osfhandle((intptr_t)tempFile, _O_APPEND);
}

#else
#error "Unsupported platform. Sorry!"
#endif

#define CHEAT_WRAP_STREAM(stream, stream_fd, name, body) \
char filename_pattern[] = "cheat_captured_stream_" #name "_XXXXXX";\
int original_stream;\
int fake_stream;\
fake_stream = mkstemp(filename_pattern);\
fflush(stream);\
original_stream = dup(stream_fd); \
fake_stream = mkstemp(filename_pattern);\
dup2(fake_stream, stream_fd);\
setbuf(stream, NULL);\
body\
Expand All @@ -42,6 +77,7 @@ int cheat_stream_contains(FILE *stream, char const *contents)

buffer = malloc(len + 1);
fread(buffer, 1, len, stream);
buffer[len] = '\0';

result = strstr(buffer, contents) != NULL;

Expand All @@ -50,8 +86,4 @@ int cheat_stream_contains(FILE *stream, char const *contents)
return result;
}

#else
#error "Unsupported platform. Sorry!"
#endif

#endif

0 comments on commit 6b61d2a

Please sign in to comment.