| #include "../../unity/unity.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <sys/stat.h> |
| #include <errno.h> |
| #include <limits.h> |
| #include <signal.h> |
|
|
| |
| |
|
|
| |
| static void split_file (void); |
|
|
| |
| static int start_files_created = 0; |
| static char test_prefix[64] = {0}; |
|
|
| |
| static char* create_temp_input_file(const char* content) { |
| char templ[] = "/tmp/csplit_test_input_XXXXXX"; |
| int fd = mkstemp(templ); |
| if (fd < 0) { |
| perror("mkstemp"); |
| return NULL; |
| } |
| size_t len = strlen(content); |
| if (len > 0) { |
| ssize_t w = write(fd, content, len); |
| if (w < 0 || (size_t)w != len) { |
| close(fd); |
| unlink(templ); |
| perror("write temp input"); |
| return NULL; |
| } |
| } |
| if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { |
| close(fd); |
| unlink(templ); |
| perror("lseek"); |
| return NULL; |
| } |
| close(fd); |
| return strdup(templ); |
| } |
|
|
| |
| |
| static char* read_file_contents(const char* path) { |
| struct stat st; |
| if (stat(path, &st) != 0) |
| return NULL; |
| size_t sz = (size_t)st.st_size; |
| FILE* f = fopen(path, "rb"); |
| if (!f) |
| return NULL; |
| char* buf = (char*)malloc(sz + 1); |
| if (!buf) { |
| fclose(f); |
| return NULL; |
| } |
| size_t r = fread(buf, 1, sz, f); |
| fclose(f); |
| if (r != sz) { |
| free(buf); |
| return NULL; |
| } |
| buf[sz] = '\0'; |
| return buf; |
| } |
|
|
| |
| |
| static const char* outfile_name_for_index(int i) { |
| |
| return make_filename(i); |
| } |
|
|
| |
| static void reset_input_state(void) { |
| |
| if (hold_area) { |
| free(hold_area); |
| hold_area = NULL; |
| } |
| hold_count = 0; |
| have_read_eof = false; |
| head = NULL; |
| last_line_number = 0; |
| current_line = 0; |
| } |
|
|
| |
| static void prepare_environment(void) { |
| |
| sigemptyset(&caught_signals); |
|
|
| |
| suppress_count = true; |
|
|
| |
| remove_files = false; |
| elide_empty_files = false; |
| suppress_matched = false; |
|
|
| |
| digits = 2; |
| suffix = NULL; |
|
|
| |
| if (!filename_space) { |
| filename_space = (char*)malloc(1024); |
| } |
|
|
| |
| if (test_prefix[0] == '\0') { |
| snprintf(test_prefix, sizeof(test_prefix), "utcs_%ld_", (long)getpid()); |
| } |
| prefix = test_prefix; |
|
|
| |
| reset_input_state(); |
|
|
| |
| start_files_created = files_created; |
| } |
|
|
| |
| static void cleanup_created_files(void) { |
| int end = files_created; |
| for (int i = start_files_created; i < end; i++) { |
| const char* name = outfile_name_for_index(i); |
| unlink(name); |
| } |
| files_created = start_files_created; |
| } |
|
|
| |
| void setUp(void) { |
| prepare_environment(); |
| } |
|
|
| void tearDown(void) { |
| cleanup_created_files(); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| void test_split_file_linecount_basic(void) { |
| const char* input = "a\nb\nc\nd\ne\n"; |
| char* path = create_temp_input_file(input); |
| TEST_ASSERT_NOT_NULL_MESSAGE(path, "Failed to create temp input"); |
|
|
| set_input_file(path); |
|
|
| |
| control_used = 0; |
| struct control* p = new_control_record(); |
| p->lines_required = 3; |
| p->argnum = 1; |
|
|
| |
| split_file(); |
|
|
| |
| int created = files_created - start_files_created; |
| TEST_ASSERT_EQUAL_INT_MESSAGE(2, created, "Expected exactly 2 output files"); |
|
|
| const char* f0 = outfile_name_for_index(start_files_created + 0); |
| const char* f1 = outfile_name_for_index(start_files_created + 1); |
|
|
| char* c0 = read_file_contents(f0); |
| char* c1 = read_file_contents(f1); |
|
|
| TEST_ASSERT_NOT_NULL_MESSAGE(c0, "Failed to read first output file"); |
| TEST_ASSERT_NOT_NULL_MESSAGE(c1, "Failed to read second output file"); |
|
|
| TEST_ASSERT_EQUAL_STRING("a\nb\n", c0); |
| TEST_ASSERT_EQUAL_STRING("c\nd\ne\n", c1); |
|
|
| free(c0); |
| free(c1); |
|
|
| unlink(path); |
| free(path); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| void test_split_file_regexp_basic(void) { |
| const char* input = "a\nb\nc\nd\ne\n"; |
| char* path = create_temp_input_file(input); |
| TEST_ASSERT_NOT_NULL_MESSAGE(path, "Failed to create temp input"); |
|
|
| set_input_file(path); |
|
|
| |
| control_used = 0; |
| struct control* p = extract_regexp(1, false, "/^c$/"); |
| (void)p; |
|
|
| |
| split_file(); |
|
|
| |
| int created = files_created - start_files_created; |
| TEST_ASSERT_EQUAL_INT_MESSAGE(2, created, "Expected exactly 2 output files"); |
|
|
| const char* f0 = outfile_name_for_index(start_files_created + 0); |
| const char* f1 = outfile_name_for_index(start_files_created + 1); |
|
|
| char* c0 = read_file_contents(f0); |
| char* c1 = read_file_contents(f1); |
|
|
| TEST_ASSERT_NOT_NULL_MESSAGE(c0, "Failed to read first output file"); |
| TEST_ASSERT_NOT_NULL_MESSAGE(c1, "Failed to read second output file"); |
|
|
| TEST_ASSERT_EQUAL_STRING("a\nb\n", c0); |
| TEST_ASSERT_EQUAL_STRING("c\nd\ne\n", c1); |
|
|
| free(c0); |
| free(c1); |
|
|
| unlink(path); |
| free(path); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| void test_split_file_regexp_suppress_matched(void) { |
| const char* input = "a\nb\nc\nd\ne\n"; |
| char* path = create_temp_input_file(input); |
| TEST_ASSERT_NOT_NULL_MESSAGE(path, "Failed to create temp input"); |
|
|
| set_input_file(path); |
|
|
| |
| control_used = 0; |
| struct control* p = extract_regexp(1, false, "/^c$/"); |
| (void)p; |
|
|
| |
| suppress_matched = true; |
|
|
| |
| split_file(); |
|
|
| |
| int created = files_created - start_files_created; |
| TEST_ASSERT_EQUAL_INT_MESSAGE(2, created, "Expected exactly 2 output files"); |
|
|
| const char* f0 = outfile_name_for_index(start_files_created + 0); |
| const char* f1 = outfile_name_for_index(start_files_created + 1); |
|
|
| char* c0 = read_file_contents(f0); |
| char* c1 = read_file_contents(f1); |
|
|
| TEST_ASSERT_NOT_NULL_MESSAGE(c0, "Failed to read first output file"); |
| TEST_ASSERT_NOT_NULL_MESSAGE(c1, "Failed to read second output file"); |
|
|
| TEST_ASSERT_EQUAL_STRING("a\nb\n", c0); |
| TEST_ASSERT_EQUAL_STRING("d\ne\n", c1); |
|
|
| free(c0); |
| free(c1); |
|
|
| unlink(path); |
| free(path); |
| } |
|
|
| int main(void) { |
| UNITY_BEGIN(); |
| RUN_TEST(test_split_file_linecount_basic); |
| RUN_TEST(test_split_file_regexp_basic); |
| RUN_TEST(test_split_file_regexp_suppress_matched); |
| return UNITY_END(); |
| } |