| #include "../../unity/unity.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <errno.h> |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| static char *testutil_build_no_line_fmt(int width, const char *sep) |
| { |
| size_t seplen = strlen(sep); |
| size_t len = (size_t)width + seplen; |
| char *s = (char *)malloc(len + 1); |
| if (!s) return NULL; |
| memset(s, ' ', (size_t)width); |
| memcpy(s + width, sep, seplen); |
| s[len] = '\0'; |
| return s; |
| } |
|
|
| |
| |
| static char *testutil_run_and_capture(const char *input) |
| { |
| FILE *in = tmpfile(); |
| if (!in) return NULL; |
|
|
| size_t inlen = strlen(input); |
| if (inlen > 0 && fwrite(input, 1, inlen, in) != inlen) { |
| fclose(in); |
| return NULL; |
| } |
| fflush(in); |
| rewind(in); |
|
|
| FILE *out = tmpfile(); |
| if (!out) { |
| fclose(in); |
| return NULL; |
| } |
|
|
| int stdout_fd = fileno(stdout); |
| int saved_fd = dup(stdout_fd); |
| if (saved_fd < 0) { |
| fclose(in); |
| fclose(out); |
| return NULL; |
| } |
|
|
| fflush(stdout); |
| if (dup2(fileno(out), stdout_fd) < 0) { |
| close(saved_fd); |
| fclose(in); |
| fclose(out); |
| return NULL; |
| } |
|
|
| |
| process_file(in); |
|
|
| |
| fflush(stdout); |
|
|
| |
| long sz = 0; |
| if (fseek(out, 0, SEEK_END) == 0) { |
| sz = ftell(out); |
| if (sz < 0) sz = 0; |
| fseek(out, 0, SEEK_SET); |
| } |
|
|
| char *buf = (char *)malloc((size_t)sz + 1); |
| if (!buf) { |
| |
| dup2(saved_fd, stdout_fd); |
| close(saved_fd); |
| fclose(in); |
| fclose(out); |
| return NULL; |
| } |
|
|
| size_t nread = 0; |
| if (sz > 0) { |
| nread = fread(buf, 1, (size_t)sz, out); |
| } |
| buf[nread] = '\0'; |
|
|
| |
| dup2(saved_fd, stdout_fd); |
| close(saved_fd); |
| fclose(in); |
| fclose(out); |
|
|
| return buf; |
| } |
|
|
| void setUp(void) { |
| |
| separator_str = "|"; |
| lineno_width = 2; |
| lineno_format = FORMAT_RIGHT_NOLZ; |
|
|
| starting_line_number = 1; |
| page_incr = 1; |
| reset_numbers = true; |
| blank_join = 1; |
|
|
| |
| body_type = "t"; |
| header_type = "n"; |
| footer_type = "n"; |
|
|
| |
| current_type = body_type; |
| current_regex = &body_regex; |
|
|
| |
| body_regex.buffer = NULL; |
| body_regex.allocated = 0; |
| body_regex.fastmap = body_fastmap; |
| body_regex.translate = NULL; |
|
|
| header_regex.buffer = NULL; |
| header_regex.allocated = 0; |
| header_regex.fastmap = header_fastmap; |
| header_regex.translate = NULL; |
|
|
| footer_regex.buffer = NULL; |
| footer_regex.allocated = 0; |
| footer_regex.fastmap = footer_fastmap; |
| footer_regex.translate = NULL; |
|
|
| |
| section_del = DEFAULT_SECTION_DELIMITERS; |
| header_del = NULL; |
| body_del = NULL; |
| footer_del = NULL; |
| header_del_len = 0; |
| body_del_len = 0; |
| footer_del_len = 0; |
|
|
| |
| line_no = starting_line_number; |
| line_no_overflow = false; |
|
|
| |
| if (print_no_line_fmt) { |
| free(print_no_line_fmt); |
| print_no_line_fmt = NULL; |
| } |
| print_no_line_fmt = testutil_build_no_line_fmt(lineno_width, separator_str); |
| } |
|
|
| void tearDown(void) { |
| if (print_no_line_fmt) { |
| free(print_no_line_fmt); |
| print_no_line_fmt = NULL; |
| } |
| } |
|
|
| |
| void test_process_file_numbers_nonempty_lines(void) |
| { |
| const char *input = "alpha\n\nbeta\n"; |
| char *out = testutil_run_and_capture(input); |
| TEST_ASSERT_NOT_NULL(out); |
|
|
| const char *expected = " 1|alpha\n" |
| " |\n" |
| " 2|beta\n"; |
| TEST_ASSERT_EQUAL_STRING(expected, out); |
| free(out); |
| } |
|
|
| |
| |
| void test_process_file_all_lines_with_blank_join(void) |
| { |
| current_type = "a"; |
| blank_join = 2; |
|
|
| |
| if (print_no_line_fmt) { free(print_no_line_fmt); } |
| print_no_line_fmt = testutil_build_no_line_fmt(lineno_width, separator_str); |
|
|
| const char *input = "\n\n\n"; |
| char *out = testutil_run_and_capture(input); |
| TEST_ASSERT_NOT_NULL(out); |
|
|
| const char *expected = " |\n" |
| " 1|\n" |
| " |\n"; |
| TEST_ASSERT_EQUAL_STRING(expected, out); |
| free(out); |
| } |
|
|
| |
| |
| void test_process_file_section_delimiters(void) |
| { |
| |
| section_del = "%%"; |
| header_del = "%%H"; |
| body_del = "%%B"; |
| footer_del = "%%F"; |
| header_del_len = strlen(header_del); |
| body_del_len = strlen(body_del); |
| footer_del_len = strlen(footer_del); |
|
|
| |
| header_type = "a"; |
| body_type = "t"; |
| current_type = body_type; |
|
|
| |
| if (print_no_line_fmt) { free(print_no_line_fmt); } |
| print_no_line_fmt = testutil_build_no_line_fmt(lineno_width, separator_str); |
|
|
| const char *input = "b1\n%%H\nh1\n%%B\nb2\n"; |
| char *out = testutil_run_and_capture(input); |
| TEST_ASSERT_NOT_NULL(out); |
|
|
| |
| |
| |
| |
| |
| |
| |
| const char *expected = " 1|b1\n" |
| "\n" |
| " 1|h1\n" |
| "\n" |
| " 1|b2\n"; |
| TEST_ASSERT_EQUAL_STRING(expected, out); |
| free(out); |
| } |
|
|
| |
| |
| void test_process_file_regex_numbering(void) |
| { |
| |
| body_regex.buffer = NULL; |
| body_regex.allocated = 0; |
| body_regex.fastmap = body_fastmap; |
| body_regex.translate = NULL; |
|
|
| |
| re_syntax_options = |
| RE_SYNTAX_POSIX_BASIC & ~RE_CONTEXT_INVALID_DUP & ~RE_NO_EMPTY_RANGES; |
|
|
| const char *pattern = "x"; |
| const char *errmsg = re_compile_pattern(pattern, strlen(pattern), &body_regex); |
| TEST_ASSERT_NULL_MESSAGE(errmsg, "Failed to compile regex pattern"); |
|
|
| current_type = "p"; |
| current_regex = &body_regex; |
|
|
| |
| if (print_no_line_fmt) { free(print_no_line_fmt); } |
| print_no_line_fmt = testutil_build_no_line_fmt(lineno_width, separator_str); |
|
|
| const char *input = "ax\nb\nx\n"; |
| char *out = testutil_run_and_capture(input); |
| TEST_ASSERT_NOT_NULL(out); |
|
|
| const char *expected = " 1|ax\n" |
| " |b\n" |
| " 2|x\n"; |
| TEST_ASSERT_EQUAL_STRING(expected, out); |
| free(out); |
| } |
|
|
| int main(void) |
| { |
| UNITY_BEGIN(); |
| RUN_TEST(test_process_file_numbers_nonempty_lines); |
| RUN_TEST(test_process_file_all_lines_with_blank_join); |
| RUN_TEST(test_process_file_section_delimiters); |
| RUN_TEST(test_process_file_regex_numbering); |
| return UNITY_END(); |
| } |