Commit 6e40df0d authored by Nicolás Peña Moreno's avatar Nicolás Peña Moreno Committed by Commit Bot

[EventTiming] Attempt to fix some flaky tests

This CL attempts to fix test flakiness.
* For the click counts, remove tests about mouseout/mouseover since
those could fail under certain starting positions of the mouse, and
the test has a pretty high flakiness score right now.
* For other tests, fix flakiness by making sure that PerformanceObserver
callbacks where mousedown is not present are ignored. This is possible
since a click triggers mousedown, mouseup, click, etc., so we cannot
just assume that mousedown will always be present at the callback.

Bug: 1074048
Change-Id: I95a082948c105cf18b51376c9d6421195b23b718
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2163775Reviewed-by: default avatarYoav Weiss <yoavweiss@chromium.org>
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#763352}
parent c41f13cf
...@@ -51,13 +51,18 @@ ...@@ -51,13 +51,18 @@
promise_test(async t => { promise_test(async t => {
assert_implements(window.PerformanceEventTiming, "Event Timing is not supported"); assert_implements(window.PerformanceEventTiming, "Event Timing is not supported");
clickTimeMin = performance.now(); clickTimeMin = performance.now();
let observedEntries = false; let observedMouseDown = false;
const observerPromise = new Promise(resolve => { const observerPromise = new Promise(resolve => {
new PerformanceObserver(t.step_func(entries => { new PerformanceObserver(t.step_func(entries => {
assert_false(observedEntries, const mouseDowns = entries.getEntriesByName('mousedown');
// Ignore the callback if there were no mousedown entries.
if (mouseDowns.length === 0)
return;
assert_false(observedMouseDown,
"Observer of main frames should only capture main-frame event-timing entries"); "Observer of main frames should only capture main-frame event-timing entries");
validateEntries(entries.getEntriesByName('mousedown')); validateEntries(mouseDowns);
observedEntries = true; observedMouseDown = true;
resolve(); resolve();
})).observe({type: 'event'}); })).observe({type: 'event'});
}); });
......
...@@ -22,10 +22,6 @@ ...@@ -22,10 +22,6 @@
assert_equals(clickCount, expectedCount,'Incorrect click count.'); assert_equals(clickCount, expectedCount,'Incorrect click count.');
assert_equals(performance.eventCounts.get('mousedown'), expectedCount, 'Incorrect mousedown count'); assert_equals(performance.eventCounts.get('mousedown'), expectedCount, 'Incorrect mousedown count');
assert_equals(performance.eventCounts.get('mouseup'), expectedCount, 'Incorrect mouseup count.'); assert_equals(performance.eventCounts.get('mouseup'), expectedCount, 'Incorrect mouseup count.');
assert_equals(performance.eventCounts.get('mouseover'), expectedCount, 'Incorrect mouseover count.');
if (expectedCount != 1) {
assert_equals(performance.eventCounts.get('mouseout'), expectedCount - 1, 'Incorrect mouseout count.');
}
resolve(); resolve();
} }
function promiseClicks(expectedCount) { function promiseClicks(expectedCount) {
......
...@@ -23,12 +23,16 @@ async_test(function(t) { ...@@ -23,12 +23,16 @@ async_test(function(t) {
}; };
} }
}); });
const observer = new PerformanceObserver(t.step_func_done((entryList) => { const observer = new PerformanceObserver(t.step_func((entryList) => {
const entries = entryList.getEntries().filter(e => e.name === 'mousedown'); const entries = entryList.getEntriesByName('mousedown');
// There must only be one click entry. if (entries.length === 0)
return;
// There must only be one mousedown entry.
assert_equals(entries.length, 1); assert_equals(entries.length, 1);
verifyClickEvent(entries[0], 'custom_button', true); verifyClickEvent(entries[0], 'custom_button', true);
assert_true(innerButtonClicked); assert_true(innerButtonClicked);
t.done()
})); }));
observer.observe({entryTypes: ['event']}); observer.observe({entryTypes: ['event']});
clickAndBlockMain('custom_button'); clickAndBlockMain('custom_button');
......
...@@ -17,25 +17,35 @@ ...@@ -17,25 +17,35 @@
while(performance.now() < end) {} while(performance.now() < end) {}
delayCalled = true; delayCalled = true;
} }
async_test(function(t) { promise_test(function(t) {
assert_implements(window.PerformanceEventTiming, 'Event Timing is not supported.'); assert_implements(window.PerformanceEventTiming, 'Event Timing is not supported.');
const observer = new PerformanceObserver(t.step_func_done((entryList) => { let observedMouseDown = false;
const entries = entryList.getEntries().filter(e => e.name === 'mousedown'); const observerPromise = new Promise(resolve => {
// There must only be one click entry: from the clickAndBlockMain() call. const observer = new PerformanceObserver(t.step_func(entryList => {
assert_equals(entries.length, 1); const mouseDowns = entryList.getEntriesByName('mousedown');
const entry = entries[0]; // Ignore cases in which there is no mousedown.
// This ensures that the entry is exposing timing from the second click, i.e. if (mouseDowns.length === 0)
// the one from the clickAndBlockMain() call. return;
assert_greater_than_equal(entry.processingStart, beforeClick);
verifyClickEvent(entry, 'div2', true); assert_false(observedMouseDown, 'There must only be one mousedown entry.');
})); assert_equals(mouseDowns.length, 1);
observer.observe({entryTypes: ['event']}); const entry = mouseDowns[0];
// This ensures that the entry is exposing timing from the second click, i.e.
// the one from the clickAndBlockMain() call.
assert_greater_than_equal(entry.processingStart, beforeClick);
verifyClickEvent(entry, 'div2', true);
observedMouseDown = true;
resolve();
}));
observer.observe({entryTypes: ['event']});
});
document.getElementById('div').click(); document.getElementById('div').click();
// Take the timestamp after the programmatic click but before the next click. // Take the timestamp after the programmatic click but before the next click.
beforeClick = performance.now(); beforeClick = performance.now();
// After the programmatic click, use another input to know when entries have been // After the programmatic click, use another input to know when entries have been
// dispatched to the PerformanceObserver callback. // dispatched to the PerformanceObserver callback.
clickAndBlockMain('div2'); const clickPromise = clickAndBlockMain('div2');
return Promise.all([observerPromise, clickPromise]);
}, "Event Timing: events from programmatic click are not observed"); }, "Event Timing: events from programmatic click are not observed");
</script> </script>
</html> </html>
...@@ -31,9 +31,11 @@ ...@@ -31,9 +31,11 @@
*/ */
async_test(function(t) { async_test(function(t) {
assert_implements(window.PerformanceEventTiming, 'Event Timing is not supported.'); assert_implements(window.PerformanceEventTiming, 'Event Timing is not supported.');
new PerformanceObserver(t.step_func_done(() => { new PerformanceObserver(t.step_func(entryList => {
validateEntries(); if (entryList.getEntriesByName('mousedown')) {
t.done(); validateEntries();
t.done();
}
})).observe({entryTypes: ['event']}); })).observe({entryTypes: ['event']});
clickAndBlockMain('button'); clickAndBlockMain('button');
}, "Event Timing: make sure event-timing entries are not retrievable by performance.getEntries*."); }, "Event Timing: make sure event-timing entries are not retrievable by performance.getEntries*.");
......
...@@ -32,28 +32,38 @@ ...@@ -32,28 +32,38 @@
target.focus(); target.focus();
} }
async_test(function(t) { promise_test(function(t) {
assert_implements(window.PerformanceEventTiming, 'Event Timing is not supported.'); assert_implements(window.PerformanceEventTiming, 'Event Timing is not supported.');
new PerformanceObserver(t.step_func_done(entryList => { let observedMouseDown = false;
const observerCallbackTime = performance.now(); const observerPromise = new Promise(resolve => {
const entries = entryList.getEntries().filter( new PerformanceObserver(t.step_func(entryList => {
entry => entry.name === 'mousedown'); const observerCallbackTime = performance.now();
assert_equals(entries.length, 1, const mouseDowns = entryList.getEntriesByName('mousedown');
"Should only observe one entry: " + // Ignore cases in which there is no mousedown.
JSON.stringify(entries) + "."); if (mouseDowns.length === 0)
assert_equals(entries[0].name, 'mousedown', return;
"The observed entry should be a click");
assert_less_than(entries[0].startTime, observerCallbackTime, assert_false(observedMouseDown, 'Got more than one callback with mousedown.');
"The startTime should be before observerCallbackTime"); assert_equals(mouseDowns.length, 1,
assert_greater_than(entries[0].startTime, trustedClickStart, "Should only observe one mousedown entry. Instead, got these: " +
"The startTime should be after trustedClickStart"); JSON.stringify(mouseDowns) + ".");
})).observe({ entryTypes: ['event'] }); assert_equals(mouseDowns[0].name, 'mousedown',
"The observed entry should be a mousedown");
assert_less_than(mouseDowns[0].startTime, observerCallbackTime,
"The startTime should be before observerCallbackTime");
assert_greater_than(mouseDowns[0].startTime, trustedClickStart,
"The startTime should be after trustedClickStart");
observedMouseDown = true;
resolve();
})).observe({ entryTypes: ['event'] });
});
// Untrusted event of a type event timing cares about. // Untrusted event of a type event timing cares about.
untrustedClickAndBlockMain('button'); untrustedClickAndBlockMain('button');
// Trusted event of a type event timing doesn't cares about. // Trusted event of a type event timing doesn't cares about.
trustedFocusAndBlockMain('button'); trustedFocusAndBlockMain('button');
// Trusted event of a type event timing cares about. // Trusted event of a type event timing cares about.
trustedClickAndBlockMain('button').then(wait); const clickPromise = trustedClickAndBlockMain('button').then(wait);
return Promise.all([observerPromise, clickPromise]);
}, "Event Timing only times certain types of trusted event."); }, "Event Timing only times certain types of trusted event.");
</script> </script>
</html> </html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment