| | #include "../../unity/unity.h" |
| | #include <stdio.h> |
| | #include <stdlib.h> |
| | #include <string.h> |
| | #include <unistd.h> |
| | #include <errno.h> |
| |
|
| | |
| | |
| |
|
| | |
| |
|
| | static void test_prepare_stdin(const char *data) |
| | { |
| | int fds[2]; |
| | if (pipe(fds) != 0) { |
| | |
| | TEST_FAIL_MESSAGE("pipe() failed"); |
| | } |
| |
|
| | |
| | ssize_t len = (ssize_t)strlen(data); |
| | ssize_t written = 0; |
| | while (written < len) { |
| | ssize_t w = write(fds[1], data + written, len - written); |
| | if (w < 0) { |
| | close(fds[0]); |
| | close(fds[1]); |
| | TEST_FAIL_MESSAGE("write() to pipe failed"); |
| | } |
| | written += w; |
| | } |
| | close(fds[1]); |
| |
|
| | |
| | if (dup2(fds[0], STDIN_FILENO) < 0) { |
| | close(fds[0]); |
| | TEST_FAIL_MESSAGE("dup2() failed"); |
| | } |
| | close(fds[0]); |
| | } |
| |
|
| | |
| | static void test_remove_created_files(void) |
| | { |
| | |
| | |
| | if (files_created > 0) { |
| | for (int i = files_created - 1; i >= 0; --i) { |
| | const char *name = make_filename(i); |
| | unlink(name); |
| | } |
| | } |
| | files_created = 0; |
| | } |
| |
|
| | |
| | static char *test_slurp_file(const char *path) |
| | { |
| | FILE *fp = fopen(path, "rb"); |
| | if (!fp) return NULL; |
| | if (fseek(fp, 0, SEEK_END) != 0) { |
| | fclose(fp); |
| | return NULL; |
| | } |
| | long sz = ftell(fp); |
| | if (sz < 0) { |
| | fclose(fp); |
| | return NULL; |
| | } |
| | if (fseek(fp, 0, SEEK_SET) != 0) { |
| | fclose(fp); |
| | return NULL; |
| | } |
| | char *buf = (char *)malloc((size_t)sz + 1); |
| | if (!buf) { |
| | fclose(fp); |
| | return NULL; |
| | } |
| | size_t n = fread(buf, 1, (size_t)sz, fp); |
| | fclose(fp); |
| | buf[n] = '\0'; |
| | return buf; |
| | } |
| |
|
| | |
| | static void test_drain_all_input(void) |
| | { |
| | struct cstring *ln; |
| | while ((ln = remove_line()) != NULL) { |
| | (void)ln; |
| | } |
| | } |
| |
|
| | |
| | static char *test_argv_storage[4] = { (char *)"csplit", (char *)"/dummy/", (char *)"%dummy%", NULL }; |
| |
|
| | |
| | void setUp(void) { |
| | |
| | suppress_count = true; |
| | elide_empty_files = false; |
| | remove_files = false; |
| | suppress_matched = false; |
| |
|
| | |
| | if (!filename_space) { |
| | filename_space = (char *)malloc(512); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(filename_space, "malloc filename_space failed"); |
| | } |
| | prefix = "tstpr_"; |
| | suffix = NULL; |
| | digits = 2; |
| |
|
| | |
| | sigemptyset(&caught_signals); |
| |
|
| | |
| | head = NULL; |
| | if (hold_area) { free(hold_area); hold_area = NULL; } |
| | hold_count = 0; |
| | have_read_eof = false; |
| | last_line_number = 0; |
| | current_line = 0; |
| |
|
| | |
| | bytes_written = 0; |
| | output_stream = NULL; |
| | output_filename = NULL; |
| | files_created = 0; |
| |
|
| | |
| | global_argv = test_argv_storage; |
| | } |
| |
|
| | |
| | void tearDown(void) { |
| | |
| | close_output_file(); |
| |
|
| | |
| | test_drain_all_input(); |
| |
|
| | |
| | test_remove_created_files(); |
| |
|
| | |
| | head = NULL; |
| | if (hold_area) { free(hold_area); hold_area = NULL; } |
| | hold_count = 0; |
| | have_read_eof = false; |
| | last_line_number = 0; |
| | current_line = 0; |
| | } |
| |
|
| | |
| | static struct control *test_make_regexp_control(int argnum, const char *pattern_with_delims) |
| | { |
| | |
| | struct control *p = extract_regexp(argnum, (pattern_with_delims[0] == '%'), pattern_with_delims); |
| | return p; |
| | } |
| |
|
| | |
| | static const char *test_last_filename(void) |
| | { |
| | if (files_created <= 0) return NULL; |
| | return make_filename(files_created - 1); |
| | } |
| |
|
| | |
| |
|
| | static void test_process_regexp_match_no_offset_writes_preceding_lines(void) |
| | { |
| | |
| | const char *input = "one\nfoo\nbar\n"; |
| | test_prepare_stdin(input); |
| |
|
| | |
| | test_argv_storage[1] = (char *)"/foo/"; |
| | struct control *p = test_make_regexp_control(1, "/foo/"); |
| |
|
| | |
| | process_regexp(p, 0); |
| |
|
| | |
| | TEST_ASSERT_EQUAL_INT(1, files_created); |
| | const char *fname = test_last_filename(); |
| | TEST_ASSERT_NOT_NULL(fname); |
| | char *content = test_slurp_file(fname); |
| | TEST_ASSERT_NOT_NULL_MESSAGE(content, "Failed to read output file"); |
| | TEST_ASSERT_EQUAL_STRING("one\n", content); |
| | free(content); |
| | } |
| |
|
| | static void test_process_regexp_positive_offset_includes_matching_line(void) |
| | { |
| | const char *input = "a\nfoo\nc\n"; |
| | test_prepare_stdin(input); |
| |
|
| | |
| | test_argv_storage[1] = (char *)"/foo/+1"; |
| | struct control *p = test_make_regexp_control(1, "/foo/+1"); |
| |
|
| | process_regexp(p, 0); |
| |
|
| | TEST_ASSERT_EQUAL_INT(1, files_created); |
| | const char *fname = test_last_filename(); |
| | TEST_ASSERT_NOT_NULL(fname); |
| | char *content = test_slurp_file(fname); |
| | TEST_ASSERT_NOT_NULL(content); |
| | TEST_ASSERT_EQUAL_STRING("a\nfoo\n", content); |
| | free(content); |
| | } |
| |
|
| | static void test_process_regexp_ignore_true_creates_no_files(void) |
| | { |
| | const char *input = "a\nfoo\nb\n"; |
| | test_prepare_stdin(input); |
| |
|
| | |
| | test_argv_storage[2] = (char *)"%foo%"; |
| | struct control *p = test_make_regexp_control(2, "%foo%"); |
| |
|
| | process_regexp(p, 0); |
| |
|
| | TEST_ASSERT_EQUAL_INT(0, files_created); |
| | |
| | } |
| |
|
| | static void test_process_regexp_negative_offset_writes_up_to_before_previous_line(void) |
| | { |
| | const char *input = "a\nb\nc\nd\n"; |
| | test_prepare_stdin(input); |
| |
|
| | |
| | test_argv_storage[1] = (char *)"/c/-1"; |
| | struct control *p = test_make_regexp_control(1, "/c/-1"); |
| |
|
| | process_regexp(p, 0); |
| |
|
| | TEST_ASSERT_EQUAL_INT(1, files_created); |
| | const char *fname = test_last_filename(); |
| | TEST_ASSERT_NOT_NULL(fname); |
| | char *content = test_slurp_file(fname); |
| | TEST_ASSERT_NOT_NULL(content); |
| | TEST_ASSERT_EQUAL_STRING("a\n", content); |
| | free(content); |
| | } |
| |
|
| | static void test_process_regexp_suppress_matched_skips_matched_line(void) |
| | { |
| | const char *input = "before\nmatch\nafter\n"; |
| | test_prepare_stdin(input); |
| |
|
| | suppress_matched = true; |
| |
|
| | test_argv_storage[1] = (char *)"/match/"; |
| | struct control *p = test_make_regexp_control(1, "/match/"); |
| |
|
| | process_regexp(p, 0); |
| |
|
| | |
| | TEST_ASSERT_EQUAL_INT(1, files_created); |
| | const char *fname = test_last_filename(); |
| | TEST_ASSERT_NOT_NULL(fname); |
| | char *content = test_slurp_file(fname); |
| | TEST_ASSERT_NOT_NULL(content); |
| | TEST_ASSERT_EQUAL_STRING("before\n", content); |
| | free(content); |
| |
|
| | |
| | struct cstring *next = remove_line(); |
| | TEST_ASSERT_NOT_NULL(next); |
| | TEST_ASSERT_EQUAL_INT_MESSAGE((int)strlen("after\n"), (int)next->len, "Unexpected next line length"); |
| | TEST_ASSERT_EQUAL_INT(0, strncmp(next->str, "after\n", next->len)); |
| | } |
| |
|
| | |
| | int main(void) |
| | { |
| | UNITY_BEGIN(); |
| | RUN_TEST(test_process_regexp_match_no_offset_writes_preceding_lines); |
| | RUN_TEST(test_process_regexp_positive_offset_includes_matching_line); |
| | RUN_TEST(test_process_regexp_ignore_true_creates_no_files); |
| | RUN_TEST(test_process_regexp_negative_offset_writes_up_to_before_previous_line); |
| | RUN_TEST(test_process_regexp_suppress_matched_skips_matched_line); |
| | return UNITY_END(); |
| | } |