File size: 4,126 Bytes
78d2150 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
#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();
} |