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

Unified Diff: utils/testrunner/dart_wrap_task.dart

Issue 10909240: Support for pixel layout tests. (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 side-by-side diff with in-line comments
Download patch
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 = '']) {
}
""";

Powered by Google App Engine
This is Rietveld 408576698