coreutils / tests /join /tests_for_add_field.c
AryaWu's picture
Upload folder using huggingface_hub
78d2150 verified
#include "../../unity/unity.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
/* Helper: free all dynamically allocated outlist nodes and reset head/tail.
outlist_head and outlist_end are defined in the program under test. */
static void reset_outlist(void)
{
/* Free all nodes starting from the first real node. */
struct outlist *p = outlist_head.next;
while (p)
{
struct outlist *n = p->next;
free(p);
p = n;
}
/* Reset list to initial empty state. */
outlist_head.next = NULL;
outlist_end = &outlist_head;
}
/* Subprocess runner to check that invalid inputs are rejected.
Returns:
1 if child terminated abnormally (signal) or with non-zero exit.
0 if child exited normally with status 0 (unexpected).
On fork/wait errors, this test will assert-fail. */
static int run_child_expect_failure(int file, idx_t field)
{
fflush(stdout);
fflush(stderr);
pid_t pid = fork();
if (pid < 0)
{
TEST_FAIL_MESSAGE("fork failed");
return 0;
}
if (pid == 0)
{
/* Child: attempt invalid call. If it returns, exit 0 to signal failure. */
/* Ensure child's list state is independent due to copy-on-write; no need to cleanup. */
add_field(file, field);
_exit(0);
}
int status = 0;
pid_t w = waitpid(pid, &status, 0);
if (w < 0)
{
TEST_FAIL_MESSAGE("waitpid failed");
return 0;
}
if (WIFEXITED(status))
{
int code = WEXITSTATUS(status);
return code != 0; /* success if non-zero exit */
}
else if (WIFSIGNALED(status))
{
/* Aborted by a signal (e.g., SIGABRT). Treat as success. */
return 1;
}
/* Other cases are unexpected; treat as failure. */
return 0;
}
void setUp(void)
{
reset_outlist();
}
void tearDown(void)
{
reset_outlist();
}
/* Test: adding a single (file=0, field=0) node into empty list. */
static void test_add_field_single_zero_file_zero_field(void)
{
TEST_ASSERT_NULL(outlist_head.next);
TEST_ASSERT_EQUAL_PTR(&outlist_head, outlist_end);
add_field(0, 0);
TEST_ASSERT_NOT_NULL(outlist_head.next);
struct outlist *n1 = outlist_head.next;
TEST_ASSERT_EQUAL_INT(0, n1->file);
TEST_ASSERT_EQUAL(0, n1->field);
TEST_ASSERT_NULL(n1->next);
TEST_ASSERT_EQUAL_PTR(n1, outlist_end);
}
/* Test: appending multiple nodes maintains correct order and content. */
static void test_add_field_multiple_append_order_and_values(void)
{
add_field(1, 3);
add_field(2, 4);
add_field(1, 0);
struct outlist *n1 = outlist_head.next;
TEST_ASSERT_NOT_NULL(n1);
TEST_ASSERT_EQUAL_INT(1, n1->file);
TEST_ASSERT_EQUAL(3, n1->field);
struct outlist *n2 = n1->next;
TEST_ASSERT_NOT_NULL(n2);
TEST_ASSERT_EQUAL_INT(2, n2->file);
TEST_ASSERT_EQUAL(4, n2->field);
struct outlist *n3 = n2->next;
TEST_ASSERT_NOT_NULL(n3);
TEST_ASSERT_EQUAL_INT(1, n3->file);
TEST_ASSERT_EQUAL(0, n3->field);
TEST_ASSERT_NULL(n3->next);
TEST_ASSERT_EQUAL_PTR(n3, outlist_end);
}
/* Test: outlist_end updates correctly after each append. */
static void test_add_field_tail_updates_correctly(void)
{
TEST_ASSERT_EQUAL_PTR(&outlist_head, outlist_end);
add_field(1, 1);
struct outlist *n1 = outlist_head.next;
TEST_ASSERT_EQUAL_PTR(n1, outlist_end);
TEST_ASSERT_NULL(n1->next);
add_field(2, 2);
struct outlist *n2 = n1->next;
TEST_ASSERT_NOT_NULL(n2);
TEST_ASSERT_EQUAL_PTR(n2, outlist_end);
TEST_ASSERT_NULL(n2->next);
TEST_ASSERT_EQUAL_PTR(n2, outlist_head.next->next);
add_field(1, 99);
struct outlist *n3 = n2->next;
TEST_ASSERT_NOT_NULL(n3);
TEST_ASSERT_EQUAL_PTR(n3, outlist_end);
TEST_ASSERT_NULL(n3->next);
TEST_ASSERT_EQUAL_INT(1, n3->file);
TEST_ASSERT_EQUAL(99, n3->field);
}
/* Test: large field value is stored as-is. */
static void test_add_field_large_field_value(void)
{
idx_t big = (idx_t)123456789;
add_field(2, big);
struct outlist *n1 = outlist_head.next;
TEST_ASSERT_NOT_NULL(n1);
TEST_ASSERT_EQUAL_INT(2, n1->file);
TEST_ASSERT_EQUAL(big, n1->field);
TEST_ASSERT_EQUAL_PTR(n1, outlist_end);
}
/* Test: invalid file number should fail (affirm). */
static void test_add_field_invalid_file_number_fails(void)
{
/* Values not equal to 0,1,2 should trigger failure. */
int ok_neg = run_child_expect_failure(-1, 0);
int ok_3 = run_child_expect_failure(3, 0);
TEST_ASSERT_TRUE(ok_neg);
TEST_ASSERT_TRUE(ok_3);
}
/* Test: file=0 with non-zero field should fail (affirm). */
static void test_add_field_file_zero_with_nonzero_field_fails(void)
{
int ok = run_child_expect_failure(0, 1);
TEST_ASSERT_TRUE(ok);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_add_field_single_zero_file_zero_field);
RUN_TEST(test_add_field_multiple_append_order_and_values);
RUN_TEST(test_add_field_tail_updates_correctly);
RUN_TEST(test_add_field_large_field_value);
RUN_TEST(test_add_field_invalid_file_number_fails);
RUN_TEST(test_add_field_file_zero_with_nonzero_field_fails);
return UNITY_END();
}