Index: utils/testrunner/dart_wrap_task.dart |
=================================================================== |
--- utils/testrunner/dart_wrap_task.dart (revision 0) |
+++ utils/testrunner/dart_wrap_task.dart (revision 0) |
@@ -0,0 +1,316 @@ |
+// Copyright (c) 2012, 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. |
+ |
+class DartWrapTask extends PipelineTask { |
Siggi Cherem (dart-lang)
2012/08/29 01:05:54
docs?
gram
2012/08/29 20:12:26
Done.
|
+ String sourceFileTemplate; |
+ String tempDartFileTemplate; |
+ |
+ DartWrapTask(this.sourceFileTemplate, this.tempDartFileTemplate); |
+ |
+ void execute(Path testfile, List stdout, List stderr, bool verboseLogging, |
+ Function exitHandler) { |
+ // Get the source test file and canonicalize the path. |
+ var sourceName = makePathAbsolute(concretize(sourceFileTemplate, testfile)); |
+ // Get the destination file. |
+ var destFile = concretize(tempDartFileTemplate, testfile); |
+ |
+ StringBuffer sbuf = new StringBuffer(); |
+ |
+ // Add the common header stuff. |
+ var p = new Path(sourceName); |
+ var u = new Path(configuration['unittest']); |
+ sbuf.add(directives(p.filenameWithoutExtension, u.toString(), sourceName)); |
+ |
+ // Add the test configuration and the action function. |
+ var action; |
+ if (configuration['list-tests']) { |
+ action = 'listTests'; |
+ sbuf.add(barebonesConfig()); |
+ sbuf.add(listTests(sourceName)); |
+ } else if (configuration['list-groups']) { |
+ sbuf.add(barebonesConfig()); |
+ sbuf.add(listGroups(sourceName)); |
+ action = 'listGroups'; |
+ } else { |
+ var runIsolated = configuration['isolate']; |
+ var runInBrowser = |
+ configuration['runtime'] != 'vm' && |
+ configuration['runtime'] != 'd8'; |
+ sbuf.add(testPrint(runInBrowser)); |
+ sbuf.add(testConfig(sourceName, runInBrowser, runIsolated, |
+ configuration['time'], |
+ configuration['summary'])); |
+ // Add the isolate stuff, if applicable. This overrides |
+ if (runIsolated) { |
+ action = 'runIsolateTests'; |
+ sbuf.add(isolateTests()); |
+ } else { |
+ action = 'runTests'; |
+ sbuf.add("runTests() { unittest.runTests(); }\n"); |
+ } |
+ } |
+ sbuf.add(formatMessage(configuration['format'])); |
+ |
+ // Add the filter, if applicable. |
+ var include = configuration['include']; |
+ var filter = false; |
+ if (include.length > 0) { |
+ sbuf.add(filterTests(include, 'true')); |
+ filter = true; |
+ } else { |
+ var exclude = configuration['exclude']; |
+ if (exclude.length > 0) { |
+ sbuf.add(filterTests(exclude, 'false')); |
+ filter = true; |
+ } |
+ } |
+ |
+ // Add the common trailer stuff. |
+ sbuf.add(dartMain(action, filter)); |
+ |
+ // Save the Dart file. |
+ createFile(destFile, sbuf.toString()); |
+ exitHandler(0); |
+ } |
+ |
+ String directives(String library, String unittest, String sourceName) { |
+ return """ |
+#library('$library'); |
+#import('dart:isolate'); |
+#import('$unittest', prefix:'unittest'); |
+#import('$sourceName', prefix: 'test'); |
+"""; |
+ } |
+ |
+ String testPrint(bool runInBrowser) { |
+ if (runInBrowser) { |
+ return """ |
+#import('dart:html'); |
+void tprint(msg) { |
+var pre = query('#console'); |
+pre.elements.add(new Text('###\$msg\\n')); |
+} |
+"""; |
+ } else { |
+ return """ |
+void tprint(msg) { |
+print('###\$msg'); |
+} |
+"""; |
+ } |
+ } |
+ |
+ String config(String body) { |
+ return """ |
+class TestRunnerConfiguration extends unittest.Configuration { |
+ get name => 'Test runner configuration'; |
+ get autoStart => false; |
+ $body |
+} |
+"""; |
+ } |
+ |
+ String barebonesConfig() { |
+ return config(''); |
+ } |
+ |
+ String testConfig(String sourceName, bool runInBrowser, bool runIsolated, |
+ bool showTime, bool summary) { |
+ StringBuffer sbuf = new StringBuffer(); |
+ if (runIsolated) { |
+ sbuf.add("var port;\nTestRunnerConfiguration(this.port);\n"); |
+ } |
+ sbuf.add(""" |
+String resultName(result) { |
Siggi Cherem (dart-lang)
2012/08/29 01:05:54
the mix of quoted code and normal code makes this
gram
2012/08/29 20:12:26
I've refactored this quite a bit; hopefully it wil
Siggi Cherem (dart-lang)
2012/08/29 20:47:35
it is easier to see with syntax highlighting, but
|
+ if (result == 'pass') return '${configuration['pass-text']}'; |
+ if (result == 'fail') return '${configuration['fail-text']}'; |
+ return '${configuration['error-text']}'; |
+} |
+void onTestStart(TestCase testCase) {} |
+void onDone(int passed, int failed, int errors, List<TestCase> results, |
+ String uncaughtError) { |
+// Print each result. |
+for (final t in results) { |
+ var groupName = '', testName = ''; |
+ var idx = t.description.lastIndexOf('###'); |
+ if (idx >= 0) { |
+ groupName = t.description.substring(0, idx).replaceAll('###', ' '); |
+ testName = t.description.substring(idx+3); |
+ } else { |
+ testName = t.description; |
+ } |
+ var stack = (t.stackTrace == null) ? '' : '\${t.stackTrace} '; |
+ var message = (t.message.length > 0) ? '\$t.message ' : ''; |
+ var elapsed = ''; |
+"""); |
+ if (showTime) { |
+ sbuf.add(""" |
+ double duration = t.runningTime.inMilliseconds; |
+ duration /= 1000; |
+ elapsed = '\${duration.toStringAsFixed(3)}s '; |
+"""); |
+ } |
+ sbuf.add(""" |
+ tprint(formatMessage('${sourceName} ', '\$groupName ', '\$testName ', |
+ elapsed, '\${resultName(t.result)} ', message, stack)); |
+} |
+"""); |
+ if (summary) { |
+ sbuf.add(""" |
+tprint(''); |
+var success = false; |
+if (passed == 0 && failed == 0 && errors == 0) { |
+ tprint('$sourceName: No tests found.'); |
+ // This is considered a failure too. |
+} else if (failed == 0 && errors == 0 && uncaughtError == null) { |
+ tprint('$sourceName: All \$passed tests passed.'); |
+ success = true; |
+} else { |
+ if (uncaughtError != null) { |
+ tprint('$sourceName: Top-level uncaught error: \$uncaughtError'); |
+ } |
+ tprint('$sourceName: \$passed PASSED, \$failed FAILED, \$errors ERRORS'); |
+} |
+"""); |
+ } |
+ if (runIsolated) { |
+ sbuf.add("var success = (passed > 0 && failed == 0 && errors == 0 " |
+ "&& uncaughtError == null);\n"); |
+ sbuf.add("port.send(success);\n}\n"); |
+ } else if (runInBrowser) { |
+ sbuf.add("window.postMessage('done', '*');\n}\n"); |
+ } else { |
+ sbuf.add("}\n"); |
+ } |
+ return config(sbuf.toString()); |
+ } |
+ |
+ String formatMessage(String format) { |
+ return """ |
+String formatMessage(filename, groupname, |
+ [ testname = '', testTime = '', result = '', |
+ message = '', stack = '' ]) { |
+ return '${format}'. |
+ replaceAll('${Meta.testResult}', result). |
+ replaceAll('${Meta.testTime}', testTime). |
+ replaceAll('${Meta.testfile}', filename). |
+ replaceAll('${Meta.testGroup}', groupname). |
+ replaceAll('${Meta.testDescription}', testname). |
+ replaceAll('${Meta.testMessage}', message). |
+ replaceAll('${Meta.testStacktrace}', stack); |
+} |
+"""; |
+ } |
+ |
+ String listGroups(String sourceName) { |
+ return """ |
+listGroups() { |
+ List tests = unittest.testCases; |
+ Map groups = {}; |
+ for (var t in tests) { |
+ var groupName, testName = ''; |
+ var idx = t.description.lastIndexOf('###'); |
+ if (idx >= 0) { |
+ groupName = t.description.substring(0, idx).replaceAll('###', ' '); |
+ if (!groups.containsKey(groupName)) { |
+ groups[groupName] = ''; |
+ } |
+ } |
+ } |
+ for (var g in groups.getKeys()) { |
+ var msg = formatMessage('${sourceName} ', '\$g '); |
+ print('###\$msg'); |
+ } |
+} |
+"""; |
+ } |
+ |
+ String listTests(String sourceName) { |
+ return """ |
+ listTests() { |
+ List tests = unittest.testCases; |
+ for (var t in tests) { |
+ var groupName, testName = ''; |
+ var idx = t.description.lastIndexOf('###'); |
+ if (idx >= 0) { |
+ groupName = t.description.substring(0, idx).replaceAll('###', ' '); |
+ testName = t.description.substring(idx+3); |
+ } else { |
+ groupName = ''; |
+ testName = t.description; |
+ } |
+ var msg = formatMessage('${sourceName} ', '\$groupName ', |
+ '\$testName '); |
+ print('###\$msg'); |
+ } |
+ } |
+"""; |
+ } |
+ |
+ String filterTests(List filters, String filterReturnValue) { |
+ StringBuffer sbuf = new StringBuffer(); |
+ sbuf.add('filterTest(t) {\n'); |
+ if (filters != null) { |
+ sbuf.add(' var name = t.description.replaceAll("###", " ");\n'); |
+ for (var f in filters) { |
+ sbuf.add(' if (name.indexOf("$f")>=0) return $filterReturnValue;\n'); |
+ } |
+ sbuf.add(' return !$filterReturnValue;\n'); |
+ } else { |
+ // TODO - is this right? Should it be filterReturnValue? |
+ sbuf.add(' return true;\n'); |
+ } |
+ sbuf.add('}\n'); |
+ return sbuf.toString(); |
+ } |
+ |
+ String isolateTests() { |
+ return """ |
+runSlaveTest() { |
+ port.receive((testName, sendport) { |
+ unittest.configure(new TestRunnerConfiguration(sendport)); |
+ unittest.group('', test.main); |
+ unittest.filterTests(testName); |
+ unittest.runTests(); |
+ }); |
+} |
+ |
+var testNum; |
+var failed; |
+ |
+runMasterTest() { |
+ var tests = unittest.testCases; |
+ SendPort sport = spawnFunction(runSlaveTest); |
+ sport.call(tests[testNum].description).then((result) { |
+ if (!result) failed = true; |
+ ++testNum; |
+ if (testNum < tests.length) { |
+ runMasterTest(); |
+ } else if (failed) { |
+ throw new Exception("Some tests failed."); |
+ } |
+ }); |
+} |
+ |
+runIsolateTests() { |
+ testNum = 0; |
+ failed = false; |
+ runMasterTest(); |
+} |
+"""; |
+ } |
+ |
+ String dartMain(String action, bool filter) { |
+ return """ |
+main() { |
+ unittest.groupSep = '###'; |
+ unittest.configure(new TestRunnerConfiguration()); |
+ unittest.group('', test.main); |
+ ${filter?'unittest.filterTests(filterTest);':''} |
+ $action(); |
+} |
+"""; |
+ } |
+ |
+} |