| #include "../../unity/unity.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdint.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
|
|
| |
| |
| |
|
|
| |
| extern FILE *in_stream; |
| extern char const *const *file_list; |
| extern char const *input_filename; |
| extern bool have_read_stdin; |
| extern intmax_t end_offset; |
| extern bool flag_dump_strings; |
|
|
| |
| extern bool open_next_file (void); |
| extern bool check_and_close (int in_errno); |
| extern bool skip (intmax_t n_skip); |
|
|
| |
| static char *create_temp_file_with_size(size_t size) { |
| char tmpl[] = "/tmp/od_skip_testXXXXXX"; |
| int fd = mkstemp(tmpl); |
| if (fd < 0) { |
| return NULL; |
| } |
|
|
| |
| size_t remaining = size; |
| char buf[4096]; |
| memset(buf, 'A', sizeof(buf)); |
|
|
| while (remaining > 0) { |
| size_t chunk = remaining < sizeof(buf) ? remaining : sizeof(buf); |
| ssize_t w = write(fd, buf, chunk); |
| if (w < 0) { |
| int e = errno; |
| close(fd); |
| unlink(tmpl); |
| errno = e; |
| return NULL; |
| } |
| remaining -= (size_t)w; |
| } |
|
|
| if (fsync(fd) != 0) { |
| |
| } |
|
|
| if (close(fd) != 0) { |
| unlink(tmpl); |
| return NULL; |
| } |
|
|
| |
| char *path = strdup(tmpl); |
| return path; |
| } |
|
|
| static long current_offset(FILE *f) { |
| off_t off = ftello(f); |
| if (off == (off_t)-1) return -1; |
| return (long)off; |
| } |
|
|
| void setUp(void) { |
| |
| in_stream = NULL; |
| have_read_stdin = false; |
| end_offset = -1; |
| flag_dump_strings = false; |
| } |
|
|
| void tearDown(void) { |
| |
| |
| |
| if (in_stream) { |
| check_and_close(0); |
| in_stream = NULL; |
| } |
| } |
|
|
| |
| static void test_skip_zero_no_stream(void) { |
| in_stream = NULL; |
| bool ok = skip(0); |
| TEST_ASSERT_TRUE(ok); |
| TEST_ASSERT_NULL(in_stream); |
| } |
|
|
| |
| static void test_skip_within_single_file_seek(void) { |
| char *p1 = create_temp_file_with_size(100000); |
| TEST_ASSERT_NOT_NULL_MESSAGE(p1, "failed to create temp file"); |
|
|
| |
| const char *flist[] = { p1, NULL }; |
| file_list = flist; |
|
|
| bool ok = open_next_file(); |
| TEST_ASSERT_TRUE(ok); |
| TEST_ASSERT_NOT_NULL(in_stream); |
| TEST_ASSERT_EQUAL_INT(0, current_offset(in_stream)); |
|
|
| ok = skip(12345); |
| TEST_ASSERT_TRUE(ok); |
| TEST_ASSERT_NOT_NULL(in_stream); |
| TEST_ASSERT_EQUAL_INT(12345, current_offset(in_stream)); |
|
|
| |
| check_and_close(0); |
|
|
| unlink(p1); |
| free(p1); |
| } |
|
|
| |
| |
| static void test_skip_across_two_files_boundary_seek_on_first(void) { |
| char *p1 = create_temp_file_with_size(5000); |
| char *p2 = create_temp_file_with_size(2000); |
| TEST_ASSERT_NOT_NULL(p1); |
| TEST_ASSERT_NOT_NULL(p2); |
|
|
| const char *flist[] = { p1, p2, NULL }; |
| file_list = flist; |
|
|
| bool ok = open_next_file(); |
| TEST_ASSERT_TRUE(ok); |
| TEST_ASSERT_NOT_NULL(in_stream); |
| TEST_ASSERT_EQUAL_INT(0, current_offset(in_stream)); |
|
|
| |
| ok = skip(5200); |
| TEST_ASSERT_TRUE(ok); |
|
|
| |
| TEST_ASSERT_NOT_NULL(in_stream); |
| long off = current_offset(in_stream); |
| TEST_ASSERT_EQUAL_INT(200, off); |
|
|
| |
| check_and_close(0); |
| unlink(p1); unlink(p2); |
| free(p1); free(p2); |
| } |
|
|
| |
| |
| static void test_skip_read_based_small_file(void) { |
| char *p1 = create_temp_file_with_size(10); |
| TEST_ASSERT_NOT_NULL(p1); |
|
|
| const char *flist[] = { p1, NULL }; |
| file_list = flist; |
|
|
| bool ok = open_next_file(); |
| TEST_ASSERT_TRUE(ok); |
| TEST_ASSERT_NOT_NULL(in_stream); |
| TEST_ASSERT_EQUAL_INT(0, current_offset(in_stream)); |
|
|
| ok = skip(6); |
| TEST_ASSERT_TRUE(ok); |
| TEST_ASSERT_EQUAL_INT(6, current_offset(in_stream)); |
|
|
| |
| check_and_close(0); |
| unlink(p1); |
| free(p1); |
| } |
|
|
| |
| |
| static void test_skip_exact_file_size_stays_on_first_at_eof(void) { |
| char *p1 = create_temp_file_with_size(1000); |
| char *p2 = create_temp_file_with_size(100); |
| TEST_ASSERT_NOT_NULL(p1); |
| TEST_ASSERT_NOT_NULL(p2); |
|
|
| const char *flist[] = { p1, p2, NULL }; |
| file_list = flist; |
|
|
| bool ok = open_next_file(); |
| TEST_ASSERT_TRUE(ok); |
| TEST_ASSERT_NOT_NULL(in_stream); |
|
|
| ok = skip(1000); |
| TEST_ASSERT_TRUE(ok); |
|
|
| |
| TEST_ASSERT_NOT_NULL(in_stream); |
| TEST_ASSERT_EQUAL_INT(1000, current_offset(in_stream)); |
|
|
| |
| check_and_close(0); |
| unlink(p1); unlink(p2); |
| free(p1); free(p2); |
| } |
|
|
| int main(void) { |
| UNITY_BEGIN(); |
|
|
| RUN_TEST(test_skip_zero_no_stream); |
| RUN_TEST(test_skip_within_single_file_seek); |
| RUN_TEST(test_skip_across_two_files_boundary_seek_on_first); |
| RUN_TEST(test_skip_read_based_small_file); |
| RUN_TEST(test_skip_exact_file_size_stays_on_first_at_eof); |
|
|
| return UNITY_END(); |
| } |