forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtestharnessreport.js
269 lines (243 loc) · 10.8 KB
/
testharnessreport.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/*
* THIS FILE INTENTIONALLY LEFT BLANK
*
* More specifically, this file is intended for vendors to implement
* code needed to integrate testharness.js tests with their own test systems.
*
* Typically such integration will attach callbacks when each test is
* has run, using add_result_callback(callback(test)), or when the whole test file has
* completed, using add_completion_callback(callback(tests, harness_status)).
*
* For more documentation about the callback functions and the
* parameters they are called with see testharness.js
*/
(function() {
var output_document = document;
// Setup for WebKit JavaScript tests
if (self.testRunner) {
testRunner.dumpAsText();
testRunner.waitUntilDone();
testRunner.setCanOpenWindows();
testRunner.setCloseRemainingWindowsWhenComplete(true);
testRunner.setDumpJavaScriptDialogs(false);
}
// Disable the default output of testharness.js. The default output formats
// test results into an HTML table. When that table is dumped as text, no
// spacing between cells is preserved, and it is therefore not readable. By
// setting output to false, the HTML table will not be created.
// Also, disable timeout (except for explicit timeout), since the Blink
// layout test runner has its own timeout mechanism.
// See: https://github.com/w3c/testharness.js/blob/master/docs/api.md#setup
setup({
"output": false,
"explicit_timeout": true
});
// Function used to convert the test status code into the corresponding
// string
function convertResult(resultStatus) {
switch (resultStatus) {
case 0:
return "PASS";
case 1:
return "FAIL";
case 2:
return "TIMEOUT";
default:
return "NOTRUN";
}
}
var localPathRegExp;
if (document.URL.startsWith("file:///")) {
var index = document.URL.indexOf("/external/wpt");
if (index >= 0) {
var localPath = document.URL.substring("file:///".length, index + "/external/wpt".length);
localPathRegExp = new RegExp(localPath.replace(/(\W)/g, "\\$1"), "g");
}
}
// Sanitizes the given text for display in test results.
function sanitize(text) {
if (!text) {
return "";
}
// Escape null characters, otherwise diff will think the file is binary.
text = text.replace(/\0/g, "\\0");
// Escape carriage returns as they break rietveld's difftools.
text = text.replace(/\r/g, "\\r");
// Replace machine-dependent path with "...".
if (localPathRegExp)
text = text.replace(localPathRegExp, "...");
return text;
}
function isWPTManualTest() {
var path = location.pathname;
if (location.hostname == 'web-platform.test' && path.endsWith('-manual.html'))
return true;
return /\/external\/wpt\/.*-manual\.html$/.test(path);
}
// Returns a directory part relative to WPT root and a basename part of the
// current test. e.g.
// Current test: file:///.../LayoutTests/external/wpt/pointerevents/foobar.html
// Output: "/pointerevents/foobar"
function pathAndBaseNameInWPT() {
var path = location.pathname;
if (location.hostname == 'web-platform.test') {
var matches = path.match(/^(\/.*)\.html$/);
return matches ? matches[1] : null;
}
var matches = path.match(/external\/wpt(\/.*)\.html$/);
return matches ? matches[1] : null;
}
function loadAutomationScript() {
var pathAndBase = pathAndBaseNameInWPT();
if (!pathAndBase)
return;
var automationPath = location.pathname.replace(/\/external\/wpt\/.*$/, '/external/wpt_automation');
if (location.hostname == 'web-platform.test')
automationPath = '/wpt_automation';
// Export importAutomationScript for use by the automation scripts.
window.importAutomationScript = function(relativePath) {
var script = document.createElement('script');
script.src = automationPath + relativePath;
document.head.appendChild(script);
}
var src;
if (pathAndBase.startsWith('/fullscreen/')) {
// Fullscreen tests all use the same automation script.
src = automationPath + '/fullscreen/auto-click.js';
} else if (pathAndBase.startsWith('/pointerevents/')
|| pathAndBase.startsWith('/uievents/')) {
// Per-test automation scripts.
src = automationPath + pathAndBase + '-automation.js';
} else {
return;
}
var script = document.createElement('script');
script.src = src;
document.head.appendChild(script);
}
var didDispatchLoadEvent = false;
window.addEventListener('load', function() {
didDispatchLoadEvent = true;
if (isWPTManualTest()) {
setTimeout(loadAutomationScript, 0);
}
}, { once: true });
add_start_callback(function(properties) {
if (properties.output_document)
output_document = properties.output_document;
});
// Using a callback function, test results will be added to the page in a
// manner that allows dumpAsText to produce readable test results.
add_completion_callback(function (tests, harness_status) {
// Create element to hold results.
var results = output_document.createElement("pre");
// Declare result string.
var resultStr = "This is a testharness.js-based test.\n";
// Check harness_status. If it is not 0, tests did not execute
// correctly, output the error code and message.
if (harness_status.status != 0) {
resultStr += "Harness Error. harness_status.status = " +
harness_status.status +
" , harness_status.message = " +
harness_status.message +
"\n";
}
// reflection tests contain huge number of tests, and Chromium code
// review tool has the 1MB diff size limit. We merge PASS lines.
if (output_document.URL.indexOf("/html/dom/reflection") >= 0) {
for (var i = 0; i < tests.length; ++i) {
if (tests[i].status == 0) {
var colon = tests[i].name.indexOf(':');
if (colon > 0) {
var prefix = tests[i].name.substring(0, colon + 1);
var j = i + 1;
for (; j < tests.length; ++j) {
if (!tests[j].name.startsWith(prefix) || tests[j].status != 0)
break;
}
if ((j - i) > 1) {
resultStr += convertResult(tests[i].status) +
" " + sanitize(prefix) + " " + (j - i) + " tests\n"
i = j - 1;
continue;
}
}
}
resultStr += convertResult(tests[i].status) + " " +
sanitize(tests[i].name) + " " +
sanitize(tests[i].message) + "\n";
}
} else {
// Iterate through tests array and build string that contains
// results for all tests.
let testResults = "";
let resultCounter = [0, 0, 0, 0];
for (var i = 0; i < tests.length; ++i) {
resultCounter[tests[i].status]++;
testResults += convertResult(tests[i].status) + " " +
sanitize(tests[i].name) + " " +
sanitize(tests[i].message) + "\n";
}
if (output_document.URL.indexOf("http://web-platform.test") >= 0 &&
tests.length >= 50 && (resultCounter[1] || resultCounter[2] || resultCounter[3])) {
// Output failure metrics if there are many.
resultStr += `Found ${tests.length} tests;` +
` ${resultCounter[0]} PASS,` +
` ${resultCounter[1]} FAIL,` +
` ${resultCounter[2]} TIMEOUT,` +
` ${resultCounter[3]} NOTRUN.\n`;
}
resultStr += testResults;
}
resultStr += "Harness: the test ran to completion.\n";
// Set results element's textContent to the results string.
results.textContent = resultStr;
function done() {
let xhtmlNS = 'http://www.w3.org/1999/xhtml';
var body = null;
if (output_document.body && output_document.body.tagName == 'BODY' && output_document.body.namespaceURI == xhtmlNS)
body = output_document.body;
// A temporary workaround since |window.self| property lookup starts
// failing if the frame is detached. |output_document| may be an
// ancestor of |self| so clearing |textContent| may detach |self|.
// To get around this, cache window.self now and use the cached
// value.
// TODO(dcheng): Remove this hack after fixing window/self/frames
// lookup in https://crbug.com/618672
var cachedSelf = window.self;
if (cachedSelf.testRunner) {
// The following DOM operations may show console messages. We
// suppress them because they are not related to the running
// test.
testRunner.setDumpConsoleMessages(false);
// Anything isn't material to the testrunner output, so should
// be hidden from the text dump.
if (body)
body.textContent = '';
}
// Add results element to output_document.
if (!body) {
// output_document might be an SVG document.
if (output_document.documentElement)
output_document.documentElement.remove();
let html = output_document.createElementNS(xhtmlNS, 'html');
output_document.appendChild(html);
body = output_document.createElementNS(xhtmlNS, 'body');
body.setAttribute('style', 'white-space:pre;');
html.appendChild(body);
}
output_document.body.appendChild(results);
if (cachedSelf.testRunner)
testRunner.notifyDone();
}
if (didDispatchLoadEvent || output_document.readyState != 'loading') {
// This function might not be the last 'completion callback', and
// another completion callback might generate more results. So, we
// don't dump the results immediately.
setTimeout(done, 0);
} else {
// Parsing the test HTML isn't finished yet.
window.addEventListener('load', done);
}
});
})();