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 |