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

Side by Side Diff: utils/testrunner/layout_test_controller.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 unified diff | Download patch | Annotate | Revision Log
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 // The following set of variables should be set by the caller that
6 // #sources this file.
7 /** Whether to include elapsed time. */
8 bool includeTime;
9
10 /** Path to DRT executable. */
11 String drt;
12
13 /** Whether to regenerate layout test files. */
14 bool regenerate;
15
16 /** Whether to output test summary. */
17 bool summarize;
18
19 /** Format strings to use for test result messages. */
20 String passFormat, failFormat, errorFormat, listFormat;
21
22 /** Location of the running test file. */
23 String sourceDir;
24
25 /** Path of the running test file. */
26 String testfile;
27
28 /** URL of the child test file. */
29 String baseUrl;
30
31 // Variable below here are local to this file.
32 var passCount = 0, failCount = 0, errorCount = 0;
33 Date start;
34
35 void tprint(msg) {
36 print('###$msg');
37 }
38
39 class Macros {
40 static const String testTime = '<TIME>';
41 static const String testfile = '<FILENAME>';
42 static const String testGroup = '<GROUPNAME>';
43 static const String testDescription = '<TESTNAME>';
44 static const String testMessage = '<MESSAGE>';
45 static const String testStacktrace = '<STACK>';
46 }
47
48 String formatMessage(filename, groupname,
49 [testname = '', testTime = '', result = '',
50 message = '', stack = '']) {
51 var format = errorFormat;
52 if (result == 'pass') format = passFormat;
53 else if (result == 'fail') format = failFormat;
54 return format.
55 replaceAll(Macros.testTime, testTime).
56 replaceAll(Macros.testfile, filename).
57 replaceAll(Macros.testGroup, groupname).
58 replaceAll(Macros.testDescription, testname).
59 replaceAll(Macros.testMessage, message).
60 replaceAll(Macros.testStacktrace, stack);
61 }
62
63 void outputResult(start, label, result, [message = '']) {
64 var idx = label.lastIndexOf('###');
65 var group = '', test = '';
66 if (idx >= 0) {
67 group = '${label.substring(0, idx).replaceAll("###", " ")} ';
68 test = '${label.substring(idx+3)} ';
69 } else {
70 test = '$label ';
71 }
72 var elapsed = '';
73 if (includeTime) {
74 var end = new Date.now();
75 double duration = (end.difference(start)).inMilliseconds.toDouble();
76 duration /= 1000;
77 elapsed = '${duration.toStringAsFixed(3)}s ';
78 }
79 tprint(formatMessage('$testfile ', group, test, elapsed, result, message));
80 }
81
82 pass(start, label) {
83 ++passCount;
84 outputResult(start, label, 'pass');
85 }
86
87 fail(start, label, message) {
88 ++failCount;
89 outputResult(start, label, 'fail', message);
90 }
91
92 error(start, label, message) {
93 ++errorCount;
94 outputResult(start, label, 'error', message);
95 }
96
97 void printSummary(String testFile, int passed, int failed, int errors,
98 [String uncaughtError = '']) {
99 tprint('');
100 if (passed == 0 && failed == 0 && errors == 0) {
101 tprint('$testFile: No tests found.');
102 } else if (failed == 0 && errors == 0 && uncaughtError == null) {
103 tprint('$testFile: All $passed tests passed.');
104 } else {
105 if (uncaughtError != null) {
106 tprint('$testFile: Top-level uncaught error: $uncaughtError');
107 }
108 tprint('$testFile: $passed PASSED, $failed FAILED, $errors ERRORS');
109 }
110 }
111
112 complete() {
113 if (summarize) {
114 printSummary(testfile, passCount, failCount, errorCount);
115 }
116 exit(failCount > 0 ? -1 : 0);
117 }
118
119 runTextLayoutTest(testNum) {
120 var url = '$baseUrl?test=$testNum';
121 var stdout = new List();
122 start = new Date.now();
123 var process = Process.start(drt, [url]);
124 StringInputStream stdoutStringStream = new StringInputStream(process.stdout);
125 stdoutStringStream.onLine = () {
126 if (stdoutStringStream.closed) return;
127 var line = stdoutStringStream.readLine();
128 while (null != line) {
129 stdout.add(line);
130 line = stdoutStringStream.readLine();
131 }
132 };
133 process.onExit = (exitCode) {
134 process.close();
135 if (stdout.length > 0 && stdout[stdout.length-1].startsWith('#EOF')) {
136 stdout.removeLast();
137 }
138 var done = false;
139 var i = 0;
140 var label = null;
141 var labelMarker = 'CONSOLE MESSAGE: #TEST ';
142 var contentMarker = 'layer at ';
143 while (i < stdout.length) {
144 if (label == null && stdout[i].startsWith(labelMarker)) {
145 label = stdout[i].substring(labelMarker.length);
146 if (label == 'NONEXISTENT') {
147 complete();
148 }
149 } else if (stdout[i].startsWith(contentMarker)) {
150 if (label == null) {
151 complete();
152 }
153 var expectedFileName =
154 '$sourceDir${Platform.pathSeparator}'
155 '${label.replaceAll("###", "_")
156 .replaceAll(const RegExp("[^A-Za-z0-9]"),"_")}.txt';
157 var expected = new File(expectedFileName);
158 if (regenerate) {
159 var ostream = expected.openOutputStream(FileMode.WRITE);
160 while (i < stdout.length) {
161 ostream.writeString(stdout[i]);
162 ostream.writeString('\n');
163 i++;
164 }
165 ostream.close();
166 pass(start, label);
167 } else if (!expected.existsSync()) {
168 fail(start, label, 'No expectation file');
169 } else {
170 var lines = expected.readAsLinesSync();
171 var actualLength = stdout.length - i;
172 var compareCount = min(lines.length, actualLength);
173 var match = true;
174 for (var j = 0; j < compareCount; j++) {
175 if (lines[j] != stdout[i+j]) {
Siggi Cherem (dart-lang) 2012/09/20 19:56:27 nit: spaces around + (here and next line)
gram 2012/09/20 20:08:17 Done.
176 fail(start, label, 'Expectation differs at line ${j+1}');
177 match = false;
178 break;
179 }
180 }
181 if (match) {
182 if (lines.length != actualLength) {
183 fail(start, label, 'Expectation file has wrong length');
184 } else {
185 pass(start, label);
186 }
187 }
188 }
189 done = true;
190 break;
191 }
192 i++;
193 }
194 if (label != null) {
195 if (!done) error(start, label, 'Failed to parse output');
196 runTextLayoutTest(testNum + 1);
197 }
198 };
199 }
200
201 runPixelLayoutTest(int testNum) {
202 var url = '$baseUrl?test=$testNum';
203 var stdout = new List();
204 start = new Date.now();
205 var process = Process.start(drt, ["$url'-p"]);
206 ListInputStream stdoutStream = process.stdout;
207 stdoutStream.onData = () {
208 if (!stdoutStream.closed) {
209 var data = stdoutStream.read();
210 stdout.addAll(data);
211 }
212 };
213 stdoutStream.onError = (e) {
214 print(e);
215 };
216 process.onExit = (exitCode) {
217 stdout.addAll(process.stdout.read());
218 process.close();
219 var labelMarker = 'CONSOLE MESSAGE: #TEST ';
220 var contentMarker = 'Content-Length: ';
221 var eol = '\n'.charCodeAt(0);
222 var pos = -1;
223 var label = null;
224 var done = false;
225
226 while(pos < stdout.length) {
227 var idx = stdout.indexOf(eol, ++pos);
228 if (idx < 0) break;
229 StringBuffer sb = new StringBuffer();
230 for (var i = pos; i < idx; i++) {
231 sb.addCharCode(stdout[i]);
232 }
233 var line = sb.toString();
234
235 if (label == null && line.startsWith(labelMarker)) {
236 label = line.substring(labelMarker.length);
237 if (label == 'NONEXISTENT') {
238 complete();
239 }
240 } else if (line.startsWith(contentMarker)) {
241 if (label == null) {
242 complete();
243 }
244 var len = int.parse(line.substring(contentMarker.length));
245 pos = idx + 1;
246 var expectedFileName =
247 '$sourceDir${Platform.pathSeparator}'
248 '${label.replaceAll("###","_").
249 replaceAll(const RegExp("[^A-Za-z0-9]"),"_")}.png';
250 var expected = new File(expectedFileName);
251 if (regenerate) {
252 var ostream = expected.openOutputStream(FileMode.WRITE);
253 ostream.writeFrom(stdout, pos, len);
254 ostream.close();
255 pass(start, label);
256 } else if (!expected.existsSync()) {
257 fail(start, label, 'No expectation file');
258 } else {
259 var bytes = expected.readAsBytesSync();
260 if (bytes.length != len) {
261 fail(start, label, 'Expectation file has wrong length');
262 } else {
263 var match = true;
264 for (var j = 0; j < len; j++) {
Siggi Cherem (dart-lang) 2012/09/20 19:56:27 seems like this loop and the one in the other onEx
gram 2012/09/20 20:08:17 We're comparing items at different offsets, so a p
265 if (bytes[j] != stdout[pos+j]) {
Siggi Cherem (dart-lang) 2012/09/20 19:56:27 ditto and next line
gram 2012/09/20 20:08:17 Done.
266 fail(start, label, 'Expectation differs at byte ${j+1}');
267 match = false;
268 break;
269 }
270 }
271 if (match) pass(start, label);
272 }
273 }
274 done = true;
275 break;
276 }
277 pos = idx;
278 }
279 if (label != null) {
280 if (!done) error(start, label, 'Failed to parse output');
281 runPixelLayoutTest(testNum + 1);
282 }
283 };
284 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698