Skip to content

Commit 1ff6967

Browse files
committed
Write non-OK harness statuses to a log file
1 parent eba88da commit 1ff6967

File tree

1 file changed

+33
-200
lines changed

1 file changed

+33
-200
lines changed

interop-scoring/main.js

+33-200
Original file line numberDiff line numberDiff line change
@@ -33,182 +33,8 @@ flags.parse();
3333

3434
const ROOT_DIR = path.join(__dirname, '..');
3535

36-
// All non-OK harness statuses. Any non-OK harness status should be investigated
37-
// before being added to this list, so that we don't score tests in the wrong
38-
// way because of a test or infrastructure issue.
39-
const KNOWN_TEST_STATUSES = new Set([
40-
// ERROR due to duplicate subtest name, fixed in https://github.com/web-platform-tests/wpt/pull/38387
41-
'/css/css-color/parsing/color-invalid-color-function.html',
42-
// TIMEOUT in Safari due to https://webkit.org/b/212201
43-
'/css/css-grid/grid-definition/grid-limits-001.html',
44-
// TIMEOUT in Firefox and Safari, all subtests present
45-
'/css/css-scroll-snap/input/keyboard.html',
46-
// ERROR in Firefox, TIMEOUT in Safari, all subtests failing in Chrome
47-
'/css/css-scroll-snap/input/snap-area-overflow-boundary.html',
48-
// TIMEOUT in Chrome with TIMEOUT subtests
49-
'/dom/events/Event-dispatch-click.html',
50-
// ERROR in Safari but linked bug is fixed
51-
'/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-requestsubmit-during-load.html',
52-
'/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-requestsubmit-during-pageshow.html',
53-
// TIMEOUT in Safari, but just a single subtest
54-
'/html/semantics/forms/form-submission-0/form-double-submit-multiple-targets.html',
55-
// TIMEOUT in Firefox and Safari, but just a single subtest
56-
'/html/semantics/forms/form-submission-0/form-double-submit-to-different-origin-frame.html',
57-
// TIMEOUT in Safari but all passing subtests due to https://bugs.webkit.org/show_bug.cgi?id=235407
58-
'/html/semantics/forms/form-submission-target/rel-base-target.html',
59-
'/html/semantics/forms/form-submission-target/rel-button-target.html',
60-
'/html/semantics/forms/form-submission-target/rel-form-target.html',
61-
'/html/semantics/forms/form-submission-target/rel-input-target.html',
62-
// ERROR in Firefox 95 and Safari 15.2, since fixed
63-
'/html/semantics/interactive-elements/the-dialog-element/dialog-showModal.html',
64-
// ERROR in Chrome 96, since fixed
65-
'/html/semantics/interactive-elements/the-dialog-element/modal-dialog-ancestor-is-inert.html',
66-
// TIMEOUT in Safari, but all subtests present
67-
'/html/semantics/forms/textfieldselection/select-event.html',
68-
'/html/semantics/forms/textfieldselection/selection-start-end.html',
69-
'/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html',
70-
'/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html',
71-
// TIMEOUT in Firefox 98, since fixed
72-
'/html/semantics/forms/the-input-element/image-click-form-data.html',
73-
// TIMEOUT in Safari, but all subtests present
74-
'/html/semantics/forms/the-input-element/range-restore-oninput-onchange-event.html',
75-
// TIMEOUT in STP 137, since fixed
76-
'/html/semantics/interactive-elements/the-dialog-element/backdrop-receives-element-events.html',
77-
// TIMEOUT for one run in Safari but has since run successfully.
78-
'/css/css-scroll-snap/snap-at-user-scroll-end.html',
79-
80-
81-
/**
82-
* The tests below have non-OK statuses that have not been investigated as of today.
83-
*/
84-
// interop-2023-contain
85-
'/css/css-contain/container-queries/nested-query-containers.html',
86-
'/css/css-contain/content-visibility/content-visibility-input-image.html',
87-
'/css/css-contain/content-visibility/content-visibility-031.html',
88-
'/css/css-contain/content-visibility/content-visibility-auto-state-changed.html',
89-
'/css/selectors/invalidation/fullscreen-pseudo-class-in-has.html',
90-
'/css/selectors/invalidation/modal-pseudo-class-in-has.html',
91-
'/css/selectors/invalidation/user-action-pseudo-classes-in-has.html',
92-
// interop-2023-modules
93-
'/html/semantics/scripting-1/the-script-element/import-assertions/empty-assertion-clause.html',
94-
'/html/semantics/scripting-1/the-script-element/import-assertions/unsupported-assertion.html',
95-
'/workers/modules/dedicated-worker-import-blob-url.any.html',
96-
'/workers/modules/dedicated-worker-import-blob-url.any.worker.html',
97-
'/workers/modules/dedicated-worker-import-data-url-cross-origin.html',
98-
'/workers/modules/dedicated-worker-import-data-url.any.html',
99-
'/workers/modules/dedicated-worker-import-data-url.any.worker.html',
100-
'/workers/modules/dedicated-worker-import-meta.html',
101-
'/workers/modules/dedicated-worker-import.any.html',
102-
'/workers/modules/dedicated-worker-import.any.worker.html',
103-
'/workers/modules/dedicated-worker-options-credentials.html',
104-
'/workers/modules/dedicated-worker-parse-error-failure.html',
105-
'/workers/modules/shared-worker-import-data-url-cross-origin.html',
106-
'/workers/modules/shared-worker-import-data-url.window.html',
107-
'/workers/modules/shared-worker-options-credentials.html',
108-
'/workers/modules/shared-worker-parse-error-failure.html',
109-
'/import-maps/acquiring/modulepreload-link-header.html',
110-
'/import-maps/acquiring/modulepreload.html',
111-
'/workers/modules/shared-worker-import-failure.html',
112-
'/import-maps/acquiring/dynamic-import.html',
113-
'/import-maps/acquiring/script-tag-inline.html',
114-
'/import-maps/acquiring/script-tag.html',
115-
'/import-maps/bare-specifiers.sub.html',
116-
// interop-2023-offscreencanvas
117-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeat.outside.html',
118-
'/html/canvas/offscreen/manual/filter/offscreencanvas.filter.w.html',
119-
'/html/canvas/offscreen/manual/convert-to-blob/offscreencanvas.convert.to.blob.w.html',
120-
'/html/canvas/offscreen/manual/draw-generic-family/2d.text.draw.generic.family.w.html',
121-
'/html/canvas/offscreen/manual/filter/offscreencanvas.filter.w.html',
122-
'/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit.w.html',
123-
'/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transfer.to.imagebitmap.w.html',
124-
'/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.transferrable.w.html',
125-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeat.basic.html',
126-
'/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.animated.poster.html',
127-
'/html/canvas/offscreen/compositing/2d.composite.globalAlpha.imagepattern.html',
128-
'/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.copy.html',
129-
'/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-atop.html',
130-
'/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.destination-in.html',
131-
'/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-in.html',
132-
'/html/canvas/offscreen/compositing/2d.composite.uncovered.pattern.source-out.html',
133-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.basic.image.html',
134-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.crosscanvas.html',
135-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.norepeat.basic.html',
136-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord1.html',
137-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord2.html',
138-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord3.html',
139-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.norepeat.outside.html',
140-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeat.coord3.html',
141-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeatx.coord1.html',
142-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeatx.outside.html',
143-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeaty.basic.html',
144-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeaty.coord1.html',
145-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeaty.outside.html',
146-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.repeat.empty.html',
147-
'/html/canvas/offscreen/shadows/2d.shadow.pattern.basic.html',
148-
'/html/canvas/offscreen/shadows/2d.shadow.pattern.transparent.2.html',
149-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeat.coord2.html',
150-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeatx.basic.html',
151-
'/html/canvas/offscreen/shadows/2d.shadow.pattern.alpha.html',
152-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.orientation.image.html',
153-
'/html/canvas/offscreen/fill-and-stroke-styles/2d.pattern.paint.repeat.coord1.html',
154-
'/html/canvas/offscreen/shadows/2d.shadow.pattern.transparent.1.html',
155-
// interop-2023-events
156-
'/uievents/mouse/cancel-mousedown-in-subframe.html',
157-
'/pointerevents/pointerevent_attributes_hoverable_pointers.html?mouse',
158-
'/pointerevents/pointerevent_attributes_nohover_pointers.html',
159-
'/pointerevents/pointerevent_disabled_form_control.html?mouse',
160-
'/html/user-activation/activation-trigger-pointerevent.html?mouse',
161-
'/pointerevents/pointerevent_movementxy.html?mouse',
162-
'/pointerevents/pointerevent_pointercapture_in_frame.html?mouse',
163-
'/uievents/mouse/attributes.html',
164-
// interop-2022-scrolling
165-
'/css/css-scroll-snap/snap-at-user-scroll-end.html',
166-
// interop-2023-webcodecs
167-
'/webcodecs/videoDecoder-codec-specific.https.any.html?av1',
168-
'/webcodecs/videoDecoder-codec-specific.https.any.html?h264_annexb',
169-
'/webcodecs/videoDecoder-codec-specific.https.any.html?h264_avc',
170-
'/webcodecs/videoDecoder-codec-specific.https.any.html?vp8',
171-
'/webcodecs/videoDecoder-codec-specific.https.any.html?vp9',
172-
'/webcodecs/videoDecoder-codec-specific.https.any.worker.html?av1',
173-
'/webcodecs/videoDecoder-codec-specific.https.any.worker.html?h264_annexb',
174-
'/webcodecs/videoDecoder-codec-specific.https.any.worker.html?h264_avc',
175-
'/webcodecs/videoDecoder-codec-specific.https.any.worker.html?vp8',
176-
'/webcodecs/videoDecoder-codec-specific.https.any.worker.html?vp9',
177-
'/webcodecs/videoDecoder-codec-specific.https.any.worker.html?av1',
178-
'/webcodecs/videoFrame-construction.any.html',
179-
'/webcodecs/videoFrame-construction.crossOriginSource.sub.html',
180-
'/webcodecs/videoFrame-construction.window.html',
181-
'/webcodecs/videoFrame-serialization.crossAgentCluster.https.html',
182-
'/webcodecs/videoFrame-serialization.crossAgentCluster.https.html',
183-
'/webcodecs/temporal-svc-encoding.https.any.html?h264',
184-
'/webcodecs/temporal-svc-encoding.https.any.html?vp8',
185-
'/webcodecs/temporal-svc-encoding.https.any.html?vp9',
186-
'/webcodecs/temporal-svc-encoding.https.any.worker.html?h264',
187-
'/webcodecs/temporal-svc-encoding.https.any.worker.html?vp8',
188-
'/webcodecs/temporal-svc-encoding.https.any.worker.html?vp9',
189-
'/webcodecs/videoFrame-serialization.crossAgentCluster.https.html',
190-
'/webcodecs/videoFrame-serialization.crossAgentCluster.https.html',
191-
'/webcodecs/videoFrame-serialization.crossAgentCluster.https.html',
192-
'/webcodecs/full-cycle-test.https.any.html?av1',
193-
'/webcodecs/full-cycle-test.https.any.html?h264_annexb',
194-
'/webcodecs/full-cycle-test.https.any.html?h264_avc',
195-
'/webcodecs/full-cycle-test.https.any.html?vp9_p0',
196-
'/webcodecs/full-cycle-test.https.any.html?vp9_p2',
197-
'/webcodecs/full-cycle-test.https.any.worker.html?av1',
198-
'/webcodecs/full-cycle-test.https.any.worker.html?h264_annexb',
199-
'/webcodecs/full-cycle-test.https.any.worker.html?h264_avc',
200-
'/webcodecs/full-cycle-test.https.any.worker.html?vp9_p0',
201-
'/webcodecs/full-cycle-test.https.any.worker.html?vp9_p2',
202-
'/webcodecs/full-cycle-test.https.any.html?vp8',
203-
'/webcodecs/full-cycle-test.https.any.worker.html?vp8',
204-
// interop-2023-webcomponents
205-
'/shadow-dom/focus/focus-shadowhost-display-none.html',
206-
'/custom-elements/form-associated/ElementInternals-labels.html',
207-
'/custom-elements/form-associated/ElementInternals-setFormValue.html',
208-
'/custom-elements/form-associated/ElementInternals-validation.html',
209-
'/custom-elements/form-associated/form-disabled-callback.html',
210-
]);
211-
36+
const RESULTS_TREE = Symbol('run results tree');
37+
const COLLECT_NON_OK_TESTS = Symbol('flag for whether to collect non-OK tests for this run');
21238

