OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Tests code generation. | 5 /// Tests code generation. |
6 /// | 6 /// |
7 /// Runs Dart Dev Compiler on all input in the `codegen` directory and checks | 7 /// Runs Dart Dev Compiler on all input in the `codegen` directory and checks |
8 /// that the output is what we expected. | 8 /// that the output is what we expected. |
9 library dev_compiler.test.codegen_test; | 9 library dev_compiler.test.codegen_test; |
10 | 10 |
11 // TODO(rnystrom): This doesn't actually run any tests any more. It just | 11 // TODO(rnystrom): This doesn't actually run any tests any more. It just |
12 // compiles stuff. This should be changed to not use unittest and just be a | 12 // compiles stuff. This should be changed to not use unittest and just be a |
13 // regular program that outputs files. | 13 // regular program that outputs files. |
14 | 14 |
15 import 'dart:convert' show JSON; | 15 import 'dart:convert' show JSON; |
16 import 'dart:io' show Directory, File, Platform; | 16 import 'dart:io' show Directory, File, Platform; |
17 import 'package:args/args.dart' show ArgParser, ArgResults; | 17 import 'package:args/args.dart' show ArgParser, ArgResults; |
18 import 'package:path/path.dart' as path; | 18 import 'package:path/path.dart' as path; |
19 import 'package:test/test.dart' show group, test; | 19 import 'package:test/test.dart' show test; |
20 | 20 |
21 import 'package:analyzer/analyzer.dart' | 21 import 'package:analyzer/analyzer.dart' |
22 show | 22 show |
23 ExportDirective, | 23 ExportDirective, |
24 ImportDirective, | 24 ImportDirective, |
25 StringLiteral, | 25 StringLiteral, |
26 UriBasedDirective, | 26 UriBasedDirective, |
27 parseDirectives; | 27 parseDirectives; |
28 import 'package:analyzer/src/generated/source.dart' show Source; | 28 import 'package:analyzer/src/generated/source.dart' show Source; |
29 import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions; | 29 import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions; |
(...skipping 19 matching lines...) Expand all Loading... |
49 /// The tests sometimes import utility libraries using a relative path. | 49 /// The tests sometimes import utility libraries using a relative path. |
50 /// Likewise, the multitests do too, and one multitest even imports its own | 50 /// Likewise, the multitests do too, and one multitest even imports its own |
51 /// non-expanded form (!). To make that simpler, we copy the entire test tree | 51 /// non-expanded form (!). To make that simpler, we copy the entire test tree |
52 /// to a generated directory and expand that multitests in there too. | 52 /// to a generated directory and expand that multitests in there too. |
53 final codegenTestDir = path.join(repoDirectory, 'gen', 'codegen_tests'); | 53 final codegenTestDir = path.join(repoDirectory, 'gen', 'codegen_tests'); |
54 | 54 |
55 /// The generated directory where tests and packages compiled to JS are | 55 /// The generated directory where tests and packages compiled to JS are |
56 /// output. | 56 /// output. |
57 final codegenOutputDir = path.join(repoDirectory, 'gen', 'codegen_output'); | 57 final codegenOutputDir = path.join(repoDirectory, 'gen', 'codegen_output'); |
58 | 58 |
59 // TODO(jmesserly): switch this to a .packages file. | |
60 final packageUrlMappings = { | |
61 'package:expect/expect.dart': path.join(codegenDir, 'expect.dart'), | |
62 'package:async_helper/async_helper.dart': | |
63 path.join(codegenDir, 'async_helper.dart'), | |
64 'package:js/js.dart': path.join(codegenDir, 'packages', 'js', 'js.dart') | |
65 }; | |
66 | |
67 final codeCoverage = Platform.environment.containsKey('COVERALLS_TOKEN'); | 59 final codeCoverage = Platform.environment.containsKey('COVERALLS_TOKEN'); |
68 | 60 |
69 RegExp filePattern; | 61 RegExp filePattern; |
70 | 62 |
71 main(List<String> arguments) { | 63 main(List<String> arguments) { |
72 if (arguments == null) arguments = []; | 64 if (arguments == null) arguments = []; |
73 ArgResults args = argParser.parse(arguments); | 65 ArgResults args = argParser.parse(arguments); |
74 filePattern = new RegExp(args.rest.length > 0 ? args.rest[0] : '.'); | 66 filePattern = new RegExp(args.rest.length > 0 ? args.rest[0] : '.'); |
75 | 67 |
76 var sdkDir = path.join(repoDirectory, 'gen', 'patched_sdk'); | 68 var sdkDir = path.join(repoDirectory, 'gen', 'patched_sdk'); |
77 var sdkSummaryFile = | 69 var sdkSummaryFile = |
78 path.join(testDirectory, '..', 'lib', 'runtime', 'dart_sdk.sum'); | 70 path.join(testDirectory, '..', 'lib', 'runtime', 'dart_sdk.sum'); |
| 71 |
| 72 var summaryPaths = new Directory(path.join(codegenOutputDir, 'pkg')) |
| 73 .listSync() |
| 74 .map((e) => e.path) |
| 75 .where((p) => p.endsWith('.sum')) |
| 76 .toList(); |
| 77 |
79 var analyzerOptions = new AnalyzerOptions( | 78 var analyzerOptions = new AnalyzerOptions( |
80 customUrlMappings: packageUrlMappings, | 79 dartSdkSummaryPath: sdkSummaryFile, summaryPaths: summaryPaths); |
81 dartSdkSummaryPath: sdkSummaryFile); | |
82 var compiler = new ModuleCompiler(analyzerOptions); | 80 var compiler = new ModuleCompiler(analyzerOptions); |
83 | 81 |
84 // Build packages tests depend on. | |
85 _buildAllPackages(compiler); | |
86 | |
87 var testDirs = [ | 82 var testDirs = [ |
88 'language', | 83 'language', |
89 'corelib', | 84 'corelib', |
90 path.join('lib', 'convert'), | 85 path.join('lib', 'convert'), |
91 path.join('lib', 'html'), | 86 path.join('lib', 'html'), |
92 path.join('lib', 'math'), | 87 path.join('lib', 'math'), |
93 path.join('lib', 'typed_data'), | 88 path.join('lib', 'typed_data'), |
94 ]; | 89 ]; |
95 | 90 |
96 // Copy all of the test files and expanded multitest files to | 91 // Copy all of the test files and expanded multitest files to |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 var unit = new BuildUnit(moduleName, path.dirname(testFile), | 129 var unit = new BuildUnit(moduleName, path.dirname(testFile), |
135 files.toList(), _moduleForLibrary); | 130 files.toList(), _moduleForLibrary); |
136 var module = compiler.compile(unit, options); | 131 var module = compiler.compile(unit, options); |
137 _writeModule( | 132 _writeModule( |
138 path.join(outDir, path.basenameWithoutExtension(testFile)), | 133 path.join(outDir, path.basenameWithoutExtension(testFile)), |
139 path.join(expectDir, path.basenameWithoutExtension(testFile)), | 134 path.join(expectDir, path.basenameWithoutExtension(testFile)), |
140 module); | 135 module); |
141 }); | 136 }); |
142 } | 137 } |
143 | 138 |
| 139 if (filePattern.hasMatch('sunflower')) { |
| 140 _buildSunflower(compiler, codegenOutputDir, codegenExpectDir); |
| 141 } |
| 142 |
144 if (codeCoverage) { | 143 if (codeCoverage) { |
145 test('build_sdk code coverage', () { | 144 test('build_sdk code coverage', () { |
146 return build_sdk.main(['--dart-sdk', sdkDir, '-o', codegenOutputDir]); | 145 return build_sdk.main(['--dart-sdk', sdkDir, '-o', codegenOutputDir]); |
147 }); | 146 }); |
148 } | 147 } |
149 } | 148 } |
150 | 149 |
151 void _writeModule(String outPath, String expectPath, JSModuleFile result) { | 150 void _writeModule(String outPath, String expectPath, JSModuleFile result) { |
152 _ensureDirectory(path.dirname(outPath)); | 151 _ensureDirectory(path.dirname(outPath)); |
153 _ensureDirectory(path.dirname(expectPath)); | 152 _ensureDirectory(path.dirname(expectPath)); |
154 | 153 |
155 String errors = result.errors.join('\n'); | 154 String errors = result.errors.join('\n'); |
156 if (errors.isNotEmpty && !errors.endsWith('\n')) errors += '\n'; | 155 if (errors.isNotEmpty && !errors.endsWith('\n')) errors += '\n'; |
157 new File(outPath + '.txt').writeAsStringSync(errors); | 156 new File(outPath + '.txt').writeAsStringSync(errors); |
158 | 157 |
159 var jsFile = new File(outPath + '.js'); | 158 var jsFile = new File(outPath + '.js'); |
| 159 var summaryFile = new File(outPath + '.sum'); |
160 var expectFile = new File(expectPath + '.js'); | 160 var expectFile = new File(expectPath + '.js'); |
161 var errorFile = new File(outPath + '.err'); | 161 var errorFile = new File(outPath + '.err'); |
162 | 162 |
163 if (result.isValid) { | 163 if (result.isValid) { |
164 jsFile.writeAsStringSync(result.code); | 164 jsFile.writeAsStringSync(result.code); |
| 165 if (result.summaryBytes != null) { |
| 166 summaryFile.writeAsBytesSync(result.summaryBytes); |
| 167 } |
165 if (result.sourceMap != null) { | 168 if (result.sourceMap != null) { |
166 var mapPath = outPath + '.js.map'; | 169 var mapPath = outPath + '.js.map'; |
167 new File(mapPath) | 170 new File(mapPath) |
168 .writeAsStringSync(JSON.encode(result.placeSourceMap(mapPath))); | 171 .writeAsStringSync(JSON.encode(result.placeSourceMap(mapPath))); |
169 } | 172 } |
170 | 173 |
171 expectFile.writeAsStringSync(result.code); | 174 expectFile.writeAsStringSync(result.code); |
172 | 175 |
173 // There are no errors, so delete any stale ".err" file. | 176 // There are no errors, so delete any stale ".err" file. |
174 if (errorFile.existsSync()) { | 177 if (errorFile.existsSync()) { |
(...skipping 25 matching lines...) Expand all Loading... |
200 } | 203 } |
201 | 204 |
202 // There are errors, so delete any stale expect ".js" file. | 205 // There are errors, so delete any stale expect ".js" file. |
203 if (expectFile.existsSync()) { | 206 if (expectFile.existsSync()) { |
204 expectFile.deleteSync(); | 207 expectFile.deleteSync(); |
205 } | 208 } |
206 expectFile.writeAsStringSync("//FAILED TO COMPILE"); | 209 expectFile.writeAsStringSync("//FAILED TO COMPILE"); |
207 } | 210 } |
208 } | 211 } |
209 | 212 |
210 void _buildAllPackages(ModuleCompiler compiler) { | |
211 group('dartdevc package', () { | |
212 _buildPackages(compiler, codegenOutputDir, codegenExpectDir); | |
213 | |
214 var packages = ['matcher', 'path', 'stack_trace']; | |
215 for (var package in packages) { | |
216 if (!filePattern.hasMatch(package)) continue; | |
217 test(package, () { | |
218 _buildPackage(compiler, codegenOutputDir, codegenExpectDir, package); | |
219 }); | |
220 } | |
221 | |
222 if (!filePattern.hasMatch('unittest')) return; | |
223 | |
224 test('unittest', () { | |
225 // Only build files applicable to the web - html_*.dart and its | |
226 // internal dependences. | |
227 _buildPackage(compiler, codegenOutputDir, codegenExpectDir, "unittest", | |
228 packageFiles: [ | |
229 'unittest.dart', | |
230 'html_config.dart', | |
231 'html_individual_config.dart', | |
232 'html_enhanced_config.dart' | |
233 ]); | |
234 }); | |
235 }); | |
236 | |
237 if (!filePattern.hasMatch('sunflower')) return; | |
238 | |
239 test('dartdevc sunflower', () { | |
240 _buildSunflower(compiler, codegenOutputDir, codegenExpectDir); | |
241 }); | |
242 } | |
243 | |
244 void _buildSunflower( | 213 void _buildSunflower( |
245 ModuleCompiler compiler, String outputDir, String expectDir) { | 214 ModuleCompiler compiler, String outputDir, String expectDir) { |
246 var baseDir = path.join(codegenDir, 'sunflower'); | 215 var baseDir = path.join(codegenDir, 'sunflower'); |
247 var files = ['sunflower', 'circle', 'painter'] | 216 var files = ['sunflower', 'circle', 'painter'] |
248 .map((f) => path.join(baseDir, '$f.dart')) | 217 .map((f) => path.join(baseDir, '$f.dart')) |
249 .toList(); | 218 .toList(); |
250 var input = new BuildUnit('sunflower', baseDir, files, _moduleForLibrary); | 219 var input = new BuildUnit('sunflower', baseDir, files, _moduleForLibrary); |
251 var options = new CompilerOptions(summarizeApi: false); | 220 var options = new CompilerOptions(summarizeApi: false); |
252 | 221 |
253 var built = compiler.compile(input, options); | 222 var built = compiler.compile(input, options); |
254 _writeModule(path.join(outputDir, 'sunflower', 'sunflower'), | 223 _writeModule(path.join(outputDir, 'sunflower', 'sunflower'), |
255 path.join(expectDir, 'sunflower', 'sunflower'), built); | 224 path.join(expectDir, 'sunflower', 'sunflower'), built); |
256 } | 225 } |
257 | 226 |
258 void _buildPackages( | |
259 ModuleCompiler compiler, String outputDir, String expectDir) { | |
260 // Note: we don't summarize these, as we're going to rely on our in-memory | |
261 // shared analysis context for caching, and `_moduleForLibrary` below | |
262 // understands these are from other modules. | |
263 var options = new CompilerOptions(sourceMap: false, summarizeApi: false); | |
264 | |
265 for (var uri in packageUrlMappings.keys) { | |
266 if (!filePattern.hasMatch(uri)) return; | |
267 | |
268 assert(uri.startsWith('package:')); | |
269 var uriPath = uri.substring('package:'.length); | |
270 var name = path.basenameWithoutExtension(uriPath); | |
271 test(name, () { | |
272 var input = new BuildUnit(name, codegenDir, [uri], _moduleForLibrary); | |
273 var built = compiler.compile(input, options); | |
274 | |
275 var outPath = path.join(outputDir, path.withoutExtension(uriPath)); | |
276 var expectPath = path.join(expectDir, path.withoutExtension(uriPath)); | |
277 _writeModule(outPath, expectPath, built); | |
278 }); | |
279 } | |
280 } | |
281 | |
282 void _buildPackage( | |
283 ModuleCompiler compiler, String outputDir, String expectDir, packageName, | |
284 {List<String> packageFiles}) { | |
285 var options = new CompilerOptions(sourceMap: false, summarizeApi: false); | |
286 | |
287 var packageRoot = path.join(codegenDir, 'packages'); | |
288 var packageInputDir = path.join(packageRoot, packageName); | |
289 List<String> files; | |
290 if (packageFiles != null) { | |
291 // Only collect files transitively reachable from packageFiles. | |
292 var reachable = new Set<String>(); | |
293 for (var file in packageFiles) { | |
294 file = path.join(packageInputDir, file); | |
295 _collectTransitiveImports(new File(file).readAsStringSync(), reachable, | |
296 packageRoot: packageRoot, from: file); | |
297 } | |
298 files = reachable.toList(); | |
299 } else { | |
300 // Collect all files in the packages directory. | |
301 files = new Directory(packageInputDir) | |
302 .listSync(recursive: true) | |
303 .where((entry) => entry.path.endsWith('.dart')) | |
304 .map((entry) => entry.path) | |
305 .toList(); | |
306 } | |
307 | |
308 var unit = | |
309 new BuildUnit(packageName, packageInputDir, files, _moduleForLibrary); | |
310 var module = compiler.compile(unit, options); | |
311 | |
312 var outPath = path.join(outputDir, packageName, packageName); | |
313 var expectPath = path.join(expectDir, packageName, packageName); | |
314 _writeModule(outPath, expectPath, module); | |
315 } | |
316 | |
317 String _moduleForLibrary(Source source) { | 227 String _moduleForLibrary(Source source) { |
318 var scheme = source.uri.scheme; | 228 var scheme = source.uri.scheme; |
319 if (scheme == 'package') { | 229 if (scheme == 'package') { |
320 return source.uri.pathSegments.first; | 230 return source.uri.pathSegments.first; |
321 } | 231 } |
322 throw new Exception('Module not found for library "${source.fullName}"'); | 232 throw new Exception('Module not found for library "${source.fullName}"'); |
323 } | 233 } |
324 | 234 |
325 List<String> _setUpTests(List<String> testDirs) { | 235 List<String> _setUpTests(List<String> testDirs) { |
326 var testFiles = <String>[]; | 236 var testFiles = <String>[]; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 /// Simplified from ParseDartTask.resolveDirective. | 340 /// Simplified from ParseDartTask.resolveDirective. |
431 String _resolveDirective(UriBasedDirective directive) { | 341 String _resolveDirective(UriBasedDirective directive) { |
432 StringLiteral uriLiteral = directive.uri; | 342 StringLiteral uriLiteral = directive.uri; |
433 String uriContent = uriLiteral.stringValue; | 343 String uriContent = uriLiteral.stringValue; |
434 if (uriContent != null) { | 344 if (uriContent != null) { |
435 uriContent = uriContent.trim(); | 345 uriContent = uriContent.trim(); |
436 directive.uriContent = uriContent; | 346 directive.uriContent = uriContent; |
437 } | 347 } |
438 return directive.validate() == null ? uriContent : null; | 348 return directive.validate() == null ? uriContent : null; |
439 } | 349 } |
OLD | NEW |