git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).