|  | // 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:front_end/src/api_prototype/front_end.dart' | 
|  | show CompilerOptions, DiagnosticMessage; | 
|  | import 'package:front_end/src/codes/cfe_codes.dart' | 
|  | show FormattedMessage, messageMissingMain; | 
|  | import 'package:front_end/src/kernel/utils.dart' show serializeComponent; | 
|  | import 'package:front_end/src/testing/compiler_common.dart' | 
|  | show | 
|  | compileScript, | 
|  | compileUnit, | 
|  | findLibrary, | 
|  | invalidCoreLibsSpecUri, | 
|  | isDartCoreLibrary; | 
|  | import 'package:kernel/ast.dart' | 
|  | show EmptyStatement, Component, ReturnStatement, StaticInvocation; | 
|  | import 'package:test/test.dart' | 
|  | show | 
|  | expect, | 
|  | greaterThan, | 
|  | group, | 
|  | isEmpty, | 
|  | isNotEmpty, | 
|  | isNotNull, | 
|  | isTrue, | 
|  | same, | 
|  | test; | 
|  |  | 
|  | void 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. | 
|  | ..onDiagnostic = errors.add; | 
|  |  | 
|  | Component? component = | 
|  | (await compileScript('main() => print("hi");', options: options)) | 
|  | ?.component; | 
|  | expect(component, isNotNull); | 
|  | 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') | 
|  | ..onDiagnostic = errors.add; | 
|  |  | 
|  | Component? component = | 
|  | (await compileScript('main() => print("hi");', options: options)) | 
|  | ?.component; | 
|  | expect(component, isNotNull); | 
|  | 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; | 
|  | Component component = | 
|  | (await compileScript('main() => print("hi");', options: options))! | 
|  | .component!; | 
|  | var core = component.libraries.firstWhere(isDartCoreLibrary); | 
|  | var printMember = core.members.firstWhere((m) => m.name.text == '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 = <DiagnosticMessage>[]; | 
|  | var options = new CompilerOptions()..onDiagnostic = errors.add; | 
|  | await compileScript('a() => print("hi");', options: options); | 
|  | expect((errors.first as FormattedMessage).problemMessage, | 
|  | messageMissingMain.problemMessage); | 
|  | }); | 
|  |  | 
|  | test('generated program contains source-info', () async { | 
|  | Component component = (await compileScript( | 
|  | 'a() => print("hi"); main() {}', | 
|  | fileName: 'a.dart'))! | 
|  | .component!; | 
|  | // 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); | 
|  | }); | 
|  |  | 
|  | // TODO(sigmund): add tests discovering libraries.json | 
|  | }); | 
|  |  | 
|  | group('kernelForComponent', () { | 
|  | test('compiler does not require a main method', () async { | 
|  | var errors = []; | 
|  | var options = new CompilerOptions()..onDiagnostic = errors.add; | 
|  | 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()..onDiagnostic = errors.add; | 
|  | 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, | 
|  | additionalDills: ['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, | 
|  | additionalDills: ['a.dill', 'bc.dill']); | 
|  | checkDCallsC(unitD1!); | 
|  |  | 
|  | var unitD2 = await compileUnit(['d.dart'], sources, | 
|  | additionalDills: ['bc.dill', 'a.dill']); | 
|  | checkDCallsC(unitD2!); | 
|  | }); | 
|  |  | 
|  | // TODO(sigmund): add tests with trimming dependencies | 
|  | }); | 
|  | } |