test: cover bytesEqual
This commit is contained in:
1 parent
b4fbcaf660
commit
2dd54aa236
1 file changed
+150
+150
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user