* [PATCH] t7527: fix flaky fsmonitor event tests with retry logic
@ 2025-12-31 23:40 Paul Tarjan via GitGitGadget
2026-01-01 0:19 ` [PATCH v2] " Paul Tarjan via GitGitGadget
0 siblings, 1 reply; 2+ messages in thread
From: Paul Tarjan via GitGitGadget @ 2025-12-31 23:40 UTC (permalink / raw)
To: git; +Cc: Paul Tarjan, Paul Tarjan
From: Paul Tarjan <github@paulisageek.com>
The fsmonitor event tests (edit, create, delete, rename, etc.) were
flaky because there can be a race between the daemon writing events
to the trace file and the test's grep commands checking for them.
Add a retry_grep() helper function (similar to retry_until_success
in lib-git-p4.sh) that retries grep with a timeout, and use it in
all event-checking tests to wait for one expected event before
checking the rest.
Signed-off-by: Paul Tarjan <github@paulisageek.com>
---
t7527: fix flaky fsmonitor event tests with retry logic
This failed in
https://github.com/git/git/actions/runs/20628166110/job/59242063331 on
an unrelated commit.
The fsmonitor event tests (edit, create, delete, rename, etc.) were
flaky because there can be a race between the daemon writing events to
the trace file and the test's grep commands checking for them.
Add a retry_grep() helper function (similar to retry_until_success in
lib-git-p4.sh) that retries grep with a timeout, and use it in all
event-checking tests to wait for one expected event before checking the
rest.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2150%2Fptarjan%2Fclaude%2Ffix-fsmonitor-test-jsXoE-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2150/ptarjan/claude/fix-fsmonitor-test-jsXoE-v1
Pull-Request: https://github.com/git/git/pull/2150
t/t7527-builtin-fsmonitor.sh | 51 +++++++++++++++++++-----------------
1 file changed, 27 insertions(+), 24 deletions(-)
diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh
index 409cd0cd12..68a10a2100 100755
--- a/t/t7527-builtin-fsmonitor.sh
+++ b/t/t7527-builtin-fsmonitor.sh
@@ -408,9 +408,8 @@ move_directory() {
# ensure we are getting the OS notifications and do not try to confirm what
# is reported by `git status`.
#
-# We run a simple query after modifying the filesystem just to introduce
-# a bit of a delay so that the trace logging from the daemon has time to
-# get flushed to disk.
+# We use retry_grep to handle races between the daemon writing events
+# to the trace file and our check.
#
# We `reset` and `clean` at the bottom of each test (and before stopping the
# daemon) because these commands might implicitly restart the daemon.
@@ -422,6 +421,24 @@ clean_up_repo_and_stop_daemon () {
rm -f .git/trace
}
+# Retry a grep up to RETRY_TIMEOUT times until it succeeds.
+#
+RETRY_TIMEOUT=5
+
+retry_grep () {
+ nr_tries_left=$RETRY_TIMEOUT
+ until grep "$1" "$2" 2>/dev/null
+ do
+ if test $nr_tries_left -eq 0
+ then
+ grep "$1" "$2"
+ return
+ fi
+ nr_tries_left=$(($nr_tries_left - 1))
+ sleep 1
+ done
+}
+
test_expect_success 'edit some files' '
test_when_finished clean_up_repo_and_stop_daemon &&
@@ -429,9 +446,7 @@ test_expect_success 'edit some files' '
edit_files &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/modified$" .git/trace &&
+ retry_grep "^event: dir1/modified$" .git/trace &&
grep "^event: dir2/modified$" .git/trace &&
grep "^event: modified$" .git/trace &&
grep "^event: dir1/untracked$" .git/trace
@@ -444,9 +459,7 @@ test_expect_success 'create some files' '
create_files &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/new$" .git/trace &&
+ retry_grep "^event: dir1/new$" .git/trace &&
grep "^event: dir2/new$" .git/trace &&
grep "^event: new$" .git/trace
'
@@ -458,9 +471,7 @@ test_expect_success 'delete some files' '
delete_files &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/delete$" .git/trace &&
+ retry_grep "^event: dir1/delete$" .git/trace &&
grep "^event: dir2/delete$" .git/trace &&
grep "^event: delete$" .git/trace
'
@@ -472,9 +483,7 @@ test_expect_success 'rename some files' '
rename_files &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/rename$" .git/trace &&
+ retry_grep "^event: dir1/rename$" .git/trace &&
grep "^event: dir2/rename$" .git/trace &&
grep "^event: rename$" .git/trace &&
grep "^event: dir1/renamed$" .git/trace &&
@@ -489,9 +498,7 @@ test_expect_success 'rename directory' '
mv dirtorename dirrenamed &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dirtorename/*$" .git/trace &&
+ retry_grep "^event: dirtorename/*$" .git/trace &&
grep "^event: dirrenamed/*$" .git/trace
'
@@ -502,9 +509,7 @@ test_expect_success 'file changes to directory' '
file_to_directory &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: delete$" .git/trace &&
+ retry_grep "^event: delete$" .git/trace &&
grep "^event: delete/new$" .git/trace
'
@@ -515,9 +520,7 @@ test_expect_success 'directory changes to a file' '
directory_to_file &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1$" .git/trace
+ retry_grep "^event: dir1$" .git/trace
'
# The next few test cases exercise the token-resync code. When filesystem
base-commit: 68cb7f9e92a5d8e9824f5b52ac3d0a9d8f653dbe
--
gitgitgadget
^ permalink raw reply related [flat|nested] 2+ messages in thread* [PATCH v2] t7527: fix flaky fsmonitor event tests with retry logic
2025-12-31 23:40 [PATCH] t7527: fix flaky fsmonitor event tests with retry logic Paul Tarjan via GitGitGadget
@ 2026-01-01 0:19 ` Paul Tarjan via GitGitGadget
0 siblings, 0 replies; 2+ messages in thread
From: Paul Tarjan via GitGitGadget @ 2026-01-01 0:19 UTC (permalink / raw)
To: git; +Cc: Paul Tarjan, Paul Tarjan
From: Paul Tarjan <github@paulisageek.com>
The fsmonitor event tests (edit, create, delete, rename, etc.) were
flaky because there can be a race between the daemon writing events
to the trace file and the test's grep commands checking for them.
Add a retry_grep() helper function (similar to retry_until_success
in lib-git-p4.sh) that retries grep with a timeout, and use it in
all event-checking tests to wait for one expected event before
checking the rest.
Signed-off-by: Paul Tarjan <github@paulisageek.com>
---
t7527: fix flaky fsmonitor event tests with retry logic
This failed in
https://github.com/git/git/actions/runs/20628166110/job/59242063331 on
an unrelated commit.
The fsmonitor event tests (edit, create, delete, rename, etc.) were
flaky because there can be a race between the daemon writing events to
the trace file and the test's grep commands checking for them.
Add a retry_grep() helper function (similar to retry_until_success in
lib-git-p4.sh) that retries grep with a timeout, and use it in all
event-checking tests to wait for one expected event before checking the
rest.
Changes since v1:
* Use retry_grep for all event checks, not just the first one (any
event can be delayed)
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2150%2Fptarjan%2Fclaude%2Ffix-fsmonitor-test-jsXoE-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2150/ptarjan/claude/fix-fsmonitor-test-jsXoE-v2
Pull-Request: https://github.com/git/git/pull/2150
Range-diff vs v1:
1: 6fafc812e1 ! 1: c275732e95 t7527: fix flaky fsmonitor event tests with retry logic
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'edit some files' '
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/modified$" .git/trace &&
+- grep "^event: dir2/modified$" .git/trace &&
+- grep "^event: modified$" .git/trace &&
+- grep "^event: dir1/untracked$" .git/trace
+ retry_grep "^event: dir1/modified$" .git/trace &&
- grep "^event: dir2/modified$" .git/trace &&
- grep "^event: modified$" .git/trace &&
- grep "^event: dir1/untracked$" .git/trace
++ retry_grep "^event: dir2/modified$" .git/trace &&
++ retry_grep "^event: modified$" .git/trace &&
++ retry_grep "^event: dir1/untracked$" .git/trace
+ '
+
+ test_expect_success 'create some files' '
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'create some files' '
create_files &&
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'create some files' '
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/new$" .git/trace &&
+- grep "^event: dir2/new$" .git/trace &&
+- grep "^event: new$" .git/trace
+ retry_grep "^event: dir1/new$" .git/trace &&
- grep "^event: dir2/new$" .git/trace &&
- grep "^event: new$" .git/trace
++ retry_grep "^event: dir2/new$" .git/trace &&
++ retry_grep "^event: new$" .git/trace
'
+
+ test_expect_success 'delete some files' '
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'delete some files' '
delete_files &&
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'delete some files' '
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/delete$" .git/trace &&
+- grep "^event: dir2/delete$" .git/trace &&
+- grep "^event: delete$" .git/trace
+ retry_grep "^event: dir1/delete$" .git/trace &&
- grep "^event: dir2/delete$" .git/trace &&
- grep "^event: delete$" .git/trace
++ retry_grep "^event: dir2/delete$" .git/trace &&
++ retry_grep "^event: delete$" .git/trace
'
+
+ test_expect_success 'rename some files' '
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'rename some files' '
rename_files &&
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'rename some files' '
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/rename$" .git/trace &&
+- grep "^event: dir2/rename$" .git/trace &&
+- grep "^event: rename$" .git/trace &&
+- grep "^event: dir1/renamed$" .git/trace &&
+- grep "^event: dir2/renamed$" .git/trace &&
+- grep "^event: renamed$" .git/trace
+ retry_grep "^event: dir1/rename$" .git/trace &&
- grep "^event: dir2/rename$" .git/trace &&
- grep "^event: rename$" .git/trace &&
- grep "^event: dir1/renamed$" .git/trace &&
++ retry_grep "^event: dir2/rename$" .git/trace &&
++ retry_grep "^event: rename$" .git/trace &&
++ retry_grep "^event: dir1/renamed$" .git/trace &&
++ retry_grep "^event: dir2/renamed$" .git/trace &&
++ retry_grep "^event: renamed$" .git/trace
+ '
+
+ test_expect_success 'rename directory' '
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'rename directory' '
mv dirtorename dirrenamed &&
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'rename directory' '
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dirtorename/*$" .git/trace &&
+- grep "^event: dirrenamed/*$" .git/trace
+ retry_grep "^event: dirtorename/*$" .git/trace &&
- grep "^event: dirrenamed/*$" .git/trace
++ retry_grep "^event: dirrenamed/*$" .git/trace
'
+ test_expect_success 'file changes to directory' '
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'file changes to directory' '
file_to_directory &&
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'file changes to directory' '
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: delete$" .git/trace &&
+- grep "^event: delete/new$" .git/trace
+ retry_grep "^event: delete$" .git/trace &&
- grep "^event: delete/new$" .git/trace
++ retry_grep "^event: delete/new$" .git/trace
'
+ test_expect_success 'directory changes to a file' '
@@ t/t7527-builtin-fsmonitor.sh: test_expect_success 'directory changes to a file' '
directory_to_file &&
t/t7527-builtin-fsmonitor.sh | 79 +++++++++++++++++++-----------------
1 file changed, 41 insertions(+), 38 deletions(-)
diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh
index 409cd0cd12..e7b4065469 100755
--- a/t/t7527-builtin-fsmonitor.sh
+++ b/t/t7527-builtin-fsmonitor.sh
@@ -408,9 +408,8 @@ move_directory() {
# ensure we are getting the OS notifications and do not try to confirm what
# is reported by `git status`.
#
-# We run a simple query after modifying the filesystem just to introduce
-# a bit of a delay so that the trace logging from the daemon has time to
-# get flushed to disk.
+# We use retry_grep to handle races between the daemon writing events
+# to the trace file and our check.
#
# We `reset` and `clean` at the bottom of each test (and before stopping the
# daemon) because these commands might implicitly restart the daemon.
@@ -422,6 +421,24 @@ clean_up_repo_and_stop_daemon () {
rm -f .git/trace
}
+# Retry a grep up to RETRY_TIMEOUT times until it succeeds.
+#
+RETRY_TIMEOUT=5
+
+retry_grep () {
+ nr_tries_left=$RETRY_TIMEOUT
+ until grep "$1" "$2" 2>/dev/null
+ do
+ if test $nr_tries_left -eq 0
+ then
+ grep "$1" "$2"
+ return
+ fi
+ nr_tries_left=$(($nr_tries_left - 1))
+ sleep 1
+ done
+}
+
test_expect_success 'edit some files' '
test_when_finished clean_up_repo_and_stop_daemon &&
@@ -429,12 +446,10 @@ test_expect_success 'edit some files' '
edit_files &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/modified$" .git/trace &&
- grep "^event: dir2/modified$" .git/trace &&
- grep "^event: modified$" .git/trace &&
- grep "^event: dir1/untracked$" .git/trace
+ retry_grep "^event: dir1/modified$" .git/trace &&
+ retry_grep "^event: dir2/modified$" .git/trace &&
+ retry_grep "^event: modified$" .git/trace &&
+ retry_grep "^event: dir1/untracked$" .git/trace
'
test_expect_success 'create some files' '
@@ -444,11 +459,9 @@ test_expect_success 'create some files' '
create_files &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/new$" .git/trace &&
- grep "^event: dir2/new$" .git/trace &&
- grep "^event: new$" .git/trace
+ retry_grep "^event: dir1/new$" .git/trace &&
+ retry_grep "^event: dir2/new$" .git/trace &&
+ retry_grep "^event: new$" .git/trace
'
test_expect_success 'delete some files' '
@@ -458,11 +471,9 @@ test_expect_success 'delete some files' '
delete_files &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/delete$" .git/trace &&
- grep "^event: dir2/delete$" .git/trace &&
- grep "^event: delete$" .git/trace
+ retry_grep "^event: dir1/delete$" .git/trace &&
+ retry_grep "^event: dir2/delete$" .git/trace &&
+ retry_grep "^event: delete$" .git/trace
'
test_expect_success 'rename some files' '
@@ -472,14 +483,12 @@ test_expect_success 'rename some files' '
rename_files &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1/rename$" .git/trace &&
- grep "^event: dir2/rename$" .git/trace &&
- grep "^event: rename$" .git/trace &&
- grep "^event: dir1/renamed$" .git/trace &&
- grep "^event: dir2/renamed$" .git/trace &&
- grep "^event: renamed$" .git/trace
+ retry_grep "^event: dir1/rename$" .git/trace &&
+ retry_grep "^event: dir2/rename$" .git/trace &&
+ retry_grep "^event: rename$" .git/trace &&
+ retry_grep "^event: dir1/renamed$" .git/trace &&
+ retry_grep "^event: dir2/renamed$" .git/trace &&
+ retry_grep "^event: renamed$" .git/trace
'
test_expect_success 'rename directory' '
@@ -489,10 +498,8 @@ test_expect_success 'rename directory' '
mv dirtorename dirrenamed &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dirtorename/*$" .git/trace &&
- grep "^event: dirrenamed/*$" .git/trace
+ retry_grep "^event: dirtorename/*$" .git/trace &&
+ retry_grep "^event: dirrenamed/*$" .git/trace
'
test_expect_success 'file changes to directory' '
@@ -502,10 +509,8 @@ test_expect_success 'file changes to directory' '
file_to_directory &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: delete$" .git/trace &&
- grep "^event: delete/new$" .git/trace
+ retry_grep "^event: delete$" .git/trace &&
+ retry_grep "^event: delete/new$" .git/trace
'
test_expect_success 'directory changes to a file' '
@@ -515,9 +520,7 @@ test_expect_success 'directory changes to a file' '
directory_to_file &&
- test-tool fsmonitor-client query --token 0 &&
-
- grep "^event: dir1$" .git/trace
+ retry_grep "^event: dir1$" .git/trace
'
# The next few test cases exercise the token-resync code. When filesystem
base-commit: 68cb7f9e92a5d8e9824f5b52ac3d0a9d8f653dbe
--
gitgitgadget
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-01-01 0:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-31 23:40 [PATCH] t7527: fix flaky fsmonitor event tests with retry logic Paul Tarjan via GitGitGadget
2026-01-01 0:19 ` [PATCH v2] " Paul Tarjan via GitGitGadget
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.