Index: tests/compiler/dart2js/exit_code_test.dart |
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..68cfa7639798b14744714fc08c0a146b57d31f94 |
--- /dev/null |
+++ b/tests/compiler/dart2js/exit_code_test.dart |
@@ -0,0 +1,232 @@ |
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+// Test the exit code of dart2js in case of exceptions, fatal errors, errors, |
+// warnings, etc. |
+ |
+ |
+import 'dart:async'; |
+import 'dart:io' show Platform; |
+ |
+import 'package:async_helper/async_helper.dart'; |
+import 'package:expect/expect.dart'; |
+ |
+import '../../../sdk/lib/_internal/compiler/compiler.dart' as api; |
+import '../../../sdk/lib/_internal/compiler/implementation/dart2js.dart' as entry; |
+import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'; |
+import '../../../sdk/lib/_internal/compiler/implementation/apiimpl.dart' as apiimpl; |
+import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart'; |
+import '../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart'; |
+import '../../../sdk/lib/_internal/compiler/implementation/util/util.dart'; |
+ |
+class TestCompiler extends apiimpl.Compiler { |
+ final String testMarker; |
+ final String testType; |
+ final Function onTest; |
+ |
+ TestCompiler(api.CompilerInputProvider inputProvider, |
+ api.CompilerOutputProvider outputProvider, |
+ api.DiagnosticHandler handler, |
+ Uri libraryRoot, |
+ Uri packageRoot, |
+ List<String> options, |
+ Map<String, dynamic> environment, |
+ String this.testMarker, |
+ String this.testType, |
+ Function this.onTest) |
+ : super(inputProvider, outputProvider, handler, libraryRoot, |
+ packageRoot, options, environment) { |
+ scanner = new TestScanner(this); |
+ test('Compiler'); |
+ } |
+ |
+ Future<bool> run(Uri uri) { |
+ test('Compiler.run'); |
+ return super.run(uri); |
+ } |
+ |
+ TreeElements analyzeElement(Element element) { |
+ test('Compiler.analyzeElement'); |
+ return super.analyzeElement(element); |
+ } |
+ |
+ void codegen(CodegenWorkItem work, CodegenEnqueuer world) { |
+ test('Compiler.codegen'); |
+ super.codegen(work, world); |
+ } |
+ |
+ withCurrentElement(Element element, f()) { |
+ return super.withCurrentElement(element, () { |
+ test('Compiler.withCurrentElement'); |
+ return f(); |
+ }); |
+ } |
+ |
+ test(String marker) { |
+ if (marker == testMarker) { |
+ switch (testType) { |
+ case 'assert': |
+ onTest(testMarker, testType); |
+ assert(false); |
+ break; |
+ case 'invariant': |
+ onTest(testMarker, testType); |
+ invariant(CURRENT_ELEMENT_SPANNABLE, false, message: marker); |
+ break; |
+ case 'warning': |
+ onTest(testMarker, testType); |
+ reportWarningCode(CURRENT_ELEMENT_SPANNABLE, |
+ MessageKind.GENERIC, {'text': marker}); |
+ break; |
+ case 'error': |
+ onTest(testMarker, testType); |
+ reportError(CURRENT_ELEMENT_SPANNABLE, |
+ MessageKind.GENERIC, {'text': marker}); |
+ break; |
+ case 'fatalError': |
+ onTest(testMarker, testType); |
+ reportFatalError(CURRENT_ELEMENT_SPANNABLE, |
+ MessageKind.GENERIC, {'text': marker}); |
+ break; |
+ case 'NoSuchMethodError': |
+ onTest(testMarker, testType); |
+ null.foo; |
+ break; |
+ case '': |
+ onTest(testMarker, testType); |
+ break; |
+ } |
+ } |
+ } |
+} |
+ |
+class TestScanner extends ScannerTask { |
+ TestScanner(TestCompiler compiler) : super(compiler); |
+ |
+ TestCompiler get compiler => super.compiler; |
+ |
+ void scanElements(CompilationUnitElement compilationUnit) { |
+ compiler.test('ScannerTask.scanElements'); |
+ super.scanElements(compilationUnit); |
+ } |
+} |
+ |
+int checkedResults = 0; |
+ |
+Future testExitCode(String marker, String type, int expectedExitCode) { |
+ bool testOccurred = false; |
+ |
+ void onTest(String testMarker, String testType) { |
+ if (testMarker == marker && testType == type) { |
+ testOccurred = true; |
+ } |
+ } |
+ return new Future(() { |
+ Future<String> compile(Uri script, |
+ Uri libraryRoot, |
+ Uri packageRoot, |
+ api.CompilerInputProvider inputProvider, |
+ api.DiagnosticHandler handler, |
+ [List<String> options = const [], |
+ api.CompilerOutputProvider outputProvider, |
+ Map<String, dynamic> environment = const {}]) { |
+ libraryRoot = Platform.script.resolve('../../../sdk/'); |
+ outputProvider = NullSink.outputProvider; |
+ handler = (uri, begin, end, message, kind) {}; |
+ Compiler compiler = new TestCompiler(inputProvider, |
+ outputProvider, |
+ handler, |
+ libraryRoot, |
+ packageRoot, |
+ options, |
+ environment, |
+ marker, |
+ type, |
+ onTest); |
+ return compiler.run(script).then((_) { |
+ String code = compiler.assembledCode; |
+ if (code != null && outputProvider != null) { |
+ String outputType = 'js'; |
+ if (options.contains('--output-type=dart')) { |
+ outputType = 'dart'; |
+ } |
+ outputProvider('', outputType) |
+ ..add(code) |
+ ..close(); |
+ code = ''; // Non-null signals success. |
+ } |
+ return code; |
+ }); |
+ } |
+ |
+ int foundExitCode; |
+ |
+ checkResult() { |
+ Expect.isTrue(testOccurred, 'testExitCode($marker, $type) did not occur'); |
+ if (foundExitCode == null) foundExitCode = 0; |
+ print('testExitCode($marker, $type) ' |
+ 'exitCode=$foundExitCode expected=$expectedExitCode'); |
+ Expect.equals(expectedExitCode, foundExitCode, |
+ 'testExitCode($marker, $type) ' |
+ 'exitCode=$foundExitCode expected=${expectedExitCode}'); |
+ checkedResults++; |
+ } |
+ |
+ void exit(exitCode) { |
+ if (foundExitCode == null) { |
+ foundExitCode = exitCode; |
+ } |
+ }; |
+ |
+ entry.exitFunc = exit; |
+ entry.compileFunc = compile; |
+ |
+ Future result = entry.internalMain( |
+ ["tests/compiler/dart2js/exit_code_helper.dart"]); |
+ return result.whenComplete(checkResult); |
+ }); |
+} |
+ |
+Future testExitCodes(String marker, Map<String,int> expectedExitCodes) { |
+ return Future.forEach(expectedExitCodes.keys, (String type) { |
+ return testExitCode(marker, type, expectedExitCodes[type]); |
+ }); |
+} |
+ |
+void main() { |
+ const beforeRun = const { |
+ '': 0, |
+ 'NoSuchMethodError': 253, |
+ 'assert': 253, |
+ 'invariant': 253 |
+ }; |
+ |
+ const duringRun = const { |
+ '': 0, |
+ 'NoSuchMethodError': 253, |
+ 'assert': 253, |
+ 'invariant': 253, |
+ 'warning': 0, |
+ 'error': 1, |
+ 'fatalError': 1, |
+ }; |
+ |
+ const tests = const { |
+ 'Compiler': beforeRun, |
+ 'Compiler.run': beforeRun, |
+ 'ScannerTask.scanElements': duringRun, |
+ 'Compiler.withCurrentElement': duringRun, |
+ 'Compiler.analyzeElement': duringRun, |
+ 'Compiler.codegen': duringRun, |
+ }; |
+ |
+ asyncStart(); |
+ Future.forEach(tests.keys, (marker) { |
+ return testExitCodes(marker, tests[marker]); |
+ }).then((_) { |
+ Expect.equals(beforeRun.length * 2 + duringRun.length * 4, |
+ checkedResults); |
+ asyncEnd(); |
+ }); |
+} |