]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
tests: add automated tests for VFS/mount bug fixes
authorTulio A M Mendes <[email protected]>
Tue, 26 May 2026 02:11:09 +0000 (23:11 -0300)
committerTulio A M Mendes <[email protected]>
Wed, 3 Jun 2026 04:02:35 +0000 (01:02 -0300)
Added 4 new automated tests in fulltest.c:
- I16: MS_REMOUNT - verify remount updates flags correctly
- I17: Mount replace rejection - verify mount without MS_REMOUNT fails
- I18: ftruncate readonly - verify ftruncate respects MS_RDONLY
- I19: Mountpoint validation - verify mount fails on non-existent or non-directory mountpoints

Updated test harnesses:
- smoke_test.exp: added 4 new test patterns (119→123 tests)
- test_battery.exp: added 4 new test patterns (27→31 tests)

Added missing errno constants (EBUSY, ENOENT, ENOTDIR) to fulltest.c

Test results:
- Smoke test: 123/123 PASS
- Zero regressions

tests/smoke_test.exp
tests/test_battery.exp
user/cmds/fulltest/fulltest.c

index 220cb8a3b60777c361732db4f674a487fbd66928..07a7929b9930631715296e508c7a3b3943b725d2 100755 (executable)
@@ -157,6 +157,10 @@ set tests {
     {"MS_RDONLY enforcement" "\\[test\\] MS_RDONLY enforcement OK"}
     {"MS_NODEV enforcement"  "\\[test\\] MS_NODEV enforcement OK"}
     {"busy umount"          "\\[test\\] busy umount OK"}
+    {"MS_REMOUNT"          "\\[test\\] MS_REMOUNT OK"}
+    {"mount replace rejection" "\\[test\\] mount replace rejection OK"}
+    {"ftruncate readonly"   "\\[test\\] ftruncate readonly OK"}
+    {"mountpoint validation" "\\[test\\] mountpoint validation OK"}
     {"sigqueue"            "\\[test\\] sigqueue OK"}
     {"clone"               "\\[test\\] clone OK"}
     {"inotify_init1"       "\\[test\\] inotify_init1 OK"}
index 104a7ac1b8a9561df317dc55273769a49e913875..272d97064d77009686df07eb6733bb97fa4070d9 100644 (file)
@@ -264,6 +264,10 @@ set patterns {
     {"MS_RDONLY enforcement" "\\[test\\] MS_RDONLY enforcement OK"}
     {"MS_NODEV enforcement"  "\\[test\\] MS_NODEV enforcement OK"}
     {"busy umount"          "\\[test\\] busy umount OK"}
+    {"MS_REMOUNT"          "\\[test\\] MS_REMOUNT OK"}
+    {"mount replace rejection" "\\[test\\] mount replace rejection OK"}
+    {"ftruncate readonly"   "\\[test\\] ftruncate readonly OK"}
+    {"mountpoint validation" "\\[test\\] mountpoint validation OK"}
     {"sigqueue"            "\\[test\\] sigqueue OK"}
     {"clone"               "\\[test\\] clone OK"}
     {"inotify_init1"       "\\[test\\] inotify_init1 OK"}
index 2190171f576f74f7e1b374d2d274de76e4421141..2cf577234f8a1e781becca74427e5d347f38c346 100644 (file)
@@ -322,6 +322,9 @@ enum {
     EAGAIN = 11,
     EINVAL = 22,
     EEXIST = 17,
+    EBUSY = 16,
+    ENOENT = 2,
+    ENOTDIR = 20,
 };
 
 enum {
@@ -5132,6 +5135,133 @@ void _start(void) {
                   (uint32_t)(sizeof("[test] busy umount OK\n") - 1));
     }
 
+    // I16: MS_REMOUNT — update flags on existing mount
+    {
+        (void)sys_mkdir("/tmp/mnt_remount");
+        if (sys_mount("none", "/tmp/mnt_remount", "tmpfs", 0) < 0) {
+            sys_write(1, "[test] remount: initial mount failed\n",
+                      (uint32_t)(sizeof("[test] remount: initial mount failed\n") - 1));
+            sys_exit(1);
+        }
+        /* Remount with MS_RDONLY */
+        if (sys_mount("none", "/tmp/mnt_remount", "tmpfs", MS_REMOUNT | MS_RDONLY) < 0) {
+            sys_write(1, "[test] remount: remount failed\n",
+                      (uint32_t)(sizeof("[test] remount: remount failed\n") - 1));
+            sys_exit(1);
+        }
+        /* Write should now fail on read-only mount */
+        int fd = sys_openat(AT_FDCWD, "/tmp/mnt_remount/test.txt", O_CREAT | O_RDWR, 0644);
+        if (fd >= 0) {
+            sys_write(1, "[test] remount: write should fail after ro remount\n",
+                      (uint32_t)(sizeof("[test] remount: write should fail after ro remount\n") - 1));
+            sys_exit(1);
+        }
+        if (sys_umount2("/tmp/mnt_remount") < 0) {
+            sys_write(1, "[test] remount: umount failed\n",
+                      (uint32_t)(sizeof("[test] remount: umount failed\n") - 1));
+            sys_exit(1);
+        }
+        sys_write(1, "[test] MS_REMOUNT OK\n",
+                  (uint32_t)(sizeof("[test] MS_REMOUNT OK\n") - 1));
+    }
+
+    // I17: Mount replace rejection — mount without MS_REMOUNT should fail
+    {
+        (void)sys_mkdir("/tmp/mnt_replace");
+        if (sys_mount("none", "/tmp/mnt_replace", "tmpfs", 0) < 0) {
+            sys_write(1, "[test] replace: initial mount failed\n",
+                      (uint32_t)(sizeof("[test] replace: initial mount failed\n") - 1));
+            sys_exit(1);
+        }
+        /* Mount without MS_REMOUNT should fail */
+        int rc = sys_mount("none", "/tmp/mnt_replace", "tmpfs", 0);
+        if (rc >= 0) {
+            sys_write(1, "[test] replace: mount should fail\n",
+                      (uint32_t)(sizeof("[test] replace: mount should fail\n") - 1));
+            sys_exit(1);
+        }
+        if (sys_umount2("/tmp/mnt_replace") < 0) {
+            sys_write(1, "[test] replace: umount failed\n",
+                      (uint32_t)(sizeof("[test] replace: umount failed\n") - 1));
+            sys_exit(1);
+        }
+        sys_write(1, "[test] mount replace rejection OK\n",
+                  (uint32_t)(sizeof("[test] mount replace rejection OK\n") - 1));
+    }
+
+    // I18: ftruncate respects MS_RDONLY
+    {
+        (void)sys_mkdir("/tmp/mnt_ftrunc");
+        if (sys_mount("none", "/tmp/mnt_ftrunc", "tmpfs", 0) < 0) {
+            sys_write(1, "[test] ftrunc: mount failed\n",
+                      (uint32_t)(sizeof("[test] ftrunc: mount failed\n") - 1));
+            sys_exit(1);
+        }
+        int fd = sys_openat(AT_FDCWD, "/tmp/mnt_ftrunc/test.txt", O_CREAT | O_RDWR, 0644);
+        if (fd < 0) {
+            sys_write(1, "[test] ftrunc: file create failed\n",
+                      (uint32_t)(sizeof("[test] ftrunc: file create failed\n") - 1));
+            sys_exit(1);
+        }
+        sys_write(fd, "hello", 5);
+        sys_close(fd);
+        /* Remount read-only */
+        if (sys_mount("none", "/tmp/mnt_ftrunc", "tmpfs", MS_REMOUNT | MS_RDONLY) < 0) {
+            sys_write(1, "[test] ftrunc: remount ro failed\n",
+                      (uint32_t)(sizeof("[test] ftrunc: remount ro failed\n") - 1));
+            sys_exit(1);
+        }
+        /* Open read-only (should succeed) */
+        fd = sys_openat(AT_FDCWD, "/tmp/mnt_ftrunc/test.txt", O_RDONLY, 0);
+        if (fd < 0) {
+            sys_write(1, "[test] ftrunc: open ro failed\n",
+                      (uint32_t)(sizeof("[test] ftrunc: open ro failed\n") - 1));
+            sys_exit(1);
+        }
+        /* ftruncate should fail on read-only mount even with file open for read */
+        if (sys_ftruncate(fd, 10) >= 0) {
+            sys_write(1, "[test] ftrunc: ftruncate should fail on ro mount\n",
+                      (uint32_t)(sizeof("[test] ftrunc: ftruncate should fail on ro mount\n") - 1));
+            sys_exit(1);
+        }
+        sys_close(fd);
+        if (sys_umount2("/tmp/mnt_ftrunc") < 0) {
+            sys_write(1, "[test] ftrunc: umount failed\n",
+                      (uint32_t)(sizeof("[test] ftrunc: umount failed\n") - 1));
+            sys_exit(1);
+        }
+        sys_write(1, "[test] ftruncate readonly OK\n",
+                  (uint32_t)(sizeof("[test] ftruncate readonly OK\n") - 1));
+    }
+
+    // I19: Mountpoint validation — mount should fail if mountpoint doesn't exist
+    {
+        int rc = sys_mount("none", "/tmp/nonexistent_mnt", "tmpfs", 0);
+        if (rc >= 0) {
+            sys_write(1, "[test] mountpoint: should fail\n",
+                      (uint32_t)(sizeof("[test] mountpoint: should fail\n") - 1));
+            sys_exit(1);
+        }
+        /* Create a file instead of directory */
+        int fd = sys_openat(AT_FDCWD, "/tmp/not_a_dir", O_CREAT | O_RDWR, 0644);
+        if (fd < 0) {
+            sys_write(1, "[test] mountpoint: file create failed\n",
+                      (uint32_t)(sizeof("[test] mountpoint: file create failed\n") - 1));
+            sys_exit(1);
+        }
+        sys_close(fd);
+        /* Mount on file should fail */
+        rc = sys_mount("none", "/tmp/not_a_dir", "tmpfs", 0);
+        if (rc >= 0) {
+            sys_write(1, "[test] mountpoint: should fail on file\n",
+                      (uint32_t)(sizeof("[test] mountpoint: should fail on file\n") - 1));
+            sys_exit(1);
+        }
+        sys_unlinkat(AT_FDCWD, "/tmp/not_a_dir", 0);
+        sys_write(1, "[test] mountpoint validation OK\n",
+                  (uint32_t)(sizeof("[test] mountpoint validation OK\n") - 1));
+    }
+
     // I13: clone — create a thread sharing address space
     {
         /* We use a simple clone with CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND