Chromium Code Reviews| Index: utils/testrunner/dart_wrap_task.dart |
| =================================================================== |
| --- utils/testrunner/dart_wrap_task.dart (revision 12392) |
| +++ utils/testrunner/dart_wrap_task.dart (working copy) |
| @@ -21,17 +21,34 @@ |
| var destFile = expandMacros(_tempDartFileTemplate, testfile); |
| var p = new Path(sourceName); |
| - if (isLayoutRenderTest(sourceName) || config.generateRenders) { |
| - makeLayoutTestWrapper(sourceName, destFile, p.filenameWithoutExtension); |
| - exitHandler(0); |
| - return; |
| + |
| + if (config.layoutText || config.layoutPixel) { |
| + // Layout tests are more complicated, as we have a 'meta' |
| + // wrapped Dart program that in turn invokes DRT to run the |
|
Siggi Cherem (dart-lang)
2012/09/14 20:01:23
we've talked about this before, but I think we sho
|
| + // normal wrapped Dart program, once for each test. So we generate |
| + // a layout test wrapper file for the real tests and a controller |
| + // wrapper to manage overall execution. |
| + var childFile = '${destFile.substring(0, destFile.length-5)}-child.dart'; |
|
Siggi Cherem (dart-lang)
2012/09/14 20:01:23
style: please add spaces around operators (destFil
gram
2012/09/19 23:24:38
Done.
|
| + makeLayoutTestWrapper(sourceName, childFile, |
| + p.filenameWithoutExtension); |
| + makeLayoutTestControllerWrapper(sourceName, destFile, childFile, |
| + p.filenameWithoutExtension, |
| + sourceName.substring(0, sourceName.length-5)); // Strip .dart. |
|
Siggi Cherem (dart-lang)
2012/09/14 20:01:23
ditto
gram
2012/09/19 23:24:38
Done.
|
| + } else { |
| + makeNonLayoutTestWrapper(sourceName, destFile, |
| + p.filenameWithoutExtension); |
| } |
| + exitHandler(0); |
| + } |
| + void makeNonLayoutTestWrapper(String sourceName, String destFile, |
| + String sourceNameWithoutExtension) { |
| + |
| // Working buffer for the Dart wrapper. |
| StringBuffer sbuf = new StringBuffer(); |
| // Add the common header stuff. |
| - sbuf.add(directives(p.filenameWithoutExtension, |
| + sbuf.add(directives(sourceNameWithoutExtension, |
| config.unittestPath, |
| sourceName)); |
| @@ -98,7 +115,6 @@ |
| // Save the Dart file. |
| createFile(destFile, sbuf.toString()); |
| - exitHandler(0); |
| } |
| void cleanup(Path testfile, List stdout, List stderr, |
| @@ -109,17 +125,16 @@ |
| void makeLayoutTestWrapper(String sourceName, String destFile, |
| String libraryName) { |
| StringBuffer sbuf = new StringBuffer(); |
| - var cfg = config.unittestPath. |
| - replaceAll('unittest.dart', 'html_layout_config.dart'); |
| sbuf.add(""" |
| #library('$libraryName'); |
| #import('dart:math'); |
| #import('dart:isolate'); |
| #import('dart:html'); |
| +#import('dart:uri'); |
| #import('${config.unittestPath}', prefix:'unittest'); |
| -#import('$cfg', prefix:'unittest'); |
| #import('$sourceName', prefix: 'test'); |
| """); |
| + |
| // Add the filter, if applicable. |
| if (config.filtering) { |
| if (config.includeFilter.length > 0) { |
| @@ -129,18 +144,288 @@ |
| } |
| } |
| sbuf.add(""" |
| + |
| +class LayoutTestConfiguration extends unittest.Configuration { |
| + get autoStart => false; |
| + void onTestResult(TestCase testCase) { |
| + window.postMessage('done', '*'); // Unblock DRT |
| + } |
| +} |
| + |
| main() { |
| -unittest.groupSep = '###'; |
| -unittest.useHtmlLayoutConfiguration(); |
| -unittest.group('', test.main); |
| -${config.filtering ? 'unittest.filterTests(filterTest);' : ''} |
| -if (window.location.search == '') unittest.runTests(); |
| + unittest.groupSep = '###'; |
| + unittest.configure(new LayoutTestConfiguration()); |
| + // Create the set of test cases. |
| + unittest.group('', test.main); |
| + // Do any user-specified test filtering. |
| + ${config.filtering ? 'unittest.filterTests(filterTest);' : ''} |
| + // Filter to the test number in the search query. |
| + var testNum = parseInt(window.location.search.substring(6)); |
| + if (testNum < 0 || testNum >= unittest.testCases.length) { |
| + print('#TEST NONEXISTENT'); |
| + } else { |
| + var name = unittest.testCases[testNum].description; |
| + print('#TEST \$name'); |
| + unittest.filterTests(name); |
| + // Run the test. |
| + unittest.runTests(); |
| + } |
| } |
| """); |
| // Save the Dart file. |
| createFile(destFile, sbuf.toString()); |
| } |
| + void makeLayoutTestControllerWrapper(String sourceName, |
| + String destName, String childName, String libraryName, |
| + String expectedDirectory) { |
| + if (config.regenerate) { |
| + var d = new Directory(expectedDirectory); |
| + if (!d.existsSync()) { |
| + d.createSync(); |
| + } |
| + } |
| + StringBuffer sbuf = new StringBuffer(); |
| + var htmlFile = childName.replaceFirst('-child.dart', '.html'); |
| + // Add common prefix. |
| + sbuf.add(""" |
|
Siggi Cherem (dart-lang)
2012/09/14 20:01:23
could we move a lot of this 'generated code' into
|
| +#library('$libraryName'); |
| +#import('dart:uri'); |
| +#import('dart:io'); |
| +#import('dart:math'); |
| + |
| +var label; |
| + |
| +main() { |
| + runTest(0); |
| +} |
| + |
| +var passCount = 0, failCount = 0, errorCount = 0; |
| + |
| +outputResult(start, label, result, [message = '']) { |
| + var idx = label.lastIndexOf('###'); |
| + var group = '', test = ''; |
| + if (idx >= 0) { |
| + group = '\${label.substring(0, idx).replaceAll("###", " ")} '; |
| + test = '\${label.substring(idx+3)} '; |
| + } else { |
| + test = '\$label '; |
| + } |
| + var elapsed = ''; |
| + if (${config.includeTime}) { |
| + var end = new Date.now(); |
| + double duration = (end - start).inMilliseconds.toDouble(); |
| + duration /= 1000; |
| + elapsed = '\${duration.toStringAsFixed(3)}s '; |
| + } |
| + tprint(formatMessage('$sourceName ', group, test, elapsed, result, message)); |
| +} |
| + |
| +pass(start, label) { |
| + ++passCount; |
| + outputResult(start, label, 'pass'); |
| +} |
| + |
| +fail(start, label, message) { |
| + ++failCount; |
| + outputResult(start, label, 'fail', message); |
| +} |
| + |
| +error(start, label, message) { |
| + ++errorCount; |
| + outputResult(start, label, 'error', message); |
| +} |
| + |
| +complete() { |
| + printSummary('$sourceName', passCount, failCount, errorCount); |
| + exit(failCount > -0 ? -1 : 0); |
| +} |
| + |
| +"""); |
| + |
| + sbuf.add(nonBrowserTestPrintFunction); |
| + sbuf.add(formatMessageFunction(config.passFormat, |
| + config.failFormat, |
| + config.errorFormat)); |
| + |
| + sbuf.add(config.produceSummary ? |
| + printSummaryFunction : stubPrintSummaryFunction); |
| + |
| + if (config.layoutText) { |
| + sbuf.add(""" |
| +runTest(testNum) { |
| + var url = 'file://$htmlFile?test=\$testNum'; |
| + var stdout = new List(); |
| + Date start = new Date.now(); |
| + var process = Process.start('${config.drtPath}', [ url ]); |
| + StringInputStream stdoutStringStream = new StringInputStream(process.stdout); |
| + stdoutStringStream.onLine = () { |
| + if (stdoutStringStream.closed) return; |
| + var line = stdoutStringStream.readLine(); |
| + while (null != line) { |
| + stdout.add(line); |
| + line = stdoutStringStream.readLine(); |
| + } |
| + }; |
| + process.onExit = (exitCode) { |
| + process.close(); |
| + if (stdout.length > 0 && stdout[stdout.length-1].startsWith('#EOF')) { |
| + stdout.removeLast(); |
| + } |
| + var done = false; |
| + var i = 0; |
| + var label = null; |
| + var labelMarker = 'CONSOLE MESSAGE: #TEST '; |
| + var contentMarker = 'layer at '; |
| + while (i < stdout.length) { |
| + if (label == null && stdout[i].startsWith(labelMarker)) { |
| + label = stdout[i].substring(labelMarker.length); |
| + if (label == 'NONEXISTENT') { |
| + complete(); |
| + } |
| + } else if (stdout[i].startsWith(contentMarker)) { |
| + if (label == null) { |
| + complete(); |
| + } |
| + var expectedFileName = |
| + '$expectedDirectory${Platform.pathSeparator}' |
| + '\${label.replaceAll("###", "_") |
| + .replaceAll(const RegExp("[^A-Za-z0-9]"),"_")}.txt'; |
| + var expected = new File(expectedFileName); |
| + if (${config.regenerate}) { |
| + var ostream = expected.openOutputStream(FileMode.WRITE); |
| + while (i < stdout.length) { |
| + ostream.writeString(stdout[i]); |
| + ostream.writeString('\\n'); |
| + i++; |
| + } |
| + ostream.close(); |
| + pass(start, label); |
| + } else { |
| + if (!expected.existsSync()) { |
| + fail(start, label, 'No expectation file'); |
| + } else { |
| + var lines = expected.readAsLinesSync(); |
| + if (lines.length != stdout.length - i) { |
| + fail(start, label, 'Expectation file has wrong length'); |
| + } else { |
| + var match = true; |
| + for (var j = 0; j < lines.length; j++) { |
| + if (lines[j] != stdout[i+j]) { |
| + fail(start, label, 'Expectation differs at line \${j+1}'); |
| + match = false; |
| + break; |
| + } |
| + } |
| + if (match) pass(start, label); |
| + } |
| + } |
| + } |
| + done = true; |
| + break; |
| + } |
| + i++; |
| + } |
| + if (label != null) { |
| + if (!done) error(start, label, 'Failed to parse output'); |
| + runTest(testNum+1); |
| + } |
| + }; |
| +} |
| +"""); |
| + } else { |
| + sbuf.add(""" |
| +runTest(testNum) { |
| + var url = 'file://$htmlFile?test=\$testNum'; |
| + var stdout = new List(); |
| + Date start = new Date.now(); |
| + var process = Process.start('${config.drtPath}', [ "\$url'-p" ]); |
| + ListInputStream stdoutStream = process.stdout; |
| + stdoutStream.onData = () { |
| + if (!stdoutStream.closed) { |
| + var data = stdoutStream.read(); |
| + stdout.addAll(data); |
| + } |
| + }; |
| + stdoutStream.onError = (e) { |
| + print(e); |
| + }; |
| + process.onExit = (exitCode) { |
| + stdout.addAll(process.stdout.read()); |
| + process.close(); |
| + var labelMarker = 'CONSOLE MESSAGE: #TEST '; |
| + var contentMarker = 'Content-Length: '; |
| + var eol = '\\n'.charCodeAt(0); |
| + var pos = -1; |
| + var label = null; |
| + var done = false; |
| + |
| + while(pos < stdout.length) { |
| + var idx = stdout.indexOf(eol, ++pos); |
| + if (idx < 0) break; |
| + StringBuffer sb = new StringBuffer(); |
| + for (var i = pos; i < idx; i++) { |
| + sb.addCharCode(stdout[i]); |
| + } |
| + var line = sb.toString(); |
| + |
| + if (label == null && line.startsWith(labelMarker)) { |
| + label = line.substring(labelMarker.length); |
| + if (label == 'NONEXISTENT') { |
| + complete(); |
| + } |
| + } else if (line.startsWith(contentMarker)) { |
| + if (label == null) { |
| + complete(); |
| + } |
| + var len = parseInt(line.substring(contentMarker.length)); |
| + pos = idx+1; |
| + var expectedFileName = |
| + '$expectedDirectory${Platform.pathSeparator}' |
| + '\${label.replaceAll("###","_"). |
| + replaceAll(const RegExp("[^A-Za-z0-9]"),"_")}.png'; |
| + var expected = new File(expectedFileName); |
| + if (${config.regenerate}) { |
| + var ostream = expected.openOutputStream(FileMode.WRITE); |
| + ostream.writeFrom(stdout, pos, len); |
| + ostream.close(); |
| + pass(start, label); |
| + } else { |
| + if (!expected.existsSync()) { |
| + fail(start, label, 'No expectation file'); |
| + } else { |
| + var bytes = expected.readAsBytesSync(); |
| + if (bytes.length != len) { |
| + fail(start, label, 'Expectation file has wrong length'); |
| + } else { |
| + var match = true; |
| + for (var j = 0; j < len; j++) { |
| + if (bytes[j] != stdout[pos+j]) { |
| + fail(start, label, 'Expectation differs at byte \${j+1}'); |
| + match = false; |
| + break; |
| + } |
| + } |
| + if (match) pass(start, label); |
| + } |
| + } |
| + } |
| + done = true; |
| + break; |
| + } |
| + pos = idx; |
| + } |
| + if (label != null) { |
| + if (!done) error(start, label, 'Failed to parse output'); |
| + runTest(testNum+1); |
| + } |
| + }; |
| +} |
| +"""); |
| + } |
| + createFile(destName, sbuf.toString()); |
| + } |
| + |
| String directives(String library, String unittest, String sourceName) { |
| return """ |
| #library('$library'); |
| @@ -258,7 +543,7 @@ |
| // A function to print the test summary. |
| final String printSummaryFunction = """ |
| void printSummary(String testFile, int passed, int failed, int errors, |
| - String uncaughtError) { |
| + [String uncaughtError = '']) { |
| tprint(''); |
| if (passed == 0 && failed == 0 && errors == 0) { |
| tprint('\$testFile: No tests found.'); |
| @@ -275,7 +560,7 @@ |
| final String stubPrintSummaryFunction = """ |
| void printSummary(String testFile, int passed, int failed, int errors, |
| - String uncaughtError) { |
| + [String uncaughtError = '']) { |
| } |
| """; |