| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 /// Runs Dart Dev Compiler on all input in the `codegen` directory and checks | 6 /// Runs Dart Dev Compiler on all input in the `codegen` directory and checks |
| 7 /// that the output is what we expected. | 7 /// that the output is what we expected. |
| 8 library dev_compiler.test.codegen_test; | 8 library dev_compiler.test.codegen_test; |
| 9 | 9 |
| 10 import 'dart:io'; | 10 import 'dart:io'; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 .listSync() | 32 .listSync() |
| 33 .where((f) => f is File) | 33 .where((f) => f is File) |
| 34 .map((f) => f.path) | 34 .map((f) => f.path) |
| 35 .where((p) => p.endsWith('.dart') && filePattern.hasMatch(p)); | 35 .where((p) => p.endsWith('.dart') && filePattern.hasMatch(p)); |
| 36 } | 36 } |
| 37 | 37 |
| 38 main(arguments) { | 38 main(arguments) { |
| 39 if (arguments == null) arguments = []; | 39 if (arguments == null) arguments = []; |
| 40 ArgResults args = argParser.parse(arguments); | 40 ArgResults args = argParser.parse(arguments); |
| 41 var filePattern = new RegExp(args.rest.length > 0 ? args.rest[0] : '.'); | 41 var filePattern = new RegExp(args.rest.length > 0 ? args.rest[0] : '.'); |
| 42 var compilerMessages = new StringBuffer(); | |
| 43 var loggerSub; | |
| 44 | |
| 45 setUp(() { | |
| 46 compilerMessages.clear(); | |
| 47 loggerSub = setupLogger(Level.CONFIG, compilerMessages.writeln); | |
| 48 }); | |
| 49 | |
| 50 tearDown(() { | |
| 51 if (loggerSub != null) { | |
| 52 loggerSub.cancel(); | |
| 53 loggerSub = null; | |
| 54 } | |
| 55 }); | |
| 56 | 42 |
| 57 var inputDir = path.join(testDirectory, 'codegen'); | 43 var inputDir = path.join(testDirectory, 'codegen'); |
| 58 var expectDir = path.join(inputDir, 'expect'); | 44 var expectDir = path.join(inputDir, 'expect'); |
| 59 | 45 |
| 60 bool compile(String entryPoint, AnalysisContext context, | 46 bool compile(String entryPoint, AnalysisContext context, |
| 61 {bool checkSdk: false, bool sourceMaps: false, bool closure: false}) { | 47 {bool checkSdk: false, bool sourceMaps: false, bool closure: false}) { |
| 62 // TODO(jmesserly): add a way to specify flags in the test file, so | 48 // TODO(jmesserly): add a way to specify flags in the test file, so |
| 63 // they're more self-contained. | 49 // they're more self-contained. |
| 64 var runtimeDir = path.join(path.dirname(testDirectory), 'lib', 'runtime'); | 50 var runtimeDir = path.join(path.dirname(testDirectory), 'lib', 'runtime'); |
| 65 var options = new CompilerOptions( | 51 var options = new CompilerOptions( |
| 66 codegenOptions: new CodegenOptions( | 52 codegenOptions: new CodegenOptions( |
| 67 outputDir: expectDir, | 53 outputDir: expectDir, |
| 68 emitSourceMaps: sourceMaps, | 54 emitSourceMaps: sourceMaps, |
| 69 closure: closure, | 55 closure: closure, |
| 70 forceCompile: checkSdk), | 56 forceCompile: checkSdk), |
| 71 useColors: false, | 57 useColors: false, |
| 72 checkSdk: checkSdk, | 58 checkSdk: checkSdk, |
| 73 runtimeDir: runtimeDir, | 59 runtimeDir: runtimeDir, |
| 74 inputs: [entryPoint], | 60 inputs: [entryPoint], |
| 75 inputBaseDir: inputDir); | 61 inputBaseDir: inputDir, |
| 62 saveMessages: true); |
| 76 var reporter = createErrorReporter(context, options); | 63 var reporter = createErrorReporter(context, options); |
| 77 return new BatchCompiler(context, options, reporter: reporter).run(); | 64 return new BatchCompiler(context, options, reporter: reporter).run(); |
| 78 } | 65 } |
| 79 | 66 |
| 80 { | 67 { |
| 81 // Expand wacky multitests into a bunch of test files. | 68 // Expand wacky multitests into a bunch of test files. |
| 82 // We'll compile each one as if it was an input. | 69 // We'll compile each one as if it was an input. |
| 83 var languageDir = path.join(inputDir, 'language'); | 70 var languageDir = path.join(inputDir, 'language'); |
| 84 var testFiles = _findTests(languageDir, filePattern); | 71 var testFiles = _findTests(languageDir, filePattern); |
| 85 | 72 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 103 outcomes.remove('runtime error'); | 90 outcomes.remove('runtime error'); |
| 104 if (outcomes.isNotEmpty) { | 91 if (outcomes.isNotEmpty) { |
| 105 // Skip all other outcomes. | 92 // Skip all other outcomes. |
| 106 // | 93 // |
| 107 // They are handled by analyzer/static type system, and | 94 // They are handled by analyzer/static type system, and |
| 108 // therefore are not interesting to run. | 95 // therefore are not interesting to run. |
| 109 tests.remove(name); | 96 tests.remove(name); |
| 110 } | 97 } |
| 111 }); | 98 }); |
| 112 | 99 |
| 100 var modifyTime = new File(filePath).lastModifiedSync(); |
| 113 var filename = path.basenameWithoutExtension(filePath); | 101 var filename = path.basenameWithoutExtension(filePath); |
| 114 tests.forEach((name, contents) { | 102 tests.forEach((name, contents) { |
| 115 new File(path.join(languageDir, '${filename}_${name}_multi.dart')) | 103 var f = new File( |
| 116 .writeAsStringSync(contents); | 104 path.join(languageDir, '${filename}_${name}_multi.dart')); |
| 105 if (!f.existsSync() || f.lastModifiedSync().isBefore(modifyTime)) { |
| 106 f.writeAsStringSync(contents); |
| 107 } |
| 117 }); | 108 }); |
| 118 } | 109 } |
| 119 } | 110 } |
| 120 } | 111 } |
| 121 | 112 |
| 122 for (var dir in [null, 'language']) { | 113 for (var dir in [null, 'language']) { |
| 123 group('dartdevc ' + path.join('test', 'codegen', dir), () { | 114 group('dartdevc ' + path.join('test', 'codegen', dir), () { |
| 124 var outDir = path.join(expectDir, dir); | 115 var outDir = path.join(expectDir, dir); |
| 125 | 116 |
| 126 var testFiles = _findTests(path.join(inputDir, dir), filePattern); | 117 var testFiles = _findTests(path.join(inputDir, dir), filePattern); |
| 127 for (var filePath in testFiles) { | 118 for (var filePath in testFiles) { |
| 128 var filename = path.basenameWithoutExtension(filePath); | 119 var filename = path.basenameWithoutExtension(filePath); |
| 129 | 120 |
| 130 test('$filename.dart', () { | 121 test('$filename.dart', () { |
| 131 compilerMessages.writeln('// Messages from compiling $filename.dart'); | |
| 132 | |
| 133 // TODO(jmesserly): this was added to get some coverage of source maps | 122 // TODO(jmesserly): this was added to get some coverage of source maps |
| 134 // and closure annotations. | 123 // and closure annotations. |
| 135 // We need a more comprehensive strategy to test them. | 124 // We need a more comprehensive strategy to test them. |
| 136 var sourceMaps = filename == 'map_keys'; | 125 var sourceMaps = filename == 'map_keys'; |
| 137 var closure = filename == 'closure'; | 126 var closure = filename == 'closure'; |
| 138 var success = compile(filePath, realSdkContext, | 127 compile(filePath, realSdkContext, |
| 139 sourceMaps: sourceMaps, closure: closure); | 128 sourceMaps: sourceMaps, closure: closure); |
| 140 | 129 |
| 141 // Write compiler messages to disk. | 130 var messageFile = new File(path.join(outDir, '$filename.txt')); |
| 142 new File(path.join(outDir, '$filename.txt')) | 131 var jsFile = new File(path.join(outDir, '$filename.js')); |
| 143 .writeAsStringSync('$compilerMessages'); | |
| 144 | 132 |
| 145 var outFile = new File(path.join(outDir, '$filename.js')); | 133 bool error = false; |
| 146 expect(outFile.existsSync(), success, | 134 if (messageFile.existsSync()) { |
| 147 reason: '${outFile.path} was created iff compilation succeeds'); | 135 var messageContents = messageFile.readAsStringSync(); |
| 136 error = messageContents.contains('severe'); |
| 137 } |
| 138 |
| 139 expect(jsFile.existsSync() == !error, true, |
| 140 reason: 'JS file should exist iff no errors were found.'); |
| 148 }); | 141 }); |
| 149 } | 142 } |
| 150 }); | 143 }); |
| 151 } | 144 } |
| 152 | 145 |
| 153 if (Platform.environment.containsKey('COVERALLS_TOKEN')) { | 146 if (Platform.environment.containsKey('COVERALLS_TOKEN')) { |
| 154 group('sdk', () { | 147 group('sdk', () { |
| 155 // The analyzer does not bubble exception messages for certain internal | 148 // The analyzer does not bubble exception messages for certain internal |
| 156 // dart:* library failures, such as failing to find | 149 // dart:* library failures, such as failing to find |
| 157 // "_internal/libraries.dart". Instead it produces an opaque "failed to | 150 // "_internal/libraries.dart". Instead it produces an opaque "failed to |
| (...skipping 23 matching lines...) Expand all Loading... |
| 181 reason: '${outFile.path} was created for dart:core'); | 174 reason: '${outFile.path} was created for dart:core'); |
| 182 }); | 175 }); |
| 183 }); | 176 }); |
| 184 } | 177 } |
| 185 | 178 |
| 186 var expectedRuntime = | 179 var expectedRuntime = |
| 187 defaultRuntimeFiles.map((f) => 'dev_compiler/runtime/$f'); | 180 defaultRuntimeFiles.map((f) => 'dev_compiler/runtime/$f'); |
| 188 | 181 |
| 189 test('devc jscodegen sunflower.html', () { | 182 test('devc jscodegen sunflower.html', () { |
| 190 var filePath = path.join(inputDir, 'sunflower', 'sunflower.html'); | 183 var filePath = path.join(inputDir, 'sunflower', 'sunflower.html'); |
| 191 compilerMessages.writeln('// Messages from compiling sunflower.html'); | 184 compile(filePath, realSdkContext); |
| 192 | |
| 193 var success = compile(filePath, realSdkContext); | |
| 194 | |
| 195 // Write compiler messages to disk. | |
| 196 new File(path.join(expectDir, 'sunflower', 'sunflower.txt')) | |
| 197 .writeAsStringSync(compilerMessages.toString()); | |
| 198 | 185 |
| 199 var expectedFiles = ['sunflower.html', 'sunflower.js',]; | 186 var expectedFiles = ['sunflower.html', 'sunflower.js',]; |
| 200 | 187 |
| 201 for (var filepath in expectedFiles) { | 188 for (var filepath in expectedFiles) { |
| 202 var outFile = new File(path.join(expectDir, 'sunflower', filepath)); | 189 var outFile = new File(path.join(expectDir, 'sunflower', filepath)); |
| 203 expect(outFile.existsSync(), success, | 190 expect(outFile.existsSync(), true, reason: '${outFile.path} was created'); |
| 204 reason: '${outFile.path} was created iff compilation succeeds'); | |
| 205 } | 191 } |
| 206 }); | 192 }); |
| 207 | 193 |
| 208 test('devc jscodegen html_input.html', () { | 194 test('devc jscodegen html_input.html', () { |
| 209 var filePath = path.join(inputDir, 'html_input.html'); | 195 var filePath = path.join(inputDir, 'html_input.html'); |
| 210 compilerMessages.writeln('// Messages from compiling html_input.html'); | 196 compile(filePath, realSdkContext); |
| 211 | |
| 212 var success = compile(filePath, realSdkContext); | |
| 213 | |
| 214 // Write compiler messages to disk. | |
| 215 new File(path.join(expectDir, 'html_input.txt')) | |
| 216 .writeAsStringSync(compilerMessages.toString()); | |
| 217 | 197 |
| 218 var expectedFiles = [ | 198 var expectedFiles = [ |
| 219 'html_input.html', | 199 'html_input.html', |
| 220 'dir/html_input_a.js', | 200 'dir/html_input_a.js', |
| 221 'dir/html_input_b.js', | 201 'dir/html_input_b.js', |
| 222 'dir/html_input_c.js', | 202 'dir/html_input_c.js', |
| 223 'dir/html_input_d.js', | 203 'dir/html_input_d.js', |
| 224 'dir/html_input_e.js' | 204 'dir/html_input_e.js' |
| 225 ]..addAll(expectedRuntime); | 205 ]..addAll(expectedRuntime); |
| 226 | 206 |
| 227 for (var filepath in expectedFiles) { | 207 for (var filepath in expectedFiles) { |
| 228 var outFile = new File(path.join(expectDir, filepath)); | 208 var outFile = new File(path.join(expectDir, filepath)); |
| 229 expect(outFile.existsSync(), success, | 209 expect(outFile.existsSync(), true, reason: '${outFile.path} was created'); |
| 230 reason: '${outFile.path} was created iff compilation succeeds'); | |
| 231 } | 210 } |
| 232 }); | 211 }); |
| 233 } | 212 } |
| 234 | 213 |
| 235 /// An implementation of analysis engine's [Logger] that prints. | 214 /// An implementation of analysis engine's [Logger] that prints. |
| 236 class PrintLogger implements Logger { | 215 class PrintLogger implements Logger { |
| 237 @override void logError(String message, [CaughtException exception]) { | 216 @override void logError(String message, [CaughtException exception]) { |
| 238 print('[AnalysisEngine] error $message $exception'); | 217 print('[AnalysisEngine] error $message $exception'); |
| 239 } | 218 } |
| 240 | 219 |
| 241 @override void logError2(String message, Object exception) { | 220 @override void logError2(String message, Object exception) { |
| 242 print('[AnalysisEngine] error $message $exception'); | 221 print('[AnalysisEngine] error $message $exception'); |
| 243 } | 222 } |
| 244 | 223 |
| 245 void logInformation(String message, [CaughtException exception]) {} | 224 void logInformation(String message, [CaughtException exception]) {} |
| 246 void logInformation2(String message, Object exception) {} | 225 void logInformation2(String message, Object exception) {} |
| 247 } | 226 } |
| OLD | NEW |