coreutils / tests /csplit /tests_for_save_buffer.c
AryaWu's picture
Upload folder using huggingface_hub
78d2150 verified
#include "../../unity/unity.h"
#include <stdlib.h>
#include <string.h>
/* We rely on the definitions from the included program:
- static struct buffer_record *head;
- static void save_buffer(struct buffer_record *buf);
- struct buffer_record and struct line definitions.
Since this file is included into the same translation unit,
we can access them directly. */
/* Helper to allocate and zero a line node */
static struct line* helper_alloc_line(void) {
struct line* l = (struct line*)malloc(sizeof(struct line));
if (l) {
memset(l, 0, sizeof(*l));
}
return l;
}
/* Helper to allocate and zero a buffer_record, with a provided line_start.
curr_line is initialized to a different allocated line to verify that
save_buffer() updates it to line_start. */
static struct buffer_record* helper_alloc_buf(struct line* line_start, struct line** out_orig_curr_line) {
struct buffer_record* b = (struct buffer_record*)malloc(sizeof(struct buffer_record));
if (b) {
memset(b, 0, sizeof(*b));
b->line_start = line_start;
struct line* bogus_curr = helper_alloc_line();
b->curr_line = bogus_curr;
b->next = (struct buffer_record*)0x1; /* set non-NULL intentionally; will be reset */
if (out_orig_curr_line) {
*out_orig_curr_line = bogus_curr;
}
}
return b;
}
/* Helper to free a chain of buffers created in tests.
We only free line_start and the buffer itself since save_buffer()
sets curr_line = line_start. */
static void helper_free_chain(struct buffer_record* start) {
while (start) {
struct buffer_record* n = start->next;
if (start->line_start) {
free(start->line_start);
}
free(start);
start = n;
}
}
/* setUp/tearDown required by Unity */
void setUp(void) {
/* Reset the global list head to ensure isolation between tests. */
head = NULL;
}
void tearDown(void) {
/* Free any buffers that may still be linked from head. */
if (head) {
helper_free_chain(head);
head = NULL;
}
}
/* Test: When head is NULL, save_buffer should set head to buf,
set buf->curr_line to buf->line_start, and clear buf->next to NULL. */
void test_save_buffer_initial_insert_sets_head_and_fields(void) {
struct line* l1 = helper_alloc_line();
TEST_ASSERT_NOT_NULL(l1);
struct line* orig_curr = NULL;
struct buffer_record* buf = helper_alloc_buf(l1, &orig_curr);
TEST_ASSERT_NOT_NULL(buf);
TEST_ASSERT_NOT_NULL(orig_curr);
/* Also create a garbage next to ensure it is cleared (we'll free it ourselves). */
struct buffer_record* garbage_next = (struct buffer_record*)malloc(sizeof(struct buffer_record));
TEST_ASSERT_NOT_NULL(garbage_next);
memset(garbage_next, 0, sizeof(*garbage_next));
buf->next = garbage_next;
TEST_ASSERT_NULL(head);
save_buffer(buf);
TEST_ASSERT_EQUAL_PTR(buf, head);
TEST_ASSERT_EQUAL_PTR(buf->line_start, buf->curr_line);
TEST_ASSERT_NULL(buf->next);
/* Cleanup: free the original (now orphan) curr_line and garbage_next, then the chain via head */
free(orig_curr);
free(garbage_next);
helper_free_chain(head);
head = NULL;
}
/* Test: Appending to a single-element list. */
void test_save_buffer_appends_to_single_element_list(void) {
/* Prepare existing head */
struct line* l_head = helper_alloc_line();
struct line* orig_curr_head = NULL;
struct buffer_record* buf_head = helper_alloc_buf(l_head, &orig_curr_head);
TEST_ASSERT_NOT_NULL(buf_head);
/* First insert: set head */
save_buffer(buf_head);
TEST_ASSERT_EQUAL_PTR(buf_head, head);
TEST_ASSERT_EQUAL_PTR(buf_head->line_start, buf_head->curr_line);
TEST_ASSERT_NULL(buf_head->next);
/* Prepare new buffer to append */
struct line* l_new = helper_alloc_line();
struct line* orig_curr_new = NULL;
struct buffer_record* buf_new = helper_alloc_buf(l_new, &orig_curr_new);
TEST_ASSERT_NOT_NULL(buf_new);
/* Append */
save_buffer(buf_new);
TEST_ASSERT_EQUAL_PTR(buf_head, head);
TEST_ASSERT_EQUAL_PTR(buf_new, buf_head->next);
TEST_ASSERT_NULL(buf_new->next);
TEST_ASSERT_EQUAL_PTR(buf_new->line_start, buf_new->curr_line);
/* Ensure existing node's curr_line remained at its line_start (already set by first save_buffer) */
TEST_ASSERT_EQUAL_PTR(buf_head->line_start, buf_head->curr_line);
/* Cleanup orphan curr_line allocations and chain */
free(orig_curr_head);
free(orig_curr_new);
helper_free_chain(head);
head = NULL;
}
/* Test: Appending to a multi-element list (length >= 2). */
void test_save_buffer_appends_to_multi_element_list(void) {
/* Build initial chain of two buffers: A -> B */
struct line* la = helper_alloc_line();
struct line* lb = helper_alloc_line();
struct line* orig_curr_a = NULL;
struct line* orig_curr_b = NULL;
struct buffer_record* A = helper_alloc_buf(la, &orig_curr_a);
struct buffer_record* B = helper_alloc_buf(lb, &orig_curr_b);
TEST_ASSERT_NOT_NULL(A);
TEST_ASSERT_NOT_NULL(B);
/* Insert A then B via save_buffer to form the chain */
save_buffer(A);
save_buffer(B);
TEST_ASSERT_EQUAL_PTR(A, head);
TEST_ASSERT_EQUAL_PTR(B, A->next);
TEST_ASSERT_NULL(B->next);
/* Prepare C and append it */
struct line* lc = helper_alloc_line();
struct line* orig_curr_c = NULL;
struct buffer_record* C = helper_alloc_buf(lc, &orig_curr_c);
TEST_ASSERT_NOT_NULL(C);
/* Record B's curr_line before appending to ensure it doesn't change */
struct line* B_curr_before = B->curr_line;
save_buffer(C);
/* Verify the chain: A -> B -> C -> NULL */
TEST_ASSERT_EQUAL_PTR(A, head);
TEST_ASSERT_EQUAL_PTR(B, A->next);
TEST_ASSERT_EQUAL_PTR(C, B->next);
TEST_ASSERT_NULL(C->next);
/* Verify new node fields updated */
TEST_ASSERT_EQUAL_PTR(C->line_start, C->curr_line);
/* Verify previous nodes unchanged except B->next now points to C */
TEST_ASSERT_EQUAL_PTR(B_curr_before, B->curr_line);
/* Cleanup orphan curr_line allocations and chain */
free(orig_curr_a);
free(orig_curr_b);
free(orig_curr_c);
helper_free_chain(head);
head = NULL;
}
/* Test: Multiple appends in sequence to ensure traversal loop works repeatedly. */
void test_save_buffer_multiple_appends_sequence(void) {
struct line* l1 = helper_alloc_line();
struct line* l2 = helper_alloc_line();
struct line* l3 = helper_alloc_line();
struct line* oc1 = NULL;
struct line* oc2 = NULL;
struct line* oc3 = NULL;
struct buffer_record* b1 = helper_alloc_buf(l1, &oc1);
struct buffer_record* b2 = helper_alloc_buf(l2, &oc2);
struct buffer_record* b3 = helper_alloc_buf(l3, &oc3);
save_buffer(b1);
save_buffer(b2);
save_buffer(b3);
TEST_ASSERT_EQUAL_PTR(b1, head);
TEST_ASSERT_EQUAL_PTR(b2, b1->next);
TEST_ASSERT_EQUAL_PTR(b3, b2->next);
TEST_ASSERT_NULL(b3->next);
TEST_ASSERT_EQUAL_PTR(b1->line_start, b1->curr_line);
TEST_ASSERT_EQUAL_PTR(b2->line_start, b2->curr_line);
TEST_ASSERT_EQUAL_PTR(b3->line_start, b3->curr_line);
free(oc1);
free(oc2);
free(oc3);
helper_free_chain(head);
head = NULL;
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_save_buffer_initial_insert_sets_head_and_fields);
RUN_TEST(test_save_buffer_appends_to_single_element_list);
RUN_TEST(test_save_buffer_appends_to_multi_element_list);
RUN_TEST(test_save_buffer_multiple_appends_sequence);
return UNITY_END();
}