Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(745)

Side by Side Diff: utils/testrunner/dart_wrap_task.dart

Issue 10897016: Testrunner for 3rd parties. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « utils/testrunner/dart_task.dart ('k') | utils/testrunner/delete_task.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
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.
4
5 /**
6 * The DartWrapTask generates a Dart wrapper for a test file, that has a
7 * test Configuration customized for the options specified by the user.
8 */
9 class DartWrapTask extends PipelineTask {
10 final String _sourceFileTemplate;
11 final String _tempDartFileTemplate;
12
13 DartWrapTask(this._sourceFileTemplate, this._tempDartFileTemplate);
14
15 void execute(Path testfile, List stdout, List stderr, bool logging,
16 Function exitHandler) {
17 // Get the source test file and canonicalize the path.
18 var sourceName = makePathAbsolute(
19 expandMacros(_sourceFileTemplate, testfile));
20 // Get the destination file.
21 var destFile = expandMacros(_tempDartFileTemplate, testfile);
22
23 // Working buffer for the Dart wrapper.
24 StringBuffer sbuf = new StringBuffer();
25
26 // Add the common header stuff.
27 var p = new Path(sourceName);
28 sbuf.add(directives(p.filenameWithoutExtension,
29 config.unittestPath,
30 sourceName));
31
32 // Add the test configuration and determine the action function.
33 var action;
34 if (config.listTests) {
35 action = 'listTests';
36 sbuf.add(barebonesConfig());
37 sbuf.add(listTestsFunction);
38 sbuf.add(formatListMessageFunction(config.listFormat));
39 } else if (config.listGroups) {
40 sbuf.add(barebonesConfig());
41 sbuf.add(listGroupsFunction);
42 sbuf.add(formatListMessageFunction(config.listFormat));
43 action = 'listGroups';
44 } else {
45
46 if (config.runInBrowser) {
47 sbuf.add(browserTestPrintFunction);
48 sbuf.add(unblockDRTFunction);
49 } else {
50 sbuf.add(nonBrowserTestPrintFunction);
51 sbuf.add(stubUnblockDRTFunction);
52 }
53
54 if (config.runIsolated) {
55 sbuf.add(runIsolateTestsFunction);
56 action = 'runIsolateTests';
57 } else {
58 sbuf.add(runTestsFunction);
59 action = 'runTests';
60 }
61
62 sbuf.add(config.includeTime ? elapsedFunction : stubElapsedFunction);
63 sbuf.add(config.produceSummary ?
64 printSummaryFunction : stubPrintSummaryFunction);
65
66 if (config.immediateOutput) {
67 sbuf.add(printTestResultFunction);
68 sbuf.add(stubPrintAllTestResultsFunction);
69 } else {
70 sbuf.add(stubPrintTestResultFunction);
71 sbuf.add(printAllTestResultsFunction);
72 }
73
74 sbuf.add(dumpTestResultFunction);
75 sbuf.add(formatMessageFunction(config.passFormat,
76 config.failFormat,
77 config.errorFormat));
78 sbuf.add(testConfig());
79 }
80
81 // Add the filter, if applicable.
82 if (config.filtering) {
83 if (config.includeFilter.length > 0) {
84 sbuf.add(filterTestFunction(config.includeFilter, 'true'));
85 } else {
86 sbuf.add(filterTestFunction(config.excludeFilter, 'false'));
87 }
88 }
89
90 // Add the common trailer stuff.
91 sbuf.add(dartMain(sourceName, action, config.filtering));
92
93 // Save the Dart file.
94 createFile(destFile, sbuf.toString());
95 exitHandler(0);
96 }
97
98 void cleanup(Path testfile, List stdout, List stderr,
99 bool logging, bool keepFiles) {
100 deleteFiles([_tempDartFileTemplate], testfile, logging, keepFiles, stdout);
101 }
102
103 String directives(String library, String unittest, String sourceName) {
104 return """
105 #library('$library');
106 #import('dart:math');
107 #import('dart:isolate');
108 #import('$unittest', prefix:'unittest');
109 #import('$sourceName', prefix: 'test');
110 """;
111 }
112
113 // The core skeleton for a config. Most of the guts is in the
114 // parameter [body].
115 String configuration([String body = '']) {
116 return """
117 class TestRunnerConfiguration extends unittest.Configuration {
118 get name => 'Test runner configuration';
119 get autoStart => false;
120 $body
121 }
122 """;
123 }
124
125 // A barebones config, used for listing tests, not running them.
126 String barebonesConfig() {
127 return configuration();
128 }
129
130 // A more complex config, used for running tests.
131 String testConfig() {
132 return configuration("""
133 void onTestResult(TestCase testCase) {
134 printResult('\$testFile ', testCase);
135 }
136
137 void onDone(int passed, int failed, int errors, List<TestCase> results,
138 String uncaughtError) {
139 var success = (passed > 0 && failed == 0 && errors == 0 &&
140 uncaughtError == null);
141 printResults(testFile, results);
142 printSummary(testFile, passed, failed, errors, uncaughtError);
143 unblockDRT();
144 }
145 """);
146 }
147
148 // The main function, that creates the config, filters the tests if
149 // necessary, then performs the action (list/run/run-isolated).
150 String dartMain(String sourceName, String action, bool filter) {
151 return """
152 var testFile = '$sourceName';
153 main() {
154 unittest.groupSep = '###';
155 unittest.configure(new TestRunnerConfiguration());
156 unittest.group('', test.main);
157 ${filter ? 'unittest.filterTests(filterTest);' : ''}
158 $action();
159 }
160 """;
161 }
162
163 // For 'printing' when we are in the browser, we add text elements
164 // to a DOM element with id 'console'.
165 final String browserTestPrintFunction = """
166 #import('dart:html');
167 void tprint(msg) {
168 var pre = query('#console');
169 pre.elements.add(new Text('###\$msg\\n'));
170 }
171 """;
172
173 // For printing when not in the browser we can just use Dart's print().
174 final String nonBrowserTestPrintFunction = """
175 void tprint(msg) {
176 print('###\$msg');
177 }
178 """;
179
180 // A function to give us the elapsed time for a test.
181 final String elapsedFunction = """
182 String elapsed(TestCase t) {
183 double duration = t.runningTime.inMilliseconds;
184 duration /= 1000;
185 return '\${duration.toStringAsFixed(3)}s ';
186 }
187 """;
188
189 // A dummy version of the elapsed function for when the user
190 // doesn't want test times included.
191 final String stubElapsedFunction = """
192 String elapsed(TestCase t) {
193 return '';
194 }
195 """;
196
197 // A function to print the results of a test.
198 final String dumpTestResultFunction = """
199 void dumpTestResult(source, TestCase t) {
200 var groupName = '', testName = '';
201 var idx = t.description.lastIndexOf('###');
202 if (idx >= 0) {
203 groupName = t.description.substring(0, idx).replaceAll('###', ' ');
204 testName = t.description.substring(idx+3);
205 } else {
206 testName = t.description;
207 }
208 var stack = (t.stackTrace == null) ? '' : '\${t.stackTrace} ';
209 var message = (t.message.length > 0) ? '\$t.message ' : '';
210 var duration = elapsed(t);
211 tprint(formatMessage(source, '\$groupName ', '\$testName ',
212 duration, t.result, message, stack));
213 }
214 """;
215
216 // A function to print the test summary.
217 final String printSummaryFunction = """
218 void printSummary(String testFile, int passed, int failed, int errors,
219 String uncaughtError) {
220 tprint('');
221 if (passed == 0 && failed == 0 && errors == 0) {
222 tprint('\$testFile: No tests found.');
223 } else if (failed == 0 && errors == 0 && uncaughtError == null) {
224 tprint('\$testFile: All \$passed tests passed.');
225 } else {
226 if (uncaughtError != null) {
227 tprint('\$testFile: Top-level uncaught error: \$uncaughtError');
228 }
229 tprint('\$testFile: \$passed PASSED, \$failed FAILED, \$errors ERRORS');
230 }
231 }
232 """;
233
234 final String stubPrintSummaryFunction = """
235 void printSummary(String testFile, int passed, int failed, int errors,
236 String uncaughtError) {
237 }
238 """;
239
240 // A function to print all test results.
241 final String printAllTestResultsFunction = """
242 void printResults(testfile, List<TestCase> results) {
243 for (final testCase in results) {
244 dumpTestResult('\$testfile ', testCase);
245 }
246 }
247 """;
248
249 final String stubPrintAllTestResultsFunction = """
250 void printResults(testfile, List<TestCase> results) {
251 }
252 """;
253
254 // A function to print a single test result.
255 final String printTestResultFunction = """
256 void printResult(testfile, TestCase testCase) {
257 dumpTestResult('\$testfile ', testCase);
258 }
259 """;
260
261 final String stubPrintTestResultFunction = """
262 void printResult(testfile, TestCase testCase) {
263 }
264 """;
265
266 final String unblockDRTFunction = """
267 void unblockDRT() {
268 window.postMessage('done', '*');
269 }
270 """;
271
272 final String stubUnblockDRTFunction = """
273 void unblockDRT() {
274 }
275 """;
276
277 // A simple format function for listing tests.
278 String formatListMessageFunction(String format) {
279 return """
280 String formatMessage(filename, groupname, [ testname = '']) {
281 return '${format}'.
282 replaceAll('${Macros.testfile}', filename).
283 replaceAll('${Macros.testGroup}', groupname).
284 replaceAll('${Macros.testDescription}', testname);
285 }
286 """;
287 }
288
289 // A richer format function for test results.
290 String formatMessageFunction(
291 String passFormat, String failFormat, String errorFormat) {
292 return """
293 String formatMessage(filename, groupname,
294 [ testname = '', testTime = '', result = '',
295 message = '', stack = '' ]) {
296 var format = '$errorFormat';
297 if (result == 'pass') format = '$passFormat';
298 else if (result == 'fail') format = '$failFormat';
299 return format.
300 replaceAll('${Macros.testTime}', testTime).
301 replaceAll('${Macros.testfile}', filename).
302 replaceAll('${Macros.testGroup}', groupname).
303 replaceAll('${Macros.testDescription}', testname).
304 replaceAll('${Macros.testMessage}', message).
305 replaceAll('${Macros.testStacktrace}', stack);
306 }
307 """;
308 }
309
310 // A function to list the test groups.
311 final String listGroupsFunction = """
312 listGroups() {
313 List tests = unittest.testCases;
314 Map groups = {};
315 for (var t in tests) {
316 var groupName, testName = '';
317 var idx = t.description.lastIndexOf('###');
318 if (idx >= 0) {
319 groupName = t.description.substring(0, idx).replaceAll('###', ' ');
320 if (!groups.containsKey(groupName)) {
321 groups[groupName] = '';
322 }
323 }
324 }
325 for (var g in groups.getKeys()) {
326 var msg = formatMessage('\$testfile ', '\$g ');
327 print('###\$msg');
328 }
329 }
330 """;
331
332 // A function to list the tests.
333 final String listTestsFunction = """
334 listTests() {
335 List tests = unittest.testCases;
336 for (var t in tests) {
337 var groupName, testName = '';
338 var idx = t.description.lastIndexOf('###');
339 if (idx >= 0) {
340 groupName = t.description.substring(0, idx).replaceAll('###', ' ');
341 testName = t.description.substring(idx+3);
342 } else {
343 groupName = '';
344 testName = t.description;
345 }
346 var msg = formatMessage('\$testfile ', '\$groupName ', '\$testName ');
347 print('###\$msg');
348 }
349 }
350 """;
351
352 // A function to filter the tests.
353 String filterTestFunction(List filters, String filterReturnValue) {
354 StringBuffer sbuf = new StringBuffer();
355 sbuf.add('filterTest(t) {\n');
356 if (filters != null) {
357 sbuf.add(' var name = t.description.replaceAll("###", " ");\n');
358 for (var f in filters) {
359 sbuf.add(' if (name.indexOf("$f")>=0) return $filterReturnValue;\n');
360 }
361 sbuf.add(' return !$filterReturnValue;\n');
362 } else {
363 sbuf.add(' return true;\n');
364 }
365 sbuf.add('}\n');
366 return sbuf.toString();
367 }
368
369 // Code to support running single tests as master/slave in isolates.
370 final String runIsolateTestsFunction = """
371 class TestRunnerSlaveConfiguration extends unittest.Configuration {
372 get name => 'Test runner slave configuration';
373 get autoStart => false;
374
375 void onDone(int passed, int failed, int errors, List<TestCase> results,
376 String uncaughtError) {
377 TestCase test = results[0];
378 masterPort.send([test.result, test.runningTime.inMilliseconds,
379 test.message, test.stackTrace]);
380 }
381 }
382
383 var masterPort;
384 runSlaveTest() {
385 port.receive((testName, sendport) {
386 masterPort = sendport;
387 unittest.configure(new TestRunnerSlaveConfiguration());
388 unittest.groupSep = '###';
389 unittest.group('', test.main);
390 unittest.filterTests(testName);
391 unittest.runTests();
392 });
393 }
394
395 var testNum;
396 var failed;
397 var errors;
398 var passed;
399
400 runMasterTest() {
401 var tests = unittest.testCases;
402 tests[testNum].startTime = new Date.now();
403 SendPort slavePort = spawnFunction(runSlaveTest);
404 slavePort.call(tests[testNum].description).then((results) {
405 var result = results[0];
406 var duration = new Duration(milliseconds: results[1]);
407 var message = results[2];
408 var stack = results[3];
409 if (result == 'pass') {
410 tests[testNum].pass();
411 ++passed;
412 } else if (result == 'fail') {
413 tests[testNum].fail(message, stack);
414 ++failed;
415 } else {
416 tests[testNum].error(message, stack);
417 ++errors;
418 }
419 tests[testNum].runningTime = duration;
420 ++testNum;
421 if (testNum < tests.length) {
422 runMasterTest();
423 } else {
424 unittest.config.onDone(passed, failed, errors,
425 unittest.testCases, null);
426 }
427 });
428 }
429
430 runIsolateTests() {
431 testNum = 0;
432 passed = failed = errors = 0;
433 runMasterTest();
434 }
435 """;
436
437 // Code for running all tests in the normal (non-isolate) way.
438 final String runTestsFunction = """
439 runTests() {
440 unittest.runTests();
441 }
442 """;
443 }
OLDNEW
« no previous file with comments | « utils/testrunner/dart_task.dart ('k') | utils/testrunner/delete_task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698