coreutils / tests /join /tests_for_delseq.c
AryaWu's picture
Upload folder using huggingface_hub
78d2150 verified
#include "../../unity/unity.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
/* Unity fixtures */
void setUp(void) {
/* No global setup required */
}
void tearDown(void) {
/* No global teardown required */
}
/* Helper: create a struct line with optional fields array and optional buffer.
Note: freeline() frees only line->fields and line->buf.buffer, then delseq
frees the struct line itself. We therefore avoid allocating per-field beg,
to prevent leaks not handled by freeline. */
static struct line* make_line_with(size_t nfields, size_t bufsize_bytes)
{
struct line *ln = (struct line*) malloc(sizeof *ln);
if (!ln) return NULL;
memset(ln, 0, sizeof *ln);
if (nfields > 0) {
ln->fields = (struct field*) malloc(nfields * sizeof *ln->fields);
if (!ln->fields) {
free(ln);
return NULL;
}
/* We do not allocate per-field beg pointers; leave them NULL with len 0. */
for (size_t i = 0; i < nfields; i++) {
ln->fields[i].beg = NULL;
ln->fields[i].len = 0;
}
ln->nfields = (idx_t)nfields;
ln->nfields_allocated = (idx_t)nfields;
} else {
ln->fields = NULL;
ln->nfields = 0;
ln->nfields_allocated = 0;
}
if (bufsize_bytes > 0) {
ln->buf.buffer = (char*) malloc(bufsize_bytes);
if (ln->buf.buffer) {
memset(ln->buf.buffer, 'X', bufsize_bytes);
ln->buf.length = (idx_t)bufsize_bytes;
} else {
ln->buf.buffer = NULL;
ln->buf.length = 0;
}
} else {
ln->buf.buffer = NULL;
ln->buf.length = 0;
}
return ln;
}
/* Test: delseq on an empty sequence (alloc=0, lines=NULL) should be a no-op */
static void test_delseq_empty_seq(void)
{
struct seq s;
s.count = 0;
s.alloc = 0;
s.lines = NULL;
delseq(&s);
TEST_ASSERT_EQUAL_UINT(0, (unsigned)s.alloc);
TEST_ASSERT_NULL(s.lines);
}
/* Test: delseq on a lines array populated entirely with NULL entries */
static void test_delseq_null_entries_only(void)
{
struct seq s;
s.count = 0;
s.alloc = 5;
s.lines = (struct line**) calloc(s.alloc, sizeof *s.lines);
TEST_ASSERT_NOT_NULL(s.lines);
void *oldptr = s.lines;
delseq(&s);
/* delseq does not modify s.alloc nor s.lines pointer value */
TEST_ASSERT_EQUAL_UINT(5, (unsigned)s.alloc);
TEST_ASSERT_EQUAL_PTR(oldptr, s.lines);
}
/* Test: delseq on a sequence with mixed entries (NULL and allocated lines).
Verifies it safely frees buffers and fields of non-NULL lines. */
static void test_delseq_mixed_entries(void)
{
struct seq s;
s.count = 0;
s.alloc = 4;
s.lines = (struct line**) malloc(s.alloc * sizeof *s.lines);
TEST_ASSERT_NOT_NULL(s.lines);
s.lines[0] = make_line_with(0, 0); /* No fields, no buffer */
s.lines[1] = NULL; /* NULL entry */
s.lines[2] = make_line_with(3, 64); /* Fields array and a buffer */
s.lines[3] = make_line_with(0, 128); /* Only buffer */
TEST_ASSERT_NOT_NULL(s.lines[0]);
TEST_ASSERT_NULL(s.lines[1]);
TEST_ASSERT_NOT_NULL(s.lines[2]);
TEST_ASSERT_NOT_NULL(s.lines[3]);
void *oldptr = s.lines;
delseq(&s);
TEST_ASSERT_EQUAL_UINT(4, (unsigned)s.alloc);
TEST_ASSERT_EQUAL_PTR(oldptr, s.lines);
}
/* Test: delseq on a larger array to exercise loop bounds and performance */
static void test_delseq_large_array(void)
{
const size_t N = 1000;
struct seq s;
s.count = 0;
s.alloc = (idx_t)N;
s.lines = (struct line**) malloc(N * sizeof *s.lines);
TEST_ASSERT_NOT_NULL(s.lines);
/* Populate every 10th element; leave others NULL */
for (size_t i = 0; i < N; i++) {
if (i % 10 == 0) {
s.lines[i] = make_line_with(2, 32);
TEST_ASSERT_NOT_NULL_MESSAGE(s.lines[i], "Allocation failed in setup");
} else {
s.lines[i] = NULL;
}
}
void *oldptr = s.lines;
delseq(&s);
TEST_ASSERT_EQUAL_UINT(N, (unsigned)s.alloc);
TEST_ASSERT_EQUAL_PTR(oldptr, s.lines);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_delseq_empty_seq);
RUN_TEST(test_delseq_null_entries_only);
RUN_TEST(test_delseq_mixed_entries);
RUN_TEST(test_delseq_large_array);
return UNITY_END();
}