git: 8fd4d1c0fff8 - main - tests: Add pjdfstest integration

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Fri, 19 Jun 2026 15:39:57 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=8fd4d1c0fff8441b42dbab767810db7aeaf796c3

commit 8fd4d1c0fff8441b42dbab767810db7aeaf796c3
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-06-19 13:27:04 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-06-19 15:20:51 +0000

    tests: Add pjdfstest integration
    
    Use ATF to wrap the new reimplementation of pjdfstest that came out of
    GSOC 2022, now available in the ports tree as filesystems/pjdfstest.
    
    So far I added tests for UFS (with several different option
    combinations), tmpfs and ZFS, plus ZFS+nullfs.  All of these create a
    memory disk, initialize the filesystem, and point the pjdfstest
    executable at it.
    
    In the future it would be good to add tests for at least NFS and p9fs.
    
    Reviewed by:    asomers
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D56605
---
 etc/mtree/BSD.tests.dist        |   2 +
 tests/sys/fs/Makefile           |   1 +
 tests/sys/fs/pjdfstest/Makefile |  12 ++++
 tests/sys/fs/pjdfstest/tmpfs.sh |  60 +++++++++++++++++++
 tests/sys/fs/pjdfstest/ufs.sh   | 130 ++++++++++++++++++++++++++++++++++++++++
 tests/sys/fs/pjdfstest/zfs.sh   |  96 +++++++++++++++++++++++++++++
 6 files changed, 301 insertions(+)

diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index b6c415e9e789..3c3662c11502 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -834,6 +834,8 @@
         fs
             fusefs
             ..
+            pjdfstest
+            ..
             tarfs
             ..
             tmpfs
diff --git a/tests/sys/fs/Makefile b/tests/sys/fs/Makefile
index 254394f43714..823a31a4dbbe 100644
--- a/tests/sys/fs/Makefile
+++ b/tests/sys/fs/Makefile
@@ -12,6 +12,7 @@ TESTSRC=		${SRCTOP}/contrib/netbsd-tests/fs
 .if ${COMPILER_FEATURES:Mc++14} && ${MK_GOOGLETEST} != "no"
 TESTS_SUBDIRS+=		fusefs
 .endif
+TESTS_SUBDIRS+=		pjdfstest
 TESTS_SUBDIRS+=		tarfs
 TESTS_SUBDIRS+=		tmpfs
 TESTS_SUBDIRS+=		unionfs
