| 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 |