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