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, | |
vsm
2016/08/25 12:19:24
Perhaps we should clear any file at the output pat
Jennifer Messerly
2016/08/25 16:21:39
It's not needed. test.sh does this at the start.
| |
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 |