Skip to content

Commit 1cd4001

Browse files
andy5995claude
andauthored
Fix test isolation (#520)
* test: set HOME to fake home to prevent accidental writes to real HOME If RMW_FAKE_HOME is ever unset mid-script, rmw falls back to $HOME. Override HOME in the meson test environment so that fallback still lands in the sandbox rather than the real home directory. test_media_root.sh is excluded from the HOME override since it intentionally unsets RMW_FAKE_HOME to exercise real-home behavior; it skips automatically on machines without the expected mount point. Closes #519 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: rewrite test_media_root.sh to use /tmp instead of hardcoded paths The old test only ran on Andy's workstation (hardcoded /mnt/918375c2 mount point and /home/andy paths). The new approach: - Compares the device ID of /tmp with $HOME using stat - Skips if they are on the same device (test condition not met) - Otherwise uses /tmp as the simulated removable media root - Creates a temporary rmw config and waste folder under /tmp - Verifies the trashinfo Path is relative per FreeDesktop Trash spec - Cleans up after itself This makes the test portable and runnable on any system where /tmp is on a separate device (e.g. tmpfs on Linux CI runners). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: use hard-link probe instead of stat for cross-device detection stat flag syntax differs between GNU (-c) and BSD/macOS (-f), making the previous approach unreliable. Hard links only succeed within the same filesystem, so attempting ln across /tmp and $HOME gives a portable, unambiguous cross-device check on Linux, macOS, and FreeBSD. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: skip test_media_root.sh if /tmp is not a top-level mount Containers and macOS often have /tmp on the root filesystem, in which case rmw correctly writes an absolute path (not a topdir relative path). Use 'df -P' to check the mount point; skip silently if /tmp is not its own top-level mount rather than failing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: use /proc/mounts instead of df+awk to check /tmp mount awk is not available in all CI containers. /proc/mounts is a standard Linux procfs file with no external tool dependencies; grep on its second field reliably detects whether /tmp is its own top-level mount point. On macOS/BSD where /proc/mounts does not exist the grep exits non-zero and the test skips silently. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: add XDG sandboxing and cleanup trap Set XDG_DATA_HOME and XDG_CONFIG_HOME in the meson test environment so rmw cannot accidentally read/write the real user's XDG dirs during tests. Add a trap in test_media_root.sh to clean up /tmp dirs on failure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: suppress SC2329 on cleanup trap function shellcheck cannot see that cleanup() is called indirectly via trap. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ebf2c74 commit 1cd4001

File tree

2 files changed

+74
-43
lines changed

2 files changed

+74
-43
lines changed

test/meson.build

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,23 @@ foreach case : test_cases
3535
test('test_' + case, exe)
3636
endforeach
3737

38+
# Set HOME to the fake home so rmw falls back safely if RMW_FAKE_HOME is ever
39+
# unset mid-script, preventing accidental writes to the real home directory.
40+
test_env = [
41+
'MESON_SOURCE_ROOT=' + meson.project_source_root(),
42+
'RMW_FAKE_HOME=' + RMW_FAKE_HOME,
43+
'HOME=' + RMW_FAKE_HOME,
44+
'XDG_DATA_HOME=' + RMW_FAKE_HOME + '/.local/share',
45+
'XDG_CONFIG_HOME=' + RMW_FAKE_HOME + '/.config',
46+
'MESON_BUILD_ROOT=' + meson.project_build_root(),
47+
]
48+
3849
foreach s : scripts
3950
test(
4051
s,
4152
files(s),
42-
env: [
43-
'MESON_SOURCE_ROOT=' + meson.project_source_root(),
44-
'RMW_FAKE_HOME=' + RMW_FAKE_HOME,
45-
'MESON_BUILD_ROOT=' + meson.project_build_root(),
46-
],
53+
env: test_env,
4754
depends: main_bin,
4855
)
4956
endforeach
57+

test/test_media_root.sh

Lines changed: 61 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
# Path should be relative
44
#
55
#https://specifications.freedesktop.org/trash-spec/1.0/#id-1.6.10.1 The key
6-
#Path contains the original location of the file/directory, as either an
7-
#absolute pathname (starting with the slash character “/”) or a relative
6+
#"Path" contains the original location of the file/directory, as either an
7+
#absolute pathname (starting with the slash character "/") or a relative
88
#pathname (starting with any other character). A relative pathname is to be
99
#from the directory in which the trash directory resides (for example, from
10-
#$XDG_DATA_HOME for the home trash directory); it MUST not include a “..”
11-
#directory, and for files not under that directory, absolute pathnames must
12-
#be used. The system SHOULD support absolute pathnames only in the home trash
10+
#$XDG_DATA_HOME for the "home trash" directory); it MUST not include a ".."
11+
#directory, and for files not "under" that directory, absolute pathnames must
12+
#be used. The system SHOULD support absolute pathnames only in the "home trash"
1313
#directory, not in the directories under $topdir.
1414

1515
set -ve
@@ -20,45 +20,68 @@ else
2020
. "${MESON_SOURCE_ROOT}/test/COMMON"
2121
fi
2222

23-
# This test will only work on Andy's workstation.
24-
# The media root, /home/andy/src is on a different partition than /home/andy
25-
# It's mounted with 'bind' and therefore has a different device id
26-
test ! -d /mnt/918375c2 && exit 0;
27-
28-
# This test use Andy's regular config, outside of the test sandbox, so don't
29-
# run it if the epoch test setup is being used. Otherwise all the waste dirs
30-
# will be purged.
31-
test -n "$RMW_TEST_EPOCHALYPSE" && exit 0;
32-
echo "hello"
23+
# This test requires /tmp to be a top-level mount point on its own device so
24+
# that rmw will write a relative Path in the trashinfo. Check /proc/mounts
25+
# (Linux); on macOS/BSD where it doesn't exist the grep fails and we skip.
26+
if ! grep -q '^[^ ]* /tmp ' /proc/mounts 2>/dev/null; then
27+
echo "/tmp is not a top-level mount point; skipping"
28+
exit 0
29+
fi
3330

31+
# /tmp is on a different device — use it as the simulated media root.
32+
TRASH_DIR="/tmp/.Trash-$(id -u)"
33+
TEST_DIR="/tmp/rmw-media-root-test"
3434
test_file="media_root_test"
35-
PREV_RMW_FAKE_HOME=${RMW_FAKE_HOME}
36-
# needs to be unset so rmw will use $HOME instead
37-
unset RMW_FAKE_HOME
38-
mkdir -p "$PREV_RMW_FAKE_HOME"
39-
test_file_path=${PREV_RMW_FAKE_HOME}/$test_file
40-
if test -f "$test_file_path"; then
41-
rm "$test_file_path"
42-
fi
43-
if test -f /home/andy/src/rmw-project/.Trash-1000/files/$test_file; then
44-
rm /home/andy/src/rmw-project/.Trash-1000/files/$test_file
45-
fi
46-
if test -f /home/andy/src/rmw-project/.Trash-1000/info/$test_file.trashinfo; then
47-
rm /home/andy/src/rmw-project/.Trash-1000/info/$test_file.trashinfo
48-
fi
35+
test_file_path="$TEST_DIR/$test_file"
36+
37+
# shellcheck disable=SC2329
38+
cleanup() {
39+
rm -rf "$TRASH_DIR" "$TEST_DIR"
40+
}
41+
trap cleanup EXIT
42+
43+
# Clean up any leftovers from a previous run
44+
rm -rf "$TRASH_DIR" "$TEST_DIR"
45+
46+
# Create test config pointing the waste folder to /tmp
47+
mkdir -p "$RMW_FAKE_HOME"
48+
TEST_CONFIG="$RMW_FAKE_HOME/media-root.testrc"
49+
printf 'WASTE = /tmp/.Trash-%s, removable\nexpire_age = 90\n' "$(id -u)" > "$TEST_CONFIG"
50+
51+
# Create waste dir manually (required because it is marked removable)
52+
mkdir -p "$TRASH_DIR/files" "$TRASH_DIR/info"
53+
mkdir -p "$TEST_DIR"
54+
4955
touch "$test_file_path"
50-
"$BIN_DIR"/rmw -c /home/andy/.config/rmwrc "$test_file_path"
56+
"$BIN_DIR"/rmw -c "$TEST_CONFIG" "$test_file_path"
5157

52-
output=$(grep Path /home/andy/src/rmw-project/.Trash-1000/info/$test_file.trashinfo)
58+
test -f "$TRASH_DIR/info/$test_file.trashinfo"
59+
test -f "$TRASH_DIR/files/$test_file"
60+
test ! -f "$test_file_path"
5361

54-
# There should be no leading '/' in the filename.
55-
path_expected=$(echo "${MESON_BUILD_ROOT}" | sed -e "s/\/home\/andy\/src\/rmw-project\///g")
56-
echo "$path_expected"
57-
test "$output" = "Path=${path_expected}/test/rmw-tests-home/test_media_root.sh_dir/media_root_test"
62+
# The Path must be relative (no leading '/') since the waste folder is at
63+
# the topdir of /tmp's partition.
64+
output=$(grep '^Path=' "$TRASH_DIR/info/$test_file.trashinfo")
65+
echo "trashinfo: $output"
66+
case "$output" in
67+
Path=/*)
68+
echo "FAIL: Path is absolute, expected relative"
69+
exit 1
70+
;;
71+
Path=*)
72+
echo "PASS: Path is relative"
73+
;;
74+
*)
75+
echo "FAIL: Path line not found"
76+
exit 1
77+
;;
78+
esac
5879

59-
output=$("$BIN_DIR"/rmw -uvv -c /home/andy/.config/rmwrc | grep media_root_test)
80+
# Restore and verify
81+
"$BIN_DIR"/rmw -uvv -c "$TEST_CONFIG"
82+
test -f "$test_file_path"
83+
test ! -f "$TRASH_DIR/info/$test_file.trashinfo"
6084

61-
test "$output" = "+'/home/andy/src/rmw-project/.Trash-1000/files/media_root_test' -> '${MESON_BUILD_ROOT}/test/rmw-tests-home/test_media_root.sh_dir/media_root_test'
62-
-/home/andy/src/rmw-project/.Trash-1000/info/media_root_test.trashinfo"
85+
rm -f "$TEST_CONFIG"
6386

6487
exit 0

0 commit comments

Comments
 (0)