make the log file test less flaky by retrying deletes and reads (#180)
Seeing a lot of flakes on windows for this test, adding some retry logic for deleting the file and also reading from it should make it more reliable.
diff --git a/pkgs/dart_mcp_server/test/dart_tooling_mcp_server_test.dart b/pkgs/dart_mcp_server/test/dart_tooling_mcp_server_test.dart
index 8d8a4c2..607c56e 100644
--- a/pkgs/dart_mcp_server/test/dart_tooling_mcp_server_test.dart
+++ b/pkgs/dart_mcp_server/test/dart_tooling_mcp_server_test.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:async';
import 'dart:io';
import 'package:test/test.dart';
@@ -23,16 +24,43 @@
});
test('logs traffic to a file', () async {
- expect(
- await File(logDescriptor.io.path).readAsLines(),
- containsAll([
- allOf(startsWith('<<<'), contains('"method":"initialize"')),
- allOf(startsWith('>>>'), contains('"serverInfo"')),
- allOf(startsWith('<<<'), contains('"notifications/initialized"')),
- ]),
+ // It may take a bit for all the lines to show up in the log.
+ await doWithRetries(
+ () async => expect(
+ await File(logDescriptor.io.path).readAsLines(),
+ containsAll([
+ allOf(startsWith('<<<'), contains('"method":"initialize"')),
+ allOf(startsWith('>>>'), contains('"serverInfo"')),
+ allOf(startsWith('<<<'), contains('"notifications/initialized"')),
+ ]),
+ ),
);
+
// Ensure the file handle is released before the file is cleaned up.
await testHarness.serverConnectionPair.serverConnection.shutdown();
+
+ // Wait for the process to release the file.
+ await doWithRetries(() => File(logDescriptor.io.path).delete());
});
});
}
+
+/// Performs [action] up to [maxRetries] times, backing off an extra 50ms
+/// between each attempt.
+FutureOr<T> doWithRetries<T>(
+ FutureOr<T> Function() action, {
+ int maxRetries = 5,
+}) async {
+ var count = 0;
+ while (true) {
+ try {
+ return await action();
+ } catch (_) {
+ if (count == maxRetries) {
+ rethrow;
+ }
+ }
+ count++;
+ await Future<void>.delayed(Duration(milliseconds: 50 * count));
+ }
+}