X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=test.c;h=6987bb3f6af9bd0b435d13c3bd60806fd65067b8;hp=d4af984ab37d0da3d6bdc622663e944f4fdc9120;hb=489ad486bcbb04da48715c4f59aa3da8dd5983a6;hpb=79282bfee009ecbf32dd77e56e470d872c222421 diff --git a/test.c b/test.c old mode 100644 new mode 100755 index d4af984..6987bb3 --- a/test.c +++ b/test.c @@ -210,7 +210,7 @@ int task_pclose(FILE **handles) { * 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. * @@ -329,7 +329,7 @@ bool task_template_generate(task_template_t *tmpl, char tag, const char *file, s /* * Create some padding for the description to align the * printing of the rules file. - */ + */ if ((desclen = strlen(tmpl->description)) > pad[0]) pad[0] = desclen; } @@ -488,7 +488,7 @@ task_template_t *task_template_compile(const char *file, const char *dir, size_t FILE *tempfile = NULL; task_template_t *tmpl = NULL; - snprintf(fullfile, sizeof(fullfile), "%s/%s", dir, file); + util_snprintf(fullfile, sizeof(fullfile), "%s/%s", dir, file); tempfile = fs_file_open(fullfile, "r"); tmpl = (task_template_t*)mem_a(sizeof(task_template_t)); @@ -497,7 +497,7 @@ task_template_t *task_template_compile(const char *file, const char *dir, size_t /* * 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; @@ -568,7 +568,7 @@ task_template_t *task_template_compile(const char *file, const char *dir, size_t 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); @@ -657,7 +657,7 @@ bool task_propagate(const char *curdir, size_t *pad, const char *defs) { dir = fs_dir_open(curdir); while ((files = fs_dir_read(dir))) { - snprintf(buffer, sizeof(buffer), "%s/%s", curdir, files->d_name); + util_snprintf(buffer, sizeof(buffer), "%s/%s", curdir, files->d_name); if (stat(buffer, &directory) == -1) { con_err("internal error: stat failed, aborting\n"); @@ -697,7 +697,16 @@ bool task_propagate(const char *curdir, size_t *pad, const char *defs) { * to test compile flags for all tests. This needs to be * BEFORE other flags (so that the .tmpl can override them) */ + #ifdef _MSC_VER + { + char buffer[4096]; + size_t size; + getenv_s(&size, buffer, sizeof(buffer), "QCFLAGS"); + qcflags = buffer; + } + #else qcflags = getenv("QCFLAGS"); + #endif /* * Generate the command required to open a pipe to a process @@ -707,7 +716,7 @@ bool task_propagate(const char *curdir, size_t *pad, const char *defs) { if (strcmp(tmpl->proceduretype, "-pp")) { if (qcflags) { if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) { - 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], curdir, tmpl->sourcefile, @@ -716,7 +725,7 @@ bool task_propagate(const char *curdir, size_t *pad, const char *defs) { tmpl->tempfilename ); } else { - 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, @@ -729,7 +738,7 @@ bool task_propagate(const char *curdir, size_t *pad, const char *defs) { } } else { if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) { - 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], curdir, tmpl->sourcefile, @@ -737,7 +746,7 @@ bool task_propagate(const char *curdir, size_t *pad, const char *defs) { tmpl->tempfilename ); } else { - 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, @@ -751,14 +760,14 @@ bool task_propagate(const char *curdir, size_t *pad, const char *defs) { } else { /* Preprocessing (qcflags mean shit all here we don't allow them) */ if (tmpl->testflags && !strcmp(tmpl->testflags, "-no-defs")) { - snprintf(buf, sizeof(buf), "%s -E %s/%s -o %s", + util_snprintf(buf, sizeof(buf), "%s -E %s/%s -o %s", task_bins[TASK_COMPILE], curdir, tmpl->sourcefile, tmpl->tempfilename ); } else { - snprintf(buf, sizeof(buf), "%s -E %s/%s %s/%s -o %s", + util_snprintf(buf, sizeof(buf), "%s -E %s/%s %s/%s -o %s", task_bins[TASK_COMPILE], curdir, defs, @@ -786,14 +795,14 @@ bool task_propagate(const char *curdir, size_t *pad, const char *defs) { * Open up some file desciptors for logging the stdout/stderr * to our own. */ - 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"))) { con_err("error opening %s for stdout\n", buf); continue; } - 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"))) { con_err("error opening %s for stderr\n", buf); @@ -829,7 +838,7 @@ void task_precleanup(const char *curdir) { strstr(files->d_name, ".stdout") || strstr(files->d_name, ".stderr")) { - 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); else @@ -859,7 +868,7 @@ void task_destroy(void) { /* * 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)) @@ -886,10 +895,12 @@ void task_destroy(void) { /* * 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; + bool preprocessing = false; FILE *execute; char buffer[4096]; memset (buffer,0,sizeof(buffer)); @@ -900,12 +911,12 @@ bool task_execute(task_template_t *tmpl, char ***line) { * actually specified. */ if (!strcmp(tmpl->executeflags, "$null")) { - snprintf(buffer, sizeof(buffer), "%s %s", + util_snprintf(buffer, sizeof(buffer), "%s %s", task_bins[TASK_EXECUTE], tmpl->tempfilename ); } else { - snprintf(buffer, sizeof(buffer), "%s %s %s", + util_snprintf(buffer, sizeof(buffer), "%s %s %s", task_bins[TASK_EXECUTE], tmpl->executeflags, tmpl->tempfilename @@ -927,6 +938,8 @@ bool task_execute(task_template_t *tmpl, char ***line) { */ if (!(execute = fs_file_open(tmpl->tempfilename, "r"))) return false; + + preprocessing = true; } /* @@ -943,7 +956,10 @@ bool task_execute(task_template_t *tmpl, char ***line) { tmpl->description, tmpl->rulesfile ); - pclose(execute); + if (preprocessing) + fs_file_close(execute); + else + pclose(execute); return false; } @@ -954,6 +970,13 @@ bool task_execute(task_template_t *tmpl, char ***line) { 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; @@ -964,7 +987,7 @@ bool task_execute(task_template_t *tmpl, char ***line) { /* * Copy to output vector for diagnostics if execution match * fails. - */ + */ vec_push(*line, data); /* reset */ @@ -975,7 +998,7 @@ bool task_execute(task_template_t *tmpl, char ***line) { data = NULL; } - if (strcmp(tmpl->proceduretype, "-pp")) + if (!preprocessing) pclose(execute); else fs_file_close(execute); @@ -985,12 +1008,12 @@ bool task_execute(task_template_t *tmpl, char ***line) { 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"; } /* @@ -1009,12 +1032,12 @@ void task_schedualize(size_t *pad) { size_t i = 0; size_t j = 0; - 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])); - 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]), ""); util_debug("TEST", "executing task: %d: %s\n", i, task_tasks[i].tmpl->description); @@ -1022,7 +1045,8 @@ void task_schedualize(size_t *pad) { * 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 @@ -1060,19 +1084,16 @@ void task_schedualize(size_t *pad) { } 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; } - if (!strcmp(task_tasks[i].tmpl->proceduretype, "-pp")) { - /* this is a pain */ - } - if (!execute) { con_out("succeeded: `%s` %*s %*s\n", task_tasks[i].tmpl->description, @@ -1080,21 +1101,31 @@ void task_schedualize(size_t *pad) { 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)" ); /* @@ -1102,7 +1133,7 @@ void task_schedualize(size_t *pad) { * 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) ); @@ -1110,25 +1141,25 @@ void task_schedualize(size_t *pad) { 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)) ? "<>" : match[d]); + con_out(" "); + con_out("| Got: \"%s\"\n", (d >= vec_size(match)) ? "<>" : 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]); @@ -1145,7 +1176,7 @@ void task_schedualize(size_t *pad) { 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); @@ -1176,11 +1207,11 @@ GMQCC_WARN bool test_perform(const char *curdir, const char *defs) { /* * 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)) {