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 |
(...skipping 22 matching lines...) Expand all Loading... |
33 import 'multitest.dart' show extractTestsFromMultitest, isMultiTest; | 33 import 'multitest.dart' show extractTestsFromMultitest, isMultiTest; |
34 import '../tool/build_sdk.dart' as build_sdk; | 34 import '../tool/build_sdk.dart' as build_sdk; |
35 import 'package:dev_compiler/src/compiler/compiler.dart'; | 35 import 'package:dev_compiler/src/compiler/compiler.dart'; |
36 | 36 |
37 final ArgParser argParser = new ArgParser() | 37 final ArgParser argParser = new ArgParser() |
38 ..addOption('dart-sdk', help: 'Dart SDK Path', defaultsTo: null); | 38 ..addOption('dart-sdk', help: 'Dart SDK Path', defaultsTo: null); |
39 | 39 |
40 /// The `test/codegen` directory. | 40 /// The `test/codegen` directory. |
41 final codegenDir = path.join(testDirectory, 'codegen'); | 41 final codegenDir = path.join(testDirectory, 'codegen'); |
42 | 42 |
| 43 /// The `test/codegen/expect` directory. |
| 44 final codegenExpectDir = path.join(codegenDir, 'expect'); |
| 45 |
43 /// The generated directory where tests, expanded multitests, and other test | 46 /// The generated directory where tests, expanded multitests, and other test |
44 /// support libraries are copied to. | 47 /// support libraries are copied to. |
45 /// | 48 /// |
46 /// The tests sometimes import utility libraries using a relative path. | 49 /// The tests sometimes import utility libraries using a relative path. |
47 /// 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 |
48 /// 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 |
49 /// to a generated directory and expand that multitests in there too. | 52 /// to a generated directory and expand that multitests in there too. |
50 final codegenTestDir = path.join(repoDirectory, 'gen', 'codegen_tests'); | 53 final codegenTestDir = path.join(repoDirectory, 'gen', 'codegen_tests'); |
51 | 54 |
52 /// The generated directory where tests and packages compiled to JS are | 55 /// The generated directory where tests and packages compiled to JS are |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 | 101 |
99 // Compile each test file to JS and put the result in gen/codegen_output. | 102 // Compile each test file to JS and put the result in gen/codegen_output. |
100 for (var testFile in testFiles) { | 103 for (var testFile in testFiles) { |
101 var relativePath = path.relative(testFile, from: codegenTestDir); | 104 var relativePath = path.relative(testFile, from: codegenTestDir); |
102 | 105 |
103 // Only compile the top-level files for generating coverage. | 106 // Only compile the top-level files for generating coverage. |
104 if (codeCoverage && path.dirname(relativePath) != ".") continue; | 107 if (codeCoverage && path.dirname(relativePath) != ".") continue; |
105 | 108 |
106 var name = path.withoutExtension(relativePath); | 109 var name = path.withoutExtension(relativePath); |
107 test('dartdevc $name', () { | 110 test('dartdevc $name', () { |
108 var outDir = path.join(codegenOutputDir, path.dirname(relativePath)); | 111 var relativeDir = path.dirname(relativePath); |
109 _ensureDirectory(outDir); | 112 var outDir = path.join(codegenOutputDir, relativeDir); |
| 113 var expectDir = path.join(codegenExpectDir, relativeDir); |
110 | 114 |
111 // Check if we need to use special compile options. | 115 // Check if we need to use special compile options. |
112 var contents = new File(testFile).readAsStringSync(); | 116 var contents = new File(testFile).readAsStringSync(); |
113 var match = | 117 var match = |
114 new RegExp(r'// compile options: (.*)').matchAsPrefix(contents); | 118 new RegExp(r'// compile options: (.*)').matchAsPrefix(contents); |
115 | 119 |
116 var args = defaultOptions.toList(); | 120 var args = defaultOptions.toList(); |
117 if (match != null) { | 121 if (match != null) { |
118 args.addAll(match.group(1).split(' ')); | 122 args.addAll(match.group(1).split(' ')); |
119 } | 123 } |
120 var options = | 124 var options = |
121 new CompilerOptions.fromArguments(compilerArgParser.parse(args)); | 125 new CompilerOptions.fromArguments(compilerArgParser.parse(args)); |
122 | 126 |
123 // Collect any other files we've imported. | 127 // Collect any other files we've imported. |
124 var files = new Set<String>(); | 128 var files = new Set<String>(); |
125 _collectTransitiveImports(contents, files, from: testFile); | 129 _collectTransitiveImports(contents, files, from: testFile); |
126 var moduleName = | 130 var moduleName = |
127 path.withoutExtension(path.relative(testFile, from: codegenTestDir)); | 131 path.withoutExtension(path.relative(testFile, from: codegenTestDir)); |
128 var unit = new BuildUnit(moduleName, path.dirname(testFile), | 132 var unit = new BuildUnit(moduleName, path.dirname(testFile), |
129 files.toList(), _moduleForLibrary); | 133 files.toList(), _moduleForLibrary); |
130 var module = compiler.compile(unit, options); | 134 var module = compiler.compile(unit, options); |
131 _writeModule( | 135 _writeModule( |
132 path.join(outDir, path.basenameWithoutExtension(testFile)), module); | 136 path.join(outDir, path.basenameWithoutExtension(testFile)), |
| 137 path.join(expectDir, path.basenameWithoutExtension(testFile)), |
| 138 module); |
133 }); | 139 }); |
134 } | 140 } |
135 | 141 |
136 if (codeCoverage) { | 142 if (codeCoverage) { |
137 test('build_sdk code coverage', () { | 143 test('build_sdk code coverage', () { |
138 return build_sdk.main(['--dart-sdk', sdkDir, '-o', codegenOutputDir]); | 144 return build_sdk.main(['--dart-sdk', sdkDir, '-o', codegenOutputDir]); |
139 }); | 145 }); |
140 } | 146 } |
141 } | 147 } |
142 | 148 |
143 void _writeModule(String outPath, JSModuleFile result) { | 149 void _writeModule(String outPath, String expectPath, JSModuleFile result) { |
144 _ensureDirectory(path.dirname(outPath)); | 150 _ensureDirectory(path.dirname(outPath)); |
| 151 _ensureDirectory(path.dirname(expectPath)); |
145 | 152 |
146 String errors = result.errors.join('\n'); | 153 String errors = result.errors.join('\n'); |
147 if (errors.isNotEmpty && !errors.endsWith('\n')) errors += '\n'; | 154 if (errors.isNotEmpty && !errors.endsWith('\n')) errors += '\n'; |
148 new File(outPath + '.txt').writeAsStringSync(errors); | 155 new File(outPath + '.txt').writeAsStringSync(errors); |
149 | 156 |
150 var jsFile = new File(outPath + '.js'); | 157 var jsFile = new File(outPath + '.js'); |
| 158 var expectFile = new File(expectPath + '.js'); |
151 var errorFile = new File(outPath + '.err'); | 159 var errorFile = new File(outPath + '.err'); |
152 | 160 |
153 if (result.isValid) { | 161 if (result.isValid) { |
154 jsFile.writeAsStringSync(result.code); | 162 jsFile.writeAsStringSync(result.code); |
155 if (result.sourceMap != null) { | 163 if (result.sourceMap != null) { |
156 var mapPath = outPath + '.js.map'; | 164 var mapPath = outPath + '.js.map'; |
157 new File(mapPath) | 165 new File(mapPath) |
158 .writeAsStringSync(JSON.encode(result.placeSourceMap(mapPath))); | 166 .writeAsStringSync(JSON.encode(result.placeSourceMap(mapPath))); |
159 } | 167 } |
160 | 168 |
| 169 expectFile.writeAsStringSync(result.code); |
| 170 |
161 // There are no errors, so delete any stale ".err" file. | 171 // There are no errors, so delete any stale ".err" file. |
162 if (errorFile.existsSync()) { | 172 if (errorFile.existsSync()) { |
163 errorFile.deleteSync(); | 173 errorFile.deleteSync(); |
164 } | 174 } |
165 } else { | 175 } else { |
166 // Also write the errors to a '.err' file for easy counting. | 176 // Also write the errors to a '.err' file for easy counting. |
167 var moduleName = result.name; | 177 var moduleName = result.name; |
168 var libraryName = path.split(moduleName).last; | 178 var libraryName = path.split(moduleName).last; |
169 var count = "[error]".allMatches(errors).length; | 179 var count = "[error]".allMatches(errors).length; |
170 var text = ''' | 180 var text = ''' |
171 dart_library.library('$moduleName', null, [ | 181 dart_library.library('$moduleName', null, [ |
172 'dart_sdk', | 182 'dart_sdk', |
173 'expect' | 183 'expect' |
174 ], function(exports, dart_sdk, expect) { | 184 ], function(exports, dart_sdk, expect) { |
175 const message = `DDC Compilation Error: $moduleName has $count errors`; | 185 const message = `DDC Compilation Error: $moduleName has $count errors`; |
176 const error = new Error(message); | 186 const error = new Error(message); |
177 exports.$libraryName = Object.create(null); | 187 exports.$libraryName = Object.create(null); |
178 exports.$libraryName.main = function() { | 188 exports.$libraryName.main = function() { |
179 throw error; | 189 throw error; |
180 } | 190 } |
181 }); | 191 }); |
182 '''; | 192 '''; |
183 errorFile.writeAsStringSync(text); | 193 errorFile.writeAsStringSync(text); |
184 | 194 |
185 // There are errors, so delete any stale ".js" file. | 195 // There are errors, so delete any stale ".js" file. |
186 if (jsFile.existsSync()) { | 196 if (jsFile.existsSync()) { |
187 jsFile.deleteSync(); | 197 jsFile.deleteSync(); |
188 } | 198 } |
| 199 |
| 200 // There are errors, so delete any stale expect ".js" file. |
| 201 if (expectFile.existsSync()) { |
| 202 expectFile.deleteSync(); |
| 203 } |
| 204 expectFile.writeAsStringSync("//FAILED TO COMPILE"); |
189 } | 205 } |
190 } | 206 } |
191 | 207 |
192 void _buildAllPackages(ModuleCompiler compiler) { | 208 void _buildAllPackages(ModuleCompiler compiler) { |
193 group('dartdevc package', () { | 209 group('dartdevc package', () { |
194 _buildPackages(compiler, codegenOutputDir); | 210 _buildPackages(compiler, codegenOutputDir, codegenExpectDir); |
195 | 211 |
196 var packages = ['matcher', 'path', 'stack_trace']; | 212 var packages = ['matcher', 'path', 'stack_trace']; |
197 for (var package in packages) { | 213 for (var package in packages) { |
198 test(package, () { | 214 test(package, () { |
199 _buildPackage(compiler, codegenOutputDir, package); | 215 _buildPackage(compiler, codegenOutputDir, codegenExpectDir, package); |
200 }); | 216 }); |
201 } | 217 } |
202 | 218 |
203 test('unittest', () { | 219 test('unittest', () { |
204 // Only build files applicable to the web - html_*.dart and its | 220 // Only build files applicable to the web - html_*.dart and its |
205 // internal dependences. | 221 // internal dependences. |
206 _buildPackage(compiler, codegenOutputDir, "unittest", packageFiles: [ | 222 _buildPackage(compiler, codegenOutputDir, codegenExpectDir, "unittest",
packageFiles: [ |
207 'unittest.dart', | 223 'unittest.dart', |
208 'html_config.dart', | 224 'html_config.dart', |
209 'html_individual_config.dart', | 225 'html_individual_config.dart', |
210 'html_enhanced_config.dart' | 226 'html_enhanced_config.dart' |
211 ]); | 227 ]); |
212 }); | 228 }); |
213 }); | 229 }); |
214 | 230 |
215 test('dartdevc sunflower', () { | 231 test('dartdevc sunflower', () { |
216 _buildSunflower(compiler, codegenOutputDir); | 232 _buildSunflower(compiler, codegenOutputDir, codegenExpectDir); |
217 }); | 233 }); |
218 } | 234 } |
219 | 235 |
220 void _buildSunflower(ModuleCompiler compiler, String outputDir) { | 236 void _buildSunflower(ModuleCompiler compiler, String outputDir, String expectDir
) { |
221 var baseDir = path.join(codegenDir, 'sunflower'); | 237 var baseDir = path.join(codegenDir, 'sunflower'); |
222 var files = ['sunflower', 'circle', 'painter'] | 238 var files = ['sunflower', 'circle', 'painter'] |
223 .map((f) => path.join(baseDir, '$f.dart')) | 239 .map((f) => path.join(baseDir, '$f.dart')) |
224 .toList(); | 240 .toList(); |
225 var input = new BuildUnit('sunflower', baseDir, files, _moduleForLibrary); | 241 var input = new BuildUnit('sunflower', baseDir, files, _moduleForLibrary); |
226 var options = new CompilerOptions(summarizeApi: false); | 242 var options = new CompilerOptions(summarizeApi: false); |
227 | 243 |
228 var built = compiler.compile(input, options); | 244 var built = compiler.compile(input, options); |
229 _writeModule(path.join(outputDir, 'sunflower', 'sunflower'), built); | 245 _writeModule(path.join(outputDir, 'sunflower', 'sunflower'), |
| 246 path.join(expectDir, 'sunflower', 'sunflower'), built); |
230 } | 247 } |
231 | 248 |
232 void _buildPackages(ModuleCompiler compiler, String outputDir) { | 249 void _buildPackages(ModuleCompiler compiler, String outputDir, String expectDir)
{ |
233 // Note: we don't summarize these, as we're going to rely on our in-memory | 250 // Note: we don't summarize these, as we're going to rely on our in-memory |
234 // shared analysis context for caching, and `_moduleForLibrary` below | 251 // shared analysis context for caching, and `_moduleForLibrary` below |
235 // understands these are from other modules. | 252 // understands these are from other modules. |
236 var options = new CompilerOptions(sourceMap: false, summarizeApi: false); | 253 var options = new CompilerOptions(sourceMap: false, summarizeApi: false); |
237 | 254 |
238 for (var uri in packageUrlMappings.keys) { | 255 for (var uri in packageUrlMappings.keys) { |
239 assert(uri.startsWith('package:')); | 256 assert(uri.startsWith('package:')); |
240 var uriPath = uri.substring('package:'.length); | 257 var uriPath = uri.substring('package:'.length); |
241 var name = path.basenameWithoutExtension(uriPath); | 258 var name = path.basenameWithoutExtension(uriPath); |
242 test(name, () { | 259 test(name, () { |
243 var input = new BuildUnit(name, codegenDir, [uri], _moduleForLibrary); | 260 var input = new BuildUnit(name, codegenDir, [uri], _moduleForLibrary); |
244 var built = compiler.compile(input, options); | 261 var built = compiler.compile(input, options); |
245 | 262 |
246 var outPath = path.join(outputDir, path.withoutExtension(uriPath)); | 263 var outPath = path.join(outputDir, path.withoutExtension(uriPath)); |
247 _writeModule(outPath, built); | 264 var expectPath = path.join(expectDir, path.withoutExtension(uriPath)); |
| 265 _writeModule(outPath, expectPath, built); |
248 }); | 266 }); |
249 } | 267 } |
250 } | 268 } |
251 | 269 |
252 void _buildPackage(ModuleCompiler compiler, String outputDir, packageName, | 270 void _buildPackage(ModuleCompiler compiler, String outputDir, String expectDir,
packageName, |
253 {List<String> packageFiles}) { | 271 {List<String> packageFiles}) { |
254 var options = new CompilerOptions(sourceMap: false, summarizeApi: false); | 272 var options = new CompilerOptions(sourceMap: false, summarizeApi: false); |
255 | 273 |
256 var packageRoot = path.join(codegenDir, 'packages'); | 274 var packageRoot = path.join(codegenDir, 'packages'); |
257 var packageInputDir = path.join(packageRoot, packageName); | 275 var packageInputDir = path.join(packageRoot, packageName); |
258 List<String> files; | 276 List<String> files; |
259 if (packageFiles != null) { | 277 if (packageFiles != null) { |
260 // Only collect files transitively reachable from packageFiles. | 278 // Only collect files transitively reachable from packageFiles. |
261 var reachable = new Set<String>(); | 279 var reachable = new Set<String>(); |
262 for (var file in packageFiles) { | 280 for (var file in packageFiles) { |
263 file = path.join(packageInputDir, file); | 281 file = path.join(packageInputDir, file); |
264 _collectTransitiveImports(new File(file).readAsStringSync(), reachable, | 282 _collectTransitiveImports(new File(file).readAsStringSync(), reachable, |
265 packageRoot: packageRoot, from: file); | 283 packageRoot: packageRoot, from: file); |
266 } | 284 } |
267 files = reachable.toList(); | 285 files = reachable.toList(); |
268 } else { | 286 } else { |
269 // Collect all files in the packages directory. | 287 // Collect all files in the packages directory. |
270 files = new Directory(packageInputDir) | 288 files = new Directory(packageInputDir) |
271 .listSync(recursive: true) | 289 .listSync(recursive: true) |
272 .where((entry) => entry.path.endsWith('.dart')) | 290 .where((entry) => entry.path.endsWith('.dart')) |
273 .map((entry) => entry.path) | 291 .map((entry) => entry.path) |
274 .toList(); | 292 .toList(); |
275 } | 293 } |
276 | 294 |
277 var unit = | 295 var unit = |
278 new BuildUnit(packageName, packageInputDir, files, _moduleForLibrary); | 296 new BuildUnit(packageName, packageInputDir, files, _moduleForLibrary); |
279 var module = compiler.compile(unit, options); | 297 var module = compiler.compile(unit, options); |
280 | 298 |
281 var outPath = path.join(outputDir, packageName, packageName); | 299 var outPath = path.join(outputDir, packageName, packageName); |
282 _writeModule(outPath, module); | 300 var expectPath = path.join(expectDir, packageName, packageName); |
| 301 _writeModule(outPath, expectPath, module); |
283 } | 302 } |
284 | 303 |
285 String _moduleForLibrary(Source source) { | 304 String _moduleForLibrary(Source source) { |
286 var scheme = source.uri.scheme; | 305 var scheme = source.uri.scheme; |
287 if (scheme == 'package') { | 306 if (scheme == 'package') { |
288 return source.uri.pathSegments.first; | 307 return source.uri.pathSegments.first; |
289 } | 308 } |
290 throw new Exception('Module not found for library "${source.fullName}"'); | 309 throw new Exception('Module not found for library "${source.fullName}"'); |
291 } | 310 } |
292 | 311 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 /// Simplified from ParseDartTask.resolveDirective. | 418 /// Simplified from ParseDartTask.resolveDirective. |
400 String _resolveDirective(UriBasedDirective directive) { | 419 String _resolveDirective(UriBasedDirective directive) { |
401 StringLiteral uriLiteral = directive.uri; | 420 StringLiteral uriLiteral = directive.uri; |
402 String uriContent = uriLiteral.stringValue; | 421 String uriContent = uriLiteral.stringValue; |
403 if (uriContent != null) { | 422 if (uriContent != null) { |
404 uriContent = uriContent.trim(); | 423 uriContent = uriContent.trim(); |
405 directive.uriContent = uriContent; | 424 directive.uriContent = uriContent; |
406 } | 425 } |
407 return directive.validate() == null ? uriContent : null; | 426 return directive.validate() == null ? uriContent : null; |
408 } | 427 } |
OLD | NEW |