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