test: cover ktestStrEq, ktestCheck and TestItem
This commit is contained in:
1 parent
95ae1a2165
commit
b00aa4cd74
2 files changed
+171
No files matched your search
+59
@@ -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
@@ -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);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user