Add some tests
This commit is contained in:
347
test/util/test_memory.c
Normal file
347
test/util/test_memory.c
Normal file
@@ -0,0 +1,347 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "dusktest.h"
|
||||
#include "util/memory.h"
|
||||
|
||||
static void test_memoryAllocate(void **state) {
|
||||
(void)state;
|
||||
|
||||
size_t size = 128;
|
||||
void *ptr = memoryAllocate(size);
|
||||
assert_non_null(ptr);
|
||||
memoryFree(ptr);
|
||||
|
||||
// Should not be able to allocate 0 bytes
|
||||
expect_assert_failure(memoryAllocate(0));
|
||||
|
||||
// Should not be able to allocate more memory than possible
|
||||
expect_assert_failure(memoryAllocate(SIZE_MAX));
|
||||
}
|
||||
|
||||
static void test_memoryFree(void **state) {
|
||||
(void)state;
|
||||
|
||||
// Create some memory
|
||||
size_t size = 64;
|
||||
void *ptr = memoryAllocate(size);
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Free
|
||||
memoryFree(ptr);
|
||||
|
||||
// Expect unable to free NULL
|
||||
expect_assert_failure(memoryFree(NULL));
|
||||
}
|
||||
|
||||
static void test_memoryCopy(void **state) {
|
||||
(void)state;
|
||||
|
||||
// Create some memory
|
||||
size_t size = 32;
|
||||
void *src = memoryAllocate(size);
|
||||
void *dest = memoryAllocate(size);
|
||||
assert_non_null(src);
|
||||
assert_non_null(dest);
|
||||
|
||||
// Fill source with known pattern and copy
|
||||
memorySet(src, 0xAB, size);
|
||||
memoryCopy(dest, src, size);
|
||||
assert_memory_equal(src, dest, size);
|
||||
|
||||
// Should not be able to copy to NULL
|
||||
expect_assert_failure(memoryCopy(NULL, src, size));
|
||||
|
||||
// Should not be able to copy from NULL
|
||||
expect_assert_failure(memoryCopy(dest, NULL, size));
|
||||
|
||||
// Cannot copy 0 bytes
|
||||
expect_assert_failure(memoryCopy(dest, src, 0));
|
||||
|
||||
// Cannot copy to itself
|
||||
expect_assert_failure(memoryCopy(src, src, size));
|
||||
|
||||
memoryFree(src);
|
||||
memoryFree(dest);
|
||||
}
|
||||
|
||||
static void test_memorySet(void **state) {
|
||||
(void)state;
|
||||
|
||||
// Allocate memory
|
||||
size_t size = 16;
|
||||
void *ptr = memoryAllocate(size);
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Fill with pattern
|
||||
memorySet(ptr, 0xCD, size);
|
||||
uint8_t expected[16];
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
expected[i] = 0xCD;
|
||||
}
|
||||
assert_memory_equal(ptr, expected, size);
|
||||
|
||||
// Cannot set to NULL
|
||||
expect_assert_failure(memorySet(NULL, 0x00, size));
|
||||
|
||||
// Canot set 0 bytes
|
||||
expect_assert_failure(memorySet(ptr, 0x00, 0));
|
||||
|
||||
memoryFree(ptr);
|
||||
}
|
||||
|
||||
static void test_memoryZero(void **state) {
|
||||
(void)state;
|
||||
|
||||
// Create some memory
|
||||
size_t size = 20;
|
||||
void *ptr = memoryAllocate(size);
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Fill and then zero
|
||||
memorySet(ptr, 0xEF, size);
|
||||
memoryZero(ptr, size);
|
||||
|
||||
// All memory should be zeroed
|
||||
uint8_t expected[20] = {0};
|
||||
assert_memory_equal(ptr, expected, size);
|
||||
|
||||
// Cannot zero to NULL pointer
|
||||
expect_assert_failure(memoryZero(NULL, size));
|
||||
|
||||
// Cannot zero 0 bytes
|
||||
expect_assert_failure(memoryZero(ptr, 0));
|
||||
|
||||
memoryFree(ptr);
|
||||
}
|
||||
|
||||
static void test_memoryCopyRangeSafe(void **state) {
|
||||
(void)state;
|
||||
|
||||
// Create some memory
|
||||
size_t size = 10;
|
||||
void *src = memoryAllocate(size);
|
||||
void *dest = memoryAllocate(size);
|
||||
assert_non_null(src);
|
||||
assert_non_null(dest);
|
||||
|
||||
// Initialize source with known pattern
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
((uint8_t*)src)[i] = (uint8_t)(i + 1); // 1, 2, ..., 10
|
||||
}
|
||||
|
||||
// Copy a range from src[2] to src[7] (5 bytes) into dest
|
||||
memoryCopyRangeSafe(dest, (uint8_t*)src + 2, (uint8_t*)src + 7, size);
|
||||
uint8_t expected[10] = {3, 4, 5, 6, 7}; // Expected data in dest
|
||||
assert_memory_equal(dest, expected, 5);
|
||||
|
||||
// Cannot copy to NULL destination
|
||||
expect_assert_failure(memoryCopyRangeSafe(NULL, src, (uint8_t*)src + 5, size));
|
||||
|
||||
// Cannot copy from NULL start
|
||||
expect_assert_failure(memoryCopyRangeSafe(dest, NULL, (uint8_t*)src + 5, size));
|
||||
|
||||
// Cannot copy from NULL end
|
||||
expect_assert_failure(memoryCopyRangeSafe(dest, (uint8_t*)src, NULL, size));
|
||||
|
||||
// Start and end are the same
|
||||
expect_assert_failure(memoryCopyRangeSafe(dest, (uint8_t*)src, (uint8_t*)src, size));
|
||||
|
||||
// End is before start
|
||||
expect_assert_failure(memoryCopyRangeSafe(dest, (uint8_t*)src + 5, (uint8_t*)src + 2, size));
|
||||
|
||||
// Size to copy exceeds maximum
|
||||
expect_assert_failure(memoryCopyRangeSafe(dest, (uint8_t*)src, (uint8_t*)src + 10, 5));
|
||||
|
||||
memoryFree(src);
|
||||
memoryFree(dest);
|
||||
}
|
||||
|
||||
static void test_memoryMove(void **state) {
|
||||
(void)state;
|
||||
|
||||
// Create some memory
|
||||
size_t size = 15;
|
||||
void *ptr = memoryAllocate(size + 5); // Extra space for overlap
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Initialize memory with known pattern
|
||||
for(size_t i = 0; i < size + 5; i++) {
|
||||
((uint8_t*)ptr)[i] = (uint8_t)(i + 1); // 1, 2, ..., size+5
|
||||
}
|
||||
|
||||
// Move overlapping region: from ptr[0..14] to ptr[5..19]
|
||||
memoryMove((uint8_t*)ptr + 5, ptr, size);
|
||||
|
||||
// Expected pattern after move
|
||||
uint8_t expected[20];
|
||||
for(size_t i = 0; i < 5; i++) {
|
||||
expected[i] = (uint8_t)(i + 1); // Original first 5 bytes
|
||||
}
|
||||
for(size_t i = 5; i < 20; i++) {
|
||||
expected[i] = (uint8_t)(i - 4); // Moved bytes
|
||||
}
|
||||
assert_memory_equal(ptr, expected, size + 5);
|
||||
|
||||
// Cannot move to NULL
|
||||
expect_assert_failure(memoryMove(NULL, ptr, size));
|
||||
|
||||
// Cannot move from NULL
|
||||
expect_assert_failure(memoryMove(ptr, NULL, size));
|
||||
|
||||
// Cannot move 0 bytes
|
||||
expect_assert_failure(memoryMove(ptr, ptr, 0));
|
||||
|
||||
// Cannot move to itself
|
||||
expect_assert_failure(memoryMove(ptr, ptr, size));
|
||||
|
||||
memoryFree(ptr);
|
||||
}
|
||||
|
||||
static void test_memoryCompare(void **state) {
|
||||
(void)state;
|
||||
|
||||
// Create two memory blocks
|
||||
size_t size = 8;
|
||||
void *a = memoryAllocate(size);
|
||||
void *b = memoryAllocate(size);
|
||||
assert_non_null(a);
|
||||
assert_non_null(b);
|
||||
|
||||
// Initialize both with same data
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
((uint8_t*)a)[i] = (uint8_t)(i + 1);
|
||||
((uint8_t*)b)[i] = (uint8_t)(i + 1);
|
||||
}
|
||||
|
||||
// They should be equal
|
||||
assert_int_equal(memoryCompare(a, b, size), 0);
|
||||
|
||||
// Change b and compare again
|
||||
((uint8_t*)b)[size - 1] = 0xFF;
|
||||
assert_true(memoryCompare(a, b, size) < 0);
|
||||
|
||||
// Change a and compare again
|
||||
((uint8_t*)a)[size - 1] = 0xFF;
|
||||
((uint8_t*)a)[size - 2] = 0xFE;
|
||||
assert_true(memoryCompare(a, b, size) > 0);
|
||||
|
||||
// CAnnot compare with NULL a
|
||||
expect_assert_failure(memoryCompare(NULL, b, size));
|
||||
|
||||
// Cannot compare with NULL b
|
||||
expect_assert_failure(memoryCompare(a, NULL, size));
|
||||
|
||||
// Comparing with self always equal
|
||||
assert_int_equal(memoryCompare(a, a, size), 0);
|
||||
assert_int_equal(memoryCompare(b, b, size), 0);
|
||||
|
||||
// Cannot compare 0 bytes
|
||||
expect_assert_failure(memoryCompare(a, b, 0));
|
||||
|
||||
memoryFree(a);
|
||||
memoryFree(b);
|
||||
}
|
||||
|
||||
static void test_memoryReallocate(void **state) {
|
||||
(void)state;
|
||||
|
||||
size_t initialSize = 16;
|
||||
void *ptr = memoryAllocate(initialSize);
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Reallocate to a larger size
|
||||
size_t newSize = 32;
|
||||
memoryReallocate(&ptr, newSize);
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Reallocate to a smaller size
|
||||
size_t smallerSize = 8;
|
||||
memoryReallocate(&ptr, smallerSize);
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Cannot realloc to size 0
|
||||
expect_assert_failure(memoryReallocate(&ptr, 0));
|
||||
|
||||
// Cannot realloc NULL pointer
|
||||
expect_assert_failure(memoryReallocate(NULL, 16));
|
||||
|
||||
// Cannot reallocate more memory than possible
|
||||
expect_assert_failure(memoryReallocate(&ptr, SIZE_MAX));
|
||||
|
||||
// All we really care about is that the pointer is valid after reallocations
|
||||
memoryFree(ptr);
|
||||
}
|
||||
|
||||
static void test_memoryResize(void **state) {
|
||||
(void)state;
|
||||
|
||||
size_t initialSize = 32;
|
||||
void *ptr = memoryAllocate(initialSize);
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Initialize memory
|
||||
for(size_t i = 0; i < initialSize; i++) {
|
||||
((uint8_t*)ptr)[i] = (uint8_t)(i + 1);
|
||||
}
|
||||
|
||||
// Equal size shouldn't touch the pointer
|
||||
void *oldPtr = ptr;
|
||||
memoryResize(&ptr, initialSize, initialSize);
|
||||
assert_non_null(ptr);
|
||||
assert_ptr_equal(ptr, oldPtr);
|
||||
|
||||
// Reallocate to a larger size
|
||||
size_t newSize = 64;
|
||||
memoryResize(&ptr, initialSize, newSize);
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Check that old data is preserved
|
||||
for(size_t i = 0; i < initialSize; i++) {
|
||||
assert_int_equal(((uint8_t*)ptr)[i], (uint8_t)(i + 1));
|
||||
}
|
||||
|
||||
// Reallocate to a smaller size
|
||||
size_t smallerSize = 16;
|
||||
memoryResize(&ptr, newSize, smallerSize);
|
||||
assert_non_null(ptr);
|
||||
|
||||
// Check that data is still correct up to the smaller size
|
||||
for(size_t i = 0; i < smallerSize; i++) {
|
||||
assert_int_equal(((uint8_t*)ptr)[i], (uint8_t)(i + 1));
|
||||
}
|
||||
|
||||
// Cannot realloc to size 0
|
||||
expect_assert_failure(memoryResize(&ptr, smallerSize, 0));
|
||||
|
||||
// Cannot take NULL
|
||||
expect_assert_failure(memoryResize(NULL, smallerSize, 16));
|
||||
|
||||
// memoryResize with oldsize of 0 not possible
|
||||
expect_assert_failure(memoryResize(&ptr, 0, 16));
|
||||
|
||||
// Cannot resize more memory than possible
|
||||
expect_assert_failure(memoryResize(&ptr, smallerSize, SIZE_MAX));
|
||||
|
||||
memoryFree(ptr);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_memoryAllocate),
|
||||
cmocka_unit_test(test_memoryFree),
|
||||
cmocka_unit_test(test_memoryCopy),
|
||||
cmocka_unit_test(test_memorySet),
|
||||
cmocka_unit_test(test_memoryZero),
|
||||
cmocka_unit_test(test_memoryCopyRangeSafe),
|
||||
cmocka_unit_test(test_memoryMove),
|
||||
cmocka_unit_test(test_memoryCompare),
|
||||
cmocka_unit_test(test_memoryReallocate),
|
||||
cmocka_unit_test(test_memoryResize),
|
||||
};
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
Reference in New Issue
Block a user