|
|
#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(); |
|
|
} |