| 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; | |
| 16 import 'dart:io' show Directory, File, Platform; | 15 import 'dart:io' show Directory, File, Platform; |
| 17 import 'package:args/args.dart' show ArgParser, ArgResults; | |
| 18 import 'package:path/path.dart' as path; | |
| 19 import 'package:test/test.dart' show test; | |
| 20 | |
| 21 import 'package:analyzer/analyzer.dart' | 16 import 'package:analyzer/analyzer.dart' |
| 22 show | 17 show |
| 23 ExportDirective, | 18 ExportDirective, |
| 24 ImportDirective, | 19 ImportDirective, |
| 25 StringLiteral, | 20 StringLiteral, |
| 26 UriBasedDirective, | 21 UriBasedDirective, |
| 27 parseDirectives; | 22 parseDirectives; |
| 28 import 'package:analyzer/src/generated/source.dart' show Source; | 23 import 'package:analyzer/src/generated/source.dart' show Source; |
| 24 import 'package:args/args.dart' show ArgParser, ArgResults; |
| 29 import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions; | 25 import 'package:dev_compiler/src/analyzer/context.dart' show AnalyzerOptions; |
| 30 import 'package:dev_compiler/src/compiler/compiler.dart' | 26 import 'package:dev_compiler/src/compiler/compiler.dart' |
| 31 show BuildUnit, CompilerOptions, ModuleCompiler; | 27 show BuildUnit, CompilerOptions, JSModuleFile, ModuleCompiler; |
| 28 import 'package:dev_compiler/src/compiler/module_builder.dart' |
| 29 show |
| 30 ModuleFormat, |
| 31 addModuleFormatOptions, |
| 32 parseModuleFormatOption, |
| 33 pathToJSIdentifier; |
| 34 import 'package:path/path.dart' as path; |
| 35 import 'package:test/test.dart' show expect, isFalse, isTrue, test; |
| 36 |
| 37 import '../tool/build_sdk.dart' as build_sdk; |
| 32 import 'testing.dart' show repoDirectory, testDirectory; | 38 import 'testing.dart' show repoDirectory, testDirectory; |
| 33 import 'multitest.dart' show extractTestsFromMultitest, isMultiTest; | 39 import 'multitest.dart' show extractTestsFromMultitest, isMultiTest; |
| 34 import '../tool/build_sdk.dart' as build_sdk; | 40 import 'not_yet_strong_tests.dart'; |
| 35 import 'package:dev_compiler/src/compiler/compiler.dart'; | |
| 36 | 41 |
| 37 final ArgParser argParser = new ArgParser() | 42 final ArgParser argParser = new ArgParser() |
| 38 ..addOption('dart-sdk', help: 'Dart SDK Path', defaultsTo: null); | 43 ..addOption('dart-sdk', help: 'Dart SDK Path', defaultsTo: null); |
| 39 | 44 |
| 40 /// The `test/codegen` directory. | 45 /// The `test/codegen` directory. |
| 41 final codegenDir = path.join(testDirectory, 'codegen'); | 46 final codegenDir = path.join(testDirectory, 'codegen'); |
| 42 | 47 |
| 43 /// The `test/codegen/expect` directory. | 48 /// The `test/codegen/expect` directory. |
| 44 final codegenExpectDir = path.join(testDirectory, 'codegen_expected'); | 49 final codegenExpectDir = path.join(testDirectory, 'codegen_expected'); |
| 45 | 50 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 60 | 65 |
| 61 RegExp filePattern; | 66 RegExp filePattern; |
| 62 | 67 |
| 63 main(List<String> arguments) { | 68 main(List<String> arguments) { |
| 64 if (arguments == null) arguments = []; | 69 if (arguments == null) arguments = []; |
| 65 ArgResults args = argParser.parse(arguments); | 70 ArgResults args = argParser.parse(arguments); |
| 66 filePattern = new RegExp(args.rest.length > 0 ? args.rest[0] : '.'); | 71 filePattern = new RegExp(args.rest.length > 0 ? args.rest[0] : '.'); |
| 67 | 72 |
| 68 var sdkDir = path.join(repoDirectory, 'gen', 'patched_sdk'); | 73 var sdkDir = path.join(repoDirectory, 'gen', 'patched_sdk'); |
| 69 var sdkSummaryFile = | 74 var sdkSummaryFile = |
| 70 path.join(testDirectory, '..', 'lib', 'runtime', 'dart_sdk.sum'); | 75 path.join(testDirectory, '..', 'lib', 'js', 'amd', 'dart_sdk.sum'); |
| 71 | 76 |
| 72 var summaryPaths = new Directory(path.join(codegenOutputDir, 'pkg')) | 77 var summaryPaths = new Directory(path.join(codegenOutputDir, 'pkg')) |
| 73 .listSync() | 78 .listSync() |
| 74 .map((e) => e.path) | 79 .map((e) => e.path) |
| 75 .where((p) => p.endsWith('.sum')) | 80 .where((p) => p.endsWith('.sum')) |
| 76 .toList(); | 81 .toList(); |
| 77 | 82 |
| 78 var analyzerOptions = new AnalyzerOptions( | 83 var analyzerOptions = new AnalyzerOptions( |
| 79 dartSdkSummaryPath: sdkSummaryFile, summaryPaths: summaryPaths); | 84 dartSdkSummaryPath: sdkSummaryFile, summaryPaths: summaryPaths); |
| 80 var compiler = new ModuleCompiler(analyzerOptions); | 85 var compiler = new ModuleCompiler(analyzerOptions); |
| 81 | 86 |
| 82 var testDirs = [ | 87 var testDirs = [ |
| 83 'language', | 88 'language', |
| 84 'corelib', | 89 'corelib', |
| 85 path.join('lib', 'convert'), | 90 path.join('lib', 'convert'), |
| 86 path.join('lib', 'html'), | 91 path.join('lib', 'html'), |
| 87 path.join('lib', 'math'), | 92 path.join('lib', 'math'), |
| 88 path.join('lib', 'mirrors'), | 93 path.join('lib', 'mirrors'), |
| 89 path.join('lib', 'typed_data'), | 94 path.join('lib', 'typed_data'), |
| 90 ]; | 95 ]; |
| 91 | 96 |
| 92 // Copy all of the test files and expanded multitest files to | 97 // Copy all of the test files and expanded multitest files to |
| 93 // gen/codegen_tests. We'll compile from there. | 98 // gen/codegen_tests. We'll compile from there. |
| 94 var testFiles = _setUpTests(testDirs); | 99 var testFiles = _setUpTests(testDirs); |
| 95 | 100 |
| 96 // Our default compiler options. Individual tests can override these. | 101 // Our default compiler options. Individual tests can override these. |
| 97 var defaultOptions = ['--no-source-map', '--no-summarize']; | 102 var defaultOptions = ['--no-source-map', '--no-summarize']; |
| 98 var compilerArgParser = new ArgParser(); | 103 var compilerArgParser = new ArgParser(); |
| 99 CompilerOptions.addArguments(compilerArgParser); | 104 CompilerOptions.addArguments(compilerArgParser); |
| 105 addModuleFormatOptions(compilerArgParser); |
| 100 | 106 |
| 101 // Compile each test file to JS and put the result in gen/codegen_output. | 107 // Compile each test file to JS and put the result in gen/codegen_output. |
| 102 for (var testFile in testFiles) { | 108 for (var testFile in testFiles) { |
| 103 var relativePath = path.relative(testFile, from: codegenTestDir); | 109 var relativePath = path.relative(testFile, from: codegenTestDir); |
| 104 | 110 |
| 105 // Only compile the top-level files for generating coverage. | 111 // Only compile the top-level files for generating coverage. |
| 106 bool isTopLevelTest = path.dirname(relativePath) == "."; | 112 bool isTopLevelTest = path.dirname(relativePath) == "."; |
| 107 if (codeCoverage && !isTopLevelTest) continue; | 113 if (codeCoverage && !isTopLevelTest) continue; |
| 108 | 114 |
| 109 var name = path.withoutExtension(relativePath); | 115 var name = path.withoutExtension(relativePath); |
| 110 test('dartdevc $name', () { | 116 test('dartdevc $name', () { |
| 111 // Check if we need to use special compile options. | 117 // Check if we need to use special compile options. |
| 112 var contents = new File(testFile).readAsStringSync(); | 118 var contents = new File(testFile).readAsStringSync(); |
| 113 var match = | 119 var match = |
| 114 new RegExp(r'// compile options: (.*)').matchAsPrefix(contents); | 120 new RegExp(r'// compile options: (.*)').matchAsPrefix(contents); |
| 115 | 121 |
| 116 var args = defaultOptions.toList(); | 122 var args = defaultOptions.toList(); |
| 117 if (match != null) { | 123 if (match != null) { |
| 118 args.addAll(match.group(1).split(' ')); | 124 args.addAll(match.group(1).split(' ')); |
| 119 } | 125 } |
| 120 var options = | 126 |
| 121 new CompilerOptions.fromArguments(compilerArgParser.parse(args)); | 127 var argResults = compilerArgParser.parse(args); |
| 128 var options = new CompilerOptions.fromArguments(argResults); |
| 129 var moduleFormat = parseModuleFormatOption(argResults).first; |
| 122 | 130 |
| 123 // Collect any other files we've imported. | 131 // Collect any other files we've imported. |
| 124 var files = new Set<String>(); | 132 var files = new Set<String>(); |
| 125 _collectTransitiveImports(contents, files, from: testFile); | 133 _collectTransitiveImports(contents, files, from: testFile); |
| 126 var unit = new BuildUnit( | 134 var unit = new BuildUnit( |
| 127 name, path.dirname(testFile), files.toList(), _moduleForLibrary); | 135 name, path.dirname(testFile), files.toList(), _moduleForLibrary); |
| 128 var module = compiler.compile(unit, options); | 136 var module = compiler.compile(unit, options); |
| 129 _writeModule(path.join(codegenOutputDir, name), | 137 |
| 130 isTopLevelTest ? path.join(codegenExpectDir, name) : null, module); | 138 bool notStrong = notYetStrongTests.contains(name); |
| 139 if (module.isValid) { |
| 140 _writeModule( |
| 141 path.join(codegenOutputDir, name), |
| 142 isTopLevelTest ? path.join(codegenExpectDir, name) : null, |
| 143 moduleFormat, |
| 144 module); |
| 145 |
| 146 expect(notStrong, isFalse, |
| 147 reason: "test $name expected strong mode errors, but compiled."); |
| 148 } else { |
| 149 expect(notStrong, isTrue, |
| 150 reason: "test $name failed to compile due to strong mode errors:" |
| 151 "\n\n${module.errors.join('\n')}."); |
| 152 } |
| 131 }); | 153 }); |
| 132 } | 154 } |
| 133 | 155 |
| 134 if (filePattern.hasMatch('sunflower')) { | 156 if (filePattern.hasMatch('sunflower')) { |
| 135 _buildSunflower(compiler, codegenOutputDir, codegenExpectDir); | 157 test('sunflower', () { |
| 158 _buildSunflower(compiler, codegenOutputDir, codegenExpectDir); |
| 159 }); |
| 136 } | 160 } |
| 137 | 161 |
| 138 if (codeCoverage) { | 162 if (codeCoverage) { |
| 139 test('build_sdk code coverage', () { | 163 test('build_sdk code coverage', () { |
| 140 return build_sdk.main(['--dart-sdk', sdkDir, '-o', codegenOutputDir]); | 164 return build_sdk.main(['--dart-sdk', sdkDir, '-o', codegenOutputDir]); |
| 141 }); | 165 }); |
| 142 } | 166 } |
| 143 } | 167 } |
| 144 | 168 |
| 145 void _writeModule(String outPath, String expectPath, JSModuleFile result) { | 169 void _writeModule(String outPath, String expectPath, ModuleFormat format, |
| 170 JSModuleFile result) { |
| 146 _ensureDirectory(path.dirname(outPath)); | 171 _ensureDirectory(path.dirname(outPath)); |
| 147 | 172 |
| 148 String errors = result.errors.join('\n'); | 173 String errors = result.errors.join('\n'); |
| 149 if (errors.isNotEmpty && !errors.endsWith('\n')) errors += '\n'; | 174 if (errors.isNotEmpty && !errors.endsWith('\n')) errors += '\n'; |
| 150 new File(outPath + '.txt').writeAsStringSync(errors); | 175 new File(outPath + '.txt').writeAsStringSync(errors); |
| 151 | 176 |
| 152 var jsFile = new File(outPath + '.js'); | 177 result.writeCodeSync(format, outPath + '.js'); |
| 153 var summaryFile = new File(outPath + '.sum'); | |
| 154 var errorFile = new File(outPath + '.err'); | |
| 155 | 178 |
| 156 if (result.isValid) { | 179 if (result.summaryBytes != null) { |
| 157 jsFile.writeAsStringSync(result.code); | 180 new File(outPath + '.sum').writeAsBytesSync(result.summaryBytes); |
| 158 if (result.summaryBytes != null) { | |
| 159 summaryFile.writeAsBytesSync(result.summaryBytes); | |
| 160 } | |
| 161 if (result.sourceMap != null) { | |
| 162 var mapPath = outPath + '.js.map'; | |
| 163 new File(mapPath) | |
| 164 .writeAsStringSync(JSON.encode(result.placeSourceMap(mapPath))); | |
| 165 } | |
| 166 | |
| 167 // There are no errors, so delete any stale ".err" file. | |
| 168 if (errorFile.existsSync()) { | |
| 169 errorFile.deleteSync(); | |
| 170 } | |
| 171 } else { | |
| 172 // Also write the errors to a '.err' file for easy counting. | |
| 173 var moduleName = result.name; | |
| 174 var libraryName = path.split(moduleName).last; | |
| 175 var count = "[error]".allMatches(errors).length; | |
| 176 var text = ''' | |
| 177 dart_library.library('$moduleName', null, [ | |
| 178 'dart_sdk', | |
| 179 'expect' | |
| 180 ], function(exports, dart_sdk, expect) { | |
| 181 const message = `DDC Compilation Error: $moduleName has $count errors`; | |
| 182 const error = new Error(message); | |
| 183 exports.$libraryName = Object.create(null); | |
| 184 exports.$libraryName.main = function() { | |
| 185 throw error; | |
| 186 } | |
| 187 }); | |
| 188 '''; | |
| 189 errorFile.writeAsStringSync(text); | |
| 190 | |
| 191 // There are errors, so delete any stale ".js" file. | |
| 192 if (jsFile.existsSync()) { | |
| 193 jsFile.deleteSync(); | |
| 194 } | |
| 195 } | 181 } |
| 196 | 182 |
| 197 // Write the expectation file if needed. | 183 // Write the expectation file if needed. |
| 198 // Generally speaking we try to avoid these tests, but they are occasionally | 184 // Generally speaking we try to avoid these tests, but they are occasionally |
| 199 // useful. | 185 // useful. |
| 200 if (expectPath != null) { | 186 if (expectPath != null) { |
| 201 _ensureDirectory(path.dirname(expectPath)); | 187 _ensureDirectory(path.dirname(expectPath)); |
| 202 | 188 |
| 203 var expectFile = new File(expectPath + '.js'); | 189 var expectFile = new File(expectPath + '.js'); |
| 204 if (result.isValid) { | 190 if (result.isValid) { |
| 205 expectFile.writeAsStringSync(result.code); | 191 result.writeCodeSync(format, expectFile.path); |
| 206 } else { | 192 } else { |
| 207 // There are errors, so delete any stale expect ".js" file. | |
| 208 if (expectFile.existsSync()) { | |
| 209 expectFile.deleteSync(); | |
| 210 } | |
| 211 expectFile.writeAsStringSync("//FAILED TO COMPILE"); | 193 expectFile.writeAsStringSync("//FAILED TO COMPILE"); |
| 212 } | 194 } |
| 213 } | 195 } |
| 214 } | 196 } |
| 215 | 197 |
| 216 void _buildSunflower( | 198 void _buildSunflower( |
| 217 ModuleCompiler compiler, String outputDir, String expectDir) { | 199 ModuleCompiler compiler, String outputDir, String expectDir) { |
| 218 var baseDir = path.join(codegenDir, 'sunflower'); | 200 var baseDir = path.join(codegenDir, 'sunflower'); |
| 219 var files = ['sunflower', 'circle', 'painter'] | 201 var files = ['sunflower', 'circle', 'painter'] |
| 220 .map((f) => path.join(baseDir, '$f.dart')) | 202 .map((f) => path.join(baseDir, '$f.dart')) |
| 221 .toList(); | 203 .toList(); |
| 222 var input = new BuildUnit('sunflower', baseDir, files, _moduleForLibrary); | 204 var input = new BuildUnit('sunflower', baseDir, files, _moduleForLibrary); |
| 223 var options = new CompilerOptions(summarizeApi: false); | 205 var options = new CompilerOptions(summarizeApi: false); |
| 224 | 206 |
| 225 var built = compiler.compile(input, options); | 207 var built = compiler.compile(input, options); |
| 226 _writeModule(path.join(outputDir, 'sunflower', 'sunflower'), | 208 _writeModule(path.join(outputDir, 'sunflower', 'sunflower'), |
| 227 path.join(expectDir, 'sunflower', 'sunflower'), built); | 209 path.join(expectDir, 'sunflower', 'sunflower'), ModuleFormat.amd, built); |
| 228 } | 210 } |
| 229 | 211 |
| 230 String _moduleForLibrary(Source source) { | 212 String _moduleForLibrary(Source source) { |
| 231 var scheme = source.uri.scheme; | 213 var scheme = source.uri.scheme; |
| 232 if (scheme == 'package') { | 214 if (scheme == 'package') { |
| 233 return source.uri.pathSegments.first; | 215 return source.uri.pathSegments.first; |
| 234 } | 216 } |
| 235 throw new Exception('Module not found for library "${source.fullName}"'); | 217 throw new Exception('Module not found for library "${source.fullName}"'); |
| 236 } | 218 } |
| 237 | 219 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 /// Simplified from ParseDartTask.resolveDirective. | 325 /// Simplified from ParseDartTask.resolveDirective. |
| 344 String _resolveDirective(UriBasedDirective directive) { | 326 String _resolveDirective(UriBasedDirective directive) { |
| 345 StringLiteral uriLiteral = directive.uri; | 327 StringLiteral uriLiteral = directive.uri; |
| 346 String uriContent = uriLiteral.stringValue; | 328 String uriContent = uriLiteral.stringValue; |
| 347 if (uriContent != null) { | 329 if (uriContent != null) { |
| 348 uriContent = uriContent.trim(); | 330 uriContent = uriContent.trim(); |
| 349 directive.uriContent = uriContent; | 331 directive.uriContent = uriContent; |
| 350 } | 332 } |
| 351 return directive.validate() == null ? uriContent : null; | 333 return directive.validate() == null ? uriContent : null; |
| 352 } | 334 } |
| OLD | NEW |