/*
- * Copyright (C) 2012, 2013
+ * Copyright (C) 2012, 2013, 2014, 2015
* Dale Weiler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
*/
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
+
#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+
#include "gmqcc.h"
static const char *task_bins[] = {
"./qcvm"
};
-/*
- * TODO: Windows version
- * this implements a unique bi-directional popen-like function that
- * allows reading data from both stdout and stderr. And writing to
- * stdin :)
- *
- * Example of use:
- * FILE *handles[3] = task_popen("ls", "-l", "r");
- * if (!handles) { perror("failed to open stdin/stdout/stderr to ls");
- * // handles[0] = stdin
- * // handles[1] = stdout
- * // handles[2] = stderr
- *
- * task_pclose(handles); // to close
- */
-#ifndef _WIN32
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <dirent.h>
-#include <unistd.h>
typedef struct {
FILE *handles[3];
- int pipes [3];
-
+ int pipes[3];
int stderr_fd;
int stdout_fd;
int pid;
} popen_t;
-static FILE ** task_popen(const char *command, const char *mode) {
+static FILE **task_popen(const char *command, const char *mode) {
int inhandle [2];
int outhandle [2];
int errhandle [2];
while (*line != '\0' && *line != ' ' &&
*line != '\t' && *line != '\n') line++;
}
- vec_push(argv, '\0');
+ vec_push(argv, (char *)0);
}
if ((data->pid = fork()) > 0) {
/* parent */
- close(inhandle [0]);
+ close(inhandle [0]);
close(outhandle [1]);
close(errhandle [1]);
-
- data->pipes [0] = inhandle [1];
- data->pipes [1] = outhandle[0];
- data->pipes [2] = errhandle[0];
-
+ data->pipes[0] = inhandle [1];
+ data->pipes[1] = outhandle[0];
+ data->pipes[2] = errhandle[0];
data->handles[0] = fdopen(inhandle [1], "w");
data->handles[1] = fdopen(outhandle[0], mode);
data->handles[2] = fdopen(errhandle[0], mode);
return status;
}
-#else
- typedef struct {
- FILE *handles[3];
- char name_err[L_tmpnam];
- char name_out[L_tmpnam];
- } popen_t;
-
- static FILE **task_popen(const char *command, const char *mode) {
- char *cmd = NULL;
- popen_t *open = (popen_t*)mem_a(sizeof(popen_t));
-
- platform_tmpnam(open->name_err);
- platform_tmpnam(open->name_out);
-
- (void)mode; /* excluded */
-
- util_asprintf(&cmd, "%s -redirout=%s -redirerr=%s", command, open->name_out, open->name_err);
-
- system(cmd); /* HACK */
- open->handles[0] = NULL;
- open->handles[1] = fs_file_open(open->name_out, "r");
- open->handles[2] = fs_file_open(open->name_err, "r");
-
- mem_d(cmd);
-
- return open->handles;
- }
-
- static int task_pclose(FILE **files) {
- popen_t *open = ((popen_t*)files);
- fs_file_close(files[1]);
- fs_file_close(files[2]);
- remove(open->name_err);
- remove(open->name_out);
-
- mem_d(open);
-
- return EXIT_SUCCESS;
- }
-# define popen _popen
-# define pclose _pclose
-#endif /*! _WIN32 */
#define TASK_COMPILE 0
#define TASK_EXECUTE 1
/* a page should be enough */
char fullfile[4096];
size_t filepadd = 0;
- FILE *tempfile = NULL;
+ FILE *tempfile = NULL;
task_template_t *tmpl = NULL;
- platform_snprintf(fullfile, sizeof(fullfile), "%s/%s", dir, file);
+ util_snprintf(fullfile, sizeof(fullfile), "%s/%s", dir, file);
- tempfile = fs_file_open(fullfile, "r");
+ tempfile = fopen(fullfile, "r");
tmpl = (task_template_t*)mem_a(sizeof(task_template_t));
task_template_nullify(tmpl);
}
success:
- fs_file_close(tempfile);
+ fclose(tempfile);
return tmpl;
failure:
* so the check to see if it's not null here is required.
*/
if (tempfile)
- fs_file_close(tempfile);
+ fclose(tempfile);
mem_d (tmpl);
return NULL;
*/
typedef struct {
task_template_t *tmpl;
- FILE **runhandles;
- FILE *stderrlog;
- FILE *stdoutlog;
- char *stdoutlogfile;
- char *stderrlogfile;
- bool compiled;
+ FILE **runhandles;
+ FILE *stderrlog;
+ FILE *stdoutlog;
+ char *stdoutlogfile;
+ char *stderrlogfile;
+ bool compiled;
} task_t;
static task_t *task_tasks = NULL;
*/
static bool task_propagate(const char *curdir, size_t *pad, const char *defs) {
bool success = true;
- DIR *dir;
- struct dirent *files;
+ DIR *dir;
+ struct dirent *files;
struct stat directory;
char buffer[4096];
size_t found = 0;
size_t i;
vec_push(directories, claim);
- dir = fs_dir_open(claim);
+ dir = opendir(claim);
/*
* Generate a list of subdirectories since we'll be checking them too
* for tmpl files.
*/
- while ((files = fs_dir_read(dir))) {
+ while ((files = readdir(dir))) {
util_asprintf(&claim, "%s/%s", curdir, files->d_name);
if (stat(claim, &directory) == -1) {
- fs_dir_close(dir);
+ closedir(dir);
mem_d(claim);
return false;
}
claim = NULL;
}
}
- fs_dir_close(dir);
+ closedir(dir);
/*
* Now do all the work, by touching all the directories inside
* use to run the tests.
*/
for (i = 0; i < vec_size(directories); i++) {
- dir = fs_dir_open(directories[i]);
+ dir = opendir(directories[i]);
- while ((files = fs_dir_read(dir))) {
- platform_snprintf(buffer, sizeof(buffer), "%s/%s", directories[i], files->d_name);
+ while ((files = readdir(dir))) {
+ util_snprintf(buffer, sizeof(buffer), "%s/%s", directories[i], files->d_name);
if (stat(buffer, &directory) == -1) {
con_err("internal error: stat failed, aborting\n");
abort();
* so we don't trample over an existing one.
*/
tmpl->tempfilename = NULL;
- util_asprintf(&tmpl->tempfilename, "%s/TMPDAT.%s", directories[i], files->d_name);
+ util_asprintf(&tmpl->tempfilename, "%s/TMPDAT.%s.dat", directories[i], files->d_name);
/*
* Additional QCFLAGS enviroment variable may be used
* to test compile flags for all tests. This needs to be
* BEFORE other flags (so that the .tmpl can override them)
*/
- qcflags = platform_getenv("QCFLAGS");
+ qcflags = getenv("QCFLAGS");
/*
* Generate the command required to open a pipe to a process
if (strcmp(tmpl->proceduretype, "-pp")) {
if (qcflags) {
if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) {
- platform_snprintf(buf, sizeof(buf), "%s %s/%s %s %s -o %s",
+ util_snprintf(buf, sizeof(buf), "%s %s/%s %s %s -o %s",
task_bins[TASK_COMPILE],
directories[i],
tmpl->sourcefile,
tmpl->tempfilename
);
} else {
- platform_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s %s -o %s",
+ util_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s %s -o %s",
task_bins[TASK_COMPILE],
curdir,
defs,
}
} else {
if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) {
- platform_snprintf(buf, sizeof(buf), "%s %s/%s %s -o %s",
+ util_snprintf(buf, sizeof(buf), "%s %s/%s %s -o %s",
task_bins[TASK_COMPILE],
directories[i],
tmpl->sourcefile,
tmpl->tempfilename
);
} else {
- platform_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s -o %s",
+ util_snprintf(buf, sizeof(buf), "%s %s/%s %s/%s %s -o %s",
task_bins[TASK_COMPILE],
curdir,
defs,
} else {
/* Preprocessing (qcflags mean shit all here we don't allow them) */
if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) {
- platform_snprintf(buf, sizeof(buf), "%s -E %s/%s -o %s",
+ util_snprintf(buf, sizeof(buf), "%s -E %s/%s %s -o %s",
task_bins[TASK_COMPILE],
directories[i],
tmpl->sourcefile,
+ tmpl->compileflags,
tmpl->tempfilename
);
} else {
- platform_snprintf(buf, sizeof(buf), "%s -E %s/%s %s/%s -o %s",
+ util_snprintf(buf, sizeof(buf), "%s -E %s/%s %s/%s %s -o %s",
task_bins[TASK_COMPILE],
curdir,
defs,
directories[i],
tmpl->sourcefile,
+ tmpl->compileflags,
tmpl->tempfilename
);
}
* Open up some file desciptors for logging the stdout/stderr
* to our own.
*/
- platform_snprintf(buf, sizeof(buf), "%s.stdout", tmpl->tempfilename);
+ util_snprintf(buf, sizeof(buf), "%s.stdout", tmpl->tempfilename);
task.stdoutlogfile = util_strdup(buf);
- if (!(task.stdoutlog = fs_file_open(buf, "w"))) {
+ if (!(task.stdoutlog = fopen(buf, "w"))) {
con_err("error opening %s for stdout\n", buf);
continue;
}
- platform_snprintf(buf, sizeof(buf), "%s.stderr", tmpl->tempfilename);
+ util_snprintf(buf, sizeof(buf), "%s.stderr", tmpl->tempfilename);
task.stderrlogfile = util_strdup(buf);
- if (!(task.stderrlog = fs_file_open(buf, "w"))) {
+ if (!(task.stderrlog = fopen(buf, "w"))) {
con_err("error opening %s for stderr\n", buf);
continue;
}
-
vec_push(task_tasks, task);
}
}
-
- fs_dir_close(dir);
+ closedir(dir);
mem_d(directories[i]); /* free claimed memory */
}
vec_free(directories);
* left behind from a previous invoke of the test-suite.
*/
static void task_precleanup(const char *curdir) {
- DIR *dir;
- struct dirent *files;
- char buffer[4096];
+ DIR *dir;
+ struct dirent *files;
+ char buffer[4096];
- dir = fs_dir_open(curdir);
+ dir = opendir(curdir);
- while ((files = fs_dir_read(dir))) {
+ while ((files = readdir(dir))) {
if (strstr(files->d_name, "TMP") ||
strstr(files->d_name, ".stdout") ||
- strstr(files->d_name, ".stderr"))
+ strstr(files->d_name, ".stderr") ||
+ strstr(files->d_name, ".dat"))
{
- platform_snprintf(buffer, sizeof(buffer), "%s/%s", curdir, files->d_name);
+ util_snprintf(buffer, sizeof(buffer), "%s/%s", curdir, files->d_name);
if (remove(buffer))
con_err("error removing temporary file: %s\n", buffer);
}
}
- fs_dir_close(dir);
+ closedir(dir);
}
static void task_destroy(void) {
* Close any open handles to files or processes here. It's mighty
* annoying to have to do all this cleanup work.
*/
- if (task_tasks[i].stdoutlog) fs_file_close (task_tasks[i].stdoutlog);
- if (task_tasks[i].stderrlog) fs_file_close (task_tasks[i].stderrlog);
+ if (task_tasks[i].stdoutlog) fclose(task_tasks[i].stdoutlog);
+ if (task_tasks[i].stderrlog) fclose(task_tasks[i].stderrlog);
/*
* Only remove the log files if the test actually compiled otherwise
bool success = true;
bool process = true;
int retval = EXIT_SUCCESS;
- FILE *execute;
+ FILE *execute;
char buffer[4096];
task_template_t *tmpl = task_tasks[i].tmpl;
* actually specified.
*/
if (!strcmp(tmpl->executeflags, "$null")) {
- platform_snprintf(buffer, sizeof(buffer), "%s %s",
+ util_snprintf(buffer, sizeof(buffer), "%s %s",
task_bins[TASK_EXECUTE],
tmpl->tempfilename
);
} else {
- platform_snprintf(buffer, sizeof(buffer), "%s %s %s",
+ util_snprintf(buffer, sizeof(buffer), "%s %s %s",
task_bins[TASK_EXECUTE],
tmpl->executeflags,
tmpl->tempfilename
* we're preprocessing, which means we need to read int
* the produced file and do some really weird shit.
*/
- if (!(execute = fs_file_open(tmpl->tempfilename, "r")))
+ if (!(execute = fopen(tmpl->tempfilename, "r")))
return false;
-
process = false;
} else {
/*
* in runhandles[2] (stderr) since that is where the compiler
* puts it's errors.
*/
- if (!(execute = fs_file_open(task_tasks[i].stderrlogfile, "r")))
+ if (!(execute = fopen(task_tasks[i].stderrlogfile, "r")))
return false;
-
process = false;
}
tmpl->rulesfile
);
if (!process)
- fs_file_close(execute);
+ fclose(execute);
else
- pclose(execute);
+ pclose((FILE*)execute);
return false;
}
}
if (process)
- retval = pclose(execute);
+ retval = pclose((FILE*)execute);
else
- fs_file_close(execute);
+ fclose(execute);
return success && retval == EXIT_SUCCESS;
}
size_t i = 0;
size_t j = 0;
size_t failed = 0;
+ int status = 0;
- platform_snprintf(space[0], sizeof(space[0]), "%d", (int)vec_size(task_tasks));
+ util_snprintf(space[0], sizeof(space[0]), "%d", (int)vec_size(task_tasks));
for (; i < vec_size(task_tasks); i++) {
memset(space[1], 0, sizeof(space[1]));
- platform_snprintf(space[1], sizeof(space[1]), "%d", (int)(i + 1));
+ util_snprintf(space[1], sizeof(space[1]), "%d", (int)(i + 1));
con_out("test #%u %*s", i + 1, strlen(space[0]) - strlen(space[1]), "");
* then we do the same for stderr.
*/
while (fs_file_getline(&data, &size, task_tasks[i].runhandles[1]) != EOF) {
- fs_file_puts(task_tasks[i].stdoutlog, data);
+ fputs(data, task_tasks[i].stdoutlog);
if (strstr(data, "failed to open file")) {
task_tasks[i].compiled = false;
task_tasks[i].compiled = false;
}
- fs_file_puts (task_tasks[i].stderrlog, data);
+ fputs(data, task_tasks[i].stderrlog);
fflush(task_tasks[i].stderrlog); /* fast flush for read */
}
continue;
}
- if (task_pclose(task_tasks[i].runhandles) != EXIT_SUCCESS && strcmp(task_tasks[i].tmpl->proceduretype, "-fail")) {
+ status = task_pclose(task_tasks[i].runhandles);
+ if ((!strcmp(task_tasks[i].tmpl->proceduretype, "-fail") && status == EXIT_SUCCESS)
+ || ( strcmp(task_tasks[i].tmpl->proceduretype, "-fail") && status == EXIT_FAILURE)) {
con_out("failure: `%s` %*s %*s\n",
task_tasks[i].tmpl->description,
(pad[0] + pad[1] - strlen(task_tasks[i].tmpl->description)) + (strlen(task_tasks[i].tmpl->rulesfile) - pad[1]),
}
int main(int argc, char **argv) {
- bool succeed = false;
- char *redirout = (char*)stdout;
- char *redirerr = (char*)stderr;
- char *defs = NULL;
+ bool succeed = false;
+ char *defs = NULL;
con_init();
OPTS_OPTION_U16(OPTION_MEMDUMPCOLS) = 16;
--argc;
if (argv[0][0] == '-') {
- if (parsecmd("redirout", &argc, &argv, &redirout, 1, false))
- continue;
- if (parsecmd("redirerr", &argc, &argv, &redirerr, 1, false))
+ if (parsecmd("defs", &argc, &argv, &defs, 1, false))
continue;
- if (parsecmd("defs", &argc, &argv, &defs, 1, false))
- continue;
-
- con_change(redirout, redirerr);
if (!strcmp(argv[0]+1, "debug")) {
OPTS_OPTION_BOOL(OPTION_DEBUG) = true;
return -1;
}
}
- con_change(redirout, redirerr);
succeed = test_perform("tests", defs);
- stat_info();
return (succeed) ? EXIT_SUCCESS : EXIT_FAILURE;
}