ab4f9351b1
The name has always been annoying because it did not add strong typing. And now there aren't variants of the VM platform to distinguish. Leave a copy at the old name to not immediately break illegal uses. TEST=ci Cq-Include-Trybots: luci.dart.try:flutter-analyze-try,flutter-frontend-try,flutter-linux-try Change-Id: Ie76fa7f16940aa1ba8d582eb5197f0ae55dc8938 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/429828 Reviewed-by: Johnni Winther <johnniwinther@google.com> Reviewed-by: Nicholas Shahan <nshahan@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
369 lines
13 KiB
Dart
369 lines
13 KiB
Dart
// Copyright (c) 2023, 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:ffi';
|
|
import 'dart:io';
|
|
|
|
import 'package:kernel/kernel.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
// Reuse some test infrastructure.
|
|
import 'frontend_server_test.dart';
|
|
|
|
void main() async {
|
|
group('full compiler tests', () {
|
|
final Uri platformKernel =
|
|
computePlatformBinariesLocation().resolve('vm_platform.dill');
|
|
final Uri sdkRoot = computePlatformBinariesLocation();
|
|
|
|
late Directory tempDir;
|
|
late File mainFile;
|
|
late File packageConfigFile;
|
|
late File nativeAssetsYamlFile;
|
|
late File dillFile;
|
|
|
|
setUp(() async {
|
|
tempDir = await Directory.systemTemp.createTemp('frontendServerTest');
|
|
|
|
mainFile = new File('${tempDir.path}/a.dart');
|
|
await mainFile.create(recursive: true);
|
|
await mainFile.writeAsString('''
|
|
void main() {
|
|
print(42);
|
|
}
|
|
''');
|
|
|
|
packageConfigFile =
|
|
new File('${tempDir.path}/.dart_tool/package_config.json');
|
|
await packageConfigFile.create(recursive: true);
|
|
await packageConfigFile.writeAsString(jsonEncode({
|
|
"configVersion": 2,
|
|
"packages": [],
|
|
}));
|
|
|
|
nativeAssetsYamlFile =
|
|
new File('${tempDir.path}/.dart_tool/native_assets.yaml');
|
|
await nativeAssetsYamlFile.create(recursive: true);
|
|
await nativeAssetsYamlFile.writeAsString(jsonEncode({
|
|
'format-version': [1, 0, 0],
|
|
'native-assets': {
|
|
new Abi.current().toString(): {
|
|
mainFile.uri.toString(): ['executable'],
|
|
},
|
|
},
|
|
}));
|
|
|
|
// Other setup.
|
|
dillFile = new File('${tempDir.path}/app.dill');
|
|
});
|
|
|
|
tearDown(() async {
|
|
return await tempDir.delete(recursive: true);
|
|
});
|
|
|
|
group('--incremental', () {
|
|
Future<void> testPassInNativeAssetsAtStartup({
|
|
List<String> additionalStartupArguments = const [],
|
|
}) async {
|
|
final FrontendServer frontendServer = new FrontendServer();
|
|
Future<int> result = frontendServer.open(<String>[
|
|
'--sdk-root=${sdkRoot.toFilePath()}',
|
|
'--incremental',
|
|
'--platform=${platformKernel.path}',
|
|
'--output-dill=${dillFile.path}',
|
|
'--native-assets=${nativeAssetsYamlFile.path}',
|
|
]);
|
|
|
|
frontendServer.compile(mainFile.path);
|
|
|
|
int count = 0;
|
|
frontendServer.listen((Result compiledResult) async {
|
|
CompilationResult result =
|
|
new CompilationResult.parse(compiledResult.status);
|
|
switch (count) {
|
|
case 0:
|
|
expect(await dillFile.exists(), equals(true));
|
|
expect(result.filename, dillFile.path);
|
|
expect(result.errorsCount, 0);
|
|
count += 1;
|
|
frontendServer.accept();
|
|
frontendServer.reset();
|
|
|
|
final Component component =
|
|
loadComponentFromBinary(dillFile.path);
|
|
final Library? nativeAssetsLibrary =
|
|
_findNativeAssetsLibrary(component);
|
|
expect(nativeAssetsLibrary, isNotNull);
|
|
|
|
final Library firstLib = component.libraries.first;
|
|
expect(firstLib.importUri != _nativeAssetsLibraryUri, true);
|
|
expect(nativeAssetsLibrary!.nonNullable, firstLib.nonNullable);
|
|
|
|
await mainFile.writeAsString('''
|
|
void main() {
|
|
print(1337);
|
|
}
|
|
''');
|
|
|
|
frontendServer.recompile(mainFile.uri);
|
|
break;
|
|
case 1:
|
|
expect(await dillFile.exists(), equals(true));
|
|
expect(result.filename, dillFile.path);
|
|
expect(result.errorsCount, 0);
|
|
frontendServer.accept();
|
|
frontendServer.quit();
|
|
|
|
final Component component =
|
|
loadComponentFromBinary(dillFile.path);
|
|
final Library? nativeAssetsLibrary =
|
|
_findNativeAssetsLibrary(component);
|
|
expect(nativeAssetsLibrary, isNotNull);
|
|
|
|
break;
|
|
}
|
|
});
|
|
expect(await result, 0);
|
|
frontendServer.close();
|
|
}
|
|
|
|
test('pass in native assets at startup', () async {
|
|
await testPassInNativeAssetsAtStartup();
|
|
});
|
|
|
|
test('--no-sound-null-safety', () async {
|
|
await testPassInNativeAssetsAtStartup(additionalStartupArguments: [
|
|
'--no-sound-null-safety',
|
|
]);
|
|
});
|
|
|
|
test('--incremental-serialization', () async {
|
|
await testPassInNativeAssetsAtStartup(additionalStartupArguments: [
|
|
'--incremental-serialization',
|
|
]);
|
|
});
|
|
|
|
test('set native assets later', () async {
|
|
final FrontendServer frontendServer = new FrontendServer();
|
|
Future<int> result = frontendServer.open(<String>[
|
|
'--sdk-root=${sdkRoot.toFilePath()}',
|
|
'--incremental',
|
|
'--platform=${platformKernel.path}',
|
|
'--output-dill=${dillFile.path}',
|
|
]);
|
|
|
|
frontendServer.compile(mainFile.path);
|
|
|
|
int count = 0;
|
|
frontendServer.listen((Result compiledResult) async {
|
|
CompilationResult result =
|
|
new CompilationResult.parse(compiledResult.status);
|
|
switch (count) {
|
|
case 0:
|
|
expect(await dillFile.exists(), equals(true));
|
|
expect(result.filename, dillFile.path);
|
|
expect(result.errorsCount, 0);
|
|
count += 1;
|
|
frontendServer.accept();
|
|
frontendServer.reset();
|
|
|
|
final Component component =
|
|
loadComponentFromBinary(dillFile.path);
|
|
final Library? nativeAssetsLibrary =
|
|
_findNativeAssetsLibrary(component);
|
|
expect(nativeAssetsLibrary, isNull);
|
|
|
|
frontendServer.setNativeAssets(uri: nativeAssetsYamlFile.uri);
|
|
frontendServer.recompile(mainFile.uri);
|
|
break;
|
|
case 1:
|
|
expect(await dillFile.exists(), equals(true));
|
|
expect(result.filename, dillFile.path);
|
|
expect(result.errorsCount, 0);
|
|
count += 1;
|
|
frontendServer.accept();
|
|
|
|
final Component component =
|
|
loadComponentFromBinary(dillFile.path);
|
|
final Library? nativeAssetsLibrary =
|
|
_findNativeAssetsLibrary(component);
|
|
expect(nativeAssetsLibrary, isNotNull);
|
|
|
|
frontendServer.compileNativeAssetsOnly();
|
|
break;
|
|
case 2:
|
|
expect(await dillFile.exists(), equals(true));
|
|
expect(result.filename, dillFile.path);
|
|
expect(result.errorsCount, 0);
|
|
count += 1;
|
|
|
|
final Component component =
|
|
loadComponentFromBinary(dillFile.path);
|
|
final Library? nativeAssetsLibrary =
|
|
_findNativeAssetsLibrary(component);
|
|
expect(nativeAssetsLibrary, isNotNull);
|
|
|
|
frontendServer.quit();
|
|
}
|
|
});
|
|
expect(await result, 0);
|
|
frontendServer.close();
|
|
});
|
|
|
|
Future<void> testInitializeFromDill({
|
|
bool passNativeAssetsOnFirstStartup = false,
|
|
bool passNativeAssetsOnSecondStartup = false,
|
|
}) async {
|
|
{
|
|
final FrontendServer frontendServer = new FrontendServer();
|
|
Future<int> frontendServerResult = frontendServer.open(<String>[
|
|
'--sdk-root=${sdkRoot.toFilePath()}',
|
|
'--incremental',
|
|
'--platform=${platformKernel.path}',
|
|
'--output-dill=${dillFile.path}',
|
|
if (passNativeAssetsOnFirstStartup)
|
|
'--native-assets=${nativeAssetsYamlFile.path}',
|
|
]);
|
|
|
|
frontendServer.compile(mainFile.path);
|
|
|
|
final Result compiledResult =
|
|
await frontendServer.receivedResults.stream.first;
|
|
CompilationResult result =
|
|
new CompilationResult.parse(compiledResult.status);
|
|
expect(await dillFile.exists(), equals(true));
|
|
expect(result.filename, dillFile.path);
|
|
expect(result.errorsCount, 0);
|
|
|
|
frontendServer.accept();
|
|
frontendServer.quit();
|
|
|
|
final Component component = loadComponentFromBinary(dillFile.path);
|
|
final Library? nativeAssetsLibrary =
|
|
_findNativeAssetsLibrary(component);
|
|
expect(nativeAssetsLibrary,
|
|
passNativeAssetsOnFirstStartup ? isNotNull : isNull);
|
|
|
|
expect(await frontendServerResult, 0);
|
|
frontendServer.close();
|
|
}
|
|
|
|
{
|
|
final FrontendServer frontendServer = new FrontendServer();
|
|
Future<int> frontendServerResult = frontendServer.open(<String>[
|
|
'--sdk-root=${sdkRoot.toFilePath()}',
|
|
'--incremental',
|
|
'--platform=${platformKernel.path}',
|
|
'--output-dill=${dillFile.path}',
|
|
'--initialize-from-dill=${dillFile.path}',
|
|
if (passNativeAssetsOnSecondStartup)
|
|
'--native-assets=${nativeAssetsYamlFile.path}',
|
|
]);
|
|
|
|
frontendServer.compile(mainFile.path);
|
|
|
|
final Result compiledResult =
|
|
await frontendServer.receivedResults.stream.first;
|
|
CompilationResult result =
|
|
new CompilationResult.parse(compiledResult.status);
|
|
expect(await dillFile.exists(), equals(true));
|
|
expect(result.filename, dillFile.path);
|
|
expect(result.errorsCount, 0);
|
|
|
|
frontendServer.accept();
|
|
frontendServer.quit();
|
|
|
|
final Component component = loadComponentFromBinary(dillFile.path);
|
|
final Library? nativeAssetsLibrary =
|
|
_findNativeAssetsLibrary(component);
|
|
expect(nativeAssetsLibrary,
|
|
passNativeAssetsOnSecondStartup ? isNotNull : isNull);
|
|
|
|
expect(await frontendServerResult, 0);
|
|
frontendServer.close();
|
|
}
|
|
}
|
|
|
|
test('--initialize-from-dill embed native-assets', () async {
|
|
// This should forget the native assets, the incremental compiler
|
|
// should be seen as an optimization, _not_ as a thing that keeps
|
|
// state intentionally.
|
|
await testInitializeFromDill(passNativeAssetsOnFirstStartup: true);
|
|
});
|
|
|
|
test('--initialize-from-dill second start with --native-assets',
|
|
() async {
|
|
await testInitializeFromDill(passNativeAssetsOnSecondStartup: true);
|
|
});
|
|
|
|
test('--initialize-from-dill replace --native-assets', () async {
|
|
// This should forget the native assets from the first invocation.
|
|
await testInitializeFromDill(
|
|
passNativeAssetsOnFirstStartup: true,
|
|
passNativeAssetsOnSecondStartup: true,
|
|
);
|
|
});
|
|
});
|
|
|
|
group('--aot --tfa', () {
|
|
test('pass in native assets at startup', () async {
|
|
final FrontendServer frontendServer = new FrontendServer();
|
|
Future<int> frontendServerResult = frontendServer.open(<String>[
|
|
'--sdk-root=${sdkRoot.toFilePath()}',
|
|
'--platform=${platformKernel.path}',
|
|
'--aot',
|
|
'--tfa',
|
|
'--output-dill=${dillFile.path}',
|
|
'--native-assets=${nativeAssetsYamlFile.path}',
|
|
mainFile.path
|
|
]);
|
|
|
|
expect(await frontendServerResult, 0);
|
|
frontendServer.close();
|
|
|
|
expect(await dillFile.exists(), equals(true));
|
|
final Component component = loadComponentFromBinary(dillFile.path);
|
|
final Library? nativeAssetsLibrary =
|
|
_findNativeAssetsLibrary(component);
|
|
expect(nativeAssetsLibrary, isNotNull);
|
|
});
|
|
|
|
test('pass in native assets only at startup', () async {
|
|
final FrontendServer frontendServer = new FrontendServer();
|
|
Future<int> frontendServerResult = frontendServer.open(<String>[
|
|
'--sdk-root=${sdkRoot.toFilePath()}',
|
|
'--platform=${platformKernel.path}',
|
|
'--aot',
|
|
'--tfa',
|
|
'--output-dill=${dillFile.path}',
|
|
'--native-assets=${nativeAssetsYamlFile.path}',
|
|
'--native-assets-only',
|
|
]);
|
|
|
|
expect(await frontendServerResult, 0);
|
|
frontendServer.close();
|
|
|
|
expect(await dillFile.exists(), equals(true));
|
|
final Component component = loadComponentFromBinary(dillFile.path);
|
|
final Library? nativeAssetsLibrary =
|
|
_findNativeAssetsLibrary(component);
|
|
expect(nativeAssetsLibrary, isNotNull);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
final Uri _nativeAssetsLibraryUri = Uri.parse('vm:ffi:native-assets');
|
|
|
|
Library? _findNativeAssetsLibrary(Component component) {
|
|
for (final Library library in component.libraries) {
|
|
if (library.importUri == _nativeAssetsLibraryUri) {
|
|
return library;
|
|
}
|
|
}
|
|
return null;
|
|
}
|