ec5e71ead4
* Rename additionalDills to additionalDillModules to indicate that it is used to load a "module", not any old dill file. * Where additionalDills was used to provide the platform use sdkSummary instead. * Remove unused constructor in KernelCompilationResults. Tested: Existing tests. Change-Id: I5f73f61db73b2bc932c211fb0b2e66ec2f5c50c5 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/495981 Reviewed-by: Alexander Markov <alexmarkov@google.com> Reviewed-by: Nicholas Shahan <nshahan@google.com> Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
206 lines
6.6 KiB
Dart
206 lines
6.6 KiB
Dart
// 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:io';
|
|
|
|
import 'package:dart2wasm/target.dart' show WasmTarget;
|
|
import 'package:front_end/src/api_unstable/vm.dart'
|
|
show
|
|
CompilerOptions,
|
|
CfeDiagnosticMessage,
|
|
computePlatformBinariesLocation,
|
|
kernelForModule,
|
|
kernelForProgram,
|
|
parseExperimentalArguments,
|
|
parseExperimentalFlags;
|
|
import 'package:kernel/ast.dart';
|
|
import 'package:kernel/text/ast_to_text.dart' show Printer;
|
|
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
|
|
import 'package:kernel/target/targets.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
/// Environment define to update expectation files on failures.
|
|
const kUpdateExpectations = 'updateExpectations';
|
|
|
|
/// Environment define to dump actual results alongside expectations.
|
|
const kDumpActualResult = 'dump.actual.result';
|
|
|
|
Future<Component> compileTestCaseToKernelProgram(
|
|
Uri sourceUri, {
|
|
required Target target,
|
|
List<String>? experimentalFlags,
|
|
Map<String, String>? environmentDefines,
|
|
Uri? packagesFileUri,
|
|
List<Uri>? linkedDependencies,
|
|
}) async {
|
|
Directory? tempDirectory;
|
|
try {
|
|
final platformFileName = (target is WasmTarget)
|
|
? target.platformFile
|
|
: 'vm_platform.dill';
|
|
final platformKernel = computePlatformBinariesLocation().resolve(
|
|
platformFileName,
|
|
);
|
|
environmentDefines ??= <String, String>{};
|
|
final options = new CompilerOptions()
|
|
..target = target
|
|
..sdkSummary = platformKernel
|
|
..environmentDefines = environmentDefines
|
|
..packagesFileUri = packagesFileUri
|
|
..explicitExperimentalFlags = parseExperimentalFlags(
|
|
parseExperimentalArguments(experimentalFlags),
|
|
onError: (String message) {
|
|
throw message;
|
|
},
|
|
)
|
|
..onDiagnostic = (CfeDiagnosticMessage message) {
|
|
fail("Compilation error: ${message.plainTextFormatted.join('\n')}");
|
|
};
|
|
if (linkedDependencies != null) {
|
|
final Component component = (await kernelForModule(
|
|
linkedDependencies,
|
|
options,
|
|
)).component!;
|
|
tempDirectory = await Directory.systemTemp.createTemp();
|
|
Uri uri = tempDirectory.uri.resolve("generated.dill");
|
|
File generated = new File.fromUri(uri);
|
|
IOSink sink = generated.openWrite();
|
|
try {
|
|
new BinaryPrinter(sink).writeComponentFile(component);
|
|
} finally {
|
|
await sink.close();
|
|
}
|
|
options..additionalDillModules = <Uri>[uri];
|
|
}
|
|
|
|
final Component component = (await kernelForProgram(
|
|
sourceUri,
|
|
options,
|
|
))!.component!;
|
|
|
|
// Make sure the library name is the same and does not depend on the order
|
|
// of test cases.
|
|
component.mainMethod!.enclosingLibrary.name = '#lib';
|
|
return component;
|
|
} finally {
|
|
await tempDirectory?.delete(recursive: true);
|
|
}
|
|
}
|
|
|
|
/// Returns a human-readable string representation of [library].
|
|
///
|
|
/// If [removeSelectorIds] is provided, selector ids above 99 are removed.
|
|
/// Extra libraries apart from the main library are passed to the front-end as
|
|
/// additional dills, which places them last in the library list, causing them
|
|
/// to have very high (and often changing) selector IDs.
|
|
String kernelLibraryToString(
|
|
Library library, {
|
|
bool removeSelectorIds = false,
|
|
}) {
|
|
final StringBuffer buffer = new StringBuffer();
|
|
final printer = new Printer(buffer, showMetadata: true);
|
|
printer.writeLibraryFile(library);
|
|
printer.writeConstantTable(library.enclosingComponent!);
|
|
String result = buffer.toString();
|
|
final libraryName = library.name;
|
|
if (libraryName != null) {
|
|
result = result.replaceAll(library.importUri.toString(), library.name!);
|
|
}
|
|
if (removeSelectorIds) {
|
|
result = result
|
|
.replaceAll(RegExp(r',methodOrSetterSelectorId:\d{3,}'), '')
|
|
.replaceAll(RegExp(r',getterSelectorId:\d{3,}'), '');
|
|
}
|
|
return result;
|
|
}
|
|
|
|
String kernelComponentToString(Component component) {
|
|
final StringBuffer buffer = new StringBuffer();
|
|
new Printer(buffer, showMetadata: true).writeComponentFile(component);
|
|
final mainLibrary = component.mainMethod!.enclosingLibrary;
|
|
return buffer.toString().replaceAll(
|
|
mainLibrary.importUri.toString(),
|
|
mainLibrary.name!,
|
|
);
|
|
}
|
|
|
|
class DevNullSink<T> implements Sink<T> {
|
|
@override
|
|
void add(T data) {}
|
|
|
|
@override
|
|
void close() {}
|
|
}
|
|
|
|
void ensureKernelCanBeSerializedToBinary(Component component) {
|
|
new BinaryPrinter(new DevNullSink<List<int>>()).writeComponentFile(component);
|
|
}
|
|
|
|
class Difference {
|
|
final int line;
|
|
final String actual;
|
|
final String expected;
|
|
|
|
Difference(this.line, this.actual, this.expected);
|
|
}
|
|
|
|
Difference findFirstDifference(String actual, String expected) {
|
|
final actualLines = actual.split('\n');
|
|
final expectedLines = expected.split('\n');
|
|
int i = 0;
|
|
for (; i < actualLines.length && i < expectedLines.length; ++i) {
|
|
if (actualLines[i] != expectedLines[i]) {
|
|
return new Difference(i + 1, actualLines[i], expectedLines[i]);
|
|
}
|
|
}
|
|
return new Difference(
|
|
i + 1,
|
|
i < actualLines.length ? actualLines[i] : '<END>',
|
|
i < expectedLines.length ? expectedLines[i] : '<END>',
|
|
);
|
|
}
|
|
|
|
void compareResultWithExpectationsFile(
|
|
Uri source,
|
|
String actual, {
|
|
String expectFilePostfix = '',
|
|
}) {
|
|
final baseFilename = '${source.toFilePath()}$expectFilePostfix';
|
|
final expectFile = new File('$baseFilename.expect');
|
|
final expected = expectFile.existsSync() ? expectFile.readAsStringSync() : '';
|
|
|
|
if (actual != expected) {
|
|
if (bool.fromEnvironment(kUpdateExpectations)) {
|
|
expectFile.writeAsStringSync(actual);
|
|
print(" Updated $expectFile");
|
|
} else {
|
|
if (bool.fromEnvironment(kDumpActualResult)) {
|
|
new File('$baseFilename.actual').writeAsStringSync(actual);
|
|
}
|
|
Difference diff = findFirstDifference(actual, expected);
|
|
fail("""
|
|
|
|
Result is different for the test case $source
|
|
|
|
The first difference is at line ${diff.line}.
|
|
Actual: ${diff.actual}
|
|
Expected: ${diff.expected}
|
|
|
|
This failure can be caused by changes in the front-end if it starts generating
|
|
different kernel AST for the same Dart programs.
|
|
|
|
In order to re-generate expectations run tests with -D$kUpdateExpectations=true VM option:
|
|
|
|
tools/test.py -m release --vm-options -D$kUpdateExpectations=true --timeout 600 pkg/vm/
|
|
|
|
In order to dump actual results into .actual files run tests with -D$kDumpActualResult=true VM option:
|
|
|
|
tools/test.py -m release --vm-options -D$kDumpActualResult=true --timeout 600 pkg/vm/
|
|
|
|
""");
|
|
}
|
|
}
|
|
}
|