t7527: fix flaky fsmonitor event tests with retry logic
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Paul Tarjan committed
Jan 1, 2026 at 00:19 UTC
cd607431e155d5d1267604dfdb4a798093c3a6d8
1 file changed
+41
-38
t/t7527-builtin-fsmonitor.sh
+41
-38
@@ -408,9 +408,8 @@ move_directory() {
408
# ensure we are getting the OS notifications and do not try to confirm what
409
# is reported by `git status`.
410
#
411
-# We run a simple query after modifying the filesystem just to introduce
412
-# a bit of a delay so that the trace logging from the daemon has time to
413
-# get flushed to disk.
411
+# We use retry_grep to handle races between the daemon writing events
412
+# to the trace file and our check.
413
#
414
# We `reset` and `clean` at the bottom of each test (and before stopping the
415
# daemon) because these commands might implicitly restart the daemon.
@@ -422,6 +421,24 @@ clean_up_repo_and_stop_daemon () {
421
rm -f .git/trace
422
}
423
424
+# Retry a grep up to RETRY_TIMEOUT times until it succeeds.
425
+#
426
+RETRY_TIMEOUT=5
427
+
428
+retry_grep () {
429
+ nr_tries_left=$RETRY_TIMEOUT
430
+ until grep "$1" "$2" 2>/dev/null
431
+ do
432
+ if test $nr_tries_left -eq 0
433
+ then
434
+ grep "$1" "$2"
435
+ return
436
+ fi
437
+ nr_tries_left=$(($nr_tries_left - 1))
438
+ sleep 1
439
+ done
440
+}
441
+
442
test_expect_success 'edit some files' '
443
test_when_finished clean_up_repo_and_stop_daemon &&
444
@@ -429,12 +446,10 @@ test_expect_success 'edit some files' '
446
447
edit_files &&
448
432
- test-tool fsmonitor-client query --token 0 &&
433
-
434
- grep "^event: dir1/modified$" .git/trace &&
435
- grep "^event: dir2/modified$" .git/trace &&
436
- grep "^event: modified$" .git/trace &&
437
- grep "^event: dir1/untracked$" .git/trace
449
+ retry_grep "^event: dir1/modified$" .git/trace &&
450
+ retry_grep "^event: dir2/modified$" .git/trace &&
451
+ retry_grep "^event: modified$" .git/trace &&
452
+ retry_grep "^event: dir1/untracked$" .git/trace
453
'
454
455
test_expect_success 'create some files' '
@@ -444,11 +459,9 @@ test_expect_success 'create some files' '
459
460
create_files &&
461
447
- test-tool fsmonitor-client query --token 0 &&
448
-
449
- grep "^event: dir1/new$" .git/trace &&
450
- grep "^event: dir2/new$" .git/trace &&
451
- grep "^event: new$" .git/trace
462
+ retry_grep "^event: dir1/new$" .git/trace &&
463
+ retry_grep "^event: dir2/new$" .git/trace &&
464
+ retry_grep "^event: new$" .git/trace
465
'
466
467
test_expect_success 'delete some files' '
@@ -458,11 +471,9 @@ test_expect_success 'delete some files' '
471
472
delete_files &&
473
461
- test-tool fsmonitor-client query --token 0 &&
462
-
463
- grep "^event: dir1/delete$" .git/trace &&
464
- grep "^event: dir2/delete$" .git/trace &&
465
- grep "^event: delete$" .git/trace
474
+ retry_grep "^event: dir1/delete$" .git/trace &&
475
+ retry_grep "^event: dir2/delete$" .git/trace &&
476
+ retry_grep "^event: delete$" .git/trace
477
'
478
479
test_expect_success 'rename some files' '
@@ -472,14 +483,12 @@ test_expect_success 'rename some files' '
483
484
rename_files &&
485
475
- test-tool fsmonitor-client query --token 0 &&
476
-
477
- grep "^event: dir1/rename$" .git/trace &&
478
- grep "^event: dir2/rename$" .git/trace &&
479
- grep "^event: rename$" .git/trace &&
480
- grep "^event: dir1/renamed$" .git/trace &&
481
- grep "^event: dir2/renamed$" .git/trace &&
482
- grep "^event: renamed$" .git/trace
486
+ retry_grep "^event: dir1/rename$" .git/trace &&
487
+ retry_grep "^event: dir2/rename$" .git/trace &&
488
+ retry_grep "^event: rename$" .git/trace &&
489
+ retry_grep "^event: dir1/renamed$" .git/trace &&
490
+ retry_grep "^event: dir2/renamed$" .git/trace &&
491
+ retry_grep "^event: renamed$" .git/trace
492
'
493
494
test_expect_success 'rename directory' '
@@ -489,10 +498,8 @@ test_expect_success 'rename directory' '
498
499
mv dirtorename dirrenamed &&
500
492
- test-tool fsmonitor-client query --token 0 &&
493
-
494
- grep "^event: dirtorename/*$" .git/trace &&
495
- grep "^event: dirrenamed/*$" .git/trace
501
+ retry_grep "^event: dirtorename/*$" .git/trace &&
502
+ retry_grep "^event: dirrenamed/*$" .git/trace
503
'
504
505
test_expect_success 'file changes to directory' '
@@ -502,10 +509,8 @@ test_expect_success 'file changes to directory' '
509
510
file_to_directory &&
511
505
- test-tool fsmonitor-client query --token 0 &&
506
-
507
- grep "^event: delete$" .git/trace &&
508
- grep "^event: delete/new$" .git/trace
512
+ retry_grep "^event: delete$" .git/trace &&
513
+ retry_grep "^event: delete/new$" .git/trace
514
'
515
516
test_expect_success 'directory changes to a file' '
@@ -515,9 +520,7 @@ test_expect_success 'directory changes to a file' '
520
521
directory_to_file &&
522
518
- test-tool fsmonitor-client query --token 0 &&
519
-
520
- grep "^event: dir1$" .git/trace
523
+ retry_grep "^event: dir1$" .git/trace
524
'
525
526
# The next few test cases exercise the token-resync code. When filesystem