21339
// Calculate interop score (passing in all browsers) for a category
21440
// after tracking the category's scores for each browser.
@@ -277,16 +103,15 @@ function aggregateInteropTestScores(testPassCounts, numBrowsers) {
277103
//
278104
// 4. Because we round down twice, the score for a category can end up lower
279105
// than if we used rational numbers.
280-
function scoreRuns(runs, allTestsSet) {
106+
function scoreRuns(runs, allTestsSet, nonOKTests) {
281107
const scores = [];
282108
const testPassCounts = new Map();
283-
const unexpectedNonOKTests = new Set();
284109

285110
try {
286111
for (const run of runs) {
287112
// Sum of the integer 0-1000 scores for each test.
288113
let score = 0;
289-
lib.results.walkTests(run.tree, (path, test, results) => {
114+
lib.results.walkTests(run[RESULTS_TREE], (path, test, results) => {
290115
const testname = path + '/' + test;
291116
if (!allTestsSet.has(testname)) {
292117
return;
@@ -305,8 +130,8 @@ function scoreRuns(runs, allTestsSet) {
305130
testPassCounts.get(testname)['subtestTotal'] = [];
306131
}
307132
if ('subtests' in results) {
308-
if (results['status'] != 'OK' && !KNOWN_TEST_STATUSES.has(testname)) {
309-
unexpectedNonOKTests.add(testname);
133+
if (results['status'] != 'OK' && run[COLLECT_NON_OK_TESTS]) {
134+
nonOKTests.add(testname);
310135
}
311136
subtestTotal = results['subtests'].length;
312137
for (const subtest of results['subtests']) {
@@ -354,27 +179,19 @@ function scoreRuns(runs, allTestsSet) {
354179
throw e;
355180
}
356181

357-
// Log and tests with unexpected non-OK statuses.
358-
if (unexpectedNonOKTests.size > 0) {
359-
console.log('Unexpected non-OK status for tests:');
360-
for (const testname of unexpectedNonOKTests.values()) {
361-
console.log(testname);
362-
}
363-
}
364182
// Calculate the interop scores that have been saved and add
365183
// the interop score to the end of the browsers' scores array.
366184
scores.push(aggregateInteropTestScores(testPassCounts, runs.length));
367185
return scores;
368186
}
369187

370-
async function scoreCategory(category, experimental, products, alignedRuns,
371-
testsSet) {
188+
async function scoreAlignedRuns(alignedRuns, testsSet, nonOKTests) {
372189
// Score the test runs.
373190
const before = Date.now();
374191
const dateToScores = new Map();
375192
for (const [date, runs] of alignedRuns.entries()) {
376193
const versions = runs.map(run => run.browser_version);
377-
const scores = scoreRuns(runs, testsSet);
194+
const scores = scoreRuns(runs, testsSet, nonOKTests);
378195
dateToScores.set(date, {versions, scores});
379196
}
380197
const after = Date.now();
@@ -432,22 +249,27 @@ async function main() {
432249
// Load the test result trees into memory; creates a list of recursive tree
433250
// structures: tree = { trees: [...], tests: [...] }. Each 'tree' represents a
434251
// directory, each 'test' is the results from a given test file.
252+
//
253+
// Also set the LAST symbol to true on the last set of aligned runs, to allow
254+
// logging non-OK harness statuses for only those.
435255
console.log('Iterating over all runs, loading test results');
436256
before = Date.now();
257+
let lastRuns = null;
437258
for (const runs of alignedRuns.values()) {
438259
for (const run of runs) {
439-
// Just in case someone ever adds a 'tree' field to the JSON.
440-
if (run.tree) {
441-
throw new Error('Run JSON contains "tree" field; code needs changed.');
442-
}
443-
run.tree = await lib.results.getGitTree(repo, run);
260+
run[RESULTS_TREE] = await lib.results.getGitTree(repo, run);
444261
}
262+
lastRuns = runs;
445263
}
446264
after = Date.now();
447265
console.log(`Loading ${alignedRuns.size} sets of runs took ` +
448266
`${after - before} ms`);
267+
for (const run of lastRuns) {
268+
run[COLLECT_NON_OK_TESTS] = true;
269+
}
449270

450271
const dateToScoresMaps = new Map();
272+
const nonOKTests = new Set();
451273

452274
// Map from labels to tests (includes)
453275
const labeledTests = new Map();
@@ -464,7 +286,12 @@ async function main() {
464286
}
465287
}
466288
}
467-
// category is an object with "name" and "labels" props.
289+
290+
// Score each category and add scores to |dateToScores|. For runs that have
291+
// COLLECT_NON_OK_TESTS set (the last ones) any non-OK harness statuses are
292+
// added to |nonOKTests|.
293+
//
294+
// Note: category is an object with "name" and "labels" props.
468295
for (const category of categories) {
469296
console.log(`Scoring runs for ${category.name}`);
470297
const testsSet = new Set();
@@ -477,14 +304,20 @@ async function main() {
477304
// Keep a unique set of tests associated with the category.
478305
labeledTestsSet.forEach(test => testsSet.add(test));
479306
}
480-
const dateToScores = await scoreCategory(category, experimental, products,
481-
alignedRuns, testsSet);
307+
const dateToScores = await scoreAlignedRuns(alignedRuns, testsSet, nonOKTests);
482308
// Store the entire dateToScores for producing the unified CSV later.
483309
dateToScoresMaps.set(category.name, dateToScores);
484310
}
485311

312+
// Write non-OK harness statuses to a file.
313+
if (nonOKTests.size) {
314+
const lines = Array.from(nonOKTests).sort();
315+
lines.push('');
316+
await fs.promises.writeFile('non-ok-harness-statuses.txt', lines.join('\n'), 'utf-8');
317+
}
318+
486319
// TODO: Once the other score CSVs are no longer used, we can push
487-
// some of this logic into scoreCategory and simplify things.
320+
// some of this logic into scoreAlignedRuns and simplify things.
488321
let unifiedCsv = 'date';
489322
for (const product of products) {
490323
const categoryLabels = categories.map(c => `${product}-${c.name}`);

0 commit comments

Comments
 (0)