test: cover sfsTest
This commit is contained in:
1 parent
1c9f3c093a
commit
e1daed794e
1 file changed
+156
+156
@@ -0,0 +1,156 @@
|
||||
#include "ktest.h"
|
||||
#include "sfs.h"
|
||||
#include "ata.h"
|
||||
#include "string.h"
|
||||
#include "heap.h"
|
||||
#include "console.h"
|
||||
#include "rtc.h"
|
||||
#include "fs.h"
|
||||
|
||||
/*
|
||||
* Every test starts with an explicit sfsFormat() so results do not depend on
|
||||
* whatever build/disk.img happened to contain from a previous `make test`
|
||||
* run (the disk image is not recreated between runs unless deleted). That
|
||||
* keeps the gate deterministic: a stale leftover file on disk must never be
|
||||
* the reason a check passes or fails.
|
||||
*/
|
||||
|
||||
KTEST(sfsFormatAndMountAreReal)
|
||||
{
|
||||
if (!KT_TRUE(t, ataPresent()))
|
||||
return;
|
||||
KT_TRUE(t, sfsFormat());
|
||||
KT_TRUE(t, sfsMounted());
|
||||
KT_GT(t, sfsCapacityBytes(), 1024 * 1024);
|
||||
|
||||
int32 root = sfsLookup("");
|
||||
KT_EQ(t, root, sfsRootInode);
|
||||
KT_EQ(t, sfsTypeOf(root), sfsTypeDir);
|
||||
KT_EQ(t, sfsSizeOf(root), 0);
|
||||
}
|
||||
|
||||
KTEST(sfsCreateFileRoundTrip)
|
||||
{
|
||||
if (!KT_TRUE(t, sfsFormat()))
|
||||
return;
|
||||
|
||||
int32 f = sfsCreateFile("hello.txt");
|
||||
KT_TRUE(t, f > 0);
|
||||
KT_EQ(t, sfsTypeOf(f), sfsTypeFile);
|
||||
KT_EQ(t, sfsSizeOf(f), 0);
|
||||
|
||||
const char* msg = "hello, disk!";
|
||||
uint64 len = strlen(msg);
|
||||
KT_EQ(t, sfsWriteAt(f, 0, msg, len), (int64)len);
|
||||
KT_EQ(t, sfsSizeOf(f), len);
|
||||
|
||||
char back[32];
|
||||
memset(back, 0, sizeof(back));
|
||||
KT_EQ(t, sfsReadAt(f, 0, back, len), (int64)len);
|
||||
KT_EQ(t, memcmp(back, msg, len), 0);
|
||||
}
|
||||
|
||||
KTEST(sfsOverwriteReflectsLatestData)
|
||||
{
|
||||
if (!KT_TRUE(t, sfsFormat()))
|
||||
return;
|
||||
|
||||
int32 f = sfsCreateFile("a.bin");
|
||||
KT_TRUE(t, f > 0);
|
||||
KT_EQ(t, sfsWriteAt(f, 0, "AAAA", 4), 4);
|
||||
KT_EQ(t, sfsWriteAt(f, 0, "BB", 2), 2);
|
||||
|
||||
char back[4];
|
||||
KT_EQ(t, sfsReadAt(f, 0, back, 4), 4);
|
||||
KT_EQ(t, memcmp(back, "BBAA", 4), 0);
|
||||
KT_EQ(t, sfsSizeOf(f), 4);
|
||||
}
|
||||
|
||||
KTEST(sfsWritePastEndZeroFillsGap)
|
||||
{
|
||||
if (!KT_TRUE(t, sfsFormat()))
|
||||
return;
|
||||
|
||||
int32 f = sfsCreateFile("gap.bin");
|
||||
KT_TRUE(t, f > 0);
|
||||
KT_EQ(t, sfsWriteAt(f, 10, "X", 1), 1);
|
||||
KT_EQ(t, sfsSizeOf(f), 11);
|
||||
|
||||
uint8 back[11];
|
||||
KT_EQ(t, sfsReadAt(f, 0, back, 11), 11);
|
||||
for (int i = 0; i < 10; i++)
|
||||
KT_EQ(t, back[i], 0);
|
||||
KT_EQ(t, back[10], 'X');
|
||||
}
|
||||
|
||||
KTEST(sfsMultiBlockFileSpansDirectPointers)
|
||||
{
|
||||
if (!KT_TRUE(t, sfsFormat()))
|
||||
return;
|
||||
|
||||
int32 f = sfsCreateFile("multi.bin");
|
||||
KT_TRUE(t, f > 0);
|
||||
|
||||
/* Big enough to span several blocks: kmalloc'd rather than kept on the
|
||||
stack, matching the rbt/slab stress-test convention (this ktest
|
||||
battery runs on the fixed 16 KiB boot stack, not a per-thread one). */
|
||||
#define sfsTestSpan (3 * sfsBlockSize + 200)
|
||||
uint8* pattern = (uint8*)kmalloc(sfsTestSpan);
|
||||
uint8* back = (uint8*)kmalloc(sfsTestSpan);
|
||||
KT_NOTNULL(t, pattern);
|
||||
KT_NOTNULL(t, back);
|
||||
if (!pattern || !back) {
|
||||
kfree(pattern);
|
||||
kfree(back);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < sfsTestSpan; i++)
|
||||
pattern[i] = (uint8)(i * 31 + 7);
|
||||
|
||||
KT_EQ(t, sfsWriteAt(f, 0, pattern, sfsTestSpan), sfsTestSpan);
|
||||
KT_EQ(t, sfsSizeOf(f), sfsTestSpan);
|
||||
|
||||
memset(back, 0, sfsTestSpan);
|
||||
KT_EQ(t, sfsReadAt(f, 0, back, sfsTestSpan), sfsTestSpan);
|
||||
KT_EQ(t, memcmp(back, pattern, sfsTestSpan), 0);
|
||||
|
||||
kfree(pattern);
|
||||
kfree(back);
|
||||
#undef sfsTestSpan
|
||||
}
|
||||
|
||||
KTEST(sfsFileGrowsThroughIndirectBlock)
|
||||
{
|
||||
if (!KT_TRUE(t, sfsFormat()))
|
||||
return;
|
||||
|
||||
int32 f = sfsCreateFile("big.bin");
|
||||
KT_TRUE(t, f > 0);
|
||||
|
||||
/* 10 direct blocks (5120 bytes) plus a chunk that only the single
|
||||
indirect block can address: this must reach past sfsDirectBlocks.
|
||||
kmalloc'd (three of these at once would be ~18 KiB, more than the
|
||||
whole 16 KiB boot stack ktest runs on). */
|
||||
#define sfsBigSpan (12 * sfsBlockSize + 33)
|
||||
uint8* pattern = (uint8*)kmalloc(sfsBigSpan);
|
||||
uint8* back = (uint8*)kmalloc(sfsBigSpan);
|
||||
uint8* verify = (uint8*)kmalloc(sfsBigSpan);
|
||||
KT_NOTNULL(t, pattern);
|
||||
KT_NOTNULL(t, back);
|
||||
KT_NOTNULL(t, verify);
|
||||
if (!pattern || !back || !verify) {
|
||||
kfree(pattern);
|
||||
kfree(back);
|
||||
kfree(verify);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < sfsBigSpan; i++)
|
||||
pattern[i] = (uint8)(i ^ 0x5A);
|
||||
|
||||
KT_EQ(t, sfsWriteAt(f, 0, pattern, sfsBigSpan), sfsBigSpan);
|
||||
KT_EQ(t, sfsSizeOf(f), sfsBigSpan);
|
||||
|
||||
memset(back, 0, sfsBigSpan);
|
||||
KT_EQ(t, sfsReadAt(f, 0, back, sfsBigSpan), sfsBigSpan);
|
||||
KT_EQ(t, memcmp(back, pattern, sfsBigSpan), 0);
|
||||
|
||||
Reference in new issue
Block a user