|  | // Copyright (c) 2022, 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:async'; | 
|  | import 'dart:convert' show utf8; | 
|  | import 'dart:isolate' show RawReceivePort, ReceivePort, SendPort; | 
|  |  | 
|  | import "../bin/kernel_service.dart" as kernel_service; | 
|  |  | 
|  | import 'package:front_end/src/api_unstable/vm.dart' show Verbosity; | 
|  |  | 
|  | final bool verbose = new bool.fromEnvironment('TEST_VERBOSE'); | 
|  |  | 
|  | Future<void> main() async { | 
|  | kernel_service.Status result; | 
|  |  | 
|  | // Expect to work with both absolute and relative package specification | 
|  | // if the file specified exists and is valid. | 
|  | result = await singleShotCompile( | 
|  | relativeEntry, | 
|  | fooSourceFiles, | 
|  | absolutePackageConfig, | 
|  | ); | 
|  | expect(result, kernel_service.Status.ok); | 
|  | result = await singleShotCompile( | 
|  | relativeEntry, | 
|  | fooSourceFiles, | 
|  | relativePackageConfig, | 
|  | ); | 
|  | expect(result, kernel_service.Status.ok); | 
|  |  | 
|  | // Expect an error with both absolute and relative package specification | 
|  | // if the file specified does not exist. | 
|  | result = await singleShotCompile( | 
|  | relativeEntry, | 
|  | fooSourceFiles, | 
|  | nonExistentAbsolutePackageConfig, | 
|  | ); | 
|  | expect(result, kernel_service.Status.error); | 
|  | result = await singleShotCompile( | 
|  | relativeEntry, | 
|  | fooSourceFiles, | 
|  | nonExistentRelativePackageConfig, | 
|  | ); | 
|  | expect(result, kernel_service.Status.error); | 
|  |  | 
|  | // Expect an error with both absolute and relative package specification | 
|  | // if the file specified does exist but is invalid. | 
|  | result = await singleShotCompile( | 
|  | relativeEntry, | 
|  | fooSourceFiles, | 
|  | invalidAbsolutePackageConfig, | 
|  | ); | 
|  | expect(result, kernel_service.Status.error); | 
|  | result = await singleShotCompile( | 
|  | relativeEntry, | 
|  | fooSourceFiles, | 
|  | invalidRelativePackageConfig, | 
|  | ); | 
|  | expect(result, kernel_service.Status.error); | 
|  | } | 
|  |  | 
|  | void expect(kernel_service.Status actual, kernel_service.Status expected) { | 
|  | if (actual != expected) { | 
|  | throw "Got $actual but expected $expected"; | 
|  | } | 
|  | } | 
|  |  | 
|  | String relativeEntry = "entry.dart"; | 
|  |  | 
|  | String relativePackageConfig = "packageConfig.json"; | 
|  | String absolutePackageConfig = Uri.base.resolve(relativePackageConfig).path; | 
|  |  | 
|  | String nonExistentRelativePackageConfig = "nonexisting.json"; | 
|  | String nonExistentAbsolutePackageConfig = | 
|  | Uri.base.resolve(nonExistentRelativePackageConfig).path; | 
|  |  | 
|  | String invalidRelativePackageConfig = "invalidPackageConfig.json"; | 
|  | String invalidAbsolutePackageConfig = | 
|  | Uri.base.resolve(invalidRelativePackageConfig).path; | 
|  |  | 
|  | List fooSourceFiles = [ | 
|  | Uri.base.resolve(relativeEntry).path, | 
|  | utf8.encode(""" | 
|  | import "package:foo/bar.dart"; | 
|  | main() { | 
|  | bar(); | 
|  | } | 
|  | """), | 
|  | Uri.base.resolve("foo/lib/bar.dart").path, | 
|  | utf8.encode(""" | 
|  | bar() { | 
|  | print("Hello from bar!"); | 
|  | } | 
|  | """), | 
|  | absolutePackageConfig, | 
|  | utf8.encode(""" | 
|  | { | 
|  | "configVersion": 2, | 
|  | "packages": [ | 
|  | { | 
|  | "name": "foo", | 
|  | "rootUri": "foo/", | 
|  | "packageUri": "lib/" | 
|  | } | 
|  | ] | 
|  | } | 
|  | """), | 
|  | invalidAbsolutePackageConfig, | 
|  | utf8.encode(/* missing comma after rootUri line*/ """ | 
|  | { | 
|  | "configVersion": 2, | 
|  | "packages": [ | 
|  | { | 
|  | "name": "foo", | 
|  | "rootUri": "foo/" | 
|  | "packageUri": "lib/" | 
|  | } | 
|  | ] | 
|  | } | 
|  | """), | 
|  | ]; | 
|  |  | 
|  | Future<kernel_service.Status> singleShotCompile( | 
|  | String entryFile, | 
|  | List sourceFiles, | 
|  | String? packageConfig, | 
|  | ) async { | 
|  | final RawReceivePort kernelServicePort = kernel_service.main(); | 
|  | final SendPort sendPort = kernelServicePort.sendPort; | 
|  | final ReceivePort myReceivePort = new ReceivePort(); | 
|  |  | 
|  | sendPort.send([ | 
|  | /* [0] = int = tag = */ kernel_service.kCompileTag, | 
|  | /* [1] = SendPort = sendport = */ myReceivePort.sendPort, | 
|  | /* [2] = String? = inputFileUri = */ entryFile, | 
|  | /* [3] = various = platformKernel = */ null, | 
|  | /* [4] = bool = incremental = */ false, | 
|  | /* [5] = bool = for_snapshot = */ false, | 
|  | /* [6] = bool = embed_sources = */ true, | 
|  | /* [8] = int = isolateGroupId = */ 42, | 
|  | /* [9] = List = sourceFiles = */ sourceFiles, | 
|  | /* [10] = bool = enableAsserts = */ true, | 
|  | /* [11] = List<String>? = experimentalFlags = */ [], | 
|  | /* [12] = String? = packageConfig = */ packageConfig, | 
|  | /* [13] = String? = multirootFilepaths = */ null, | 
|  | /* [14] = String? = multirootScheme = */ null, | 
|  | /* [16] = String = verbosityLevel = */ Verbosity.all.name, | 
|  | /* [17] = bool = enableMirrors = */ false, | 
|  | ]); | 
|  |  | 
|  | // Wait for kernel-service response. | 
|  | final StreamIterator streamIterator = new StreamIterator(myReceivePort); | 
|  | await streamIterator.moveNext(); | 
|  |  | 
|  | // Close ports so we can return below. | 
|  | kernelServicePort.close(); | 
|  | myReceivePort.close(); | 
|  |  | 
|  | // Examine kernel-service response. | 
|  | final List m = streamIterator.current as List; | 
|  | final int status = m.first; | 
|  | if (status == kernel_service.Status.ok.index) { | 
|  | expectLength(m, 2); | 
|  | final List<int> bytes = m[1]; | 
|  | if (verbose) { | 
|  | print("OK --- ${bytes.length} bytes dill"); | 
|  | } | 
|  | return kernel_service.Status.ok; | 
|  | } else if (status == kernel_service.Status.error.index) { | 
|  | expectLength(m, 3); | 
|  | final String errors = m[1]; | 
|  | final List<int> bytes = m[2]; | 
|  | if (verbose) { | 
|  | print("Compiled with errors --- $errors and ${bytes.length} bytes dill"); | 
|  | } | 
|  | return kernel_service.Status.error; | 
|  | } else if (status == kernel_service.Status.crash.index) { | 
|  | expectLength(m, 2); | 
|  | final String errors = m[1]; | 
|  | if (verbose) { | 
|  | print("Compiler crashed --- $errors"); | 
|  | } | 
|  | return kernel_service.Status.crash; | 
|  | } else { | 
|  | throw "Unknow status: $m"; | 
|  | } | 
|  | } | 
|  |  | 
|  | void expectLength(List list, int expectedLength) { | 
|  | if (list.length != expectedLength) { | 
|  | throw "Expected $expectedLength entries, got ${list.length}: $list"; | 
|  | } | 
|  | } |