From f86b6bd2ba8e84be283e34166ff0ec0d516b0311 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sat, 18 Apr 2026 14:58:46 +0200 Subject: [PATCH 1/2] test(watch): add unit coverage for watch_get_checksum polling helper --- tests/unit/watch_checksum_test.sh | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 tests/unit/watch_checksum_test.sh diff --git a/tests/unit/watch_checksum_test.sh b/tests/unit/watch_checksum_test.sh new file mode 100644 index 00000000..64c094ab --- /dev/null +++ b/tests/unit/watch_checksum_test.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash + +# shellcheck disable=SC2329 # Test functions are invoked indirectly by bashunit + +############################ +# bashunit::main::watch_get_checksum +############################ + +function test_checksum_is_stable_for_unchanged_paths() { + local dir + dir=$(bashunit::temp_dir watch_stable) + : >"$dir/foo.sh" + + local first second + first=$(bashunit::main::watch_get_checksum "$dir") + second=$(bashunit::main::watch_get_checksum "$dir") + + assert_equals "$first" "$second" +} + +function test_checksum_changes_when_file_mtime_changes() { + local dir + dir=$(bashunit::temp_dir watch_change) + local file="$dir/foo.sh" + : >"$file" + touch -t 202001010000 "$file" + + local before after + before=$(bashunit::main::watch_get_checksum "$dir") + touch -t 202501010000 "$file" + after=$(bashunit::main::watch_get_checksum "$dir") + + assert_not_equals "$before" "$after" +} + +function test_checksum_differs_when_new_file_appears() { + local dir + dir=$(bashunit::temp_dir watch_new_file) + : >"$dir/a.sh" + + local before after + before=$(bashunit::main::watch_get_checksum "$dir") + : >"$dir/b.sh" + after=$(bashunit::main::watch_get_checksum "$dir") + + assert_not_equals "$before" "$after" +} + +function test_checksum_ignores_non_sh_files() { + local dir + dir=$(bashunit::temp_dir watch_non_sh) + : >"$dir/keep.sh" + + local before after + before=$(bashunit::main::watch_get_checksum "$dir") + : >"$dir/ignored.txt" + : >"$dir/ignored.md" + after=$(bashunit::main::watch_get_checksum "$dir") + + assert_equals "$before" "$after" +} + +function test_checksum_handles_single_file_path() { + local dir + dir=$(bashunit::temp_dir watch_file) + local file="$dir/single.sh" + : >"$file" + touch -t 202001010000 "$file" + + local before after + before=$(bashunit::main::watch_get_checksum "$file") + touch -t 202501010000 "$file" + after=$(bashunit::main::watch_get_checksum "$file") + + assert_not_equals "$before" "$after" +} + +function test_checksum_is_empty_for_missing_path() { + local missing="/nonexistent/path/$$/xyz" + + assert_empty "$(bashunit::main::watch_get_checksum "$missing")" +} From 160acfa7ecadbbe94c1e9dc8d1a7361caf4223e8 Mon Sep 17 00:00:00 2001 From: Chemaclass Date: Sat, 18 Apr 2026 15:06:47 +0200 Subject: [PATCH 2/2] fix(watch): prefer GNU stat for cross-platform checksum compatibility On Linux, `stat -f` returns filesystem info (not per-file mtime), so the checksum changed whenever any file on the filesystem changed, including non-.sh files. Reversed order to try GNU `stat -c` first and fall back to BSD `stat -f` on macOS. --- src/main.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main.sh b/src/main.sh index cb8a5908..40f3e134 100644 --- a/src/main.sh +++ b/src/main.sh @@ -543,14 +543,14 @@ function bashunit::main::watch_get_checksum() { if [ -d "$file" ]; then local found found=$(find "$file" -name '*.sh' -type f \ - -exec stat -f '%m %N' {} + 2>/dev/null || + -exec stat -c '%Y %n' {} + 2>/dev/null || find "$file" -name '*.sh' -type f \ - -exec stat -c '%Y %n' {} + 2>/dev/null) || true + -exec stat -f '%m %N' {} + 2>/dev/null) || true checksum="${checksum}${found}" elif [ -f "$file" ]; then local mtime - mtime=$(stat -f '%m' "$file" 2>/dev/null || - stat -c '%Y' "$file" 2>/dev/null) || true + mtime=$(stat -c '%Y' "$file" 2>/dev/null || + stat -f '%m' "$file" 2>/dev/null) || true checksum="${checksum}${mtime} ${file}" fi done