diff --git a/src/coreTest.c b/src/coreTest.c new file mode 100644 index 0000000..04d29c2 --- /dev/null +++ b/src/coreTest.c @@ -0,0 +1,157 @@ +#include "ktest.h" +#include "string.h" +#include "heap.h" +#include "pmm.h" +#include "vfs.h" +#include "fs.h" +#include "sfs.h" + +/* + * Regression coverage for the subsystems that already existed before the + * in-kernel test harness: the freestanding string routines, the free-list + * heap, the physical frame allocator and the VFS/tmpfs path. These run + * against the live kernel, so a regression in any of them fails the boot gate. + */ + +KTEST(coreStringMem) +{ + char buf[32]; + + memset(buf, 'A', sizeof(buf)); + KT_EQ(t, buf[0], 'A'); + KT_EQ(t, buf[31], 'A'); + + memset(buf, 0, sizeof(buf)); + KT_EQ(t, buf[0], 0); + + const char* src = "frostbyte"; + memcpy(buf, src, 10); + KT_STREQ(t, buf, "frostbyte"); + KT_EQ(t, strlen(buf), 9); + + KT_EQ(t, memcmp("abc", "abc", 3), 0); + KT_TRUE(t, memcmp("abc", "abd", 3) < 0); + KT_TRUE(t, memcmp("abd", "abc", 3) > 0); + + KT_EQ(t, strcmp("abc", "abc"), 0); + KT_TRUE(t, strcmp("abc", "abd") < 0); + KT_EQ(t, strncmp("abcdef", "abcxxx", 3), 0); + KT_TRUE(t, strncmp("abcdef", "abcxxx", 4) != 0); +} + +KTEST(coreMemmoveOverlap) +{ + char buf[16]; + memcpy(buf, "0123456789", 11); + + /* forward overlap: dest > src */ + memmove(buf + 2, buf, 8); + buf[10] = 0; + KT_STREQ(t, buf, "0101234567"); + + memcpy(buf, "0123456789", 11); + /* backward overlap: dest < src */ + memmove(buf, buf + 2, 8); + buf[8] = 0; + KT_STREQ(t, buf, "23456789"); +} + +KTEST(coreHeapAllocFree) +{ + uint64 freeBefore = heapFreeBytes(); + + void* a = kmalloc(100); + void* b = kmalloc(200); + void* c = kmalloc(100); + KT_NOTNULL(t, a); + KT_NOTNULL(t, b); + KT_NOTNULL(t, c); + KT_NE(t, a, b); + KT_NE(t, b, c); + + /* freeing b and re-allocating a same-or-smaller block reuses the hole */ + kfree(b); + void* d = kmalloc(150); + KT_EQP(t, d, b); + + kfree(a); + kfree(c); + kfree(d); + + /* everything returned: free bytes back to (at least) where we started */ + KT_GE(t, heapFreeBytes(), freeBefore); +} + +KTEST(coreHeapRealloc) +{ + char* p = (char*)kmalloc(8); + KT_NOTNULL(t, p); + memcpy(p, "1234567", 8); + + p = (char*)krealloc(p, 64); + KT_NOTNULL(t, p); + KT_STREQ(t, p, "1234567"); /* contents preserved across grow */ + + p = (char*)krealloc(p, 4); + KT_NOTNULL(t, p); + KT_EQ(t, memcmp(p, "1234", 4), 0); + + kfree(p); +} + +KTEST(corePmmAllocDistinct) +{ + uint64 freeBefore = pmmFreeFrames(); + + uint64 f1 = pmmAlloc(); + uint64 f2 = pmmAlloc(); + uint64 f3 = pmmAlloc(); + KT_NE(t, f1, 0); + KT_NE(t, f2, 0); + KT_NE(t, f3, 0); + KT_NE(t, f1, f2); + KT_NE(t, f2, f3); + KT_NE(t, f1, f3); + KT_EQ(t, f1 & (frameSize - 1), 0); /* page aligned */ + + KT_EQ(t, pmmFreeFrames(), freeBefore - 3); + + pmmFree(f1); + pmmFree(f2); + pmmFree(f3); + KT_EQ(t, pmmFreeFrames(), freeBefore); +} + +KTEST(coreVfsTmpfsRoundtrip) +{ + int fd = vfsOpen("/tmp/coretest.txt", oReadWrite | oCreate | oTrunc); + KT_GE(t, fd, 0); + if (fd < 0) + return; + + const char* msg = "hello vfs"; + KT_EQ(t, vfsWrite(fd, msg, 9), 9); + + KT_EQ(t, vfsLseek(fd, 0, seekSet), 0); + char rd[16]; + memset(rd, 0, sizeof(rd)); + KT_EQ(t, vfsRead(fd, rd, 9), 9); + KT_STREQ(t, rd, "hello vfs"); + + KT_EQ(t, vfsLseek(fd, 0, seekEnd), 9); + vfsClose(fd); + + FbStat st; + KT_EQ(t, vfsStat("/tmp/coretest.txt", &st), 0); + KT_EQ(t, st.size, 9); + KT_EQ(t, st.type, fsTypeFile); + + KT_EQ(t, vfsUnlink("/tmp/coretest.txt"), 0); + KT_EQ(t, vfsStat("/tmp/coretest.txt", &st), -1); /* gone */ +} + +KTEST(coreVfsMkdirGetdents) +{ + KT_EQ(t, vfsMkdir("/tmp/cd"), 0); + KT_EQ(t, vfsMkdir("/tmp/cd"), -1); /* already exists */ +