|
|
#include "../../unity/unity.h" |
|
|
|
|
|
#include <errno.h> |
|
|
#include <sys/stat.h> |
|
|
#include <stddef.h> |
|
|
#include <stdint.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
int ret; |
|
|
int err; |
|
|
mode_t mode; |
|
|
} fstat_plan_t; |
|
|
|
|
|
static fstat_plan_t g_plan[16]; |
|
|
static int g_plan_len = 0; |
|
|
static int g_plan_idx = 0; |
|
|
static int g_fstat_call_count = 0; |
|
|
|
|
|
static void fstat_stub_reset(void) |
|
|
{ |
|
|
g_plan_len = 0; |
|
|
g_plan_idx = 0; |
|
|
g_fstat_call_count = 0; |
|
|
} |
|
|
|
|
|
static void fstat_stub_add(int ret, int err, mode_t mode) |
|
|
{ |
|
|
if (g_plan_len < (int)(sizeof g_plan / sizeof g_plan[0])) { |
|
|
g_plan[g_plan_len].ret = ret; |
|
|
g_plan[g_plan_len].err = err; |
|
|
g_plan[g_plan_len].mode = mode; |
|
|
g_plan_len++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int fstat(int fd, struct stat *st) |
|
|
{ |
|
|
(void)fd; |
|
|
g_fstat_call_count++; |
|
|
|
|
|
|
|
|
int ret = 0; |
|
|
int err = 0; |
|
|
mode_t mode = (mode_t) (S_IFREG | 0644); |
|
|
|
|
|
if (g_plan_idx < g_plan_len) { |
|
|
ret = g_plan[g_plan_idx].ret; |
|
|
err = g_plan[g_plan_idx].err; |
|
|
mode = g_plan[g_plan_idx].mode; |
|
|
g_plan_idx++; |
|
|
} |
|
|
|
|
|
errno = err; |
|
|
if (ret == 0 && st) { |
|
|
|
|
|
st->st_mode = mode; |
|
|
} |
|
|
return ret; |
|
|
} |
|
|
|
|
|
|
|
|
void setUp(void) |
|
|
{ |
|
|
fstat_stub_reset(); |
|
|
errno = 0; |
|
|
} |
|
|
|
|
|
void tearDown(void) |
|
|
{ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void test_ifstat_success_immediate(void) |
|
|
{ |
|
|
struct stat st; |
|
|
st.st_mode = 0; |
|
|
mode_t expect_mode = (mode_t)(S_IFREG | 0600); |
|
|
|
|
|
fstat_stub_add(0, 0, expect_mode); |
|
|
|
|
|
int rc = ifstat(123, &st); |
|
|
TEST_ASSERT_EQUAL_INT(0, rc); |
|
|
TEST_ASSERT_EQUAL_INT(expect_mode, st.st_mode); |
|
|
TEST_ASSERT_EQUAL_INT(1, g_fstat_call_count); |
|
|
} |
|
|
|
|
|
void test_ifstat_retries_once_on_EINTR_then_success(void) |
|
|
{ |
|
|
struct stat st; |
|
|
st.st_mode = 0; |
|
|
mode_t expect_mode = (mode_t)(S_IFDIR | 0755); |
|
|
|
|
|
fstat_stub_add(-1, EINTR, 0); |
|
|
fstat_stub_add(0, 0, expect_mode); |
|
|
|
|
|
int rc = ifstat(5, &st); |
|
|
TEST_ASSERT_EQUAL_INT(0, rc); |
|
|
TEST_ASSERT_EQUAL_INT(expect_mode, st.st_mode); |
|
|
TEST_ASSERT_EQUAL_INT(2, g_fstat_call_count); |
|
|
} |
|
|
|
|
|
void test_ifstat_retries_multiple_EINTR_then_success(void) |
|
|
{ |
|
|
struct stat st; |
|
|
st.st_mode = 0; |
|
|
mode_t expect_mode = (mode_t)(S_IFIFO | 0640); |
|
|
|
|
|
fstat_stub_add(-1, EINTR, 0); |
|
|
fstat_stub_add(-1, EINTR, 0); |
|
|
fstat_stub_add(-1, EINTR, 0); |
|
|
fstat_stub_add(0, 0, expect_mode); |
|
|
|
|
|
int rc = ifstat(7, &st); |
|
|
TEST_ASSERT_EQUAL_INT(0, rc); |
|
|
TEST_ASSERT_EQUAL_INT(expect_mode, st.st_mode); |
|
|
TEST_ASSERT_EQUAL_INT(4, g_fstat_call_count); |
|
|
} |
|
|
|
|
|
void test_ifstat_non_EINTR_error_propagates_no_retry(void) |
|
|
{ |
|
|
struct stat st; |
|
|
st.st_mode = 0xDEAD; |
|
|
|
|
|
fstat_stub_add(-1, ENOENT, 0); |
|
|
|
|
|
errno = 0; |
|
|
int rc = ifstat(9, &st); |
|
|
TEST_ASSERT_EQUAL_INT(-1, rc); |
|
|
TEST_ASSERT_EQUAL_INT(ENOENT, errno); |
|
|
TEST_ASSERT_EQUAL_INT(1, g_fstat_call_count); |
|
|
TEST_ASSERT_EQUAL_INT(0xDEAD, st.st_mode); |
|
|
} |
|
|
|
|
|
int main(void) |
|
|
{ |
|
|
UNITY_BEGIN(); |
|
|
RUN_TEST(test_ifstat_success_immediate); |
|
|
RUN_TEST(test_ifstat_retries_once_on_EINTR_then_success); |
|
|
RUN_TEST(test_ifstat_retries_multiple_EINTR_then_success); |
|
|
RUN_TEST(test_ifstat_non_EINTR_error_propagates_no_retry); |
|
|
return UNITY_END(); |
|
|
} |