coreutils / tests /csplit /tests_for_read_input.c
AryaWu's picture
Upload folder using huggingface_hub
78d2150 verified
#include "../../unity/unity.h"
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/wait.h>
#include <signal.h>
/* Access to static globals/functions is available since this file is included
into the same translation unit after their definitions. */
static int saved_stdin_fd = -1;
/* Helper: set STDIN to the read end of a new pipe; return write end */
static int make_pipe_and_set_stdin(void) {
int fds[2];
if (pipe(fds) != 0) {
TEST_FAIL_MESSAGE("pipe() failed");
}
/* fds[0] is read end, fds[1] is write end */
if (dup2(fds[0], STDIN_FILENO) < 0) {
close(fds[0]);
close(fds[1]);
TEST_FAIL_MESSAGE("dup2() failed to set STDIN");
}
close(fds[0]); /* read end duplicated to STDIN; close original */
return fds[1]; /* return write end to caller */
}
void setUp(void) {
/* Save current STDIN so we can restore it after each test */
saved_stdin_fd = dup(STDIN_FILENO);
if (saved_stdin_fd < 0) {
TEST_FAIL_MESSAGE("dup(STDIN_FILENO) failed in setUp");
}
/* Reset EOF flag before each test */
have_read_eof = false;
/* Ensure caught_signals is an empty set to keep cleanup() safe if triggered */
sigemptyset(&caught_signals);
}
void tearDown(void) {
/* Restore STDIN */
if (saved_stdin_fd >= 0) {
if (dup2(saved_stdin_fd, STDIN_FILENO) < 0) {
TEST_FAIL_MESSAGE("dup2() failed restoring STDIN");
}
close(saved_stdin_fd);
saved_stdin_fd = -1;
}
}
/* Test: when max_n_bytes == 0, returns 0 and does not touch have_read_eof */
void test_read_input_zero_max_does_not_change_eof(void) {
have_read_eof = false;
char buf[4] = {0};
idx_t n = read_input(buf, 0);
TEST_ASSERT_EQUAL_INT(0, (int)n);
TEST_ASSERT_FALSE(have_read_eof);
have_read_eof = true;
n = read_input(buf, 0);
TEST_ASSERT_EQUAL_INT(0, (int)n);
TEST_ASSERT_TRUE(have_read_eof);
}
/* Test: reads available bytes and does not set EOF */
void test_read_input_reads_available_bytes(void) {
int w = make_pipe_and_set_stdin();
const char *msg = "hello world";
size_t len = strlen(msg);
ssize_t wr = write(w, msg, len);
close(w);
TEST_ASSERT_EQUAL_INT((int)len, (int)wr);
char buf[64];
memset(buf, 0, sizeof buf);
idx_t n = read_input(buf, (idx_t)sizeof buf);
TEST_ASSERT_EQUAL_INT((int)len, (int)n);
TEST_ASSERT_EQUAL_MEMORY(msg, buf, len);
TEST_ASSERT_FALSE(have_read_eof);
}
/* Test: EOF handling sets have_read_eof and returns 0; remains true on subsequent calls */
void test_read_input_sets_eof_when_no_data(void) {
int w = make_pipe_and_set_stdin();
/* No write; close writer to produce EOF */
close(w);
char buf[8];
idx_t n1 = read_input(buf, (idx_t)sizeof buf);
TEST_ASSERT_EQUAL_INT(0, (int)n1);
TEST_ASSERT_TRUE(have_read_eof);
/* Subsequent call should also return 0 and keep EOF true */
idx_t n2 = read_input(buf, (idx_t)sizeof buf);
TEST_ASSERT_EQUAL_INT(0, (int)n2);
TEST_ASSERT_TRUE(have_read_eof);
}
/* Test: bounded read respects max_n_bytes less than available data */
void test_read_input_respects_max_bytes_limit(void) {
int w = make_pipe_and_set_stdin();
const char *msg = "abcdef";
ssize_t wr = write(w, msg, 6);
close(w);
TEST_ASSERT_EQUAL_INT(6, (int)wr);
char buf[4] = {0};
idx_t n = read_input(buf, 3);
TEST_ASSERT_EQUAL_INT(3, (int)n);
TEST_ASSERT_EQUAL_MEMORY("abc", buf, 3);
TEST_ASSERT_FALSE(have_read_eof);
}
/* Test: error path when STDIN is invalid causes process to exit with EXIT_FAILURE.
Use fork to isolate the exit from the test runner. */
void test_read_input_on_bad_fd_exits_failure(void) {
fflush(stdout);
fflush(stderr);
pid_t pid = fork();
TEST_ASSERT_TRUE_MESSAGE(pid >= 0, "fork() failed");
if (pid == 0) {
/* Child: invalidate STDIN and call read_input */
sigemptyset(&caught_signals); /* ensure cleanup() uses a known signal set */
close(STDIN_FILENO);
char buf[1];
/* This should print an error and exit(EXIT_FAILURE) via cleanup_fatal */
(void)read_input(buf, 1);
/* If we get here, the function did not exit as expected */
_exit(0);
} else {
int status = 0;
pid_t wp = waitpid(pid, &status, 0);
TEST_ASSERT_EQUAL_INT_MESSAGE(pid, wp, "waitpid failed");
TEST_ASSERT_TRUE(WIFEXITED(status));
TEST_ASSERT_EQUAL_INT(EXIT_FAILURE, WEXITSTATUS(status));
}
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_read_input_zero_max_does_not_change_eof);
RUN_TEST(test_read_input_reads_available_bytes);
RUN_TEST(test_read_input_sets_eof_when_no_data);
RUN_TEST(test_read_input_respects_max_bytes_limit);
RUN_TEST(test_read_input_on_bad_fd_exits_failure);
return UNITY_END();
}