X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=tools%2Fccanlint%2Ftests%2Fexamples_run.c;h=3bdb655efcfb2fc3609392c0fef231ec8dff16d9;hp=5c06c263e5228ebc0fffaf9e19abdc9ce6f7503e;hb=b87f63cb8228c8fcbf760defdcf9e4c332da7667;hpb=caf366998b97b7cc29bc1f33c285feb2f5d33bff diff --git a/tools/ccanlint/tests/examples_run.c b/tools/ccanlint/tests/examples_run.c index 5c06c263..3bdb655e 100644 --- a/tools/ccanlint/tests/examples_run.c +++ b/tools/ccanlint/tests/examples_run.c @@ -1,8 +1,8 @@ #include #include -#include #include #include +#include #include #include #include @@ -60,7 +60,7 @@ static bool scan_forv(const void *ctx, for (len = 1; input[len-1]; len++) { ret = scan_forv(ctx, input + len, fmt+2, &ap); if (ret) { - *p = talloc_strndup(ctx, input, len); + *p = tal_strndup(ctx, input, len); ret = true; break; } @@ -82,150 +82,112 @@ static bool scan_for(const void *ctx, const char *input, const char *fmt, ...) } static char *find_expect(struct ccan_file *file, - char **lines, char **input, bool *exact, + char **lines, char **input, + bool *contains, bool *whitespace, bool *error, unsigned *line) { - char *expect; - const char *fmt; + char *rest, *expect; + *error = false; for (; lines[*line]; (*line)++) { char *p = lines[*line] + strspn(lines[*line], " \t"); if (!strstarts(p, "//")) continue; p += strspn(p, "/ "); - foreach_ptr(fmt, - "given '%s', outputs '%s'", - "given '%s' outputs '%s'", - "given \"%s\", outputs \"%s\"", - "given \"%s\" outputs \"%s\"") { - if (scan_for(file, p, fmt, input, &expect)) { - *exact = true; - return expect; - } - } - - foreach_ptr(fmt, - "given '%s', output contains '%s'", - "given '%s' output contains '%s'", - "given \"%s\", output contains \"%s\"", - "given \"%s\" output contains \"%s\"") { - if (scan_for(file, p, fmt, input, &expect)) { - *exact = false; - return expect; - } - } - foreach_ptr(fmt, "outputs '%s'", "outputs \"%s\"") { - if (scan_for(file, p, fmt, &expect)) { - *input = cast_const(char *, ""); - *exact = true; - return expect; + /* With or without input? */ + if (strncasecmp(p, "given", strlen("given")) == 0) { + /* Must be of form */ + if (!scan_for(file, p, "given \"%s\" %s", input, &p)) { + *error = true; + return p; } + } else { + *input = NULL; } - foreach_ptr(fmt, - "given '%s', output contains '%s'", - "given '%s' output contains '%s'", - "given \"%s\", output contains \"%s\"", - "given \"%s\" output contains \"%s\"") { - if (scan_for(file, p, fmt, input, &expect)) { - *exact = false; - return expect; - } + if (scan_for(file, p, "outputs \"%s\"", &expect)) { + *whitespace = true; + *contains = false; + return expect; } - /* Unquoted versions... we can get this wrong! */ - foreach_ptr(fmt, - "given %s, outputs '%s'", - "given '%s', outputs %s", - "given %s, outputs \"%s\"", - "given \"%s\", outputs %s", - "given %s, outputs %s", - "given %s outputs '%s'", - "given '%s' outputs %s", - "given %s outputs \"%s\"", - "given \"%s\" outputs %s", - "given %s outputs %s") { - if (scan_for(file, p, fmt, input, &expect)) { - *exact = true; - return expect; - } + if (scan_for(file, p, "output contains \"%s\"", &expect)) { + *whitespace = true; + *contains = true; + return expect; } - foreach_ptr(fmt, - "given %s, output contains '%s'", - "given '%s', output contains %s", - "given %s, output contains \"%s\"", - "given \"%s\", output contains %s", - "given %s, output contains %s", - "given %s output contains '%s'", - "given '%s' output contains %s", - "given %s output contains \"%s\"", - "given \"%s\" output contains %s", - "given %s output contains %s") { - if (scan_for(file, p, fmt, input, &expect)) { - *exact = false; - return expect; - } + /* Whitespace-ignoring versions. */ + if (scan_for(file, p, "outputs %s", &expect)) { + *whitespace = false; + *contains = false; + return expect; } - foreach_ptr(fmt, - "outputs '%s'", - "outputs \"%s\"", - "outputs %s") { - if (scan_for(file, p, fmt, &expect)) { - *input = cast_const(char *, ""); - *exact = true; - return expect; - } + if (scan_for(file, p, "output contains %s", &expect)) { + *whitespace = false; + *contains = true; + return expect; } - foreach_ptr(fmt, - "output contains '%s'", - "output contains \"%s\"", - "output contains %s") { - if (scan_for(file, p, fmt, &expect)) { - *input = cast_const(char *, ""); - *exact = false; - return expect; - } + /* Other malformed line? */ + if (*input || !strncasecmp(p, "output", strlen("output"))) { + *error = true; + return p; } - } + } return NULL; } -static char *trim(char *string) -{ - while (strends(string, "\n")) - string[strlen(string)-1] = '\0'; - return string; -} - static char *unexpected(struct ccan_file *i, const char *input, - const char *expect, bool exact) + const char *expect, bool contains, bool whitespace) { char *output, *cmd; + const char *p; bool ok; unsigned int default_time = default_timeout_ms; - cmd = talloc_asprintf(i, "echo '%s' | %s %s", - input, i->compiled, input); + if (input) + cmd = tal_fmt(i, "echo '%s' | %s %s", + input, i->compiled[COMPILE_NORMAL], input); + else + cmd = tal_fmt(i, "%s", i->compiled[COMPILE_NORMAL]); output = run_with_timeout(i, cmd, &ok, &default_time); if (!ok) - return talloc_asprintf(i, "Exited with non-zero status\n"); + return tal_fmt(i, "Exited with non-zero status\n"); + + /* Substitute \n */ + while ((p = strstr(expect, "\\n")) != NULL) { + expect = tal_fmt(cmd, "%.*s\n%s", (int)(p - expect), expect, + p+2); + } + + if (!whitespace) { + /* Normalize to spaces. */ + expect = tal_strjoin(cmd, + tal_strsplit(cmd, expect, " \n\t", + STR_NO_EMPTY), + " ", STR_NO_TRAIL); + output = tal_strjoin(cmd, + tal_strsplit(cmd, output, " \n\t", + STR_NO_EMPTY), + " ", STR_NO_TRAIL); + } - if (exact) { - if (streq(output, expect) || streq(trim(output), expect)) + if (contains) { + if (strstr(output, expect)) return NULL; } else { - if (strstr(output, expect)) + if (streq(output, expect)) return NULL; } + return output; } -static void run_examples(struct manifest *m, bool keep, +static void run_examples(struct manifest *m, unsigned int *timeleft, struct score *score) { struct ccan_file *i; @@ -238,21 +200,32 @@ static void run_examples(struct manifest *m, bool keep, list_for_each(list, i, list) { char **lines, *expect, *input, *output; unsigned int linenum = 0; - bool exact; + bool contains, whitespace, error; lines = get_ccan_file_lines(i); - for (expect = find_expect(i, lines, &input, &exact, + for (expect = find_expect(i, lines, &input, + &contains, &whitespace, &error, &linenum); expect; linenum++, expect = find_expect(i, lines, &input, - &exact, &linenum)) { - if (i->compiled == NULL) + &contains, &whitespace, + &error, &linenum)) { + if (error) { + score_file_error(score, i, linenum+1, + "Unparsable test line '%s'", + lines[linenum]); + score->pass = false; + break; + } + + if (i->compiled[COMPILE_NORMAL] == NULL) continue; score->total++; - output = unexpected(i, input, expect, exact); + output = unexpected(i, input, expect, + contains, whitespace); if (!output) { score->score++; continue; @@ -260,7 +233,7 @@ static void run_examples(struct manifest *m, bool keep, score_file_error(score, i, linenum+1, "output '%s' didn't %s '%s'\n", output, - exact ? "match" : "contain", + contains ? "contain" : "match", expect); score->pass = false; } @@ -268,6 +241,7 @@ static void run_examples(struct manifest *m, bool keep, } } +/* FIXME: Test with reduced features, valgrind! */ struct ccanlint examples_run = { .key = "examples_run", .name = "Module examples with expected output give that output",