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

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

Issue 10914049: Added support for layout render tests. These use expected values for the text render output from Du… (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
« no previous file with comments | « utils/testrunner/dart_wrap_task.dart ('k') | utils/testrunner/html_wrap_task.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** A pipeline task for running DumpRenderTree. */ 5 /** A pipeline task for running DumpRenderTree. */
6 class DrtTask extends RunProcessTask { 6 class DrtTask extends RunProcessTask {
7 7
8 DrtTask(String htmlFileTemplate) { 8 String _testFileTemplate;
9
10 DrtTask(this._testFileTemplate, String htmlFileTemplate) {
9 init(config.drtPath, ['--no-timeout', htmlFileTemplate], config.timeout); 11 init(config.drtPath, ['--no-timeout', htmlFileTemplate], config.timeout);
10 } 12 }
13
14 // In order to extract the relevant parts of the DRT render text
15 // output we use a somewhat kludgy approach, but it should be robust.
16 // DRT formats output with indentation, and we know that the test title
17 // is on a line with 12 spaces indent followed by 'text run', while the
18 // IFrame body elements are all indented at least 18 spaces.
19 const TEST_LABEL_LINE_PREFIX = ' text run';
20 const BODY_LINE_PREFIX = ' ';
21
22 void execute(Path testfile, List stdout, List stderr, bool logging,
23 Function exitHandler) {
24
25 var testname = expandMacros(_testFileTemplate, testfile);
26 var isLayout = isLayoutRenderTest(testname) || config.generateRenders;
27
28 if (!isLayout) {
29 super.execute(testfile, stdout, stderr, logging, exitHandler);
30 } else {
31 var tmpLog = new List<String>();
32 super.execute(testfile, tmpLog, tmpLog, true,
33 (code) {
34 var layoutFile = layoutFileName(testname);
35 var layouts = getFileContents(layoutFile, false);
36 var i = 0;
37 StringBuffer sbuf = null;
38 if (config.generateRenders) {
39 sbuf = new StringBuffer();
40 }
41 while ( i < tmpLog.length) {
42 var line = tmpLog[i];
43 if (logging) {
44 stdout.add(line);
45 }
46 if (line.startsWith(TEST_LABEL_LINE_PREFIX)) {
47 var j = i+1;
48 var start = -1, end = -1;
49 // Walk forward to the next label or end of log.
50 while (j < tmpLog.length &&
51 !tmpLog[j].startsWith(TEST_LABEL_LINE_PREFIX)) {
52 // Is this a body render line?
53 if (tmpLog[j].startsWith(BODY_LINE_PREFIX)) {
54 if (start < 0) { // Is it the first?
55 start = j;
56 }
57 } else { // Not a render line.
58 if (start >= 0 && end < 0) {
59 // We were just in a set of render lines, so this
60 // line is the first non-member.
61 end = j;
62 }
63 }
64 j++;
65 }
66 if (start >= 0) { // We have some render lines.
67 if (end < 0) {
68 end = tmpLog.length; // Sanity.
69 }
70 var actualLayout = new List<String>();
71 while (start < end) {
72 actualLayout.add(
73 tmpLog[start++].substring(BODY_LINE_PREFIX.length));
74 }
75 var testName = checkTest(testfile, line, layouts,
76 actualLayout, stdout);
77 if (testName == null) {
78 code = -1;
79 } else if (config.generateRenders) {
80 sbuf.add(testName);
81 sbuf.add('\n');
82 for (var renderLine in actualLayout) {
83 sbuf.add(renderLine);
84 sbuf.add('\n');
85 }
86 }
87 }
88 i = j;
89 } else {
90 i++;
91 }
92 }
93 if (config.generateRenders) {
94 createFile(layoutFile, sbuf.toString());
95 }
96 exitHandler(code);
97 });
98 }
99 }
100
101 /**
102 * Verify whether a test passed - it must pass the code expectations,
103 * and have validated layout. Report success or failure in a test
104 * result message. Upon success the render section name is returned
105 * (useful for `config.generateRenders`); otherwise null is returned.
106 */
107 String checkTest(Path testfile, String label, List layouts,
108 List actual, List out) {
109 var testGroup = null;
110 var testName = null;
111
112 // The label line has the form:
113 // "result:duration:<test>//message"
114 // where <test> is a test name or series of one or more group names
115 // followed by a test name, separated by ###.
116
117 // First extract test state, duration, name and message. If the test
118 // passed we can ignore these and continue to layout verification, but
119 // if the test failed we want to know that so we can report failure.
120 //
121 // TODO(gram) - currently we lose the stack trace although the user
122 // will get it in the overall output if they used --verbose. We may
123 // want to fix this properly at some point.
124 var labelParser = const RegExp('\"\([a-z]*\):\([0-9]*\):\(.*\)//\(.*\)\"');
125 Match match = labelParser.firstMatch(label);
126 var result = match.group(1);
127 var duration = parseDouble(match.group(2)) / 1000;
128 var test = match.group(3);
129 var message = match.group(4);
130
131 // Split name up with group.
132 var idx = test.lastIndexOf('###');
133 if (idx >= 0) {
134 testGroup = test.substring(0, idx).replaceAll('###', ' ');
135 testName = test.substring(idx+3);
136 } else {
137 testGroup = '';
138 testName = test;
139 }
140 var section = '[${_pad(testGroup)}$testName]';
141
142 if (config.generateRenders) {
143 // Do nothing; fake a pass.
144 out.add(_formatMessage(config.passFormat,
145 testfile, testGroup, testName, duration, ''));
146 } else if (result != 'pass') {
147 // The test failed separately from layout; just report that
148 // failure.
149 out.add(_formatMessage(
150 (result == 'fail' ? config.failFormat : config.errorFormat),
151 testfile, testGroup, testName, duration, message));
152 return null;
153 } else {
154 // The test passed, at least the expectations. So check the layout.
155 var expected = _getLayout(layouts, section);
156 var failMessage = null;
157 var lineNum = 0;
158 if (expected != null) {
159 while (lineNum < expected.length) {
160 if (lineNum >= actual.length) {
161 failMessage = 'expected "${expected[lineNum]}" but got nothing';
162 break;
163 } else {
164 if (expected[lineNum] != actual[lineNum]) {
165 failMessage = 'expected "${expected[lineNum]}" '
166 'but got "${actual[lineNum]}"';
167 break;
168 }
169 }
170 lineNum++;
171 }
172 if (failMessage == null && lineNum < actual.length) {
173 failMessage = 'expected nothing but got "${actual[lineNum]}"';
174 }
175 }
176 if (failMessage != null) {
177 out.add(_formatMessage(config.failFormat,
178 testfile, testGroup, testName, duration,
179 'Layout content mismatch at line $lineNum: '
180 '$failMessage'));
181 return null;
182 } else {
183 out.add(_formatMessage(config.passFormat,
184 testfile, testGroup, testName, duration, ''));
185 }
186 }
187 return section;
188 }
189
190 /** Get the expected layout for a test. */
191 List _getLayout(List layouts, String section) {
192 List layout = new List();
193 for (var i = 0; i < layouts.length; i++) {
194 if (layouts[i] == section) {
195 ++i;
196 while (i < layouts.length && !layouts[i].startsWith('[')) {
197 layout.add(layouts[i++]);
198 }
199 break;
200 }
201 }
202 return layout;
203 }
204
205 /** Pad a string with a rightmost space unless it is empty. */
206 static String _pad(s) => (s.length > 0) ? '$s ' : s;
207
208 /** Format a test result message. */
209 String _formatMessage(String format,
210 Path testfile, String testGroup, String testName,
211 double duration, String message) {
212 String fname = makePathAbsolute(testfile.directoryPath.toString());
213 return "###${format.
214 replaceAll(Macros.testTime, '${duration.toStringAsFixed(3)}s ').
215 replaceAll(Macros.testfile, _pad(fname)).
216 replaceAll(Macros.testGroup, _pad(testGroup)).
217 replaceAll(Macros.testDescription, _pad(testName)).
218 replaceAll(Macros.testMessage, _pad(message))}";
219 }
11 } 220 }
OLDNEW
« no previous file with comments | « utils/testrunner/dart_wrap_task.dart ('k') | utils/testrunner/html_wrap_task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698