| // 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 | 
 |         expect, | 
 |         greaterThan, | 
 |         group, | 
 |         isEmpty, | 
 |         isNotEmpty, | 
 |         isNotNull, | 
 |         isTrue, | 
 |         same, | 
 |         test; | 
 |  | 
 | import 'package:front_end/src/api_prototype/front_end.dart' | 
 |     show CompilerOptions, DiagnosticMessage; | 
 |  | 
 | import 'package:front_end/src/fasta/fasta_codes.dart' | 
 |     show FormattedMessage, 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; | 
 |  | 
 | 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 | 
 |   }); | 
 | } |