Skip to content

Commit 4dbddc8

Browse files
authored
Address flakes from using temp directory to run tests (#2649)
2172ba7 added support to run tests in a temporary directory. This results in two flaky issues: 1. On Windows, build_daemon tests may fail to delete the temp directory because the process may have not been torn down yet, so it may still be accessing the file system. There was an initial retry after 1 second, but that appears to be not enough looking at a recent test run. 2. If a test times out, its tearDown may not be called. In this case, the ResidentWebRunner in frontend_server may not restore the current directory in the LocalFileSystem. This leads to cascading failures in subsequent tests due to no longer being in a path that contains 'webdev'. See https://github.com/dart-lang/webdev/actions/runs/15989286213/job/45099373212?pr=2641 for an example. See dart-lang/test#897 as well for tracking work to call tearDown on timeouts. To address the above issues: 1. Increase the delay between the two tries and assert this only occurs on Windows. 2. Cache the current directory so that it can be used in utilities.dart with the same (correct) value every time.
1 parent b61423d commit 4dbddc8

File tree

8 files changed

+44
-29
lines changed

8 files changed

+44
-29
lines changed

dwds/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## 24.4.1-wip
2+
13
## 24.4.0
24

35
- Added support for breakpoint registering on a hot reload with the DDC library bundle format using PausePostRequests.

dwds/lib/src/version.dart

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dwds/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: dwds
22
# Every time this changes you need to run `dart run build_runner build`.
3-
version: 24.4.0
3+
version: 24.4.1-wip
44

55
description: >-
66
A service that proxies between the Chrome debug protocol and the Dart VM

dwds/test/fixtures/context.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,12 @@ class TestContext {
322322
_webRunner = ResidentWebRunner(
323323
mainUri: entry,
324324
urlTunneler: debugSettings.urlEncoder,
325-
projectDirectory: p.toUri(project.absolutePackageDirectory),
325+
projectDirectory: Directory(project.absolutePackageDirectory).uri,
326326
packageConfigFile: project.packageConfigFile,
327327
packageUriMapper: packageUriMapper,
328-
fileSystemRoots: [p.toUri(project.absolutePackageDirectory)],
328+
fileSystemRoots: [
329+
Directory(project.absolutePackageDirectory).uri,
330+
],
329331
fileSystemScheme: 'org-dartlang-app',
330332
outputPath: outputDir.path,
331333
compilerOptions: compilerOptions,

dwds/test/fixtures/project.dart

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,18 @@ class TestProject {
241241
_fixturesCopy.deleteSync(recursive: true);
242242
} on FileSystemException catch (_) {
243243
// On Windows, the build daemon process might still be accessing the
244-
// working directory, so wait a second and then try again.
245-
await Future.delayed(const Duration(seconds: 1));
246-
_fixturesCopy.deleteSync(recursive: true);
244+
// working directory, so try again with an exponential backoff.
245+
var seconds = 1;
246+
final maxAttempts = 3;
247+
for (var attempt = 0; attempt < maxAttempts; attempt++) {
248+
try {
249+
_fixturesCopy.deleteSync(recursive: true);
250+
break;
251+
} on FileSystemException catch (_) {
252+
await Future.delayed(Duration(seconds: seconds));
253+
seconds *= 2;
254+
}
255+
}
247256
}
248257
}
249258

frontend_server_common/lib/src/asset_server.dart

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class TestAssetServer implements AssetReader {
2626
// Fallback to "application/octet-stream" on null which
2727
// makes no claims as to the structure of the data.
2828
static const String _defaultMimeType = 'application/octet-stream';
29+
final Uri _projectDirectory;
2930
final FileSystem _fileSystem;
3031
final HttpServer _httpServer;
3132
final Map<String, Uint8List> _files = {};
@@ -41,6 +42,7 @@ class TestAssetServer implements AssetReader {
4142
this._httpServer,
4243
this._packageUriMapper,
4344
this.internetAddress,
45+
this._projectDirectory,
4446
this._fileSystem,
4547
this._sdkLayout,
4648
) {
@@ -65,6 +67,7 @@ class TestAssetServer implements AssetReader {
6567
/// trace.
6668
static Future<TestAssetServer> start(
6769
String sdkDirectory,
70+
Uri projectDirectory,
6871
FileSystem fileSystem,
6972
String index,
7073
String hostname,
@@ -75,8 +78,8 @@ class TestAssetServer implements AssetReader {
7578
final address = (await InternetAddress.lookup(hostname)).first;
7679
final httpServer = await HttpServer.bind(address, port);
7780
final sdkLayout = TestSdkLayout.createDefault(sdkDirectory);
78-
final server = TestAssetServer(
79-
index, httpServer, packageUriMapper, address, fileSystem, sdkLayout);
81+
final server = TestAssetServer(index, httpServer, packageUriMapper, address,
82+
projectDirectory, fileSystem, sdkLayout);
8083
return server;
8184
}
8285

@@ -94,7 +97,7 @@ class TestAssetServer implements AssetReader {
9497
final headers = <String, String>{};
9598

9699
if (request.url.path.endsWith('.html')) {
97-
final indexFile = _fileSystem.file(index);
100+
final indexFile = _fileSystem.file(_projectDirectory.resolve(index));
98101
if (indexFile.existsSync()) {
99102
headers[HttpHeaders.contentTypeHeader] = 'text/html';
100103
headers[HttpHeaders.contentLengthHeader] =
@@ -244,8 +247,7 @@ class TestAssetServer implements AssetReader {
244247
// If this is a dart file, it must be on the local file system and is
245248
// likely coming from a source map request. The tool doesn't currently
246249
// consider the case of Dart files as assets.
247-
final dartFile =
248-
_fileSystem.file(_fileSystem.currentDirectory.uri.resolve(path));
250+
final dartFile = _fileSystem.file(_projectDirectory.resolve(path));
249251
if (dartFile.existsSync()) {
250252
return dartFile;
251253
}
@@ -255,7 +257,10 @@ class TestAssetServer implements AssetReader {
255257
// The file might have been a package file which is signaled by a
256258
// `/packages/<package>/<path>` request.
257259
if (segments.first == 'packages') {
258-
final resolved = _packageUriMapper.serverPathToResolvedUri(path);
260+
var resolved = _packageUriMapper.serverPathToResolvedUri(path);
261+
if (resolved != null) {
262+
resolved = _projectDirectory.resolveUri(resolved);
263+
}
259264
final packageFile = _fileSystem.file(resolved);
260265
if (packageFile.existsSync()) {
261266
return packageFile;
@@ -311,7 +316,7 @@ class TestAssetServer implements AssetReader {
311316
}
312317

313318
String _parseBasePathFromIndexHtml(String index) {
314-
final file = _fileSystem.file(index);
319+
final file = _fileSystem.file(_projectDirectory.resolve(index));
315320
if (!file.existsSync()) {
316321
throw StateError('Index file $index is not found');
317322
}

frontend_server_common/lib/src/devfs.dart

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,11 @@ class WebDevFS {
5151

5252
final TestSdkLayout sdkLayout;
5353
final CompilerOptions compilerOptions;
54-
late final Directory _savedCurrentDirectory;
5554

5655
Future<Uri> create() async {
57-
_savedCurrentDirectory = fileSystem.currentDirectory;
58-
59-
fileSystem.currentDirectory = projectDirectory.toFilePath();
60-
6156
assetServer = await TestAssetServer.start(
6257
sdkLayout.sdkDirectory,
58+
projectDirectory,
6359
fileSystem,
6460
index,
6561
hostname,
@@ -71,7 +67,6 @@ class WebDevFS {
7167
}
7268

7369
Future<void> dispose() {
74-
fileSystem.currentDirectory = _savedCurrentDirectory;
7570
return assetServer.close();
7671
}
7772

@@ -84,7 +79,8 @@ class WebDevFS {
8479
required bool fullRestart,
8580
}) async {
8681
final mainPath = mainUri.toFilePath();
87-
final outputDirectoryPath = fileSystem.file(mainPath).parent.path;
82+
final outputDirectory = fileSystem.directory(
83+
fileSystem.file(projectDirectory.resolve(mainPath)).parent.path);
8884
final entryPoint = mainUri.toString();
8985

9086
var prefix = '';
@@ -103,7 +99,10 @@ class WebDevFS {
10399
final bootstrap = '${prefix}main_module.bootstrap.js';
104100

105101
assetServer.writeFile(
106-
entryPoint, fileSystem.file(mainPath).readAsStringSync());
102+
entryPoint,
103+
fileSystem
104+
.file(projectDirectory.resolve(mainPath))
105+
.readAsStringSync());
107106
assetServer.writeFile(stackMapper, stackTraceMapper.readAsStringSync());
108107

109108
switch (ddcModuleFormat) {
@@ -199,14 +198,13 @@ class WebDevFS {
199198
File metadataFile;
200199
List<String> modules;
201200
try {
202-
final parentDirectory = fileSystem.directory(outputDirectoryPath);
203201
codeFile =
204-
parentDirectory.childFile('${compilerOutput.outputFilename}.sources');
202+
outputDirectory.childFile('${compilerOutput.outputFilename}.sources');
205203
manifestFile =
206-
parentDirectory.childFile('${compilerOutput.outputFilename}.json');
204+
outputDirectory.childFile('${compilerOutput.outputFilename}.json');
207205
sourcemapFile =
208-
parentDirectory.childFile('${compilerOutput.outputFilename}.map');
209-
metadataFile = parentDirectory
206+
outputDirectory.childFile('${compilerOutput.outputFilename}.map');
207+
metadataFile = outputDirectory
210208
.childFile('${compilerOutput.outputFilename}.metadata');
211209
modules = assetServer.write(
212210
codeFile, manifestFile, sourcemapFile, metadataFile);

frontend_server_common/lib/src/frontend_server_client.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,6 @@ class ResidentCompiler {
402402
if (compilerOptions.moduleFormat == ModuleFormat.ddc)
403403
'--dartdevc-module-format=ddc'
404404
];
405-
406405
_logger.info(args.join(' '));
407406
final workingDirectory = projectDirectory.toFilePath();
408407
_server = await Process.start(sdkLayout.dartAotRuntimePath, args,
@@ -657,7 +656,7 @@ String _toMultiRootPath(
657656
for (final fileSystemRoot in fileSystemRoots) {
658657
final rootPath = fileSystemRoot.toFilePath(windows: Platform.isWindows);
659658
if (filePath.startsWith(rootPath)) {
660-
return '$scheme://${filePath.substring(rootPath.length)}';
659+
return '$scheme:///${filePath.substring(rootPath.length)}';
661660
}
662661
}
663662
return fileUri.toString();

0 commit comments

Comments
 (0)