Compare commits

...

3 Commits

Author SHA1 Message Date
5483540b5f Merge pull request 'feat/adds-null-checks' (#4) from feat/adds-null-checks into main
All checks were successful
CI / build (push) Successful in 19s
Reviewed-on: http://gitea.hideyoshi.com.br/HideyoshiNakazone/dynamic_array/pulls/4
2026-04-16 00:06:56 +00:00
a8cd5fb7a8 test: add null handling tests for dynamic array functions
Some checks failed
CI / build (pull_request) Successful in 16s
CI / build (push) Has been cancelled
2026-04-15 21:06:35 -03:00
09e1a360fd feat: add null checks to dynamic array macros for improved safety 2026-04-15 20:59:52 -03:00
2 changed files with 134 additions and 33 deletions

View File

@@ -23,51 +23,75 @@ typedef struct {
} ArrayHeader; } ArrayHeader;
#define array_create(arr) \ #define array_create(arr) \
do { \ do { \
ArrayHeader *header = malloc(sizeof(*arr) * DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE + sizeof(ArrayHeader)); \ ArrayHeader *header = malloc( \
header->size = 0; \ sizeof(*(arr)) * DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE + sizeof(ArrayHeader) \
header->capacity = DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE; \ ); \
\ if (header == NULL) { \
arr = (void *)(header + 1); \ abort(); \
} \
header->size = 0; \
header->capacity = DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE; \
\
(arr) = (void *)(header + 1); \
} while(0) } while(0)
#define array_get_header(arr) ((ArrayHeader*)(arr) - 1) #define array_get_header(arr) \
((arr) ? ((ArrayHeader*)(arr) - 1) : NULL)
#define array_destroy(arr) \ #define array_destroy(arr) \
do { \ do { \
free(array_get_header(arr)); \ if ((arr) == NULL) { \
arr = NULL; \ break; \
} \
free(array_get_header(arr)); \
(arr) = NULL; \
} while (0) } while (0)
#define array_push_value(arr, value) \ #define array_push_value(arr, value) \
do { \ do { \
ArrayHeader *header = array_get_header(arr); \ if ((arr) == NULL) { \
if (header->size + 1 > header->capacity) { \ array_create(arr); \
size_t new_capacity = header->capacity * DYNAMIC_ARRAY_CAPACITY_FACTOR; \ } \
ArrayHeader *new_header = realloc(header, sizeof(*arr) * new_capacity + sizeof(ArrayHeader)); \ ArrayHeader *header = array_get_header(arr); \
if (new_header != NULL) { \ if (header->size >= header->capacity) { \
header = new_header; \ size_t new_capacity = header->capacity * DYNAMIC_ARRAY_CAPACITY_FACTOR; \
} \ ArrayHeader *new_header = realloc( \
header->capacity = new_capacity; \ header, sizeof(*(arr)) * new_capacity + sizeof(ArrayHeader) \
arr = (void *)(header + 1); \ ); \
} \ if (new_header == NULL) { \
arr[header->size] = value; \ abort(); \
header->size++; \ } \
header = new_header; \
header->capacity = new_capacity; \
(arr) = (void *)(header + 1); \
} \
(arr)[header->size] = (value); \
header->size++; \
} while (0) } while (0)
#define array_pop(arr) \ #define array_pop(arr) \
do { \ do { \
ArrayHeader *header = array_get_header(arr); \ if ((arr) == NULL) { \
if (header->size == 0) { \ break; \
break; \ } \
} \ ArrayHeader *header = array_get_header(arr); \
header->size--; \ if (header->size == 0) { \
break; \
} \
header->size--; \
} while (0) } while (0)
#define array_size(arr) \
((arr) ? array_get_header(arr)->size : 0)
#define array_capacity(arr) \
((arr) ? array_get_header(arr)->capacity : 0)
#endif #endif

View File

@@ -178,6 +178,74 @@ void test_array_looping(void) {
} }
/* --- array_get_header branch: NULL arr → returns NULL --- */
void test_array_get_header_on_null_returns_null(void) {
int *arr = NULL;
TEST_ASSERT_NULL(array_get_header(arr));
}
/* --- array_destroy branch: NULL arr → no-op, does not crash --- */
void test_array_destroy_on_null_is_noop(void) {
int *arr = NULL;
array_destroy(arr);
TEST_ASSERT_NULL(arr);
}
/* --- array_push_value branch: NULL arr → auto-creates the array --- */
void test_array_push_value_on_null_auto_creates(void) {
int *arr = NULL;
array_push_value(arr, 7);
TEST_ASSERT_NOT_NULL(arr);
TEST_ASSERT_EQUAL(7, arr[0]);
TEST_ASSERT_EQUAL(1, array_get_header(arr)->size);
array_destroy(arr);
}
/* --- array_pop branch: NULL arr → no-op, does not crash --- */
void test_array_pop_on_null_is_noop(void) {
int *arr = NULL;
array_pop(arr);
TEST_ASSERT_NULL(arr);
}
/* --- array_size branch: NULL arr → 0 --- */
void test_array_size_on_null_returns_zero(void) {
int *arr = NULL;
TEST_ASSERT_EQUAL(0, array_size(arr));
}
/* --- array_size branch: non-NULL arr → current size --- */
void test_array_size_returns_current_size(void) {
int *arr = NULL;
array_create(arr);
array_push_value(arr, 1);
array_push_value(arr, 2);
TEST_ASSERT_EQUAL(2, array_size(arr));
array_destroy(arr);
}
/* --- array_capacity branch: NULL arr → 0 --- */
void test_array_capacity_on_null_returns_zero(void) {
int *arr = NULL;
TEST_ASSERT_EQUAL(0, array_capacity(arr));
}
/* --- array_capacity branch: non-NULL arr → current capacity --- */
void test_array_capacity_returns_current_capacity(void) {
int *arr = NULL;
array_create(arr);
TEST_ASSERT_EQUAL(DYNAMIC_ARRAY_DEFAULT_ARRAY_SIZE, array_capacity(arr));
array_destroy(arr);
}
int main(void) int main(void)
{ {
UNITY_BEGIN(); UNITY_BEGIN();
@@ -195,5 +263,14 @@ int main(void)
RUN_TEST(test_array_values_correct_after_growth); RUN_TEST(test_array_values_correct_after_growth);
RUN_TEST(test_array_looping); RUN_TEST(test_array_looping);
RUN_TEST(test_array_get_header_on_null_returns_null);
RUN_TEST(test_array_destroy_on_null_is_noop);
RUN_TEST(test_array_push_value_on_null_auto_creates);
RUN_TEST(test_array_pop_on_null_is_noop);
RUN_TEST(test_array_size_on_null_returns_zero);
RUN_TEST(test_array_size_returns_current_size);
RUN_TEST(test_array_capacity_on_null_returns_zero);
RUN_TEST(test_array_capacity_returns_current_capacity);
return UNITY_END(); return UNITY_END();
} }