#include "../../unity/unity.h" #include #include #include #include #include #include #include /* The function under test is available due to inclusion in same TU: static void elseek_diagnostic (off_t offset, int whence, char const *filename); We'll call it directly below. */ /* Helpers to capture stderr output around a single call */ 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; } /* Redirect stderr to the pipe write end */ if (dup2(pipefd[1], STDERR_FILENO) < 0) { close(saved_stderr); close(pipefd[0]); close(pipefd[1]); return NULL; } close(pipefd[1]); /* Only fd 2 writes to the pipe now */ /* Set errno as desired and invoke function under test */ errno = errnum; elseek_diagnostic(offset, whence, filename); /* Flush and restore stderr */ fflush(stderr); if (dup2(saved_stderr, STDERR_FILENO) < 0) { /* Even if restore fails, attempt to read captured data */ } close(saved_stderr); /* Read all data from the pipe read end */ 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; /* EOF or error */ } close(pipefd[0]); /* NUL-terminate */ 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) { /* no-op */ } void tearDown(void) { /* no-op */ } 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); /* Expect the key phrase and the numeric offset */ TEST_ASSERT_TRUE_MESSAGE(contains_substr(out, "cannot seek to offset 123"), "Expected 'cannot seek to offset 123' in output"); /* Filename should appear (possibly quoted), so just search for raw name */ 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); /* Expect the key phrase and the numeric offset */ TEST_ASSERT_TRUE_MESSAGE(contains_substr(out, "cannot seek to relative offset 456"), "Expected 'cannot seek to relative offset 456' in output"); /* Filename should appear (possibly quoted) */ 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); /* Ensure the negative value is printed correctly */ TEST_ASSERT_TRUE_MESSAGE(contains_substr(out, "cannot seek to relative offset -5"), "Expected negative offset '-5' to appear correctly"); /* Filename presence */ 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(); }