Record the working directory for VM platform (#1804)
Towards #1803
A VM test can change the working directory for the entire process. If
this happens it will change the result for the absolute path against the
relative paths provided to the VM platform plugin.
Record `Directory.current` when the platform plugin is instantiated. Any
place where an absolute path is needed attempt to resolve against the
original working directory.
Move some top-level methods into the plugin so they can read the cached
working directory.
This only works for VM tests, since other test platforms may be instantiated
after the VM tests have started running. Impacted users can workaround
this by running VM tests separately from other platforms.
diff --git a/pkgs/test/CHANGELOG.md b/pkgs/test/CHANGELOG.md
index 3ff28c4..96e3523 100644
--- a/pkgs/test/CHANGELOG.md
+++ b/pkgs/test/CHANGELOG.md
@@ -3,6 +3,8 @@
* Add documentation for the `--ignore-timeouts` argument.
* Merge command lines args repeating the same test path to run the suite one
time with all the test cases across the different arguments.
+* Fix VM tests which run after some test has changed the working directory.
+ There are still issues with browser tests after changing directory.
## 1.22.0
diff --git a/pkgs/test/test/runner/runner_test.dart b/pkgs/test/test/runner/runner_test.dart
index e232f0d..248fd66 100644
--- a/pkgs/test/test/runner/runner_test.dart
+++ b/pkgs/test/test/runner/runner_test.dart
@@ -891,4 +891,44 @@
}
});
});
+
+ group('runs tests after changing directories', () {
+ setUp(() async {
+ await d.file('a_test.dart', '''
+@TestOn('vm')
+import 'dart:io';
+
+import 'package:test/test.dart';
+
+void main() {
+ test('changes directory', () {
+ Directory.current = Directory.current.parent;
+ });
+}
+''').create();
+ await d.file('b_test.dart', '''
+import 'package:test/test.dart';
+
+void main() {
+ test('passes', () {
+ expect(true, true);
+ });
+}
+''').create();
+ });
+ test('on the VM platform', () async {
+ var test = await runTest(['-p', 'vm', 'a_test.dart', 'b_test.dart']);
+ await expectLater(
+ test.stdout, emitsThrough(contains('+2: All tests passed!')));
+ await test.shouldExit(0);
+ });
+
+ test('on the browser platform', () async {
+ var test =
+ await runTest(['-p', 'vm,chrome', 'a_test.dart', 'b_test.dart']);
+ await expectLater(
+ test.stdout, emitsThrough(contains('+3: All tests passed!')));
+ await test.shouldExit(0);
+ }, skip: 'https://github.com/dart-lang/test/issues/1803');
+ });
}
diff --git a/pkgs/test_core/CHANGELOG.md b/pkgs/test_core/CHANGELOG.md
index 0257cb1..4e6f691 100644
--- a/pkgs/test_core/CHANGELOG.md
+++ b/pkgs/test_core/CHANGELOG.md
@@ -4,6 +4,8 @@
`Configuration`.
* Merge command lines args repeating the same test path to run the suite one
time with all the test cases across the different arguments.
+* Fix VM tests which run after some test has changed the working directory.
+ There are still issues with browser tests after changing directory.
# 0.4.20
diff --git a/pkgs/test_core/lib/src/runner/vm/platform.dart b/pkgs/test_core/lib/src/runner/vm/platform.dart
index a3a7174..2ea9483 100644
--- a/pkgs/test_core/lib/src/runner/vm/platform.dart
+++ b/pkgs/test_core/lib/src/runner/vm/platform.dart
@@ -39,6 +39,7 @@
final _compiler = TestCompiler(
p.join(p.current, '.dart_tool', 'test', 'incremental_kernel'));
final _closeMemo = AsyncMemoizer<void>();
+ final _workingDirectory = Directory.current.uri;
@override
Future<RunnerSuite?> load(String path, SuitePlatform platform,
@@ -86,7 +87,7 @@
await Service.controlWebServer(enable: true, silenceOutput: true);
var isolateID = Service.getIsolateID(isolate)!;
- var libraryPath = p.toUri(p.absolute(path)).toString();
+ var libraryPath = _absolute(path).toString();
var serverUri = info.serverUri!;
client = await vmServiceConnectUri(_wsUriFor(serverUri).toString());
var isolateNumber = int.parse(isolateID.split('/').last);
@@ -126,6 +127,12 @@
@override
Future close() => _closeMemo.runOnce(_compiler.dispose);
+ Uri _absolute(String path) {
+ final uri = p.toUri(path);
+ if (uri.isAbsolute) return uri;
+ return _workingDirectory.resolveUri(uri);
+ }
+
/// Spawns an isolate and passes it [message].
///
/// This isolate connects an [IsolateChannel] to [message] and sends the
@@ -153,8 +160,7 @@
/// isolate.
Future<Isolate> _spawnKernelIsolate(
String path, SendPort message, Metadata suiteMetadata) async {
- final response =
- await _compiler.compile(File(path).absolute.uri, suiteMetadata);
+ final response = await _compiler.compile(_absolute(path), suiteMetadata);
var compiledDill = response.kernelOutputUri?.toFilePath();
if (compiledDill == null || response.errorCount > 0) {
throw LoadException(path, response.compilerOutput ?? 'unknown error');
@@ -162,39 +168,40 @@
return await Isolate.spawnUri(p.toUri(compiledDill), [], message,
packageConfig: await packageConfigUri, checked: true);
}
-}
-Future<Isolate> _spawnDataIsolate(
- String path, SendPort message, Metadata suiteMetadata) async {
- return await dart.runInIsolate('''
+ Future<Isolate> _spawnDataIsolate(
+ String path, SendPort message, Metadata suiteMetadata) async {
+ return await dart.runInIsolate('''
${suiteMetadata.languageVersionComment ?? await rootPackageLanguageVersionComment}
import "dart:isolate";
import "package:test_core/src/bootstrap/vm.dart";
- import "${p.toUri(p.absolute(path))}" as test;
+ import "${_absolute(path)}" as test;
void main(_, SendPort sendPort) {
internalBootstrapVmTest(() => test.main, sendPort);
}
''', message);
-}
+ }
-Future<Isolate> _spawnPrecompiledIsolate(
- String testPath, SendPort message, String precompiledPath) async {
- testPath = p.absolute('${p.join(precompiledPath, testPath)}.vm_test.dart');
- var dillTestpath =
- '${testPath.substring(0, testPath.length - '.dart'.length)}.vm.app.dill';
- if (await File(dillTestpath).exists()) {
- testPath = dillTestpath;
- }
- File? packageConfig =
- File(p.join(precompiledPath, '.dart_tool/package_config.json'));
- if (!(await packageConfig.exists())) {
- packageConfig = File(p.join(precompiledPath, '.packages'));
- if (!(await packageConfig.exists())) {
- packageConfig = null;
+ Future<Isolate> _spawnPrecompiledIsolate(
+ String testPath, SendPort message, String precompiledPath) async {
+ testPath =
+ _absolute('${p.join(precompiledPath, testPath)}.vm_test.dart').path;
+ var dillTestpath =
+ '${testPath.substring(0, testPath.length - '.dart'.length)}.vm.app.dill';
+ if (await File(dillTestpath).exists()) {
+ testPath = dillTestpath;
}
+ File? packageConfig =
+ File(p.join(precompiledPath, '.dart_tool/package_config.json'));
+ if (!(await packageConfig.exists())) {
+ packageConfig = File(p.join(precompiledPath, '.packages'));
+ if (!(await packageConfig.exists())) {
+ packageConfig = null;
+ }
+ }
+ return await Isolate.spawnUri(p.toUri(testPath), [], message,
+ packageConfig: packageConfig?.uri, checked: true);
}
- return await Isolate.spawnUri(p.toUri(testPath), [], message,
- packageConfig: packageConfig?.uri, checked: true);
}
Future<Map<String, dynamic>> _gatherCoverage(Environment environment) async {