summaryrefslogtreecommitdiff
path: root/na/test/test_vfs_io.cc
diff options
context:
space:
mode:
Diffstat (limited to 'na/test/test_vfs_io.cc')
-rw-r--r--na/test/test_vfs_io.cc345
1 files changed, 0 insertions, 345 deletions
diff --git a/na/test/test_vfs_io.cc b/na/test/test_vfs_io.cc
deleted file mode 100644
index 3d3b125..0000000
--- a/na/test/test_vfs_io.cc
+++ /dev/null
@@ -1,345 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-/*
- * test_vfs_io.cc — Self-tests for VFS file I/O via syscalls
- *
- * Tests openat, read, write, close, lseek, dup, fstat, getdents64,
- * getcwd, chdir, and mkdirat through the kernel syscall layer.
- */
-
-#include <lume/selftest.h>
-#include <lume/errno.h>
-#include <lume/file.h>
-#include <lume/fs.h>
-#include <lume/fs_types.h>
-#include <lume/task.h>
-#include <lume/fdtable.h>
-
-/* Syscall entry points */
-int64 sys_openat(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_close(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_read(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_write(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_lseek(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_dup(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_dup3(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_fstat_wrapper(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_getcwd(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_chdir(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_mkdirat(uint64, uint64, uint64, uint64, uint64, uint64);
-int64 sys_getdents64(uint64, uint64, uint64, uint64, uint64, uint64);
-
-/* Helper: open a file, returns fd or negative error */
-static int64 open_file(const char* path, int flags, uint32 mode)
-{
- return sys_openat(
- static_cast<uint64>(-100), /* AT_FDCWD */
- reinterpret_cast<uint64>(path),
- static_cast<uint64>(flags),
- static_cast<uint64>(mode), 0, 0);
-}
-
-void selftest_vfs_io()
-{
- /* ---- openat O_CREAT creates a file ---- */
- st_begin("vfs_io: openat O_CREAT creates file");
- {
- int64 fd = open_file("/vfs_test_file", O_CREAT | O_WRONLY, 0644);
- ST_ASSERT(fd >= 0);
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- openat existing file ---- */
- st_begin("vfs_io: openat existing file succeeds");
- {
- int64 fd = open_file("/vfs_test_file", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- openat nonexistent without O_CREAT returns -ENOENT ---- */
- st_begin("vfs_io: openat nonexistent returns -ENOENT");
- {
- int64 fd = open_file("/no_such_file_ever", O_RDONLY, 0);
- ST_ASSERT_EQ(fd, (int64)-ENOENT);
- }
- st_pass();
-
- /* ---- write then read ---- */
- st_begin("vfs_io: write then read back data");
- {
- /* Write */
- int64 fd = open_file("/vfs_rw_test", O_CREAT | O_WRONLY, 0644);
- ST_ASSERT(fd >= 0);
-
- const char* msg = "Hello VFS!";
- int64 written = sys_write(
- static_cast<uint64>(fd),
- reinterpret_cast<uint64>(msg),
- 10, 0, 0, 0);
- ST_ASSERT_EQ(written, (int64)10);
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
-
- /* Read */
- fd = open_file("/vfs_rw_test", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
-
- char buf[32] = {};
- int64 nread = sys_read(
- static_cast<uint64>(fd),
- reinterpret_cast<uint64>(buf),
- sizeof(buf), 0, 0, 0);
- ST_ASSERT_EQ(nread, (int64)10);
-
- bool match = true;
- for (int i = 0; i < 10; i++) {
- if (buf[i] != msg[i]) { match = false; break; }
- }
- ST_ASSERT(match);
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- read past EOF returns 0 ---- */
- st_begin("vfs_io: read past EOF returns 0");
- {
- int64 fd = open_file("/vfs_rw_test", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
-
- char buf[64];
- /* First read: 10 bytes */
- int64 n1 = sys_read(static_cast<uint64>(fd),
- reinterpret_cast<uint64>(buf), 64, 0, 0, 0);
- ST_ASSERT_EQ(n1, (int64)10);
-
- /* Second read: should be 0 (EOF) */
- int64 n2 = sys_read(static_cast<uint64>(fd),
- reinterpret_cast<uint64>(buf), 64, 0, 0, 0);
- ST_ASSERT_EQ(n2, (int64)0);
-
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- O_TRUNC clears file content ---- */
- st_begin("vfs_io: O_TRUNC clears file content");
- {
- int64 fd = open_file("/vfs_rw_test", O_WRONLY | O_TRUNC, 0);
- ST_ASSERT(fd >= 0);
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
-
- fd = open_file("/vfs_rw_test", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
-
- char buf[16];
- int64 n = sys_read(static_cast<uint64>(fd),
- reinterpret_cast<uint64>(buf), 16, 0, 0, 0);
- ST_ASSERT_EQ(n, (int64)0); /* truncated = empty */
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- close invalid fd returns -EBADF ---- */
- st_begin("vfs_io: close bad fd returns -EBADF");
- {
- int64 ret = sys_close(999, 0, 0, 0, 0, 0);
- ST_ASSERT_EQ(ret, (int64)-EBADF);
- }
- st_pass();
-
- /* ---- read/write on bad fd returns -EBADF ---- */
- st_begin("vfs_io: read/write bad fd returns -EBADF");
- {
- char buf[8];
- int64 r = sys_read(999, reinterpret_cast<uint64>(buf), 8, 0, 0, 0);
- ST_ASSERT_EQ(r, (int64)-EBADF);
-
- int64 w = sys_write(999, reinterpret_cast<uint64>(buf), 8, 0, 0, 0);
- ST_ASSERT_EQ(w, (int64)-EBADF);
- }
- st_pass();
-
- /* ---- lseek SEEK_SET / SEEK_CUR / SEEK_END ---- */
- st_begin("vfs_io: lseek SEEK_SET/CUR/END");
- {
- /* Write 20 bytes */
- int64 fd = open_file("/vfs_lseek_test", O_CREAT | O_RDWR, 0644);
- ST_ASSERT(fd >= 0);
-
- char data[20];
- for (int i = 0; i < 20; i++) data[i] = static_cast<char>('A' + i);
- sys_write(static_cast<uint64>(fd),
- reinterpret_cast<uint64>(data), 20, 0, 0, 0);
-
- /* SEEK_SET to 5 */
- int64 pos = sys_lseek(static_cast<uint64>(fd), 5, SEEK_SET, 0, 0, 0);
- ST_ASSERT_EQ(pos, (int64)5);
-
- /* Read 1 byte, should be 'F' */
- char c = 0;
- sys_read(static_cast<uint64>(fd),
- reinterpret_cast<uint64>(&c), 1, 0, 0, 0);
- ST_ASSERT_EQ(c, 'F');
-
- /* SEEK_CUR +3 → pos 9 */
- pos = sys_lseek(static_cast<uint64>(fd), 3, SEEK_CUR, 0, 0, 0);
- ST_ASSERT_EQ(pos, (int64)9);
-
- /* SEEK_END -1 → pos 19 */
- pos = sys_lseek(static_cast<uint64>(fd), -1, SEEK_END, 0, 0, 0);
- ST_ASSERT_EQ(pos, (int64)19);
-
- sys_read(static_cast<uint64>(fd),
- reinterpret_cast<uint64>(&c), 1, 0, 0, 0);
- ST_ASSERT_EQ(c, 'T');
-
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- lseek invalid whence returns -EINVAL ---- */
- st_begin("vfs_io: lseek invalid whence");
- {
- int64 fd = open_file("/vfs_lseek_test", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
- int64 ret = sys_lseek(static_cast<uint64>(fd), 0, 99, 0, 0, 0);
- ST_ASSERT_EQ(ret, (int64)-EINVAL);
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- dup: duplicate fd shares file position ---- */
- st_begin("vfs_io: dup shares file position");
- {
- int64 fd1 = open_file("/vfs_lseek_test", O_RDONLY, 0);
- ST_ASSERT(fd1 >= 0);
-
- int64 fd2 = sys_dup(static_cast<uint64>(fd1), 0, 0, 0, 0, 0);
- ST_ASSERT(fd2 >= 0);
- ST_ASSERT_NE(fd1, fd2);
-
- /* Both should work for reading */
- char c = 0;
- int64 n = sys_read(static_cast<uint64>(fd2),
- reinterpret_cast<uint64>(&c), 1, 0, 0, 0);
- ST_ASSERT_EQ(n, (int64)1);
-
- sys_close(static_cast<uint64>(fd1), 0, 0, 0, 0, 0);
- sys_close(static_cast<uint64>(fd2), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- fstat: basic stat ---- */
- st_begin("vfs_io: fstat returns valid kstat");
- {
- int64 fd = open_file("/vfs_lseek_test", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
-
- kstat st{};
- int64 ret = sys_fstat_wrapper(
- static_cast<uint64>(fd),
- reinterpret_cast<uint64>(&st), 0, 0, 0, 0);
- ST_ASSERT_EQ(ret, (int64)0);
- ST_ASSERT(S_ISREG(st.st_mode));
- ST_ASSERT_EQ(st.st_size, (int64)20);
-
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- getcwd: returns "/" ---- */
- st_begin("vfs_io: getcwd returns /");
- {
- char buf[64] = {};
- int64 len = sys_getcwd(
- reinterpret_cast<uint64>(buf), 64, 0, 0, 0, 0);
- ST_ASSERT(len > 0);
- ST_ASSERT_EQ(buf[0], '/');
- }
- st_pass();
-
- /* ---- mkdirat: create directory ---- */
- st_begin("vfs_io: mkdirat creates directory");
- {
- int64 ret = sys_mkdirat(
- static_cast<uint64>(-100),
- reinterpret_cast<uint64>("/vfs_io_dir"),
- 0755, 0, 0, 0);
- ST_ASSERT_EQ(ret, (int64)0);
-
- /* Open it to confirm it's a directory */
- int64 fd = open_file("/vfs_io_dir", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
-
- kstat st{};
- sys_fstat_wrapper(static_cast<uint64>(fd),
- reinterpret_cast<uint64>(&st), 0, 0, 0, 0);
- ST_ASSERT(S_ISDIR(st.st_mode));
-
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- getdents64: list root directory ---- */
- st_begin("vfs_io: getdents64 lists root children");
- {
- int64 fd = open_file("/", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
-
- char buf[512] = {};
- int64 n = sys_getdents64(
- static_cast<uint64>(fd),
- reinterpret_cast<uint64>(buf),
- 512, 0, 0, 0);
- ST_ASSERT(n > 0); /* At least "." and ".." */
-
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- write to O_RDONLY fd returns -EBADF ---- */
- st_begin("vfs_io: write to O_RDONLY returns -EBADF");
- {
- int64 fd = open_file("/vfs_rw_test", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
-
- char buf[] = "x";
- int64 w = sys_write(static_cast<uint64>(fd),
- reinterpret_cast<uint64>(buf), 1, 0, 0, 0);
- ST_ASSERT_EQ(w, (int64)-EBADF);
- sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- }
- st_pass();
-
- /* ---- double close returns -EBADF ---- */
- st_begin("vfs_io: double close returns -EBADF");
- {
- int64 fd = open_file("/vfs_rw_test", O_RDONLY, 0);
- ST_ASSERT(fd >= 0);
-
- int64 r1 = sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- ST_ASSERT_EQ(r1, (int64)0);
-
- int64 r2 = sys_close(static_cast<uint64>(fd), 0, 0, 0, 0, 0);
- ST_ASSERT_EQ(r2, (int64)-EBADF);
- }
- st_pass();
-
- /* ---- fd reuse after close ---- */
- st_begin("vfs_io: fd reuse after close");
- {
- int64 fd1 = open_file("/vfs_rw_test", O_RDONLY, 0);
- ST_ASSERT(fd1 >= 0);
- sys_close(static_cast<uint64>(fd1), 0, 0, 0, 0, 0);
-
- int64 fd2 = open_file("/vfs_rw_test", O_RDONLY, 0);
- ST_ASSERT(fd2 >= 0);
- /* fd2 should reuse the slot of fd1 */
- ST_ASSERT(fd2 <= fd1);
- sys_close(static_cast<uint64>(fd2), 0, 0, 0, 0, 0);
- }
- st_pass();
-}