Skip to content

Commit 79494ce

Browse files
committed
test(mem-alloc): add tests for huge allocations and OOM scenarios
1 parent 5e718e6 commit 79494ce

File tree

2 files changed

+212
-0
lines changed

2 files changed

+212
-0
lines changed

tests/unit/mem-alloc/mem_alloc_test.c

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,3 +580,210 @@ test_wasm_runtime_aligned_alloc_multiple_alignments(void **state)
580580
wasm_runtime_destroy();
581581
free(init_args.mem_alloc_option.pool.heap_buf);
582582
}
583+
584+
/* Test: Normal allocation with huge size (near upper limit) */
585+
static void
586+
test_normal_alloc_huge_size(void **state)
587+
{
588+
mem_allocator_t allocator;
589+
char heap_buf[1024 * 1024]; /* 1MB heap */
590+
void *ptr;
591+
size_t huge_size;
592+
593+
allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
594+
assert_non_null(allocator);
595+
596+
/* Try to allocate most of the heap */
597+
huge_size = sizeof(heap_buf) - 4096; /* Leave some overhead */
598+
ptr = mem_allocator_malloc(allocator, huge_size);
599+
600+
/* May succeed or fail depending on internal fragmentation */
601+
if (ptr) {
602+
/* If it succeeds, verify it's properly allocated */
603+
assert_true(is_aligned(ptr, 8));
604+
mem_allocator_free(allocator, ptr);
605+
}
606+
607+
/* Try allocation at exact upper limit - should handle gracefully */
608+
huge_size = SIZE_MAX - 1024;
609+
ptr = mem_allocator_malloc(allocator, huge_size);
610+
assert_null(ptr); /* Should fail gracefully, not crash */
611+
612+
mem_allocator_destroy(allocator);
613+
}
614+
615+
/* Test: Aligned allocation with huge size (near upper limit) */
616+
static void
617+
test_aligned_alloc_huge_size(void **state)
618+
{
619+
mem_allocator_t allocator;
620+
char heap_buf[1024 * 1024]; /* 1MB heap */
621+
void *ptr;
622+
size_t huge_size;
623+
624+
allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
625+
assert_non_null(allocator);
626+
627+
/* Try to allocate most of the heap with alignment */
628+
huge_size = 512 * 1024; /* Size must be multiple of alignment */
629+
ptr = mem_allocator_malloc_aligned(allocator, huge_size, 512);
630+
631+
/* May succeed or fail depending on alignment overhead */
632+
if (ptr) {
633+
assert_true(is_aligned(ptr, 512));
634+
mem_allocator_free(allocator, ptr);
635+
}
636+
637+
/* Try allocation at extreme size - should fail gracefully */
638+
huge_size = (SIZE_MAX / 2) & ~(size_t)4095; /* Aligned to 4096 */
639+
ptr = mem_allocator_malloc_aligned(allocator, huge_size, 4096);
640+
assert_null(ptr); /* Should fail gracefully, not crash */
641+
642+
mem_allocator_destroy(allocator);
643+
}
644+
645+
/* Test: Normal allocations until OOM */
646+
static void
647+
test_normal_alloc_until_oom(void **state)
648+
{
649+
mem_allocator_t allocator;
650+
char heap_buf[256 * 1024];
651+
void *ptrs[1000];
652+
int count = 0;
653+
654+
allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
655+
assert_non_null(allocator);
656+
657+
/* Allocate until we run out of memory */
658+
for (int i = 0; i < 1000; i++) {
659+
ptrs[i] = mem_allocator_malloc(allocator, 1024);
660+
if (ptrs[i]) {
661+
count++;
662+
}
663+
else {
664+
/* OOM reached - this is expected */
665+
break;
666+
}
667+
}
668+
669+
/* Should have allocated at least some blocks */
670+
assert_true(count > 10);
671+
assert_true(count < 1000); /* Should not have allocated all */
672+
673+
/* Should still be able to free what we allocated */
674+
for (int i = 0; i < count; i++) {
675+
mem_allocator_free(allocator, ptrs[i]);
676+
}
677+
678+
/* After freeing, should be able to allocate again */
679+
void *ptr = mem_allocator_malloc(allocator, 1024);
680+
assert_non_null(ptr);
681+
mem_allocator_free(allocator, ptr);
682+
683+
mem_allocator_destroy(allocator);
684+
}
685+
686+
/* Test: Aligned allocations until OOM */
687+
static void
688+
test_aligned_alloc_until_oom(void **state)
689+
{
690+
mem_allocator_t allocator;
691+
char heap_buf[512 * 1024];
692+
void *ptrs[500];
693+
int count = 0;
694+
695+
allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
696+
assert_non_null(allocator);
697+
698+
/* Allocate with alignment until we run out of memory */
699+
for (int i = 0; i < 500; i++) {
700+
/* Alternate between different alignments */
701+
int align = (i % 2 == 0) ? 64 : 128;
702+
ptrs[i] = mem_allocator_malloc_aligned(allocator, align * 20, align);
703+
if (ptrs[i]) {
704+
assert_true(is_aligned(ptrs[i], align));
705+
count++;
706+
}
707+
else {
708+
/* OOM reached - this is expected */
709+
break;
710+
}
711+
}
712+
713+
/* Should have allocated at least some blocks */
714+
assert_true(count > 5);
715+
assert_true(count < 500); /* Should not have allocated all */
716+
717+
/* Free all allocated blocks */
718+
for (int i = 0; i < count; i++) {
719+
mem_allocator_free(allocator, ptrs[i]);
720+
}
721+
722+
/* After freeing, should be able to allocate again */
723+
void *ptr = mem_allocator_malloc_aligned(allocator, 256, 64);
724+
assert_non_null(ptr);
725+
mem_allocator_free(allocator, ptr);
726+
727+
mem_allocator_destroy(allocator);
728+
}
729+
730+
/* Test: Mixed normal and aligned allocations until OOM */
731+
static void
732+
test_mixed_alloc_until_oom(void **state)
733+
{
734+
mem_allocator_t allocator;
735+
char heap_buf[128 * 1024];
736+
void *ptrs[1000];
737+
bool is_aligned_alloc[1000];
738+
int count = 0;
739+
740+
allocator = mem_allocator_create(heap_buf, sizeof(heap_buf));
741+
assert_non_null(allocator);
742+
743+
/* Alternate between normal and aligned allocations until OOM */
744+
for (int i = 0; i < 1000; i++) {
745+
if (i % 3 == 0) {
746+
/* Aligned allocation */
747+
ptrs[i] = mem_allocator_malloc_aligned(allocator, 128, 64);
748+
is_aligned_alloc[i] = true;
749+
}
750+
else {
751+
/* Normal allocation */
752+
ptrs[i] = mem_allocator_malloc(allocator, 512);
753+
is_aligned_alloc[i] = false;
754+
}
755+
756+
if (ptrs[i]) {
757+
if (is_aligned_alloc[i]) {
758+
assert_true(is_aligned(ptrs[i], 64));
759+
}
760+
count++;
761+
}
762+
else {
763+
/* OOM reached */
764+
break;
765+
}
766+
}
767+
768+
/* Should have allocated a reasonable number of blocks */
769+
assert_true(count > 20);
770+
assert_true(count < 1000); /* Should not have allocated all */
771+
772+
/* Free in random order (every other block first) */
773+
for (int i = 0; i < count; i += 2) {
774+
mem_allocator_free(allocator, ptrs[i]);
775+
}
776+
for (int i = 1; i < count; i += 2) {
777+
mem_allocator_free(allocator, ptrs[i]);
778+
}
779+
780+
/* Verify allocator still works after OOM and free */
781+
void *ptr1 = mem_allocator_malloc(allocator, 1024);
782+
void *ptr2 = mem_allocator_malloc_aligned(allocator, 128, 64);
783+
assert_non_null(ptr1);
784+
assert_non_null(ptr2);
785+
mem_allocator_free(allocator, ptr1);
786+
mem_allocator_free(allocator, ptr2);
787+
788+
mem_allocator_destroy(allocator);
789+
}

tests/unit/mem-alloc/test_runner.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ main(void)
3232
cmocka_unit_test(test_wasm_runtime_aligned_alloc_system_mode),
3333
cmocka_unit_test(test_wasm_runtime_realloc_rejects_aligned),
3434
cmocka_unit_test(test_wasm_runtime_aligned_alloc_multiple_alignments),
35+
cmocka_unit_test(test_normal_alloc_huge_size),
36+
cmocka_unit_test(test_aligned_alloc_huge_size),
37+
cmocka_unit_test(test_normal_alloc_until_oom),
38+
cmocka_unit_test(test_aligned_alloc_until_oom),
39+
cmocka_unit_test(test_mixed_alloc_until_oom),
3540
};
3641

3742
return cmocka_run_group_tests(tests, NULL, NULL);

0 commit comments

Comments
 (0)