coreutils / tests /cut /tests_for_cut_file.c
AryaWu's picture
Upload folder using huggingface_hub
78d2150 verified
#include "../../unity/unity.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
/* Test-helper state */
static FILE *test_last_stream_seen = NULL;
static int test_callback_invoked = 0;
static size_t test_bytes_read = 0;
/* Prototypes of target under test are available since this file is included
into the same translation unit as cut_file. We can call cut_file directly. */
/* Helper: create a temporary file with the given content, return malloc'ed path. */
static char *make_temp_file_with_content(const char *content)
{
char tmp_template[] = "/tmp/cut_ut_XXXXXX";
int fd = mkstemp(tmp_template);
TEST_ASSERT_MESSAGE(fd >= 0, "mkstemp failed");
size_t len = strlen(content);
if (len > 0)
{
ssize_t w = write(fd, content, len);
TEST_ASSERT_MESSAGE(w == (ssize_t)len, "write failed to write all content");
}
int rc = close(fd);
TEST_ASSERT_MESSAGE(rc == 0, "close(temp file) failed");
/* Return a heap-allocated copy of the path so caller can free it. */
char *path = (char *)malloc(strlen(tmp_template) + 1);
TEST_ASSERT_NOT_NULL(path);
strcpy(path, tmp_template);
return path;
}
/* Helper: reopen stdin from given path. */
static void reopen_stdin_from_path(const char *path)
{
FILE *f = freopen(path, "r", stdin);
TEST_ASSERT_MESSAGE(f != NULL, "freopen on stdin failed");
}
/* cut_stream callback that reads all bytes from the given stream */
static void test_cut_stream_read_all(FILE *s)
{
test_callback_invoked++;
test_last_stream_seen = s;
test_bytes_read = 0;
int ch;
while ((ch = getc(s)) != EOF)
{
test_bytes_read++;
}
}
/* cut_stream callback that does nothing */
static void test_cut_stream_noop(FILE *s)
{
(void)s;
test_callback_invoked++;
test_last_stream_seen = s;
}
/* Unity fixtures */
void setUp(void)
{
test_last_stream_seen = NULL;
test_callback_invoked = 0;
test_bytes_read = 0;
errno = 0;
/* Reset the program's internal flag before each test. */
/* have_read_stdin is defined in the production code above, static at file scope.
Since this test is included in the same translation unit, we can access it. */
extern bool have_read_stdin; /* forward declaration to appease some compilers */
have_read_stdin = false;
/* Ensure stdin has no error/eof flags set */
clearerr(stdin);
}
void tearDown(void)
{
/* Nothing special */
}
/* Test: Using "-" uses stdin, sets have_read_stdin, invokes callback, and clears EOF */
static void test_cut_file_stdin_reads_and_clears_eof(void)
{
/* Prepare stdin with some data */
char *p = make_temp_file_with_content("ABC");
reopen_stdin_from_path(p);
extern bool have_read_stdin;
bool ok = cut_file("-", test_cut_stream_read_all);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_TRUE(have_read_stdin);
TEST_ASSERT_EQUAL_INT(1, test_callback_invoked);
TEST_ASSERT_EQUAL_PTR(stdin, test_last_stream_seen);
TEST_ASSERT_EQUAL_UINT32(3u, (unsigned) test_bytes_read);
/* Because cut_file clears errors and EOF on stdin, feof(stdin) must be false */
TEST_ASSERT_FALSE(feof(stdin));
free(p);
}
/* Test: Regular file path is opened, callback sees that FILE*, and success is returned */
static void test_cut_file_regular_file_success(void)
{
char *p = make_temp_file_with_content("xyz123");
extern bool have_read_stdin;
bool ok = cut_file(p, test_cut_stream_read_all);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_FALSE(have_read_stdin);
TEST_ASSERT_EQUAL_INT(1, test_callback_invoked);
TEST_ASSERT_NOT_NULL(test_last_stream_seen);
/* For a regular file, cut_file opens its own stream, which must not be stdin */
TEST_ASSERT_NOT_EQUAL_PTR(stdin, test_last_stream_seen);
TEST_ASSERT_EQUAL_UINT32(6u, (unsigned) test_bytes_read);
/* Clean up the temporary file */
int rc = unlink(p);
(void)rc; /* Ignore unlink failure on platforms that restrict deleting open files */
free(p);
}
/* Test: Nonexistent file returns false and does not invoke the callback */
static void test_cut_file_nonexistent_returns_false(void)
{
const char *nonexistent = "/tmp/cut_ut_no_such_file____XXXX";
extern bool have_read_stdin;
bool ok = cut_file(nonexistent, test_cut_stream_noop);
TEST_ASSERT_FALSE(ok);
TEST_ASSERT_EQUAL_INT(0, test_callback_invoked);
TEST_ASSERT_FALSE(have_read_stdin);
}
/* Test: Using "-" without reading still sets have_read_stdin and returns true */
static void test_cut_file_stdin_no_read_sets_flag(void)
{
/* Prepare stdin with empty file */
char *p = make_temp_file_with_content("");
reopen_stdin_from_path(p);
extern bool have_read_stdin;
bool ok = cut_file("-", test_cut_stream_noop);
TEST_ASSERT_TRUE(ok);
TEST_ASSERT_TRUE(have_read_stdin);
TEST_ASSERT_EQUAL_INT(1, test_callback_invoked);
TEST_ASSERT_EQUAL_PTR(stdin, test_last_stream_seen);
/* No read was performed, but also no EOF should be set after clearerr */
TEST_ASSERT_FALSE(feof(stdin));
free(p);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_cut_file_stdin_reads_and_clears_eof);
RUN_TEST(test_cut_file_regular_file_success);
RUN_TEST(test_cut_file_nonexistent_returns_false);
RUN_TEST(test_cut_file_stdin_no_read_sets_flag);
return UNITY_END();
}