test: cover bytesEqual

This commit is contained in:
dualfroz committed 2026-09-12 19:42:30 +02:00
1 parent b4fbcaf660
commit 2dd54aa236
1 file changed
+150
+150
View File
@@ -0,0 +1,150 @@
#include "ulib.h"
#include "fs.h"
/*
* Exercises the persistent SFS filesystem (sfs.h/sfs.c) through the exact
* same syscall path a real userspace program would use: open/write/read/
* close/mkdir/getdents/unlink on paths under "/mnt", which vfs.c dispatches
* to sfs.c instead of the kmalloc-based tmpfs tree. Proves the full stack
* (syscall -> vfs -> sfs -> real block I/O on the same ATA disk /dev/disk0
* uses) works end to end, not just the in-kernel sfs.c unit tests.
*/
static int bytesEqual(const char* a, const char* b, unsigned long n)
{
for (unsigned long i = 0; i < n; i++)
if (a[i] != b[i])
return 0;
return 1;
}
int main(void)
{
print("fstest: start, pid=");
printDec(userGetpid());
print("\n");
/* Nested directory creation. */
if (userMkdir("/mnt/app") != 0) {
print("fstest: FAIL mkdir /mnt/app\n");
return 1;
}
if (userMkdir("/mnt/app/logs") != 0) {
print("fstest: FAIL mkdir /mnt/app/logs\n");
return 1;
}
/* Create + write + close, then reopen with a fresh fd to prove the data
lives past the writer's own fd, not just in that fd's local state. */
const char* payload = "frostbyte fstest payload line one\n";
unsigned long payloadLen = stringLength(payload);
int wfd = (int)userOpen("/mnt/app/logs/boot.log", oReadWrite | oCreate);
if (wfd < 0) {
print("fstest: FAIL open for create\n");
return 1;
}
if (userWrite(wfd, payload, payloadLen) != (long)payloadLen) {
print("fstest: FAIL short write\n");
return 1;
}
userClose(wfd);
FbStat st;
if (userStat("/mnt/app/logs/boot.log", &st) != 0 || st.size != payloadLen) {
print("fstest: FAIL stat size mismatch\n");
return 1;
}
int rfd = (int)userOpen("/mnt/app/logs/boot.log", oReadOnly);
if (rfd < 0) {
print("fstest: FAIL reopen\n");
return 1;
}
char back[128];
long got = userRead(rfd, back, sizeof(back));
if (got != (long)payloadLen || !bytesEqual(back, payload, payloadLen)) {
print("fstest: FAIL reopen round-trip mismatch\n");
return 1;
}
userClose(rfd);
print("fstest: create/write/reopen/read round-trip ok\n");
/* Append across two separate open() calls: growth must pick up where
the previous session's data ended. */
int afd = (int)userOpen("/mnt/app/logs/boot.log", oReadWrite | oAppend);
if (afd < 0) {
print("fstest: FAIL open for append\n");
return 1;
}
const char* more = "line two\n";
unsigned long moreLen = stringLength(more);
if (userWrite(afd, more, moreLen) != (long)moreLen) {
print("fstest: FAIL append write\n");
return 1;
}
userClose(afd);
if (userStat("/mnt/app/logs/boot.log", &st) != 0 || st.size != payloadLen + moreLen) {
print("fstest: FAIL stat after append\n");
return 1;
}
print("fstest: append across reopen ok\n");
/* A second, unrelated file in the same directory, to exercise readdir
against more than one entry. */
int cfd = (int)userOpen("/mnt/app/logs/counters.txt", oReadWrite | oCreate);
if (cfd < 0) {
print("fstest: FAIL create second file\n");
return 1;
}
userWrite(cfd, "0", 1);
userClose(cfd);
int dfd = (int)userOpen("/mnt/app/logs", oReadOnly);
if (dfd < 0) {
print("fstest: FAIL open dir for listing\n");
return 1;
}
FbDirent entries[8];
long entCount = userGetdents(dfd, entries, sizeof(entries));
userClose(dfd);
if (entCount != 2 * (long)sizeof(FbDirent)) {
print("fstest: FAIL readdir entry count\n");
return 1;
}
int sawBoot = 0, sawCounters = 0;
for (int i = 0; i < 2; i++) {
if (entries[i].type != fsTypeFile) {
print("fstest: FAIL readdir entry type\n");
return 1;
}
if (bytesEqual(entries[i].name, "boot.log", 9))
sawBoot = 1;
if (bytesEqual(entries[i].name, "counters.txt", 13))
sawCounters = 1;
}
if (!sawBoot || !sawCounters) {
print("fstest: FAIL readdir missing an expected entry\n");
return 1;
}
print("fstest: readdir lists both files ok\n");
/* Unlink one, verify it is gone and its sibling survives. */
if (userUnlink("/mnt/app/logs/counters.txt") != 0) {
print("fstest: FAIL unlink counters.txt\n");
return 1;
}
if (userStat("/mnt/app/logs/counters.txt", &st) == 0) {
print("fstest: FAIL unlinked file still stat-able\n");
return 1;
}
if (userStat("/mnt/app/logs/boot.log", &st) != 0) {
print("fstest: FAIL sibling disappeared after unlink\n");
return 1;
}
print("fstest: unlink ok, sibling survives\n");
print("fstest: done\n");
return 0;
}