Chromium Code Reviews| Index: utils/testrunner/drt_task.dart |
| =================================================================== |
| --- utils/testrunner/drt_task.dart (revision 11648) |
| +++ utils/testrunner/drt_task.dart (working copy) |
| @@ -5,7 +5,224 @@ |
| /** A pipeline task for running DumpRenderTree. */ |
| class DrtTask extends RunProcessTask { |
| - DrtTask(String htmlFileTemplate) { |
| + String _testFileTemplate; |
| + |
| + DrtTask(this._testFileTemplate, String htmlFileTemplate) { |
| init(config.drtPath, ['--no-timeout', htmlFileTemplate], config.timeout); |
| } |
| + |
| + var testLabelLinePrefix = ' text run'; |
|
Siggi Cherem (dart-lang)
2012/09/05 17:45:41
since these are constant: mark these two as `stati
gram
2012/09/06 18:25:25
Done.
|
| + var bodyLinePrefix = ' '; |
|
Siggi Cherem (dart-lang)
2012/09/05 17:45:41
I'm not sure I understand this parsing and why is
gram
2012/09/06 18:25:25
I added a comment that hopefully explains this.
|
| + |
| + void execute(Path testfile, List stdout, List stderr, bool logging, |
| + Function exitHandler) { |
| + |
| + var testname = expandMacros(_testFileTemplate, testfile); |
| + var isLayout = isLayoutRenderTest(testname) || config.generateRenders; |
| + |
| + if (!isLayout) { |
| + super.execute(testfile, stdout, stderr, logging, exitHandler); |
| + } else { |
| + var tmpLog = new List<String>(); |
| + super.execute(testfile, tmpLog, tmpLog, true, |
| + (code) { |
| + var layoutFile = layoutFileName(testname); |
| + var layouts = getFileContents(layoutFile, false); |
| + var i = 0; |
| + StringBuffer sbuf = null; |
| + if (config.generateRenders) { |
| + sbuf = new StringBuffer(); |
| + } |
| + while ( i < tmpLog.length) { |
| + var line = tmpLog[i]; |
| + if (logging) { |
| + stdout.add(line); |
| + } |
| + if (line.startsWith(testLabelLinePrefix)) { |
| + var j = i+1; |
| + var start = -1, end = -1; |
| + // Walk forward to the next label or end of log. |
| + while (j < tmpLog.length && |
| + !tmpLog[j].startsWith(testLabelLinePrefix)) { |
| + // Is this a body render line? |
| + if (tmpLog[j].startsWith(bodyLinePrefix)) { |
| + if (start < 0) { // Is it the first? |
| + start = j; |
| + } |
| + } else { // Not a render line. |
| + if (start >= 0 && end < 0) { |
| + // We were just in a set of render lines, so this |
| + // line is the first non-member. |
| + end = j; |
| + } |
| + } |
| + j++; |
| + } |
| + if (start >= 0) { // We have some render lines. |
| + if (end < 0) { |
| + end = tmpLog.length; // Sanity. |
| + } |
| + var actualLayout = new List<String>(); |
| + while (start < end) { |
| + actualLayout.add( |
| + tmpLog[start++].substring(bodyLinePrefix.length)); |
| + } |
| + var testName = checkTest(testfile, line, layouts, |
| + actualLayout, stdout); |
| + if (testName == null) { |
| + code = -1; |
| + } else if (config.generateRenders) { |
| + sbuf.add(testName); |
| + sbuf.add('\n'); |
| + for (var renderLine in actualLayout) { |
| + sbuf.add(renderLine); |
| + sbuf.add('\n'); |
| + } |
| + } |
| + } |
| + i = j; |
| + } else { |
| + i++; |
| + } |
| + } |
| + if (config.generateRenders) { |
| + createFile(layoutFile, sbuf.toString()); |
| + } |
| + exitHandler(code); |
| + }); |
| + } |
| + } |
| + |
| + /** |
| + * Verify whether a test passed - it must pass the code expectations, |
| + * and have validated layout. Report success or failure in a test |
| + * result message. Upon success the render section name is returned |
| + * (useful for `config.generateRenders`); otherwise null is returned. |
| + */ |
| + String checkTest(Path testfile, String label, List layouts, |
| + List actual, List out) { |
| + var testGroup = null; |
| + var testName = null; |
| + |
| + // The label line has the form: |
| + // "result:duration:<test>//message" |
| + // where <test> is a test name or series of one or more group names |
| + // followed by a test name, separated by ###. |
| + |
| + // First extract test state, duration, name and message. If the test |
| + // passed we can ignore these and continue to layout verification, but |
| + // if the test failed we want to know that so we can report failure. |
| + // |
| + // TODO(gram) - currently we lose the stack trace although the user |
| + // will get it in the overall output if they used --verbose. We may |
| + // want to fix this properly at some point. |
| + |
| + // Trim leading text up to opening quote. |
| + var idx = label.indexOf('"'); |
|
Siggi Cherem (dart-lang)
2012/09/05 17:45:41
please use regex here.
gram
2012/09/06 18:25:25
Done.
|
| + label = label.substring(idx+1); |
| + |
| + // Extract the result. |
| + idx = label.indexOf(':'); |
| + var result = label.substring(0, idx); |
| + |
| + // Extract the duration. |
| + ++idx; |
| + var idx2 = label.indexOf(':', idx); |
| + var duration = parseDouble(label.substring(idx, idx2)) / 1000; |
| + |
| + // Extract the test groups and name, and the message. |
| + idx = idx2+1; |
| + idx2 = label.indexOf('//', idx); |
| + var test = label.substring(idx, idx2); |
| + var message = label.substring(idx2+2, label.length-1); |
| + |
| + // Split name up with group. |
| + idx = test.lastIndexOf('###'); |
| + if (idx >= 0) { |
| + testGroup = test.substring(0, idx).replaceAll('###', ' '); |
| + testName = test.substring(idx+3); |
| + } else { |
| + testGroup = ''; |
| + testName = test; |
| + } |
| + var section = '[${_pad(testGroup)}$testName]'; |
| + |
| + if (config.generateRenders) { |
| + // Do nothing; fake a pass. |
| + out.add(_formatMessage(config.passFormat, |
| + testfile, testGroup, testName, duration, '')); |
| + } else if (result != 'pass') { |
| + // The test failed separately from layout; just report that |
| + // failure. |
| + out.add(_formatMessage( |
| + (result == 'fail' ? config.failFormat : config.errorFormat), |
| + testfile, testGroup, testName, duration, message)); |
| + return null; |
| + } else { |
| + // The test passed, at least the expectations. So check the layout. |
| + var expected = _getLayout(layouts, section); |
| + var failMessage = null; |
| + var lineNum = 0; |
| + if (expected != null) { |
| + while (lineNum < expected.length) { |
| + if (lineNum >= actual.length) { |
| + failMessage = 'expected "${expected[lineNum]}" but got nothing'; |
| + break; |
| + } else { |
| + if (expected[lineNum] != actual[lineNum]) { |
| + failMessage = 'expected "${expected[lineNum]}" ' |
| + 'but got "${actual[lineNum]}"'; |
| + break; |
| + } |
| + } |
| + lineNum++; |
| + } |
| + if (failMessage == null && lineNum < actual.length) { |
| + failMessage = 'expected nothing but got "${actual[lineNum]}"'; |
| + } |
| + } |
| + if (failMessage != null) { |
| + out.add(_formatMessage(config.failFormat, |
| + testfile, testGroup, testName, duration, |
| + 'Layout content mismatch at line $lineNum: ' |
| + '$failMessage')); |
| + return null; |
| + } else { |
| + out.add(_formatMessage(config.passFormat, |
| + testfile, testGroup, testName, duration, '')); |
| + } |
| + } |
| + return section; |
| + } |
| + |
| + /** Get the expected layout for a test. */ |
| + List _getLayout(List layouts, String section) { |
| + List layout = new List(); |
| + for (var i = 0; i < layouts.length; i++) { |
| + if (layouts[i] == section) { |
| + ++i; |
| + while (i < layouts.length && !layouts[i].startsWith('[')) { |
| + layout.add(layouts[i++]); |
| + } |
| + break; |
| + } |
| + } |
| + return layout; |
| + } |
| + |
| + /** Pad a string with a rightmost space unless it is empty. */ |
| + String _pad(s) => (s.length > 0) ? '$s ' : s; |
|
Siggi Cherem (dart-lang)
2012/09/05 17:45:41
+static
gram
2012/09/06 18:25:25
Done.
|
| + |
| + /** Format a test result message. */ |
| + String _formatMessage(String format, |
| + Path testfile, String testGroup, String testName, |
| + double duration, String message) { |
| + String fname = makePathAbsolute(testfile.directoryPath.toString()); |
| + return "###${format. |
| + replaceAll(Macros.testTime, '${duration.toStringAsFixed(3)}s '). |
| + replaceAll(Macros.testfile, _pad(fname)). |
| + replaceAll(Macros.testGroup, _pad(testGroup)). |
| + replaceAll(Macros.testDescription, _pad(testName)). |
| + replaceAll(Macros.testMessage, _pad(message))}"; |
| + } |
| } |