OLD | NEW |
---|---|
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 var testLabelLinePrefix = ' text run'; | |
Siggi Cherem (dart-lang)
2012/09/05 17:45:41
since these are constant: mark these two as `stati
gram
2012/09/06 18:25:25
Done.
| |
15 var bodyLinePrefix = ' '; | |
Siggi Cherem (dart-lang)
2012/09/05 17:45:41
I'm not sure I understand this parsing and why is
gram
2012/09/06 18:25:25
I added a comment that hopefully explains this.
| |
16 | |
17 void execute(Path testfile, List stdout, List stderr, bool logging, | |
18 Function exitHandler) { | |
19 | |
20 var testname = expandMacros(_testFileTemplate, testfile); | |
21 var isLayout = isLayoutRenderTest(testname) || config.generateRenders; | |
22 | |
23 if (!isLayout) { | |
24 super.execute(testfile, stdout, stderr, logging, exitHandler); | |
25 } else { | |
26 var tmpLog = new List<String>(); | |
27 super.execute(testfile, tmpLog, tmpLog, true, | |
28 (code) { | |
29 var layoutFile = layoutFileName(testname); | |
30 var layouts = getFileContents(layoutFile, false); | |
31 var i = 0; | |
32 StringBuffer sbuf = null; | |
33 if (config.generateRenders) { | |
34 sbuf = new StringBuffer(); | |
35 } | |
36 while ( i < tmpLog.length) { | |
37 var line = tmpLog[i]; | |
38 if (logging) { | |
39 stdout.add(line); | |
40 } | |
41 if (line.startsWith(testLabelLinePrefix)) { | |
42 var j = i+1; | |
43 var start = -1, end = -1; | |
44 // Walk forward to the next label or end of log. | |
45 while (j < tmpLog.length && | |
46 !tmpLog[j].startsWith(testLabelLinePrefix)) { | |
47 // Is this a body render line? | |
48 if (tmpLog[j].startsWith(bodyLinePrefix)) { | |
49 if (start < 0) { // Is it the first? | |
50 start = j; | |
51 } | |
52 } else { // Not a render line. | |
53 if (start >= 0 && end < 0) { | |
54 // We were just in a set of render lines, so this | |
55 // line is the first non-member. | |
56 end = j; | |
57 } | |
58 } | |
59 j++; | |
60 } | |
61 if (start >= 0) { // We have some render lines. | |
62 if (end < 0) { | |
63 end = tmpLog.length; // Sanity. | |
64 } | |
65 var actualLayout = new List<String>(); | |
66 while (start < end) { | |
67 actualLayout.add( | |
68 tmpLog[start++].substring(bodyLinePrefix.length)); | |
69 } | |
70 var testName = checkTest(testfile, line, layouts, | |
71 actualLayout, stdout); | |
72 if (testName == null) { | |
73 code = -1; | |
74 } else if (config.generateRenders) { | |
75 sbuf.add(testName); | |
76 sbuf.add('\n'); | |
77 for (var renderLine in actualLayout) { | |
78 sbuf.add(renderLine); | |
79 sbuf.add('\n'); | |
80 } | |
81 } | |
82 } | |
83 i = j; | |
84 } else { | |
85 i++; | |
86 } | |
87 } | |
88 if (config.generateRenders) { | |
89 createFile(layoutFile, sbuf.toString()); | |
90 } | |
91 exitHandler(code); | |
92 }); | |
93 } | |
94 } | |
95 | |
96 /** | |
97 * Verify whether a test passed - it must pass the code expectations, | |
98 * and have validated layout. Report success or failure in a test | |
99 * result message. Upon success the render section name is returned | |
100 * (useful for `config.generateRenders`); otherwise null is returned. | |
101 */ | |
102 String checkTest(Path testfile, String label, List layouts, | |
103 List actual, List out) { | |
104 var testGroup = null; | |
105 var testName = null; | |
106 | |
107 // The label line has the form: | |
108 // "result:duration:<test>//message" | |
109 // where <test> is a test name or series of one or more group names | |
110 // followed by a test name, separated by ###. | |
111 | |
112 // First extract test state, duration, name and message. If the test | |
113 // passed we can ignore these and continue to layout verification, but | |
114 // if the test failed we want to know that so we can report failure. | |
115 // | |
116 // TODO(gram) - currently we lose the stack trace although the user | |
117 // will get it in the overall output if they used --verbose. We may | |
118 // want to fix this properly at some point. | |
119 | |
120 // Trim leading text up to opening quote. | |
121 var idx = label.indexOf('"'); | |
Siggi Cherem (dart-lang)
2012/09/05 17:45:41
please use regex here.
gram
2012/09/06 18:25:25
Done.
| |
122 label = label.substring(idx+1); | |
123 | |
124 // Extract the result. | |
125 idx = label.indexOf(':'); | |
126 var result = label.substring(0, idx); | |
127 | |
128 // Extract the duration. | |
129 ++idx; | |
130 var idx2 = label.indexOf(':', idx); | |
131 var duration = parseDouble(label.substring(idx, idx2)) / 1000; | |
132 | |
133 // Extract the test groups and name, and the message. | |
134 idx = idx2+1; | |
135 idx2 = label.indexOf('//', idx); | |
136 var test = label.substring(idx, idx2); | |
137 var message = label.substring(idx2+2, label.length-1); | |
138 | |
139 // Split name up with group. | |
140 idx = test.lastIndexOf('###'); | |
141 if (idx >= 0) { | |
142 testGroup = test.substring(0, idx).replaceAll('###', ' '); | |
143 testName = test.substring(idx+3); | |
144 } else { | |
145 testGroup = ''; | |
146 testName = test; | |
147 } | |
148 var section = '[${_pad(testGroup)}$testName]'; | |
149 | |
150 if (config.generateRenders) { | |
151 // Do nothing; fake a pass. | |
152 out.add(_formatMessage(config.passFormat, | |
153 testfile, testGroup, testName, duration, '')); | |
154 } else if (result != 'pass') { | |
155 // The test failed separately from layout; just report that | |
156 // failure. | |
157 out.add(_formatMessage( | |
158 (result == 'fail' ? config.failFormat : config.errorFormat), | |
159 testfile, testGroup, testName, duration, message)); | |
160 return null; | |
161 } else { | |
162 // The test passed, at least the expectations. So check the layout. | |
163 var expected = _getLayout(layouts, section); | |
164 var failMessage = null; | |
165 var lineNum = 0; | |
166 if (expected != null) { | |
167 while (lineNum < expected.length) { | |
168 if (lineNum >= actual.length) { | |
169 failMessage = 'expected "${expected[lineNum]}" but got nothing'; | |
170 break; | |
171 } else { | |
172 if (expected[lineNum] != actual[lineNum]) { | |
173 failMessage = 'expected "${expected[lineNum]}" ' | |
174 'but got "${actual[lineNum]}"'; | |
175 break; | |
176 } | |
177 } | |
178 lineNum++; | |
179 } | |
180 if (failMessage == null && lineNum < actual.length) { | |
181 failMessage = 'expected nothing but got "${actual[lineNum]}"'; | |
182 } | |
183 } | |
184 if (failMessage != null) { | |
185 out.add(_formatMessage(config.failFormat, | |
186 testfile, testGroup, testName, duration, | |
187 'Layout content mismatch at line $lineNum: ' | |
188 '$failMessage')); | |
189 return null; | |
190 } else { | |
191 out.add(_formatMessage(config.passFormat, | |
192 testfile, testGroup, testName, duration, '')); | |
193 } | |
194 } | |
195 return section; | |
196 } | |
197 | |
198 /** Get the expected layout for a test. */ | |
199 List _getLayout(List layouts, String section) { | |
200 List layout = new List(); | |
201 for (var i = 0; i < layouts.length; i++) { | |
202 if (layouts[i] == section) { | |
203 ++i; | |
204 while (i < layouts.length && !layouts[i].startsWith('[')) { | |
205 layout.add(layouts[i++]); | |
206 } | |
207 break; | |
208 } | |
209 } | |
210 return layout; | |
211 } | |
212 | |
213 /** Pad a string with a rightmost space unless it is empty. */ | |
214 String _pad(s) => (s.length > 0) ? '$s ' : s; | |
Siggi Cherem (dart-lang)
2012/09/05 17:45:41
+static
gram
2012/09/06 18:25:25
Done.
| |
215 | |
216 /** Format a test result message. */ | |
217 String _formatMessage(String format, | |
218 Path testfile, String testGroup, String testName, | |
219 double duration, String message) { | |
220 String fname = makePathAbsolute(testfile.directoryPath.toString()); | |
221 return "###${format. | |
222 replaceAll(Macros.testTime, '${duration.toStringAsFixed(3)}s '). | |
223 replaceAll(Macros.testfile, _pad(fname)). | |
224 replaceAll(Macros.testGroup, _pad(testGroup)). | |
225 replaceAll(Macros.testDescription, _pad(testName)). | |
226 replaceAll(Macros.testMessage, _pad(message))}"; | |
227 } | |
11 } | 228 } |
OLD | NEW |