Files
sdk/pkg/front_end/test/kernel_generator_test.dart
T
Sigmund Cherem 9b44fc39c8 Deprecate chaseDependencies option.
The option is not used by any client at this time and removing it simplifies the
next stack of changes I'll be making on how we compose file systems.

I also don't believe we will necessarily add this back as an option, but instead
it might be that clients requriing hermeticity will provide a custom file system
that helps with that.

Change-Id: I401efb042920d234382b6c041b13d40ffae5c908
Reviewed-on: https://dart-review.googlesource.com/56462
Commit-Queue: Peter von der Ahé <ahe@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
2018-05-24 04:57:01 +00:00

233 lines
8.1 KiB
Dart

// Copyright (c) 2017, 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 'package:kernel/ast.dart'
show EmptyStatement, Component, ReturnStatement, StaticInvocation;
import 'package:test/test.dart'
show
contains,
expect,
greaterThan,
group,
isEmpty,
isFalse,
isNotEmpty,
isNotNull,
isNull,
isTrue,
same,
test;
import 'package:front_end/src/api_prototype/front_end.dart'
show CompilerOptions;
import 'package:front_end/src/fasta/deprecated_problems.dart'
show deprecated_InputError;
import 'package:front_end/src/fasta/fasta_codes.dart' show messageMissingMain;
import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
import 'package:front_end/src/testing/compiler_common.dart'
show
compileScript,
compileUnit,
findLibrary,
invalidCoreLibsSpecUri,
isDartCoreLibrary;
main() {
group('kernelForProgram', () {
test('compiler fails if it cannot find sdk sources', () async {
var errors = [];
var options = new CompilerOptions()
..librariesSpecificationUri = invalidCoreLibsSpecUri
..sdkSummary = null
..compileSdk = true // To prevent FE from loading an sdk-summary.
..onError = (e) => errors.add(e);
var component =
await compileScript('main() => print("hi");', options: options);
expect(component, isNull);
expect(errors, isNotEmpty);
});
test('compiler fails if it cannot find sdk summary', () async {
var errors = [];
var options = new CompilerOptions()
..sdkSummary =
Uri.parse('org-dartlang-test:///not_existing_summary_file')
..onError = (e) => errors.add(e);
var component =
await compileScript('main() => print("hi");', options: options);
expect(component, isNull);
expect(errors, isNotEmpty);
});
test('by default component is compiled using the full platform file',
() async {
var options = new CompilerOptions()
// Note: we define [librariesSpecificationUri] with a specification that
// contains broken URIs to ensure we do not attempt to lookup for
// sources of the sdk directly.
..librariesSpecificationUri = invalidCoreLibsSpecUri;
var component =
await compileScript('main() => print("hi");', options: options);
var core = component.libraries.firstWhere(isDartCoreLibrary);
var printMember = core.members.firstWhere((m) => m.name.name == 'print');
// Note: summaries created by the SDK today contain empty statements as
// method bodies.
expect(printMember.function.body is! EmptyStatement, isTrue);
});
test('compiler requires a main method', () async {
var errors = [];
var options = new CompilerOptions()..onError = (e) => errors.add(e);
await compileScript('a() => print("hi");', options: options);
expect(errors.first.message, messageMissingMain.message);
});
// TODO(ahe): This test is wrong at least with respect to expecting that
// [deprecated_InputError] leaks through the API. Furthermore, the default
// behavior should be to recover from errors, as this is the most important
// use case we have.
test('default error handler throws on errors', () async {
var options = new CompilerOptions();
var exceptionThrown = false;
try {
await compileScript('a() => print("hi");', options: options);
} on deprecated_InputError catch (e) {
exceptionThrown = true;
expect('${e.error}', contains("Compilation aborted"));
}
expect(exceptionThrown, isTrue);
}, skip: true /* Issue 30194 */);
test('generated program contains source-info', () async {
var component = await compileScript('a() => print("hi"); main() {}',
fileName: 'a.dart');
// Kernel always store an empty '' key in the map, so there is always at
// least one. Having more means that source-info is added.
expect(component.uriToSource.keys.length, greaterThan(1));
expect(
component.uriToSource[Uri.parse('org-dartlang-test:///a/b/c/a.dart')],
isNotNull);
});
test('code from summary dependencies are marked external', () async {
var component = await compileScript('a() => print("hi"); main() {}',
fileName: 'a.dart');
for (var lib in component.libraries) {
if (lib.importUri.scheme == 'dart') {
expect(lib.isExternal, isTrue);
}
}
// Pretend that the compiled code is a summary
var bytes = serializeComponent(component);
component = await compileScript(
{
'b.dart': 'import "a.dart" as m; b() => m.a(); main() {}',
'summary.dill': bytes
},
fileName: 'b.dart',
inputSummaries: ['summary.dill']);
var aLib = component.libraries
.firstWhere((lib) => lib.importUri.path == '/a/b/c/a.dart');
expect(aLib.isExternal, isTrue);
});
test('code from linked dependencies are not marked external', () async {
var component = await compileScript('a() => print("hi"); main() {}',
fileName: 'a.dart');
for (var lib in component.libraries) {
if (lib.importUri.scheme == 'dart') {
expect(lib.isExternal, isTrue);
}
}
var bytes = serializeComponent(component);
component = await compileScript(
{
'b.dart': 'import "a.dart" as m; b() => m.a(); main() {}',
'link.dill': bytes
},
fileName: 'b.dart',
linkedDependencies: ['link.dill']);
var aLib = component.libraries
.firstWhere((lib) => lib.importUri.path == '/a/b/c/a.dart');
expect(aLib.isExternal, isFalse);
});
// TODO(sigmund): add tests discovering libraries.json
});
group('kernelForComponent', () {
test('compiler does not require a main method', () async {
var errors = [];
var options = new CompilerOptions()..onError = (e) => errors.add(e);
await compileUnit(['a.dart'], {'a.dart': 'a() => print("hi");'},
options: options);
expect(errors, isEmpty);
});
test('compiler is not hermetic by default', () async {
var errors = [];
var options = new CompilerOptions()..onError = (e) => errors.add(e);
await compileUnit([
'a.dart'
], {
'a.dart': 'import "b.dart"; a() => print("hi");',
'b.dart': ''
}, options: options);
expect(errors, isEmpty);
});
test('dependencies can be loaded in any order', () async {
var sources = <String, dynamic>{
'a.dart': 'a() => print("hi");',
'b.dart': 'import "a.dart"; b() => a();',
'c.dart': 'import "b.dart"; c() => b();',
'd.dart': 'import "c.dart"; d() => c();',
};
var unitA = await compileUnit(['a.dart'], sources);
// Pretend that the compiled code is a summary
sources['a.dill'] = serializeComponent(unitA);
var unitBC = await compileUnit(['b.dart', 'c.dart'], sources,
inputSummaries: ['a.dill']);
// Pretend that the compiled code is a summary
sources['bc.dill'] = serializeComponent(unitBC);
void checkDCallsC(Component component) {
var dLib = findLibrary(component, 'd.dart');
var cLib = findLibrary(component, 'c.dart');
var dMethod = dLib.procedures.first;
var dBody = dMethod.function.body;
var dCall = (dBody as ReturnStatement).expression;
var callTarget =
(dCall as StaticInvocation).targetReference.asProcedure;
expect(callTarget, same(cLib.procedures.first));
}
var unitD1 = await compileUnit(['d.dart'], sources,
inputSummaries: ['a.dill', 'bc.dill']);
checkDCallsC(unitD1);
var unitD2 = await compileUnit(['d.dart'], sources,
inputSummaries: ['bc.dill', 'a.dill']);
checkDCallsC(unitD2);
});
// TODO(sigmund): add tests with trimming dependencies
});
}