#include "../../unity/unity.h" #include #include #include /* Unity fixtures */ void setUp(void) { /* no-op */ } void tearDown(void) { /* no-op */ } /* Helper to initialize an empty line object */ static void init_empty_line(struct line* l) { memset(l, 0, sizeof(*l)); } /* Test: basic append on an empty line should allocate and store the field */ static void test_extract_field_basic_append(void) { struct line l; init_empty_line(&l); char buf[] = "hello"; extract_field(&l, buf, (idx_t)5); TEST_ASSERT_EQUAL_INT(1, (int)l.nfields); TEST_ASSERT_TRUE(l.nfields_allocated >= 1); TEST_ASSERT_NOT_NULL(l.fields); TEST_ASSERT_EQUAL_PTR(buf, l.fields[0].beg); TEST_ASSERT_EQUAL_INT(5, (int)l.fields[0].len); /* cleanup */ freeline(&l); } /* Test: multiple appends should grow capacity as needed and preserve entries */ static void test_extract_field_multiple_growth_and_preserve(void) { struct line l; init_empty_line(&l); enum { N = 50 }; /* enough iterations to ensure multiple growths */ char storage[N][16]; for (int i = 0; i < N; ++i) { /* create distinct content and pointers */ int n = snprintf(storage[i], sizeof(storage[i]), "f%02d", i); if (n < 0) n = 0; extract_field(&l, storage[i], (idx_t)n); /* After each insertion, verify counters and last entry */ TEST_ASSERT_EQUAL_INT(i + 1, (int)l.nfields); TEST_ASSERT_TRUE(l.nfields_allocated >= l.nfields); TEST_ASSERT_EQUAL_PTR(storage[i], l.fields[i].beg); TEST_ASSERT_EQUAL_INT(n, (int)l.fields[i].len); /* Also spot-check some earlier entries remain intact */ if (i >= 3) { TEST_ASSERT_EQUAL_PTR(storage[0], l.fields[0].beg); TEST_ASSERT_EQUAL_PTR(storage[1], l.fields[1].beg); TEST_ASSERT_EQUAL_PTR(storage[2], l.fields[2].beg); } } /* Verify all entries match after the loop */ for (int i = 0; i < N; ++i) { int n = (int)strlen(storage[i]); /* was written by snprintf */ TEST_ASSERT_EQUAL_PTR(storage[i], l.fields[i].beg); TEST_ASSERT_EQUAL_INT(n, (int)l.fields[i].len); } /* cleanup */ freeline(&l); } /* Test: when there is preallocated capacity, pointer should not change on insert */ static void test_extract_field_no_realloc_when_capacity_available(void) { struct line l; init_empty_line(&l); /* Preallocate capacity for 8 fields */ l.nfields_allocated = 8; l.fields = (struct field*) malloc(sizeof(struct field) * l.nfields_allocated); TEST_ASSERT_NOT_NULL(l.fields); struct field* oldptr = l.fields; char buf1[] = "A"; extract_field(&l, buf1, (idx_t)1); TEST_ASSERT_EQUAL_PTR(oldptr, l.fields); TEST_ASSERT_EQUAL_INT(1, (int)l.nfields); TEST_ASSERT_EQUAL_PTR(buf1, l.fields[0].beg); TEST_ASSERT_EQUAL_INT(1, (int)l.fields[0].len); /* cleanup */ freeline(&l); } /* Test: zero-length field should be recorded and increase count */ static void test_extract_field_zero_length(void) { struct line l; init_empty_line(&l); char dummy = 'X'; extract_field(&l, &dummy, (idx_t)0); TEST_ASSERT_EQUAL_INT(1, (int)l.nfields); TEST_ASSERT_EQUAL_PTR(&dummy, l.fields[0].beg); TEST_ASSERT_EQUAL_INT(0, (int)l.fields[0].len); /* Add another zero-length to ensure multiple zero-length fields work */ char dummy2 = 'Y'; extract_field(&l, &dummy2, (idx_t)0); TEST_ASSERT_EQUAL_INT(2, (int)l.nfields); TEST_ASSERT_EQUAL_PTR(&dummy2, l.fields[1].beg); TEST_ASSERT_EQUAL_INT(0, (int)l.fields[1].len); /* cleanup */ freeline(&l); } /* Test: large length value should be stored as-is (no copying performed) */ static void test_extract_field_large_len_value(void) { struct line l; init_empty_line(&l); char buf[] = "x"; idx_t large_len = (idx_t)123456; /* arbitrary large length, not used for access */ extract_field(&l, buf, large_len); TEST_ASSERT_EQUAL_INT(1, (int)l.nfields); TEST_ASSERT_EQUAL_PTR(buf, l.fields[0].beg); TEST_ASSERT_EQUAL_INT((int)large_len, (int)l.fields[0].len); /* cleanup */ freeline(&l); } int main(void) { UNITY_BEGIN(); RUN_TEST(test_extract_field_basic_append); RUN_TEST(test_extract_field_multiple_growth_and_preserve); RUN_TEST(test_extract_field_no_realloc_when_capacity_available); RUN_TEST(test_extract_field_zero_length); RUN_TEST(test_extract_field_large_len_value); return UNITY_END(); }