blob: d5efa2c243397ab607bb5a7d889db75ae1906b1b [file] [log] [blame]
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// 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:io';
import 'package:expect/expect.dart';
import 'package:path/path.dart' as path;
final executable = Platform.executable;
main() async {
// Run the Dart VM with or without:
// --packages=<packages|package_config>
for (final runWithPackagesArg in const [true, false]) {
// Run the isolate with or without
// Isolate.spawnUri(..., packageConfig: <packages|package_config>)
print('TEST runWithPackagesArg = $runWithPackagesArg ');
for (final spawnWithPackageConfig in const [true, false]) {
print('TEST spawnWithPackageConfig = $spawnWithPackageConfig ');
final bool checkForResolveUri =
runWithPackagesArg || !spawnWithPackageConfig;
await runDotPackagesTest(
runWithPackagesArg, spawnWithPackageConfig, checkForResolveUri);
for (final optionalPackageUri in const [true, false]) {
print('TEST optionalPackageUri = $optionalPackageUri');
await runPackageConfigTest(runWithPackagesArg, spawnWithPackageConfig,
optionalPackageUri, checkForResolveUri);
}
}
}
}
Future runPackageConfigTest(bool withPackagesArg, bool spawnWithArg,
bool optionalPackageUri, bool checkForResolveUri) async {
await withApplicationDirAndDotDartToolPackageConfig(
(String tempDir, String packageJson, String mainFile) async {
final args = [if (withPackagesArg) '--packages=$packageJson', mainFile];
await run(executable, args);
}, spawnWithArg, optionalPackageUri, checkForResolveUri);
}
Future runDotPackagesTest(
bool withPackagesArg, bool spawnWithArg, bool checkForResolveUri) async {
await withApplicationDirAndDotPackages(
(String tempDir, String dotPackagesFile, String mainFile) async {
final args = [
if (withPackagesArg) '--packages=$dotPackagesFile',
mainFile,
];
await run(executable, args);
}, spawnWithArg, checkForResolveUri);
}
Future withApplicationDirAndDotPackages(
Future fn(String tempDir, String packagesDir, String mainFile),
bool spawnWithArg,
bool checkForResolveUri) async {
await withTempDir((String tempDir) async {
// Setup ".packages"
final dotPackagesFile =
path.join(tempDir, spawnWithArg ? 'baz.packages' : '.packages');
await File(dotPackagesFile).writeAsString(buildDotPackages('foo'));
final mainFile = path.join(tempDir, 'main.dart');
final childIsolateFile = path.join(tempDir, 'child_isolate.dart');
final importUri = 'package:foo/child_isolate.dart';
await File(childIsolateFile).writeAsString(buildChildIsolate());
await File(mainFile).writeAsString(buildMainIsolate(
importUri,
spawnWithArg ? dotPackagesFile : null,
checkForResolveUri ? childIsolateFile : null));
await fn(tempDir, dotPackagesFile, mainFile);
});
}
Future withApplicationDirAndDotDartToolPackageConfig(
Future fn(String tempDir, String packageJson, String mainFile),
bool spawnWithArg,
bool optionalPackageUri,
bool checkForResolveUri) async {
await withTempDir((String tempDir) async {
// Setup ".dart_tool/package_config.json"
final dotDartToolDir = path.join(tempDir, '.dart_tool');
await Directory(dotDartToolDir).create();
final packageConfigJsonFile = path.join(
dotDartToolDir, spawnWithArg ? 'baz.packages' : 'package_config.json');
await File(packageConfigJsonFile)
.writeAsString(buildPackageConfig('foo', optionalPackageUri));
// Setup actual application
final mainFile = path.join(tempDir, 'main.dart');
final childIsolateFile = path.join(tempDir, 'child_isolate.dart');
final importUri = 'package:foo/child_isolate.dart';
await File(childIsolateFile).writeAsString(buildChildIsolate());
await File(mainFile).writeAsString(buildMainIsolate(
importUri,
spawnWithArg ? packageConfigJsonFile : null,
checkForResolveUri ? childIsolateFile : null));
await fn(tempDir, packageConfigJsonFile, mainFile);
});
}
Future withTempDir(Future fn(String dir)) async {
final dir = await Directory.systemTemp.createTemp('spawn_uri');
try {
await fn(dir.absolute.path);
} finally {
await dir.delete(recursive: true);
}
}
Future<ProcessResult> run(String executable, List<String> args,
{String? cwd}) async {
print('Running $executable ${args.join(' ')}');
final String workingDirectory = cwd ?? Directory.current.absolute.path;
final result = await Process.run(executable, ['--trace-loading', ...args],
workingDirectory: workingDirectory);
print('exitCode:\n${result.exitCode}');
print('stdout:\n${result.stdout}');
print('stdout:\n${result.stderr}');
Expect.equals(0, result.exitCode);
return result;
}
String buildDotPackages(String packageName) => '$packageName:.';
String buildPackageConfig(String packageName, bool optionalPackageUri) => '''
{
"configVersion": 2,
"packages": [
{
"name": "$packageName",
"rootUri": "../"
${optionalPackageUri ? ', "packageUri": "./"' : ''}
}
]
}
''';
String buildChildIsolate() => '''
import 'dart:isolate';
main(List<String> args, SendPort message) {
message.send('child isolate is done');
}
''';
String buildMainIsolate(
String spawnUri, String? packageConfigUri, String? childIsolatePath) =>
'''
import 'dart:isolate';
import 'dart:io' as io;
main(List<String> args) async {
io.exitCode = 1;
final uri = Uri.parse('$spawnUri');
final resolvedUri = await Isolate.resolvePackageUri(uri);
if ("""\${resolvedUri?.toFilePath()}""" != r"""$childIsolatePath""") {
throw 'Could not Isolate.resolvePackageUri(uri).';
}
final rp = ReceivePort();
final isolateArgs = <String>['a'];
await Isolate.spawnUri(
uri,
isolateArgs,
rp.sendPort,
packageConfig: ${packageConfigUri != null ? 'Uri.file(r"$packageConfigUri")' : 'null'});
final childIsolateMessage = await rp.first;
if (childIsolateMessage != 'child isolate is done') {
throw 'Did not receive correct message from child isolate.';
}
// Test was successful.
io.exitCode = 0;
}
''';