| // 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> | |
| 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; | |
| } | |
| '''; |