[pseudo][PATCH 3/6] tests: Add test that returned stat is correct
Mark Hatle <[email protected]>
| Newsgroups | org.yoctoproject.lists.yocto-patches |
|---|---|
| Message-ID | <[email protected]> |
From: Mark Hatle <[email protected]> There are concerns that if PSEUDO_FS_MODE and PSEUDO_DB_MODE get out of sync with each other that invalid modules could be returned in some cases. AI-Generated: Implemented with the assistance of github CoPilot (Claude Opus 4.6) Signed-off-by: Mark Hatle <[email protected]> Signed-off-by: Mark Hatle <[email protected]> --- test/test-db-mode.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/test-db-mode.sh | 10 +++++ 2 files changed, 127 insertions(+) create mode 100644 test/test-db-mode.c create mode 100755 test/test-db-mode.sh diff --git a/test/test-db-mode.c b/test/test-db-mode.c new file mode 100644 index 0000000..1e470c2 --- /dev/null +++ b/test/test-db-mode.c @@ -0,0 +1,117 @@ +/* + * Test that PSEUDO_DB_MODE correctly reconstructs permissions at file + * creation time. PSEUDO_DB_MODE is used when a file is created (open + * with O_CREAT, mkdir, etc.) to recover the intended mode from the + * filesystem mode (which has been mangled by PSEUDO_FS_MODE). + * + * If PSEUDO_DB_MODE is broken, the mode stored in the database at + * creation time will be wrong, which we detect by stat'ing immediately + * after creation (before any chmod). + * + * SPDX-License-Identifier: LGPL-2.1-only + */ + +#include <sys/stat.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> + +static int test_creat_mode(mode_t mode) { + const char *path = "test-db-mode-tmp"; + struct stat st; + + /* Remove any prior file */ + unlink(path); + + /* Clear umask so it doesn't interfere */ + mode_t old_umask = umask(0); + + int fd = open(path, O_CREAT | O_WRONLY | O_EXCL, mode); + if (fd < 0) { + perror("open"); + umask(old_umask); + return 1; + } + close(fd); + + if (stat(path, &st) != 0) { + perror("stat"); + unlink(path); + umask(old_umask); + return 1; + } + + mode_t got = st.st_mode & 07777; + unlink(path); + umask(old_umask); + + if (got != mode) { + fprintf(stderr, "FAIL: open(O_CREAT, 0%04o) -> stat 0%04o\n", mode, got); + return 1; + } + return 0; +} + +static int test_mkdir_mode(mode_t mode) { + const char *path = "test-db-mode-dir-tmp"; + struct stat st; + + rmdir(path); + + mode_t old_umask = umask(0); + + if (mkdir(path, mode) != 0) { + perror("mkdir"); + umask(old_umask); + return 1; + } + + if (stat(path, &st) != 0) { + perror("stat"); + rmdir(path); + umask(old_umask); + return 1; + } + + mode_t got = st.st_mode & 07777; + rmdir(path); + umask(old_umask); + + if (got != mode) { + fprintf(stderr, "FAIL: mkdir(0%04o) -> stat 0%04o\n", mode, got); + return 1; + } + return 0; +} + +int main(void) { + int failures = 0; + int total = 0; + + /* Test all octet values simultaneously: 00000, 01111, 02222, ..., 07777 */ + mode_t modes[] = { + 00000, 01111, 02222, 03333, 04444, 05555, 06666, 07777, + }; + int num_modes = sizeof(modes) / sizeof(modes[0]); + + for (int i = 0; i < num_modes; i++) { + total++; + if (test_creat_mode(modes[i]) != 0) + failures++; + } + + for (int i = 0; i < num_modes; i++) { + total++; + if (test_mkdir_mode(modes[i]) != 0) + failures++; + } + + if (failures > 0) { + fprintf(stderr, "%d/%d mode tests failed\n", failures, total); + return 2; + } + return 0; +} diff --git a/test/test-db-mode.sh b/test/test-db-mode.sh new file mode 100755 index 0000000..b3e97ad --- /dev/null +++ b/test/test-db-mode.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# +# SPDX-License-Identifier: LGPL-2.1-only +# +# Test that PSEUDO_DB_MODE correctly reconstructs permission bits +# at file/directory creation time. + +trap "rm -rf test-db-mode-tmp test-db-mode-dir-tmp" EXIT + +./test/test-db-mode -- 1.8.3.1