diff --git a/tools/preprocess_pragmas.c b/tools/preprocess_pragmas.c index e31b863d07..5e750aab02 100644 --- a/tools/preprocess_pragmas.c +++ b/tools/preprocess_pragmas.c @@ -24,9 +24,14 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } char* const version = argv[1]; - const int len_version = strlen(version); char* const filename = argv[2]; + const size_t len_version = strlen(version); + char version_needle[len_version + 2]; + memcpy(version_needle, version, len_version); + version_needle[len_version] = ':'; + version_needle[len_version + 1] = '\0'; + char buf[32 * 1024]; char* const bufend = buf + sizeof(buf); char* bufp = buf; @@ -90,13 +95,8 @@ int main(int argc, char** argv) { } if (is_in_pragma) { *line_end = '\0'; - char* version_amount_item = strstr(line, version); + char* version_amount_item = strstr(line, version_needle); if (version_amount_item != NULL) { - if (version_amount_item[len_version] != ':') { - fprintf(stderr, "Found version %s in pragma line but no :amount attached\n", version); - fprintf(stderr, "%s\n", line); - return EXIT_FAILURE; - } char* version_amount_str_start = &version_amount_item[len_version + 1]; char* version_amount_str_end; long amount = strtol(version_amount_str_start, &version_amount_str_end, 10); diff --git a/tools/tests/README b/tools/tests/README new file mode 100644 index 0000000000..843622e417 --- /dev/null +++ b/tools/tests/README @@ -0,0 +1 @@ +This folder contains tests for the tools living in this repo. diff --git a/tools/tests/test_preprocess_pragmas.py b/tools/tests/test_preprocess_pragmas.py new file mode 100644 index 0000000000..16caf3fd62 --- /dev/null +++ b/tools/tests/test_preprocess_pragmas.py @@ -0,0 +1,107 @@ +import difflib +from pathlib import Path +import subprocess + + +# change to True to print output source on failed tests +PRINT_FAILED_OUTPUT = False + +PREPROCESS_PRAGMAS_P = Path("tools/preprocess_pragmas") + + +def fake_struct(pragma_line, i): + return f"struct increment_block_number_{pragma_line:05}_{i:03};" + + +def fake_structs(pragma_line, amount): + return "\n".join(fake_struct(pragma_line, i) for i in range(amount)) + + +data = { + "test_noarg": ( + "gc-us", + "source.c", + """\ +abc +#pragma increment_block_number +def +""", + f"""\ +abc +{fake_structs(2, 256)} +#line 3 "source.c" +def +""", + ), + "test_one_arg_match": ( + "gc-us", + "source.c", + """\ +abc +#pragma increment_block_number "gc-us:17" +def +""", + f"""\ +abc +{fake_structs(2, 17)} +#line 3 "source.c" +def +""", + ), + "test_one_arg_no_match": ( + "gc-us", + "source.c", + """\ +abc +#pragma increment_block_number "gc-us-mq:17" +def +""", + f"""\ +abc +{fake_structs(2, 256)} +#line 3 "source.c" +def +""", + ), + "test_several_args": ( + "gc-us", + "source.c", + """\ +abc +#pragma increment_block_number "gc-us-mq:200 gc-us:250" +def +""", + f"""\ +abc +{fake_structs(2, 250)} +#line 3 "source.c" +def +""", + ), +} + +for test_name, (version, filename, source_in, expected_source_out) in data.items(): + p = subprocess.Popen( + [str(PREPROCESS_PRAGMAS_P), version, filename], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + encoding="UTF-8", + ) + source_out, _ = p.communicate(input=source_in) + if p.returncode != 0: + print(f"{PREPROCESS_PRAGMAS_P} ended with {p.returncode} on {test_name}") + exit(1) + if source_out != expected_source_out: + print(f"failed test {test_name}") + if PRINT_FAILED_OUTPUT: + print(source_out) + for l in difflib.unified_diff( + expected_source_out.splitlines(), + source_out.splitlines(), + "expected output", + "actual output", + ): + print(l) + exit(1) + +print("all tests ok")