| #include "../../unity/unity.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <sys/types.h> |
|
|
| |
| |
| |
|
|
| |
| static char* capture_elseek_diagnostic(off_t offset, int whence, const char* filename, int errnum) |
| { |
| int saved_stderr = dup(STDERR_FILENO); |
| if (saved_stderr < 0) |
| return NULL; |
|
|
| int pipefd[2]; |
| if (pipe(pipefd) != 0) { |
| close(saved_stderr); |
| return NULL; |
| } |
|
|
| |
| if (dup2(pipefd[1], STDERR_FILENO) < 0) { |
| close(saved_stderr); |
| close(pipefd[0]); |
| close(pipefd[1]); |
| return NULL; |
| } |
| close(pipefd[1]); |
|
|
| |
| errno = errnum; |
| elseek_diagnostic(offset, whence, filename); |
|
|
| |
| fflush(stderr); |
| if (dup2(saved_stderr, STDERR_FILENO) < 0) { |
| |
| } |
| close(saved_stderr); |
|
|
| |
| size_t cap = 256; |
| size_t len = 0; |
| char *buf = (char*)malloc(cap); |
| if (!buf) { |
| close(pipefd[0]); |
| return NULL; |
| } |
|
|
| while (1) { |
| if (len + 128 > cap) { |
| size_t new_cap = cap * 2; |
| char *nb = (char*)realloc(buf, new_cap); |
| if (!nb) { |
| free(buf); |
| close(pipefd[0]); |
| return NULL; |
| } |
| buf = nb; |
| cap = new_cap; |
| } |
| ssize_t n = read(pipefd[0], buf + len, cap - len); |
| if (n > 0) { |
| len += (size_t)n; |
| continue; |
| } |
| break; |
| } |
| close(pipefd[0]); |
|
|
| |
| if (len == cap) { |
| char *nb = (char*)realloc(buf, cap + 1); |
| if (!nb) { |
| free(buf); |
| return NULL; |
| } |
| buf = nb; |
| } |
| buf[len] = '\0'; |
| return buf; |
| } |
|
|
| static int contains_substr(const char* haystack, const char* needle) |
| { |
| return haystack && needle && strstr(haystack, needle) != NULL; |
| } |
|
|
| void setUp(void) { |
| |
| } |
| void tearDown(void) { |
| |
| } |
|
|
| static void test_elseek_diagnostic_seek_set_message(void) |
| { |
| const char *fname = "foo.txt"; |
| off_t off = 123; |
| char *out = capture_elseek_diagnostic(off, SEEK_SET, fname, EINVAL); |
| TEST_ASSERT_NOT_NULL(out); |
|
|
| |
| TEST_ASSERT_TRUE_MESSAGE(contains_substr(out, "cannot seek to offset 123"), |
| "Expected 'cannot seek to offset 123' in output"); |
|
|
| |
| TEST_ASSERT_TRUE_MESSAGE(contains_substr(out, "foo.txt"), |
| "Expected filename to appear in output"); |
|
|
| free(out); |
| } |
|
|
| static void test_elseek_diagnostic_seek_cur_message(void) |
| { |
| const char *fname = "bar.dat"; |
| off_t off = 456; |
| char *out = capture_elseek_diagnostic(off, SEEK_CUR, fname, EFBIG); |
| TEST_ASSERT_NOT_NULL(out); |
|
|
| |
| TEST_ASSERT_TRUE_MESSAGE(contains_substr(out, "cannot seek to relative offset 456"), |
| "Expected 'cannot seek to relative offset 456' in output"); |
|
|
| |
| TEST_ASSERT_TRUE_MESSAGE(contains_substr(out, "bar.dat"), |
| "Expected filename to appear in output"); |
|
|
| free(out); |
| } |
|
|
| static void test_elseek_diagnostic_negative_offset_printed(void) |
| { |
| const char *fname = "neg.bin"; |
| off_t off = -5; |
| char *out = capture_elseek_diagnostic(off, SEEK_CUR, fname, EINVAL); |
| TEST_ASSERT_NOT_NULL(out); |
|
|
| |
| TEST_ASSERT_TRUE_MESSAGE(contains_substr(out, "cannot seek to relative offset -5"), |
| "Expected negative offset '-5' to appear correctly"); |
|
|
| |
| TEST_ASSERT_TRUE_MESSAGE(contains_substr(out, "neg.bin"), |
| "Expected filename to appear in output"); |
|
|
| free(out); |
| } |
|
|
| int main(void) |
| { |
| UNITY_BEGIN(); |
| RUN_TEST(test_elseek_diagnostic_seek_set_message); |
| RUN_TEST(test_elseek_diagnostic_seek_cur_message); |
| RUN_TEST(test_elseek_diagnostic_negative_offset_printed); |
| return UNITY_END(); |
| } |