OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 import 'package:front_end/front_end.dart'; |
| 6 import 'package:front_end/src/fasta/kernel/utils.dart'; |
| 7 import 'package:front_end/src/testing/compiler_common.dart'; |
| 8 import 'package:kernel/ast.dart'; |
| 9 |
| 10 import 'package:test/test.dart'; |
| 11 |
| 12 main() { |
| 13 group('kernelForProgram', () { |
| 14 test('compiler fails if it cannot find sdk sources', () async { |
| 15 var errors = []; |
| 16 var options = new CompilerOptions() |
| 17 ..dartLibraries = invalidCoreLibs |
| 18 ..sdkSummary = null |
| 19 ..compileSdk = true // To prevent FE from loading an sdk-summary. |
| 20 ..onError = (e) => errors.add(e); |
| 21 |
| 22 var program = |
| 23 await compileScript('main() => print("hi");', options: options); |
| 24 expect(program, isNull); |
| 25 expect(errors, isNotEmpty); |
| 26 }); |
| 27 |
| 28 test('compiler fails if it cannot find sdk summary', () async { |
| 29 var errors = []; |
| 30 var options = new CompilerOptions() |
| 31 ..sdkSummary = Uri.parse('file:///not_existing_summary_file') |
| 32 ..onError = (e) => errors.add(e); |
| 33 |
| 34 var program = |
| 35 await compileScript('main() => print("hi");', options: options); |
| 36 expect(program, isNull); |
| 37 expect(errors, isNotEmpty); |
| 38 }); |
| 39 |
| 40 test('by default program is compiled using summaries', () async { |
| 41 var options = new CompilerOptions() |
| 42 // Note: we define [dartLibraries] with broken URIs to ensure we do not |
| 43 // attempt to lookup for sources of the sdk directly. |
| 44 ..dartLibraries = invalidCoreLibs; |
| 45 var program = |
| 46 await compileScript('main() => print("hi");', options: options); |
| 47 var core = program.libraries.firstWhere(isDartCoreLibrary); |
| 48 var printMember = core.members.firstWhere((m) => m.name.name == 'print'); |
| 49 |
| 50 // Note: summaries created by the SDK today contain empty statements as |
| 51 // method bodies. |
| 52 expect(printMember.function.body is EmptyStatement, isTrue); |
| 53 }); |
| 54 |
| 55 test('compiler requires a main method', () async { |
| 56 var errors = []; |
| 57 var options = new CompilerOptions()..onError = (e) => errors.add(e); |
| 58 await compileScript('a() => print("hi");', options: options); |
| 59 expect('${errors.first}', contains("No 'main' method found")); |
| 60 }); |
| 61 |
| 62 test('default error handler throws', () async { |
| 63 var exceptionThrown = false; |
| 64 try { |
| 65 await compileScript('a() => print("hi");'); |
| 66 } catch (e) { |
| 67 exceptionThrown = true; |
| 68 expect('$e', contains("No 'main' method found")); |
| 69 } |
| 70 expect(exceptionThrown, isTrue); |
| 71 }); |
| 72 |
| 73 test('generated program contains source-info', () async { |
| 74 var program = await compileScript('a() => print("hi"); main() {}', |
| 75 fileName: 'a.dart'); |
| 76 // Kernel always store an empty '' key in the map, so there is always at |
| 77 // least one. Having more means that source-info is added. |
| 78 expect(program.uriToSource.keys.length, greaterThan(1)); |
| 79 expect(program.uriToSource['file:///a/b/c/a.dart'], isNotNull); |
| 80 }); |
| 81 |
| 82 test('code from summary dependencies are marked external', () async { |
| 83 var program = await compileScript('a() => print("hi"); main() {}', |
| 84 fileName: 'a.dart'); |
| 85 for (var lib in program.libraries) { |
| 86 if (lib.importUri.scheme == 'dart') { |
| 87 expect(lib.isExternal, isTrue); |
| 88 } |
| 89 } |
| 90 |
| 91 // Pretend that the compiled code is a summary |
| 92 var bytes = serializeProgram(program); |
| 93 program = await compileScript( |
| 94 { |
| 95 'b.dart': 'import "a.dart" as m; b() => m.a(); main() {}', |
| 96 'summary.dill': bytes |
| 97 }, |
| 98 fileName: 'b.dart', |
| 99 inputSummaries: ['summary.dill']); |
| 100 |
| 101 var aLib = program.libraries |
| 102 .firstWhere((lib) => lib.importUri.path == '/a/b/c/a.dart'); |
| 103 expect(aLib.isExternal, isTrue); |
| 104 }); |
| 105 |
| 106 test('code from linked dependencies are not marked external', () async { |
| 107 var program = await compileScript('a() => print("hi"); main() {}', |
| 108 fileName: 'a.dart'); |
| 109 for (var lib in program.libraries) { |
| 110 if (lib.importUri.scheme == 'dart') { |
| 111 expect(lib.isExternal, isTrue); |
| 112 } |
| 113 } |
| 114 |
| 115 var bytes = serializeProgram(program); |
| 116 program = await compileScript( |
| 117 { |
| 118 'b.dart': 'import "a.dart" as m; b() => m.a(); main() {}', |
| 119 'link.dill': bytes |
| 120 }, |
| 121 fileName: 'b.dart', |
| 122 linkedDependencies: ['link.dill']); |
| 123 |
| 124 var aLib = program.libraries |
| 125 .firstWhere((lib) => lib.importUri.path == '/a/b/c/a.dart'); |
| 126 expect(aLib.isExternal, isFalse); |
| 127 }); |
| 128 |
| 129 // TODO(sigmund): add tests discovering libraries.json |
| 130 }); |
| 131 |
| 132 group('kernelForBuildUnit', () { |
| 133 test('compiler does not require a main method', () async { |
| 134 var errors = []; |
| 135 var options = new CompilerOptions()..onError = (e) => errors.add(e); |
| 136 await compileUnit(['a.dart'], {'a.dart': 'a() => print("hi");'}, |
| 137 options: options); |
| 138 expect(errors, isEmpty); |
| 139 }); |
| 140 |
| 141 test('compiler by default is hermetic', () async { |
| 142 var errors = []; |
| 143 var options = new CompilerOptions()..onError = (e) => errors.add(e); |
| 144 var sources = { |
| 145 'a.dart': 'import "b.dart"; a() => print("hi");', |
| 146 'b.dart': '' |
| 147 }; |
| 148 await compileUnit(['a.dart'], sources, options: options); |
| 149 expect(errors.first.toString(), contains('Invalid access')); |
| 150 errors.clear(); |
| 151 |
| 152 await compileUnit(['a.dart', 'b.dart'], sources, options: options); |
| 153 expect(errors, isEmpty); |
| 154 }); |
| 155 |
| 156 test('chaseDependencies=true removes hermetic restriction', () async { |
| 157 var errors = []; |
| 158 var options = new CompilerOptions() |
| 159 ..chaseDependencies = true |
| 160 ..onError = (e) => errors.add(e); |
| 161 await compileUnit([ |
| 162 'a.dart' |
| 163 ], { |
| 164 'a.dart': 'import "b.dart"; a() => print("hi");', |
| 165 'b.dart': '' |
| 166 }, options: options); |
| 167 expect(errors, isEmpty); |
| 168 }); |
| 169 |
| 170 test('dependencies can be loaded in any order', () async { |
| 171 var sources = <String, dynamic>{ |
| 172 'a.dart': 'a() => print("hi");', |
| 173 'b.dart': 'import "a.dart"; b() => a();', |
| 174 'c.dart': 'import "b.dart"; c() => b();', |
| 175 'd.dart': 'import "c.dart"; d() => c();', |
| 176 }; |
| 177 |
| 178 var unitA = await compileUnit(['a.dart'], sources); |
| 179 // Pretend that the compiled code is a summary |
| 180 sources['a.dill'] = serializeProgram(unitA); |
| 181 |
| 182 var unitBC = await compileUnit(['b.dart', 'c.dart'], sources, |
| 183 inputSummaries: ['a.dill']); |
| 184 |
| 185 // Pretend that the compiled code is a summary |
| 186 sources['bc.dill'] = serializeProgram(unitBC); |
| 187 |
| 188 void checkDCallsC(Program program) { |
| 189 var dLib = findLibrary(program, 'd.dart'); |
| 190 var cLib = findLibrary(program, 'c.dart'); |
| 191 var dMethod = dLib.procedures.first; |
| 192 var dBody = dMethod.function.body; |
| 193 var dCall = (dBody as ReturnStatement).expression; |
| 194 var callTarget = |
| 195 (dCall as StaticInvocation).targetReference.asProcedure; |
| 196 expect(callTarget, same(cLib.procedures.first)); |
| 197 } |
| 198 |
| 199 var unitD1 = await compileUnit(['d.dart'], sources, |
| 200 inputSummaries: ['a.dill', 'bc.dill']); |
| 201 checkDCallsC(unitD1); |
| 202 |
| 203 var unitD2 = await compileUnit(['d.dart'], sources, |
| 204 inputSummaries: ['bc.dill', 'a.dill']); |
| 205 checkDCallsC(unitD2); |
| 206 }); |
| 207 |
| 208 // TODO(sigmund): add tests with trimming dependencies |
| 209 }); |
| 210 } |
OLD | NEW |