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