| // 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. |
| |
| // @dart = 2.9 |
| |
| 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> |
| final futures = <Future>[]; |
| 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; |
| for (final optionalPackageUri in const [true, false]) { |
| print('TEST optionalPackageUri = $optionalPackageUri'); |
| futures.add(runPackageConfigTest(runWithPackagesArg, |
| spawnWithPackageConfig, optionalPackageUri, checkForResolveUri)); |
| } |
| } |
| } |
| await Future.wait(futures); |
| } |
| |
| 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 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; |
| } |
| '''; |