| #include "../../unity/unity.h" |
|
|
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <errno.h> |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
|
|
| |
| typedef struct { |
| int saved_fd; |
| int tmp_fd; |
| char path[64]; |
| } capture_ctx; |
|
|
| static int begin_capture(capture_ctx *ctx) { |
| strcpy(ctx->path, "/tmp/nl_cap_XXXXXX"); |
| ctx->tmp_fd = mkstemp(ctx->path); |
| if (ctx->tmp_fd < 0) return -1; |
|
|
| ctx->saved_fd = dup(fileno(stdout)); |
| if (ctx->saved_fd < 0) { |
| close(ctx->tmp_fd); |
| unlink(ctx->path); |
| return -1; |
| } |
|
|
| fflush(stdout); |
| if (dup2(ctx->tmp_fd, fileno(stdout)) < 0) { |
| close(ctx->tmp_fd); |
| close(ctx->saved_fd); |
| unlink(ctx->path); |
| return -1; |
| } |
| return 0; |
| } |
|
|
| |
| static char *end_capture(capture_ctx *ctx) { |
| fflush(stdout); |
|
|
| |
| dup2(ctx->saved_fd, fileno(stdout)); |
| close(ctx->saved_fd); |
|
|
| |
| struct stat st; |
| if (fstat(ctx->tmp_fd, &st) != 0) { |
| close(ctx->tmp_fd); |
| unlink(ctx->path); |
| return NULL; |
| } |
|
|
| off_t sz = st.st_size; |
| if (lseek(ctx->tmp_fd, 0, SEEK_SET) < 0) { |
| close(ctx->tmp_fd); |
| unlink(ctx->path); |
| return NULL; |
| } |
|
|
| char *buf = (char *)malloc((size_t)sz + 1); |
| if (!buf) { |
| close(ctx->tmp_fd); |
| unlink(ctx->path); |
| return NULL; |
| } |
|
|
| ssize_t rd = read(ctx->tmp_fd, buf, (size_t)sz); |
| if (rd < 0) { |
| free(buf); |
| close(ctx->tmp_fd); |
| unlink(ctx->path); |
| return NULL; |
| } |
| buf[rd] = '\0'; |
|
|
| close(ctx->tmp_fd); |
| unlink(ctx->path); |
| return buf; |
| } |
|
|
| |
| |
| static char *set_line(const char *s) { |
| size_t len = strlen(s); |
| char *copy = (char *)malloc(len); |
| memcpy(copy, s, len); |
| line_buf.buffer = copy; |
| line_buf.length = len; |
| return copy; |
| } |
|
|
| |
| static char *call_and_capture_proc_text(const char *content) { |
| capture_ctx ctx; |
| if (begin_capture(&ctx) != 0) { |
| return NULL; |
| } |
| char *mem = set_line(content); |
| |
| proc_text(); |
| char *out = end_capture(&ctx); |
| free(mem); |
| return out; |
| } |
|
|
| |
| |
| |
| static void reset_proc_text_static_state(void) { |
| const char *saved_type = current_type; |
| intmax_t saved_blank_join = blank_join; |
| char const *saved_sep = separator_str; |
| char const *saved_fmt = lineno_format; |
| int saved_width = lineno_width; |
| char const *saved_no_line_fmt = print_no_line_fmt; |
| intmax_t saved_line_no = line_no; |
| intmax_t saved_incr = page_incr; |
|
|
| current_type = "a"; |
| blank_join = 2; |
| separator_str = "|"; |
| lineno_format = FORMAT_RIGHT_NOLZ; |
| lineno_width = 2; |
| print_no_line_fmt = ""; |
| line_no = 1; |
| page_incr = 1; |
|
|
| capture_ctx ctx; |
| if (begin_capture(&ctx) == 0) { |
| char *mem = set_line("R\n"); |
| proc_text(); |
| char *d = end_capture(&ctx); |
| free(mem); |
| free(d); |
| } |
|
|
| |
| current_type = saved_type; |
| blank_join = saved_blank_join; |
| separator_str = saved_sep; |
| lineno_format = saved_fmt; |
| lineno_width = saved_width; |
| print_no_line_fmt = saved_no_line_fmt; |
| line_no = saved_line_no; |
| page_incr = saved_incr; |
| } |
|
|
| void setUp(void) { |
| |
| separator_str = "|"; |
| lineno_format = FORMAT_RIGHT_NOLZ; |
| lineno_width = 3; |
| page_incr = 1; |
| line_no = 1; |
| line_no_overflow = false; |
| print_no_line_fmt = "U"; |
| current_type = "n"; |
| blank_join = 1; |
| reset_proc_text_static_state(); |
| } |
|
|
| void tearDown(void) { |
| |
| } |
|
|
| |
| static void test_proc_text_a_blank_join_1(void) { |
| current_type = "a"; |
| blank_join = 1; |
| separator_str = "|"; |
| lineno_width = 3; |
| lineno_format = FORMAT_RIGHT_NOLZ; |
| print_no_line_fmt = "<>"; |
| line_no = 7; |
| page_incr = 1; |
|
|
| char *out1 = call_and_capture_proc_text("X\n"); |
| TEST_ASSERT_NOT_NULL(out1); |
| TEST_ASSERT_EQUAL_STRING(" 7|X\n", out1); |
| free(out1); |
| TEST_ASSERT_EQUAL_INT64(8, line_no); |
|
|
| char *out2 = call_and_capture_proc_text("\n"); |
| TEST_ASSERT_NOT_NULL(out2); |
| TEST_ASSERT_EQUAL_STRING(" 8|\n", out2); |
| free(out2); |
| TEST_ASSERT_EQUAL_INT64(9, line_no); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| static void test_proc_text_a_blank_join_gt1_sequence(void) { |
| current_type = "a"; |
| blank_join = 3; |
| separator_str = "|"; |
| lineno_width = 2; |
| lineno_format = FORMAT_RIGHT_NOLZ; |
| print_no_line_fmt = "U"; |
| line_no = 1; |
| page_incr = 1; |
|
|
| char *o1 = call_and_capture_proc_text("\n"); |
| TEST_ASSERT_NOT_NULL(o1); |
| TEST_ASSERT_EQUAL_STRING("U\n", o1); |
| free(o1); |
| TEST_ASSERT_EQUAL_INT64(1, line_no); |
|
|
| char *o2 = call_and_capture_proc_text("\n"); |
| TEST_ASSERT_NOT_NULL(o2); |
| TEST_ASSERT_EQUAL_STRING("U\n", o2); |
| free(o2); |
| TEST_ASSERT_EQUAL_INT64(1, line_no); |
|
|
| char *o3 = call_and_capture_proc_text("\n"); |
| TEST_ASSERT_NOT_NULL(o3); |
| TEST_ASSERT_EQUAL_STRING(" 1|\n", o3); |
| free(o3); |
| TEST_ASSERT_EQUAL_INT64(2, line_no); |
|
|
| char *o4 = call_and_capture_proc_text("\n"); |
| TEST_ASSERT_NOT_NULL(o4); |
| TEST_ASSERT_EQUAL_STRING("U\n", o4); |
| free(o4); |
| TEST_ASSERT_EQUAL_INT64(2, line_no); |
|
|
| char *o5 = call_and_capture_proc_text("abc\n"); |
| TEST_ASSERT_NOT_NULL(o5); |
| TEST_ASSERT_EQUAL_STRING(" 2|abc\n", o5); |
| free(o5); |
| TEST_ASSERT_EQUAL_INT64(3, line_no); |
| } |
|
|
| |
| static void test_proc_text_t_type(void) { |
| current_type = "t"; |
| print_no_line_fmt = "X"; |
| separator_str = "|"; |
| lineno_width = 2; |
| lineno_format = FORMAT_RIGHT_NOLZ; |
| line_no = 42; |
| page_incr = 1; |
|
|
| char *o1 = call_and_capture_proc_text("hello\n"); |
| TEST_ASSERT_NOT_NULL(o1); |
| TEST_ASSERT_EQUAL_STRING("42|hello\n", o1); |
| free(o1); |
| TEST_ASSERT_EQUAL_INT64(43, line_no); |
|
|
| char *o2 = call_and_capture_proc_text("\n"); |
| TEST_ASSERT_NOT_NULL(o2); |
| TEST_ASSERT_EQUAL_STRING("X\n", o2); |
| free(o2); |
| |
| TEST_ASSERT_EQUAL_INT64(43, line_no); |
| } |
|
|
| |
| static void test_proc_text_n_type(void) { |
| current_type = "n"; |
| print_no_line_fmt = "Z"; |
| separator_str = "|"; |
| lineno_width = 2; |
| lineno_format = FORMAT_RIGHT_NOLZ; |
| line_no = 5; |
| page_incr = 1; |
|
|
| char *o1 = call_and_capture_proc_text("q\n"); |
| TEST_ASSERT_NOT_NULL(o1); |
| TEST_ASSERT_EQUAL_STRING("Zq\n", o1); |
| free(o1); |
| TEST_ASSERT_EQUAL_INT64(5, line_no); |
|
|
| char *o2 = call_and_capture_proc_text("\n"); |
| TEST_ASSERT_NOT_NULL(o2); |
| TEST_ASSERT_EQUAL_STRING("Z\n", o2); |
| free(o2); |
| TEST_ASSERT_EQUAL_INT64(5, line_no); |
| } |
|
|
| |
| |
| static void test_proc_text_p_type_regex(void) { |
| |
| current_type = "p"; |
| current_regex = &body_regex; |
|
|
| |
| 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 *errmsg = re_compile_pattern("foo", strlen("foo"), &body_regex); |
| TEST_ASSERT_NULL_MESSAGE(errmsg, "Failed to compile regex pattern"); |
|
|
| print_no_line_fmt = "N"; |
| separator_str = "|"; |
| lineno_width = 2; |
| lineno_format = FORMAT_RIGHT_NOLZ; |
| line_no = 5; |
| page_incr = 1; |
|
|
| char *o1 = call_and_capture_proc_text("foo\n"); |
| TEST_ASSERT_NOT_NULL(o1); |
| TEST_ASSERT_EQUAL_STRING(" 5|foo\n", o1); |
| free(o1); |
| TEST_ASSERT_EQUAL_INT64(6, line_no); |
|
|
| char *o2 = call_and_capture_proc_text("bar\n"); |
| TEST_ASSERT_NOT_NULL(o2); |
| TEST_ASSERT_EQUAL_STRING("Nbar\n", o2); |
| free(o2); |
| TEST_ASSERT_EQUAL_INT64(6, line_no); |
| } |
|
|
| |
| static void test_proc_text_page_incr(void) { |
| current_type = "a"; |
| blank_join = 1; |
| separator_str = "|"; |
| lineno_width = 3; |
| lineno_format = FORMAT_RIGHT_NOLZ; |
| print_no_line_fmt = ""; |
| line_no = 10; |
| page_incr = 10; |
|
|
| char *o = call_and_capture_proc_text("X\n"); |
| TEST_ASSERT_NOT_NULL(o); |
| TEST_ASSERT_EQUAL_STRING(" 10|X\n", o); |
| free(o); |
| TEST_ASSERT_EQUAL_INT64(20, line_no); |
| } |
|
|
| int main(void) { |
| UNITY_BEGIN(); |
|
|
| RUN_TEST(test_proc_text_a_blank_join_1); |
| RUN_TEST(test_proc_text_a_blank_join_gt1_sequence); |
| RUN_TEST(test_proc_text_t_type); |
| RUN_TEST(test_proc_text_n_type); |
| RUN_TEST(test_proc_text_p_type_regex); |
| RUN_TEST(test_proc_text_page_incr); |
|
|
| return UNITY_END(); |
| } |