-
Notifications
You must be signed in to change notification settings - Fork 226
[WIP] use frontend server for VM test platform #1399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jakemac53
merged 28 commits into
dart-lang:master
from
jonahwilliams:frontend_server_compilation
Mar 23, 2021
Merged
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
3eddc2a
use frontend server for VM test platform
jonahwilliams 5f1c76f
Merge branch 'master' of github.com:dart-lang/test into frontend_serv…
jonahwilliams 778dbbb
opt out of null safety
jonahwilliams c0879ba
switch to frontend_server_client
jonahwilliams 6c6f959
use rootPackageLanguageVersionComment
jonahwilliams 8bac872
fix year
jonahwilliams 313f557
merge with master
jonahwilliams f932ad6
tweak tests and add comment
jonahwilliams c98910b
require latest frontend_server_client
jakemac53 000da33
Merge branch 'master' into frontend_server_compilation
jakemac53 6353265
fix up some null safety issues
jakemac53 3fb3e7a
produce a LoadException if the app fails to compile
jakemac53 0a5831c
remove unused import
jakemac53 4998cc9
add errorCount and check it
jakemac53 b323cab
pass the current package config to the frotnend server
jakemac53 bf1aa14
fix tests and expectations to match the new output
jakemac53 ad98660
delete output dill dir synchronously
jakemac53 e6ea03e
dont print incremental dependencies
jakemac53 164bf1b
add --use-data-isolate-strategy flag for use primarily in bazel
jakemac53 21a1b25
add some basic data isolate strategy tests
jakemac53 2a78037
fix up help output and expectations
jakemac53 e85f228
remove unused imports
jakemac53 8d96df0
code review updates
jakemac53 dae0aa2
update to use package:pool, move fields above constructor
jakemac53 2e2fac3
improve error handling of a sigkill during suite loading
jakemac53 08d1859
Merge branch 'master' into frontend_server_compilation
jakemac53 aa23f0c
Update pkgs/test_core/lib/src/runner/configuration.dart
jakemac53 98cc83d
Update pkgs/test/test/runner/data_isolate_strategy_test.dart
jakemac53 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,273 @@ | ||
| // Copyright (c) 2018, 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'; | ||
| import 'dart:io'; | ||
| import 'dart:math' as math; | ||
| import 'dart:typed_data'; | ||
|
|
||
| // ignore: import_of_legacy_library_into_null_safe | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| import 'package:package_config/package_config.dart'; | ||
| import 'package:path/path.dart' as path; | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| import 'package:test_api/backend.dart'; // ignore: deprecated_member_use | ||
|
|
||
| /// A request to the [TestCompiler] for recompilation. | ||
| class _CompilationRequest { | ||
| _CompilationRequest(this.mainUri, this.result, this.metadata); | ||
|
|
||
| Uri mainUri; | ||
| Metadata metadata; | ||
| Completer<String> result; | ||
| } | ||
|
|
||
| class TestCompiler { | ||
| TestCompiler(this._dillCachePath) | ||
| : _outputDillDirectory = | ||
| Directory.systemTemp.createTempSync('dart_test.') { | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| _outputDill = File(path.join(_outputDillDirectory.path, 'output.dill')); | ||
| _compilerController.stream.listen(_onCompilationRequest, onDone: () { | ||
| _outputDillDirectory.deleteSync(recursive: true); | ||
| }); | ||
| } | ||
|
|
||
| final String _dillCachePath; | ||
| final Directory _outputDillDirectory; | ||
| final _compilerController = StreamController<_CompilationRequest>(); | ||
| final _compilationQueue = <_CompilationRequest>[]; | ||
| final _stdoutHandler = _StdoutHandler(); | ||
|
|
||
| File? _outputDill; | ||
| Process? _compiler; | ||
| PackageConfig? _packageConfig; | ||
|
|
||
| Future<String?> compile(Uri mainDart, Metadata metadata) { | ||
| final completer = Completer<String>(); | ||
| if (_compilerController.isClosed) { | ||
| return Future.value(null); | ||
| } | ||
| _compilerController.add(_CompilationRequest(mainDart, completer, metadata)); | ||
| return completer.future; | ||
| } | ||
|
|
||
| Future<void> _shutdown() async { | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (_compiler != null) { | ||
| _compiler!.kill(); | ||
| _compiler = null; | ||
| } | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| Future<void> dispose() async { | ||
| await _compilerController.close(); | ||
| await _shutdown(); | ||
| } | ||
|
|
||
| Future<String> _languageVersionComment(Uri testUri) async { | ||
| var localPackageConfig = _packageConfig ??= await loadPackageConfig(File( | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| path.join( | ||
| Directory.current.path, '.dart_tool', 'package_config.json'))); | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| var package = localPackageConfig.packageOf(testUri) as Package?; | ||
| if (package == null) { | ||
| return ''; | ||
| } | ||
| return '// @dart=${package.languageVersion.major}.${package.languageVersion.minor}'; | ||
| } | ||
|
|
||
| Future<String> _generateEntrypoint( | ||
| Uri testUri, Metadata suiteMetadata) async { | ||
| return ''' | ||
| ${suiteMetadata.languageVersionComment ?? await _languageVersionComment(testUri)} | ||
| import "dart:isolate"; | ||
|
|
||
| import "package:test_core/src/bootstrap/vm.dart"; | ||
|
|
||
| import "$testUri" as test; | ||
|
|
||
| void main(_, SendPort sendPort) { | ||
| internalBootstrapVmTest(() => test.main, sendPort); | ||
| } | ||
| '''; | ||
| } | ||
|
|
||
| // Handle a compilation request. | ||
| Future<void> _onCompilationRequest(_CompilationRequest request) async { | ||
| final isEmpty = _compilationQueue.isEmpty; | ||
| _compilationQueue.add(request); | ||
| if (!isEmpty) { | ||
| return; | ||
| } | ||
| while (_compilationQueue.isNotEmpty) { | ||
| final request = _compilationQueue.first; | ||
| var firstCompile = false; | ||
| _CompilerOutput? compilerOutput; | ||
| final contents = | ||
| await _generateEntrypoint(request.mainUri, request.metadata); | ||
| final tempFile = File(path.join(_outputDillDirectory.path, 'test.dart')) | ||
| ..writeAsStringSync(contents); | ||
|
|
||
| if (_compiler == null) { | ||
| compilerOutput = await _createCompiler(tempFile.uri); | ||
| firstCompile = true; | ||
| } else { | ||
| compilerOutput = await _recompile( | ||
| tempFile.uri, | ||
| ); | ||
| } | ||
| final outputPath = compilerOutput?.outputFilename; | ||
| if (outputPath == null || compilerOutput!.errorCount > 0) { | ||
| request.result.complete(null); | ||
| await _shutdown(); | ||
| } else { | ||
| final outputFile = File(outputPath); | ||
| final kernelReadyToRun = await outputFile.copy('${tempFile.path}.dill'); | ||
| final testCache = File(_dillCachePath); | ||
| if (firstCompile || | ||
| !testCache.existsSync() || | ||
| (testCache.lengthSync() < outputFile.lengthSync())) { | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // Keep the cache file up-to-date and include as many packages as possible, | ||
| // using the kernel size as an approximation. | ||
| if (!testCache.parent.existsSync()) { | ||
| testCache.parent.createSync(recursive: true); | ||
| } | ||
| await outputFile.copy(_dillCachePath); | ||
| } | ||
| request.result.complete(kernelReadyToRun.absolute.path); | ||
| _accept(); | ||
| _reset(); | ||
| } | ||
| _compilationQueue.removeAt(0); | ||
| } | ||
| } | ||
|
|
||
| String _generateInputKey(math.Random random) { | ||
| final bytes = Uint8List(16); | ||
| for (var i = 0; i < 16; i++) { | ||
| bytes[i] = random.nextInt(25) + 65; | ||
| } | ||
| return String.fromCharCodes(bytes); | ||
| } | ||
|
|
||
| Future<_CompilerOutput?> _recompile(Uri mainUri) { | ||
| _stdoutHandler.reset(); | ||
| final inputKey = _generateInputKey(math.Random()); | ||
| _compiler!.stdin.writeln('recompile $mainUri $inputKey'); | ||
| _compiler!.stdin.writeln('$mainUri'); | ||
| _compiler!.stdin.writeln('$inputKey'); | ||
| return _stdoutHandler.compilerOutput.future; | ||
| } | ||
|
|
||
| void _accept() { | ||
| _compiler!.stdin.writeln('accept'); | ||
| } | ||
|
|
||
| void _reset() { | ||
| _compiler!.stdin.writeln('reset'); | ||
| _stdoutHandler.reset(expectSources: false); | ||
| } | ||
|
|
||
| Future<_CompilerOutput?> _createCompiler(Uri testUri) async { | ||
| final frontendServer = path.normalize(path.join(Platform.resolvedExecutable, | ||
| '..', 'snapshots', 'frontend_server.dart.snapshot')); | ||
| final sdkRoot = Directory( | ||
| path.relative(path.join(Platform.resolvedExecutable, '..', '..'))) | ||
| .uri; | ||
| final platformDill = 'lib/_internal/vm_platform_strong.dill'; | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| final process = await Process.start(Platform.resolvedExecutable, <String>[ | ||
jakemac53 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| '--disable-dart-dev', | ||
| frontendServer, | ||
| '--incremental', | ||
| '--sdk-root=$sdkRoot', | ||
| '--no-print-incremental-dependencies', | ||
| '--target=vm', | ||
| '--output-dill=${_outputDill!.path}', | ||
| '--initialize-from-dill=$_dillCachePath', | ||
| '--platform=$platformDill', | ||
| '--packages=${path.join(Directory.current.path, '.packages')}' | ||
| ]); | ||
| process.stdout | ||
| .transform(utf8.decoder) | ||
| .transform(const LineSplitter()) | ||
| .listen(_stdoutHandler.handler); | ||
| process.stderr | ||
| .transform(utf8.decoder) | ||
| .transform(const LineSplitter()) | ||
| .listen(print); | ||
| process.stdin.writeln('compile $testUri'); | ||
| _compiler = process; | ||
| return _stdoutHandler.compilerOutput.future; | ||
| } | ||
| } | ||
|
|
||
| enum _StdoutState { CollectDiagnostic, CollectDependencies } | ||
|
|
||
| class _CompilerOutput { | ||
| const _CompilerOutput(this.outputFilename, this.errorCount, this.sources); | ||
|
|
||
| final String? outputFilename; | ||
| final int errorCount; | ||
| final List<Uri> sources; | ||
| } | ||
|
|
||
| class _StdoutHandler { | ||
| String? boundaryKey; | ||
| _StdoutState state = _StdoutState.CollectDiagnostic; | ||
| Completer<_CompilerOutput> compilerOutput = Completer<_CompilerOutput>(); | ||
| final sources = <Uri>[]; | ||
|
|
||
| bool _suppressCompilerMessages = false; | ||
| bool _expectSources = true; | ||
|
|
||
| void handler(String message) { | ||
| const kResultPrefix = 'result '; | ||
| if (boundaryKey == null && message.startsWith(kResultPrefix)) { | ||
| boundaryKey = message.substring(kResultPrefix.length); | ||
| return; | ||
| } | ||
| if (message.startsWith(boundaryKey!)) { | ||
| if (_expectSources) { | ||
| if (state == _StdoutState.CollectDiagnostic) { | ||
| state = _StdoutState.CollectDependencies; | ||
| return; | ||
| } | ||
| } | ||
| if (message.length <= boundaryKey!.length) { | ||
| compilerOutput.complete(null); | ||
| return; | ||
| } | ||
| final spaceDelimiter = message.lastIndexOf(' '); | ||
| compilerOutput.complete(_CompilerOutput( | ||
| message.substring(boundaryKey!.length + 1, spaceDelimiter), | ||
| int.parse(message.substring(spaceDelimiter + 1).trim()), | ||
| sources)); | ||
| return; | ||
| } | ||
| if (state == _StdoutState.CollectDiagnostic) { | ||
| if (!_suppressCompilerMessages) { | ||
| print(message); | ||
| } | ||
| } else { | ||
| assert(state == _StdoutState.CollectDependencies); | ||
| switch (message[0]) { | ||
| case '+': | ||
| sources.add(Uri.parse(message.substring(1))); | ||
| break; | ||
| case '-': | ||
| sources.remove(Uri.parse(message.substring(1))); | ||
| break; | ||
| default: | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // This is needed to get ready to process next compilation result output, | ||
| // with its own boundary key and new completer. | ||
| void reset( | ||
| {bool suppressCompilerMessages = false, bool expectSources = true}) { | ||
| boundaryKey = null; | ||
| compilerOutput = Completer<_CompilerOutput>(); | ||
| _suppressCompilerMessages = suppressCompilerMessages; | ||
| _expectSources = expectSources; | ||
| state = _StdoutState.CollectDiagnostic; | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.