From 8fe67d9b3e4d8d0eda63e568dca60d455531fcd6 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Sat, 12 Sep 2026 17:29:33 +0200 Subject: [PATCH] test: cover spinlockTest and vecTest --- src/spinlockTest.c | 73 ++++++++++++++++++++++++++++ src/vecTest.c | 116 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 src/spinlockTest.c create mode 100644 src/vecTest.c diff --git a/src/spinlockTest.c b/src/spinlockTest.c new file mode 100644 index 0000000..fd8d0d4 --- /dev/null +++ b/src/spinlockTest.c @@ -0,0 +1,73 @@ +#include "ktest.h" +#include "spinlock.h" + +KTEST(spinLockInitStartsUnlocked) +{ + SpinLock lock; + spinLockInit(&lock); + KT_FALSE(t, spinLockIsLocked(&lock)); +} + +KTEST(spinLockAcquireReleaseCycle) +{ + SpinLock lock; + spinLockInit(&lock); + + uint64 flags = spinLockAcquire(&lock); + KT_TRUE(t, spinLockIsLocked(&lock)); + + spinLockRelease(&lock, flags); + KT_FALSE(t, spinLockIsLocked(&lock)); + + /* lock is reusable after release */ + flags = spinLockAcquire(&lock); + KT_TRUE(t, spinLockIsLocked(&lock)); + spinLockRelease(&lock, flags); + KT_FALSE(t, spinLockIsLocked(&lock)); +} + +KTEST(spinLockTryAcquireFailsWhenHeld) +{ + SpinLock lock; + spinLockInit(&lock); + + uint64 flags; + KT_TRUE(t, spinLockTryAcquire(&lock, &flags)); + KT_TRUE(t, spinLockIsLocked(&lock)); + + /* second attempt must not block (and must not touch flags/state) since + nothing else on a single core will ever release it for us */ + uint64 otherFlags = 0xDEADBEEF; + KT_FALSE(t, spinLockTryAcquire(&lock, &otherFlags)); + KT_EQU(t, otherFlags, 0xDEADBEEF); + KT_TRUE(t, spinLockIsLocked(&lock)); + + spinLockRelease(&lock, flags); + KT_FALSE(t, spinLockIsLocked(&lock)); + + /* now that it is free, tryAcquire succeeds again */ + KT_TRUE(t, spinLockTryAcquire(&lock, &flags)); + spinLockRelease(&lock, flags); +} + +KTEST(spinLockIndependentLocksDoNotInterfere) +{ + SpinLock a, b; + spinLockInit(&a); + spinLockInit(&b); + + uint64 flagsA = spinLockAcquire(&a); + KT_TRUE(t, spinLockIsLocked(&a)); + KT_FALSE(t, spinLockIsLocked(&b)); + + uint64 flagsB = spinLockAcquire(&b); + KT_TRUE(t, spinLockIsLocked(&a)); + KT_TRUE(t, spinLockIsLocked(&b)); + + spinLockRelease(&a, flagsA); + KT_FALSE(t, spinLockIsLocked(&a)); + KT_TRUE(t, spinLockIsLocked(&b)); + + spinLockRelease(&b, flagsB); + KT_FALSE(t, spinLockIsLocked(&b)); +} diff --git a/src/vecTest.c b/src/vecTest.c new file mode 100644 index 0000000..0b9cc50 --- /dev/null +++ b/src/vecTest.c @@ -0,0 +1,116 @@ +#include "ktest.h" +#include "vec.h" + +KTEST(vecPushPopGrows) +{ + Vec v; + vecInit(&v, sizeof(int)); + KT_TRUE(t, vecIsEmpty(&v)); + KT_EQ(t, vecCap(&v), 0); + + for (int i = 0; i < 20; i++) + KT_TRUE(t, vecPush(&v, &i)); + KT_EQ(t, vecLen(&v), 20); + KT_GE(t, vecCap(&v), 20); + + for (int i = 0; i < 20; i++) + KT_EQ(t, *(int*)vecAt(&v, (usize)i), i); + + int popped = -1; + KT_TRUE(t, vecPop(&v, &popped)); + KT_EQ(t, popped, 19); + KT_EQ(t, vecLen(&v), 19); + + vecFree(&v); +} + +KTEST(vecPopEmptyFails) +{ + Vec v; + vecInit(&v, sizeof(int)); + int out; + KT_FALSE(t, vecPop(&v, &out)); + KT_NULL(t, vecAt(&v, 0)); + vecFree(&v); +} + +KTEST(vecSetAt) +{ + Vec v; + vecInit(&v, sizeof(int)); + for (int i = 0; i < 5; i++) + vecPush(&v, &i); + + int replacement = 99; + KT_TRUE(t, vecSet(&v, 2, &replacement)); + KT_EQ(t, *(int*)vecAt(&v, 2), 99); + KT_FALSE(t, vecSet(&v, 10, &replacement)); /* out of range */ + + vecFree(&v); +} + +KTEST(vecInsertRemoveShifts) +{ + Vec v; + vecInit(&v, sizeof(int)); + for (int i = 0; i < 5; i++) + vecPush(&v, &i); /* 0 1 2 3 4 */ + + int inserted = 100; + KT_TRUE(t, vecInsert(&v, 2, &inserted)); /* 0 1 100 2 3 4 */ + KT_EQ(t, vecLen(&v), 6); + KT_EQ(t, *(int*)vecAt(&v, 2), 100); + KT_EQ(t, *(int*)vecAt(&v, 3), 2); + KT_EQ(t, *(int*)vecAt(&v, 5), 4); + + int removed = -1; + KT_TRUE(t, vecRemove(&v, 2, &removed)); /* back to 0 1 2 3 4 */ + KT_EQ(t, removed, 100); + KT_EQ(t, vecLen(&v), 5); + for (int i = 0; i < 5; i++) + KT_EQ(t, *(int*)vecAt(&v, (usize)i), i); + + vecFree(&v); +} + +KTEST(vecClearKeepsCapacity) +{ + Vec v; + vecInit(&v, sizeof(int)); + for (int i = 0; i < 8; i++) + vecPush(&v, &i); + usize capBefore = vecCap(&v); + + vecClear(&v); + KT_EQ(t, vecLen(&v), 0); + KT_TRUE(t, vecIsEmpty(&v)); + KT_EQ(t, vecCap(&v), capBefore); /* clear does not free backing storage */ + + int again = 7; + KT_TRUE(t, vecPush(&v, &again)); + KT_EQ(t, *(int*)vecAt(&v, 0), 7); + + vecFree(&v); +} + +KTEST(vecStructElements) +{ + typedef struct { int32 x; int32 y; } Point; + + Vec v; + vecInit(&v, sizeof(Point)); + + Point a = { 1, 2 }; + Point b = { 3, 4 }; + vecPush(&v, &a); + vecPush(&v, &b); + + Point* pa = (Point*)vecAt(&v, 0); + Point* pb = (Point*)vecAt(&v, 1); + KT_EQ(t, pa->x, 1); + KT_EQ(t, pa->y, 2); + KT_EQ(t, pb->x, 3); + KT_EQ(t, pb->y, 4); + + vecFree(&v); +}