diff --git a/tests/sys/fs/pjdfstest/Makefile b/tests/sys/fs/pjdfstest/Makefile
new file mode 100644
index 000000000000..62e937198e34
--- /dev/null
+++ b/tests/sys/fs/pjdfstest/Makefile
@@ -0,0 +1,12 @@
+TESTSDIR=	${TESTSBASE}/sys/fs/pjdfstest
+
+PACKAGE=	tests
+
+ATF_TESTS_SH+=	tmpfs	\
+		ufs	\
+		zfs
+
+# Tests use an external resource.
+TEST_METADATA.p9fs+=	is_exclusive=true
+
+.include <bsd.test.mk>
diff --git a/tests/sys/fs/pjdfstest/tmpfs.sh b/tests/sys/fs/pjdfstest/tmpfs.sh
new file mode 100644
index 000000000000..cd56acbd04c6
--- /dev/null
+++ b/tests/sys/fs/pjdfstest/tmpfs.sh
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2026 Mark Johnston <markj@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+setup()
+{
+	cat <<__EOF__ > pjdfstest.toml
+[features]
+chflags = {}
+posix_fallocate = {}
+rename_ctime = {}
+stat_st_birthtime = {}
+utimensat = {}
+utime_now = {}
+
+[settings]
+naptime = 0.001
+__EOF__
+
+	atf_check mkdir mnt
+	atf_check mount -t tmpfs none mnt
+}
+
+doit()
+{
+	atf_check -o ignore pjdfstest -c pjdfstest.toml -p mnt
+	atf_check umount mnt
+	atf_check rmdir mnt
+}
+
+cleanup()
+{
+	if [ -d ./mnt ]; then
+		umount ./mnt
+	fi
+}
+
+atf_test_case tmpfs cleanup
+tmpfs_head()
+{
+	atf_set descr "Checks that pjdfstest passes on tmpfs"
+	atf_set require.progs pjdfstest
+	atf_set require.user root
+}
+tmpfs_body()
+{
+	setup
+	doit
+}
+tmpfs_cleanup()
+{
+	cleanup
+}
+
+atf_init_test_cases()
+{
+	atf_add_test_case tmpfs
+}
diff --git a/tests/sys/fs/pjdfstest/ufs.sh b/tests/sys/fs/pjdfstest/ufs.sh
new file mode 100644
index 000000000000..4bba5698df00
--- /dev/null
+++ b/tests/sys/fs/pjdfstest/ufs.sh
@@ -0,0 +1,130 @@
+#
+# Copyright (c) 2026 Mark Johnston <markj@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+setup()
+{
+	local md
+
+	atf_check -o save:md mdconfig -a -t swap -s 1g
+	md=/dev/$(cat md)
+	atf_check -o ignore -e ignore newfs -t $@ $md
+
+	cat <<__EOF__ > pjdfstest.toml
+[features]
+chflags = {}
+posix_fallocate = {}
+rename_ctime = {}
+stat_st_birthtime = {}
+utimensat = {}
+utime_now = {}
+
+[settings]
+naptime = 0.001
+__EOF__
+
+	atf_check mkdir mnt
+	atf_check mount $md ./mnt
+}
+
+doit()
+{
+	atf_check -o ignore pjdfstest -c pjdfstest.toml -p mnt
+	atf_check umount ./mnt
+	atf_check rmdir ./mnt
+}
+
+cleanup()
+{
+	if [ -d ./mnt ]; then
+		umount ./mnt
+	fi
+	if [ -s md ]; then
+		mdconfig -d -u $(cat md)
+	fi
+}
+
+atf_test_case ufs1 cleanup
+ufs1_head()
+{
+	atf_set descr "Run pjdfstest on a UFS1 filesystem"
+	atf_set require.user root
+	atf_set require.progs pjdfstest
+}
+ufs1_body()
+{
+	setup -O 1
+	# UFS1 doesn't have 64-bit timestamps or a birthtime field in the inode.
+	cat >> pjdfstest.toml <<__EOF__
+expected_failures = [
+"utimensat::birthtime",
+"utimensat::y2038"
+]
+__EOF__
+	doit
+}
+ufs1_cleanup()
+{
+	cleanup
+}
+
+atf_test_case ufs2_nosu cleanup
+ufs2_nosu_head()
+{
+	atf_set descr "Run pjdfstest on a UFS2 filesystem without soft updates"
+	atf_set require.user root
+	atf_set require.progs pjdfstest
+}
+ufs2_nosu_body()
+{
+	setup -O 2 -u
+	doit
+}
+ufs2_nosu_cleanup()
+{
+	cleanup
+}
+
+atf_test_case ufs2_su cleanup
+ufs2_su_head()
+{
+	atf_set descr "Run pjdfstest on a UFS2 filesystem with soft updates"
+	atf_set require.user root
+	atf_set require.progs pjdfstest
+}
+ufs2_su_body()
+{
+	setup -O 2 -U
+	doit
+}
+ufs2_su_cleanup()
+{
+	cleanup
+}
+
+atf_test_case ufs2_suj cleanup
+ufs2_suj_head()
+{
+	atf_set descr "Run pjdfstest on a UFS2 filesystem with soft updates journaling"
+	atf_set require.user root
+	atf_set require.progs pjdfstest
+}
+ufs2_suj_body()
+{
+	setup -O 2 -U -j
+	doit
+}
+ufs2_suj_cleanup()
+{
+	cleanup
+}
+
+atf_init_test_cases()
+{
+	atf_add_test_case ufs1
+	atf_add_test_case ufs2_nosu
+	atf_add_test_case ufs2_su
+	atf_add_test_case ufs2_suj
+}
diff --git a/tests/sys/fs/pjdfstest/zfs.sh b/tests/sys/fs/pjdfstest/zfs.sh
new file mode 100644
index 000000000000..44e539b7abd2
--- /dev/null
+++ b/tests/sys/fs/pjdfstest/zfs.sh
@@ -0,0 +1,96 @@
+#
+# Copyright (c) 2026 Mark Johnston <markj@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+setup()
+{
+	local disk pool
+
+	truncate -s 1g disk
+
+	cat <<__EOF__ > pjdfstest.toml
+[features]
+chflags = {}
+rename_ctime = {}
+stat_st_birthtime = {}
+utimensat = {}
+utime_now = {}
+
+[settings]
+naptime = 0.001
+__EOF__
+
+	atf_check mkdir mnt
+	pool=pjdfstest$$
+	atf_check zpool create -m $(pwd)/mnt $pool $(pwd)/disk
+	echo $pool > pool
+}
+
+doit()
+{
+	local mp
+
+	mp=${1:-mnt}
+	atf_check -o ignore pjdfstest -c pjdfstest.toml -p $mp
+	if [ "$mp" != "mnt" ]; then
+		atf_check umount $mp
+		atf_check rmdir $mp
+	fi
+	atf_check zpool destroy $(cat pool)
+	atf_check rm -f pool
+}
+
+cleanup()
+{
+	if [ -s pool ]; then
+		zpool destroy $(cat pool)
+	fi
+}
+
+atf_test_case zfs cleanup
+zfs_head()
+{
+	atf_set descr "Checks that pjdfstest passes on zfs"
+	atf_set require.user root
+	atf_set require.progs pjdfstest
+}
+zfs_body()
+{
+	setup
+	doit
+}
+zfs_cleanup()
+{
+	cleanup
+}
+
+atf_test_case zfs_nullfs cleanup
+zfs_nullfs_head()
+{
+	atf_set descr "Checks that pjdfstest passes on zfs mounted via nullfs"
+	atf_set require.user root
+	atf_set require.progs pjdfstest
+}
+zfs_nullfs_body()
+{
+	setup
+	atf_check mkdir mnt2
+	atf_check mount -t nullfs mnt mnt2
+	doit mnt2
+}
+zfs_nullfs_cleanup()
+{
+	if [ -d mnt2 ]; then
+		umount mnt2
+		rmdir mnt2
+	fi
+	cleanup
+}
+
+atf_init_test_cases()
+{
+	atf_add_test_case zfs
+	atf_add_test_case zfs_nullfs
+}