X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=tools%2Fccanlint%2Ftests%2Fexamples_run.c;h=6c746b64a3722f362b6908f59abd4f39f1c5a5a5;hb=1ddb7420f1ac53c060aec62e26702d1d7029fc54;hp=7fe41654b443cdf28da5c7f6e910efc9d33e1d2e;hpb=f9423c171395571f9880286190d9cf63da147668;p=ccan diff --git a/tools/ccanlint/tests/examples_run.c b/tools/ccanlint/tests/examples_run.c index 7fe41654..6c746b64 100644 --- a/tools/ccanlint/tests/examples_run.c +++ b/tools/ccanlint/tests/examples_run.c @@ -1,8 +1,9 @@ #include #include -#include #include #include +#include +#include #include #include #include @@ -36,10 +37,10 @@ static bool scan_forv(const void *ctx, va_copy(ap, *args); - if (isspace(fmt[0])) { + if (cisspace(fmt[0])) { /* One format space can swallow many input spaces */ ret = false; - while (isspace(input[0])) { + while (cisspace(input[0])) { if (scan_forv(ctx, ++input, fmt+1, &ap)) { ret = true; break; @@ -59,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; } @@ -81,151 +82,113 @@ 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; + *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; + /* 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, "outputs '%s'", "outputs \"%s\"") { - if (scan_for(file, p, fmt, &expect)) { - *input = ""; - *exact = true; - return expect; - } + if (scan_for(file, p, "outputs \"%s\"", &expect)) { + *whitespace = true; + *contains = false; + 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; - } + if (scan_for(file, p, "output contains \"%s\"", &expect)) { + *whitespace = true; + *contains = true; + 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; - } + /* Whitespace-ignoring versions. */ + if (scan_for(file, p, "outputs %s", &expect)) { + *whitespace = false; + *contains = false; + 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; - } + if (scan_for(file, p, "output contains %s", &expect)) { + *whitespace = false; + *contains = true; + return expect; } - foreach_ptr(fmt, - "outputs '%s'", - "outputs \"%s\"", - "outputs %s") { - if (scan_for(file, p, fmt, &expect)) { - *input = ""; - *exact = true; - return expect; - } + /* Other malformed line? */ + if (*input || !strncasecmp(p, "output", strlen("output"))) { + *error = true; + return p; } - - foreach_ptr(fmt, - "output contains '%s'", - "output contains \"%s\"", - "output contains %s") { - if (scan_for(file, p, fmt, &expect)) { - *input = ""; - *exact = false; - return expect; - } - } - } + } 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 (exact) { - if (streq(output, expect) || streq(trim(output), expect)) + 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 (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, - unsigned int *timeleft, struct score *score) +static void run_examples(struct manifest *m, + unsigned int *timeleft UNNEEDED, struct score *score) { struct ccan_file *i; struct list_head *list; @@ -237,45 +200,54 @@ 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)) { - char *err; - score->total++; - 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; - output = unexpected(i, input, expect, exact); + score->total++; + output = unexpected(i, input, expect, + contains, whitespace); if (!output) { score->score++; continue; } - err = talloc_asprintf(score, - "output '%s' didn't" - " %s '%s'\n", - output, - exact - ? "match" : "contain", - expect); - score_file_error(score, i, linenum+1, err); + score_file_error(score, i, linenum+1, + "output '%s' didn't %s '%s'\n", + output, + contains ? "contain" : "match", + expect); score->pass = false; } } } } +/* FIXME: Test with reduced features, valgrind! */ struct ccanlint examples_run = { .key = "examples_run", .name = "Module examples with expected output give that output", .check = run_examples, .can_run = can_run, + .needs = "examples_compile" }; -REGISTER_TEST(examples_run, &examples_compile, NULL); +REGISTER_TEST(examples_run);