* This will perform compilation and execution
* -fail
* This will perform compilation, but requires
- * the compilation to fail in order to succeed.
+ * the compilation to fail in order to succeed.
*
* This must be provided, this tag is NOT optional.
*
/*
* Create some padding for the description to align the
* printing of the rules file.
- */
+ */
if ((desclen = strlen(tmpl->description)) > pad[0])
pad[0] = desclen;
}
/*
* Create some padding for the printing to align the
* printing of the rules file to the console.
- */
+ */
if ((filepadd = strlen(fullfile)) > pad[1])
pad[1] = filepadd;
if (tmpl->comparematch)
con_err("template compile warning: %s erroneous tag `M:` when only failing\n", file);
} else if (!strcmp(tmpl->proceduretype, "-pp")) {
- if (!tmpl->executeflags)
+ if (tmpl->executeflags)
con_err("template compile warning: %s erroneous tag `E:` when only preprocessing\n", file);
if (!tmpl->comparematch) {
con_err("template compile error: %s missing `M:` tag (use `$null` for exclude)\n", file);
/*
* Only remove the log files if the test actually compiled otherwise
* forget about it (or if it didn't compile, and the procedure type
- * was set to -fail (meaning it shouldn't compile) .. stil remove)
+ * was set to -fail (meaning it shouldn't compile) .. stil remove)
*/
if (task_tasks[i].compiled || !strcmp(task_tasks[i].tmpl->proceduretype, "-fail")) {
if (remove(task_tasks[i].stdoutlogfile))
/*
* This executes the QCVM task for a specificly compiled progs.dat
* using the template passed into it for call-flags and user defined
- * messages.
+ * messages IF the procedure type is -execute, otherwise it matches
+ * the preprocessor output.
*/
-bool task_execute(task_template_t *tmpl, char ***line) {
+bool task_trymatch(task_template_t *tmpl, char ***line) {
bool success = true;
FILE *execute;
char buffer[4096];
memset (buffer,0,sizeof(buffer));
- /*
- * Drop the execution flags for the QCVM if none where
- * actually specified.
- */
- if (!strcmp(tmpl->executeflags, "$null")) {
- snprintf(buffer, sizeof(buffer), "%s %s",
- task_bins[TASK_EXECUTE],
- tmpl->tempfilename
+ if (strcmp(tmpl->proceduretype, "-pp")) {
+ /*
+ * Drop the execution flags for the QCVM if none where
+ * actually specified.
+ */
+ if (!strcmp(tmpl->executeflags, "$null")) {
+ snprintf(buffer, sizeof(buffer), "%s %s",
+ task_bins[TASK_EXECUTE],
+ tmpl->tempfilename
+ );
+ } else {
+ snprintf(buffer, sizeof(buffer), "%s %s %s",
+ task_bins[TASK_EXECUTE],
+ tmpl->executeflags,
+ tmpl->tempfilename
+ );
+ }
+
+ util_debug("TEST", "executing qcvm: `%s` [%s]\n",
+ tmpl->description,
+ buffer
);
+
+ execute = popen(buffer, "r");
+ if (!execute)
+ return false;
} else {
- 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")))
+ return false;
}
- util_debug("TEST", "executing qcvm: `%s` [%s]\n",
- tmpl->description,
- buffer
- );
-
- execute = popen(buffer, "r");
- if (!execute)
- return false;
-
/*
* Now lets read the lines and compare them to the matches we expect
* and handle accordingly.
if (strrchr(data, '\n'))
*strrchr(data, '\n') = '\0';
+ /*
+ * If data is just null now, that means the line was an empty
+ * one and for that, we just ignore it.
+ */
+ if (!*data)
+ continue;
+
if (vec_size(tmpl->comparematch) > compare) {
if (strcmp(data, tmpl->comparematch[compare++]))
success = false;
/*
* Copy to output vector for diagnostics if execution match
* fails.
- */
+ */
vec_push(*line, data);
/* reset */
mem_d(data);
data = NULL;
}
- pclose(execute);
+
+ if (strcmp(tmpl->proceduretype, "-pp"))
+ pclose(execute);
+ else
+ fs_file_close(execute);
+
return success;
}
const char *task_type(task_template_t *tmpl) {
if (!strcmp(tmpl->proceduretype, "-pp"))
- return "type: preprocessor test";
+ return "type: preprocessor";
if (!strcmp(tmpl->proceduretype, "-execute"))
- return "type: execution test";
+ return "type: execution";
if (!strcmp(tmpl->proceduretype, "-compile"))
- return "type: compile test";
- return "type: fail test";
+ return "type: compile";
+ return "type: fail";
}
/*
for (; i < vec_size(task_tasks); i++) {
memset(space[1], 0, sizeof(space[1]));
snprintf(space[1], sizeof(space[1]), "%d", (int)(i + 1));
-
+
con_out("test #%u %*s", i + 1, strlen(space[0]) - strlen(space[1]), "");
util_debug("TEST", "executing task: %d: %s\n", i, task_tasks[i].tmpl->description);
* Generate a task from thin air if it requires execution in
* the QCVM.
*/
- execute = !!(!strcmp(task_tasks[i].tmpl->proceduretype, "-execute"));
+ execute = !! (!strcmp(task_tasks[i].tmpl->proceduretype, "-execute")) ||
+ (!strcmp(task_tasks[i].tmpl->proceduretype, "-pp"));
/*
* We assume it compiled before we actually compiled :). On error
}
if (!task_tasks[i].compiled && strcmp(task_tasks[i].tmpl->proceduretype, "-fail")) {
- con_err("failure: `%s` (failed to compile) see %s.stdout and %s.stderr [%s]\n",
+ con_out("failure: `%s` %*s %*s\n",
task_tasks[i].tmpl->description,
- task_tasks[i].tmpl->tempfilename,
- task_tasks[i].tmpl->tempfilename,
- task_tasks[i].tmpl->rulesfile
+ (pad[0] + pad[1] - strlen(task_tasks[i].tmpl->description)) + (strlen(task_tasks[i].tmpl->rulesfile) - pad[1]),
+ task_tasks[i].tmpl->rulesfile,
+ (pad[1] + pad[2] - strlen(task_tasks[i].tmpl->rulesfile)) + (strlen("(failed to compile)") - pad[2]),
+ "(failed to compile)"
);
continue;
}
task_tasks[i].tmpl->rulesfile,
(pad[1] + pad[2] - strlen(task_tasks[i].tmpl->rulesfile)) + (strlen(task_type(task_tasks[i].tmpl)) - pad[2]),
task_type(task_tasks[i].tmpl)
-
+
);
continue;
}
/*
* If we made it here that concludes the task is to be executed
- * in the virtual machine.
+ * in the virtual machine (or the preprocessor output needs to
+ * be matched).
*/
- if (!task_execute(task_tasks[i].tmpl, &match)) {
+ if (!task_trymatch(task_tasks[i].tmpl, &match)) {
size_t d = 0;
- con_err("failure: `%s` (invalid results from execution) [%s]\n",
+ con_out("failure: `%s` %*s %*s\n",
task_tasks[i].tmpl->description,
- task_tasks[i].tmpl->rulesfile
+ (pad[0] + pad[1] - strlen(task_tasks[i].tmpl->description)) + (strlen(task_tasks[i].tmpl->rulesfile) - pad[1]),
+ task_tasks[i].tmpl->rulesfile,
+ (pad[1] + pad[2] - strlen(task_tasks[i].tmpl->rulesfile)) + (strlen(
+ (strcmp(task_tasks[i].tmpl->proceduretype, "-pp"))
+ ? "(invalid results from execution)"
+ : "(invalid results from preprocessing)"
+ ) - pad[2]),
+ (strcmp(task_tasks[i].tmpl->proceduretype, "-pp"))
+ ? "(invalid results from execution)"
+ : "(invalid results from preprocessing)"
);
/*
* handler for the all the given matches in the template file and
* what was actually returned from executing.
*/
- con_err(" Expected From %u Matches: (got %u Matches)\n",
+ con_out(" Expected From %u Matches: (got %u Matches)\n",
vec_size(task_tasks[i].tmpl->comparematch),
vec_size(match)
);
char *select = task_tasks[i].tmpl->comparematch[d];
size_t length = 40 - strlen(select);
- con_err(" Expected: \"%s\"", select);
+ con_out(" Expected: \"%s\"", select);
while (length --)
- con_err(" ");
- con_err("| Got: \"%s\"\n", (d >= vec_size(match)) ? "<<nothing else to compare>>" : match[d]);
+ con_out(" ");
+ con_out("| Got: \"%s\"\n", (d >= vec_size(match)) ? "<<nothing else to compare>>" : match[d]);
}
/*
* Print the non-expected out (since we are simply not expecting it)
* This will help track down bugs in template files that fail to match
* something.
- */
+ */
if (vec_size(match) > vec_size(task_tasks[i].tmpl->comparematch)) {
for (d = 0; d < vec_size(match) - vec_size(task_tasks[i].tmpl->comparematch); d++) {
- con_err(" Expected: Nothing | Got: \"%s\"\n",
+ con_out(" Expected: Nothing | Got: \"%s\"\n",
match[d + vec_size(task_tasks[i].tmpl->comparematch)]
);
}
}
-
+
for (j = 0; j < vec_size(match); j++)
mem_d(match[j]);
task_tasks[i].tmpl->rulesfile,
(pad[1] + pad[2] - strlen(task_tasks[i].tmpl->rulesfile)) + (strlen(task_type(task_tasks[i].tmpl))- pad[2]),
task_type(task_tasks[i].tmpl)
-
+
);
}
mem_d(data);
/*
* If the default definition file isn't set to anything. We will
* use the default_defs here, which is "defs.qc"
- */
+ */
if (!defs) {
defs = default_defs;
}
-
+
task_precleanup(curdir);
if (!task_propagate(curdir, pad, defs)) {