|
|
#include "../../unity/unity.h" |
|
|
#include <unistd.h> |
|
|
#include <stdint.h> |
|
|
#include <inttypes.h> |
|
|
#include <limits.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static off_t get_pending_for_fd(int fd) { |
|
|
return cache_round(fd, 0); |
|
|
} |
|
|
|
|
|
|
|
|
static void reset_pending_for_fd(int fd) { |
|
|
off_t p = cache_round(fd, 0); |
|
|
if (p != 0) { |
|
|
off_t need = (off_t)IO_BUFSIZE - p; |
|
|
|
|
|
(void)cache_round(fd, need); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void assert_off_t_eq(off_t actual, intmax_t expected) { |
|
|
TEST_ASSERT_EQUAL_INT64((int64_t)expected, (int64_t)actual); |
|
|
} |
|
|
|
|
|
void setUp(void) { |
|
|
|
|
|
reset_pending_for_fd(STDIN_FILENO); |
|
|
reset_pending_for_fd(STDOUT_FILENO); |
|
|
} |
|
|
|
|
|
void tearDown(void) { |
|
|
|
|
|
reset_pending_for_fd(STDIN_FILENO); |
|
|
reset_pending_for_fd(STDOUT_FILENO); |
|
|
} |
|
|
|
|
|
|
|
|
void test_cache_round_initial_state(void) { |
|
|
TEST_ASSERT(IO_BUFSIZE > 0); |
|
|
|
|
|
off_t p_in = get_pending_for_fd(STDIN_FILENO); |
|
|
off_t p_out = get_pending_for_fd(STDOUT_FILENO); |
|
|
|
|
|
assert_off_t_eq(p_in, 0); |
|
|
assert_off_t_eq(p_out, 0); |
|
|
} |
|
|
|
|
|
|
|
|
void test_cache_round_accumulate_and_round_stdin(void) { |
|
|
TEST_ASSERT(IO_BUFSIZE > 1); |
|
|
|
|
|
off_t part1 = (off_t)(IO_BUFSIZE / 2); |
|
|
if (part1 == 0) part1 = 1; |
|
|
off_t part2 = (off_t)IO_BUFSIZE - part1; |
|
|
|
|
|
off_t r1 = cache_round(STDIN_FILENO, part1); |
|
|
assert_off_t_eq(r1, 0); |
|
|
assert_off_t_eq(get_pending_for_fd(STDIN_FILENO), part1); |
|
|
|
|
|
off_t r2 = cache_round(STDIN_FILENO, part2); |
|
|
assert_off_t_eq(r2, IO_BUFSIZE); |
|
|
assert_off_t_eq(get_pending_for_fd(STDIN_FILENO), 0); |
|
|
} |
|
|
|
|
|
|
|
|
void test_cache_round_independent_stdin_stdout(void) { |
|
|
|
|
|
off_t r_in1 = cache_round(STDIN_FILENO, 1); |
|
|
assert_off_t_eq(r_in1, 0); |
|
|
assert_off_t_eq(get_pending_for_fd(STDIN_FILENO), 1); |
|
|
|
|
|
|
|
|
assert_off_t_eq(get_pending_for_fd(STDOUT_FILENO), 0); |
|
|
|
|
|
|
|
|
off_t r_out1 = cache_round(STDOUT_FILENO, (off_t)IO_BUFSIZE + 3); |
|
|
assert_off_t_eq(r_out1, IO_BUFSIZE); |
|
|
assert_off_t_eq(get_pending_for_fd(STDOUT_FILENO), 3); |
|
|
|
|
|
|
|
|
assert_off_t_eq(get_pending_for_fd(STDIN_FILENO), 1); |
|
|
} |
|
|
|
|
|
|
|
|
void test_cache_round_len_zero_returns_pending(void) { |
|
|
|
|
|
off_t r = cache_round(STDIN_FILENO, 5); |
|
|
assert_off_t_eq(r, 0); |
|
|
|
|
|
off_t p1 = cache_round(STDIN_FILENO, 0); |
|
|
assert_off_t_eq(p1, 5); |
|
|
|
|
|
|
|
|
off_t p2 = cache_round(STDIN_FILENO, 0); |
|
|
assert_off_t_eq(p2, 5); |
|
|
} |
|
|
|
|
|
|
|
|
void test_cache_round_exact_multiple_returns_len_and_clears_pending(void) { |
|
|
off_t len = (off_t)IO_BUFSIZE * 3; |
|
|
off_t r = cache_round(STDIN_FILENO, len); |
|
|
assert_off_t_eq(r, len); |
|
|
assert_off_t_eq(get_pending_for_fd(STDIN_FILENO), 0); |
|
|
|
|
|
|
|
|
off_t r2 = cache_round(STDIN_FILENO, 2); |
|
|
assert_off_t_eq(r2, 0); |
|
|
assert_off_t_eq(get_pending_for_fd(STDIN_FILENO), 2); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void test_cache_round_overflow_behavior(void) { |
|
|
|
|
|
(void)cache_round(STDIN_FILENO, 1); |
|
|
assert_off_t_eq(get_pending_for_fd(STDIN_FILENO), 1); |
|
|
|
|
|
|
|
|
off_t r = cache_round(STDIN_FILENO, (off_t)INTMAX_MAX); |
|
|
|
|
|
intmax_t remainder = (intmax_t)(INTMAX_MAX % (intmax_t)IO_BUFSIZE); |
|
|
intmax_t expected_return = (intmax_t)INTMAX_MAX - remainder; |
|
|
|
|
|
assert_off_t_eq(r, expected_return); |
|
|
assert_off_t_eq(get_pending_for_fd(STDIN_FILENO), remainder); |
|
|
} |
|
|
|
|
|
int main(void) { |
|
|
UNITY_BEGIN(); |
|
|
|
|
|
RUN_TEST(test_cache_round_initial_state); |
|
|
RUN_TEST(test_cache_round_accumulate_and_round_stdin); |
|
|
RUN_TEST(test_cache_round_independent_stdin_stdout); |
|
|
RUN_TEST(test_cache_round_len_zero_returns_pending); |
|
|
RUN_TEST(test_cache_round_exact_multiple_returns_len_and_clears_pending); |
|
|
RUN_TEST(test_cache_round_overflow_behavior); |
|
|
|
|
|
return UNITY_END(); |
|
|
} |