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

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

Issue 59093003: Remove unmaintained utils/testrunner (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month 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/http_server_runner.dart ('k') | utils/testrunner/layout_test_runner.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 // The following set of variables should be set by the caller that
6 // #sources this file.
7 /** Whether to include elapsed time. */
8
9 part of test_controller;
10
11 bool includeTime;
12
13 /** Path to DRT executable. */
14 String drt;
15
16 /** Whether to regenerate layout test files. */
17 bool regenerate;
18
19 /** Whether to output test summary. */
20 bool summarize;
21
22 /** Whether to print results immediately as they come in. */
23 bool immediate;
24
25 /** Format strings to use for test result messages. */
26 String passFormat, failFormat, errorFormat, listFormat;
27
28 /** Location of the running test file. */
29 String sourceDir;
30
31 /** Path of the running test file. */
32 String testfile;
33
34 /** URL of the child test file. */
35 String baseUrl;
36
37 /** The print function to use. */
38 Function tprint;
39
40 /** A callback function to notify the caller we are done. */
41 Function notifyDone;
42
43 // Variable below here are local to this file.
44 var passCount = 0, failCount = 0, errorCount = 0;
45 DateTime start;
46
47 class Macros {
48 static const String testTime = '<TIME>';
49 static const String testfile = '<FILENAME>';
50 static const String testGroup = '<GROUPNAME>';
51 static const String testDescription = '<TESTNAME>';
52 static const String testMessage = '<MESSAGE>';
53 static const String testStacktrace = '<STACK>';
54 }
55
56 String formatMessage(filename, groupname,
57 [testname = '', testTime = '', result = '',
58 message = '', stack = '']) {
59 var format = errorFormat;
60 if (result == 'pass') format = passFormat;
61 else if (result == 'fail') format = failFormat;
62 return format.
63 replaceAll(Macros.testTime, testTime).
64 replaceAll(Macros.testfile, filename).
65 replaceAll(Macros.testGroup, groupname).
66 replaceAll(Macros.testDescription, testname).
67 replaceAll(Macros.testMessage, message).
68 replaceAll(Macros.testStacktrace, stack);
69 }
70
71 void outputResult(start, label, result, [message = '']) {
72 var idx = label.lastIndexOf('###');
73 var group = '', test = '';
74 if (idx >= 0) {
75 group = '${label.substring(0, idx).replaceAll("###", " ")} ';
76 test = '${label.substring(idx+3)} ';
77 } else {
78 test = '$label ';
79 }
80 var elapsed = '';
81 if (includeTime) {
82 var end = new DateTime.now();
83 double duration = (end.difference(start)).inMilliseconds.toDouble();
84 duration /= 1000;
85 elapsed = '${duration.toStringAsFixed(3)}s ';
86 }
87 tprint(formatMessage('$testfile ', group, test, elapsed, result, message));
88 }
89
90 pass(start, label) {
91 ++passCount;
92 outputResult(start, label, 'pass');
93 }
94
95 fail(start, label, message) {
96 ++failCount;
97 outputResult(start, label, 'fail', message);
98 }
99
100 error(start, label, message) {
101 ++errorCount;
102 outputResult(start, label, 'error', message);
103 }
104
105 void printSummary(String testFile, int passed, int failed, int errors,
106 [String uncaughtError = '']) {
107 tprint('');
108 if (passed == 0 && failed == 0 && errors == 0) {
109 tprint('$testFile: No tests found.');
110 } else if (failed == 0 && errors == 0 && uncaughtError == null) {
111 tprint('$testFile: All $passed tests passed.');
112 } else {
113 if (uncaughtError != null) {
114 tprint('$testFile: Top-level uncaught error: $uncaughtError');
115 }
116 tprint('$testFile: $passed PASSED, $failed FAILED, $errors ERRORS');
117 }
118 }
119
120 complete() {
121 if (summarize) {
122 printSummary(testfile, passCount, failCount, errorCount);
123 }
124 notifyDone(failCount > 0 ? -1 : 0);
125 }
126
127 /*
128 * Run an external process [cmd] with command line arguments [args].
129 * [timeout] can be used to forcefully terminate the process after
130 * some number of seconds. This is used by runCommand and startProcess.
131 * If [procId] is non-zero (i.e. called from startProcess) then a reference
132 * to the [Process] will be put in a map with key [procId]; in this case
133 * the process can be terminated later by calling [stopProcess] and
134 * passing in the [procId].
135 * [outputMonitor] is an optional function that will be called back with each
136 * line of output from the process.
137 * Returns a [Future] for when the process terminates.
138 */
139 Future _processHelper(String command, List<String> args,
140 List stdout, List stderr,
141 int timeout, int procId, Function outputMonitor, bool raw) {
142 var timer = null;
143 return Process.start(command, args).then((process) {
144
145 timer = new Timer(new Duration(seconds: timeout), () {
146 timer = null;
147 process.kill();
148 });
149
150 if (raw) {
151 process.stdout.listen((c) { stdout.addAll(c); });
152 } else {
153 _pipeStream(process.stdout, stdout, outputMonitor);
154 }
155 _pipeStream(process.stderr, stderr, outputMonitor);
156 return process.exitCode;
157 }).then((exitCode) {
158 if (timer != null) {
159 timer.cancel();
160 }
161 return exitCode;
162 })
163 .catchError((e) {
164 stderr.add("#Error starting process $command: ${e.error}");
165 });
166 }
167
168 void _pipeStream(Stream stream, List<String> destination,
169 Function outputMonitor) {
170 stream
171 .transform(UTF8.decoder)
172 .transform(new LineTransformer())
173 .listen((String line) {
174 if (outputMonitor != null) {
175 outputMonitor(line);
176 }
177 destination.add(line);
178 });
179 }
180
181 /**
182 * Run an external process [cmd] with command line arguments [args].
183 * [timeout] can be used to forcefully terminate the process after
184 * some number of seconds.
185 * Returns a [Future] for when the process terminates.
186 */
187 Future runCommand(String command, List<String> args,
188 List stdout, List stderr,
189 {int timeout: 300, Function outputMonitor,
190 bool raw: false}) {
191 return _processHelper(command, args, stdout, stderr,
192 timeout, 0, outputMonitor, raw);
193 }
194
195 String parseLabel(String line) {
196 if (line.startsWith('CONSOLE MESSAGE')) {
197 var idx = line.indexOf('#TEST ');
198 if (idx > 0) {
199 return line.substring(idx + 6);
200 }
201 }
202 return null;
203 }
204
205 runTextLayoutTest(testNum) {
206 var url = '$baseUrl?test=$testNum';
207 var stdout = new List();
208 var stderr = new List();
209 start = new DateTime.now();
210 runCommand(drt, [url], stdout, stderr).then((e) {
211 if (stdout.length > 0 && stdout[stdout.length-1].startsWith('#EOF')) {
212 stdout.removeLast();
213 }
214 var done = false;
215 var i = 0;
216 var label = null;
217 var contentMarker = 'layer at ';
218 while (i < stdout.length) {
219 if (label == null && (label = parseLabel(stdout[i])) != null) {
220 if (label == 'NONEXISTENT') {
221 complete();
222 return;
223 }
224 } else if (stdout[i].startsWith(contentMarker)) {
225 if (label == null) {
226 complete();
227 return;
228 }
229 var expectedFileName =
230 '$sourceDir${Platform.pathSeparator}'
231 '${label.replaceAll("###", "_")
232 .replaceAll(new RegExp("[^A-Za-z0-9]"),"_")}.txt';
233 var expected = new File(expectedFileName);
234 if (regenerate) {
235 var osink = expected.openWrite();
236 while (i < stdout.length) {
237 osink.write(stdout[i]);
238 osink.write('\n');
239 i++;
240 }
241 osink.close();
242 pass(start, label);
243 } else if (!expected.existsSync()) {
244 fail(start, label, 'No expectation file');
245 } else {
246 var lines = expected.readAsLinesSync();
247 var actualLength = stdout.length - i;
248 var compareCount = min(lines.length, actualLength);
249 var match = true;
250 for (var j = 0; j < compareCount; j++) {
251 if (lines[j] != stdout[i + j]) {
252 fail(start, label, 'Expectation differs at line ${j + 1}');
253 match = false;
254 break;
255 }
256 }
257 if (match) {
258 if (lines.length != actualLength) {
259 fail(start, label, 'Expectation file has wrong length');
260 } else {
261 pass(start, label);
262 }
263 }
264 }
265 done = true;
266 break;
267 }
268 i++;
269 }
270 if (label != null) {
271 if (!done) error(start, label, 'Failed to parse output');
272 runTextLayoutTest(testNum + 1);
273 }
274 });
275 }
276
277 runPixelLayoutTest(int testNum) {
278 var url = '$baseUrl?test=$testNum';
279 var stdout = new List();
280 var stderr = new List();
281 start = new DateTime.now();
282 runCommand(drt, ["$url'-p"], stdout, stderr, raw:true).then((exitCode) {
283 var contentMarker = 'Content-Length: ';
284 var eol = '\n'.codeUnitAt(0);
285 var pos = 0;
286 var label = null;
287 var done = false;
288
289 while(pos < stdout.length) {
290 StringBuffer sb = new StringBuffer();
291 while (pos < stdout.length && stdout[pos] != eol) {
292 sb.writeCharCode(stdout[pos++]);
293 }
294 if (++pos >= stdout.length && line == '') break;
295 var line = sb.toString();
296
297 if (label == null && (label = parseLabel(line)) != null) {
298 if (label == 'NONEXISTENT') {
299 complete();
300 }
301 } else if (line.startsWith(contentMarker)) {
302 if (label == null) {
303 complete();
304 }
305 var len = int.parse(line.substring(contentMarker.length));
306 var expectedFileName =
307 '$sourceDir${Platform.pathSeparator}'
308 '${label.replaceAll("###","_").
309 replaceAll(new RegExp("[^A-Za-z0-9]"),"_")}.png';
310 var expected = new File(expectedFileName);
311 if (regenerate) {
312 var osink = expected.openWrite();
313 stdout.removeRange(0, pos);
314 stdout.length = len;
315 osink.add(stdout);
316 osink.close();
317 pass(start, label);
318 } else if (!expected.existsSync()) {
319 fail(start, label, 'No expectation file');
320 } else {
321 var bytes = expected.readAsBytesSync();
322 if (bytes.length != len) {
323 fail(start, label, 'Expectation file has wrong length');
324 } else {
325 var match = true;
326 for (var j = 0; j < len; j++) {
327 if (bytes[j] != stdout[pos + j]) {
328 fail(start, label, 'Expectation differs at byte ${j + 1}');
329 match = false;
330 break;
331 }
332 }
333 if (match) pass(start, label);
334 }
335 }
336 done = true;
337 break;
338 }
339 }
340 if (label != null) {
341 if (!done) error(start, label, 'Failed to parse output');
342 runPixelLayoutTest(testNum + 1);
343 }
344 });
345 }
346
347 void init() {
348 // Get the name of the directory that has the expectation files
349 // (by stripping .dart suffix from test file path).
350 // Create it if it does not exist.
351 sourceDir = testfile.substring(0, testfile.length - 5);
352 if (regenerate) {
353 var d = new Directory(sourceDir);
354 if (!d.existsSync()) {
355 d.createSync();
356 }
357 }
358 }
359
360 void runPixelLayoutTests() {
361 init();
362 runPixelLayoutTest(0);
363 }
364
365 void runTextLayoutTests() {
366 init();
367 runTextLayoutTest(0);
368 }
OLDNEW
« no previous file with comments | « utils/testrunner/http_server_runner.dart ('k') | utils/testrunner/layout_test_runner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698