test: cover ktestStrEq, ktestCheck and TestItem

This commit is contained in:
dualfroz committed 2026-09-10 17:39:03 +02:00
1 parent 95ae1a2165
commit b00aa4cd74
2 files changed
+171

No files matched your search

+59
View File
@@ -0,0 +1,59 @@
#include "ktest.h"
#include "console.h"
/* Bracketed by the linker script (see linker.ld, .rodata output section):
the ".ktests" input section holds one const KtestEntry* per registered
test. Iterating [start, end) visits every test in link order. */
extern const KtestEntry* const ktestArrayStart[];
extern const KtestEntry* const ktestArrayEnd[];
bool ktestStrEq(const char* a, const char* b)
{
if (a == nullptr || b == nullptr)
return a == b;
while (*a && (*a == *b)) {
a++;
b++;
}
return *a == *b;
}
bool ktestCheck(KtestCtx* t, bool ok, const char* expr, const char* file, int line)
{
t->checks++;
if (!ok) {
t->failures++;
kprintf(" FAIL %s:%d %s\n", file, line, expr);
}
return ok;
}
uint64 ktestRunAll(void)
{
uint64 totalTests = 0;
uint64 totalChecks = 0;
uint64 totalFailures = 0;
uint64 failedTests = 0;
kprintf("\n==== ktest: running in-kernel self-tests ====\n");
for (const KtestEntry* const* p = ktestArrayStart; p < ktestArrayEnd; p++) {
const KtestEntry* e = *p;
KtestCtx t = { e->name, 0, 0 };
e->fn(&t);
totalTests++;
totalChecks += t.checks;
totalFailures += t.failures;
if (t.failures) {
failedTests++;
kprintf(" [FAIL] %s (%lu/%lu checks failed)\n", e->name, t.failures, t.checks);
} else {
kprintf(" [ ok ] %s (%lu checks)\n", e->name, t.checks);
}
}
kprintf("==== ktest done: %lu of %lu tests failed ====\n", failedTests, totalTests);
kprintf("KTEST SUMMARY: %lu tests, %lu checks, %lu failed\n",
totalTests, totalChecks, totalFailures);
return totalFailures;
}
+112
View File
@@ -0,0 +1,112 @@
#include "ktest.h"
#include "list.h"
typedef struct TestItem {
int value;
ListNode node;
} TestItem;
KTEST(listEmptyInit)
{
ListNode head;
listInit(&head);
KT_TRUE(t, listEmpty(&head));
KT_EQ(t, listLen(&head), 0);
KT_NULL(t, listFront(&head));
KT_NULL(t, listBack(&head));
}
KTEST(listPushBackOrder)
{
ListNode head;
listInit(&head);
TestItem items[4];
for (int i = 0; i < 4; i++) {
items[i].value = i;
listPushBack(&head, &items[i].node);
}
KT_FALSE(t, listEmpty(&head));
KT_EQ(t, listLen(&head), 4);
int expected = 0;
ListNode* cursor;
listForEach(cursor, &head) {
TestItem* item = listEntry(cursor, TestItem, node);
KT_EQ(t, item->value, expected);
expected++;
}
KT_EQ(t, expected, 4);
TestItem* front = listEntry(listFront(&head), TestItem, node);
TestItem* back = listEntry(listBack(&head), TestItem, node);
KT_EQ(t, front->value, 0);
KT_EQ(t, back->value, 3);
}
KTEST(listPushFrontOrder)
{
ListNode head;
listInit(&head);
TestItem items[3];
for (int i = 0; i < 3; i++) {
items[i].value = i;
listPushFront(&head, &items[i].node);
}
/* pushing 0,1,2 to the front in order yields 2,1,0 */
int expected[3] = { 2, 1, 0 };
int idx = 0;
ListNode* cursor;
listForEach(cursor, &head) {
TestItem* item = listEntry(cursor, TestItem, node);
KT_EQ(t, item->value, expected[idx]);
idx++;
}
}
KTEST(listRemoveMiddle)
{
ListNode head;
listInit(&head);
TestItem items[3];
for (int i = 0; i < 3; i++) {
items[i].value = i;
listPushBack(&head, &items[i].node);
}
listRemove(&items[1].node);
KT_EQ(t, listLen(&head), 2);
int idx = 0;
int expected[2] = { 0, 2 };
ListNode* cursor;
listForEach(cursor, &head) {
TestItem* item = listEntry(cursor, TestItem, node);
KT_EQ(t, item->value, expected[idx]);
idx++;
}
/* a removed node becomes its own trivial list */
KT_TRUE(t, listEmpty(&items[1].node));
}
KTEST(listRemoveAllEmptiesList)
{
ListNode head;
listInit(&head);
TestItem items[2];
items[0].value = 10;
items[1].value = 20;
listPushBack(&head, &items[0].node);
listPushBack(&head, &items[1].node);
listRemove(&items[0].node);
listRemove(&items[1].node);
KT_TRUE(t, listEmpty(&head));
KT_EQ(t, listLen(&head), 0);
}