Commit 6a386512 authored by Olga Gerchikov's avatar Olga Gerchikov Committed by Commit Bot

Fixed flaky playback-rate test.

Root cause for the flakiness:
  1.Due to crbug.com/937382, composited worklet animation current time is not identical to the
    current time passed to the animator instance in the worklet scope (which is passed through to
    local time in this test).
  2.Not waiting enough for the compositing thread to update the styles.
The fix:
  1.Changed the test to compare against reference worklet animation's effect local time that has
    default playback rate.
  2.Explicitly wait for the style updates before comparing to the expected results.

Bug: 915352
Change-Id: I35cb3f89048568bc830aff8a6473f6d2aef5aaeb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1497789
Commit-Queue: Olga Gerchikov <gerchiko@microsoft.com>
Reviewed-by: default avatarMajid Valipour <majidvp@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638721}
parent 3a6d6ae5
...@@ -5987,8 +5987,7 @@ crbug.com/935064 external/wpt/content-security-policy/unsafe-hashes/javascript_s ...@@ -5987,8 +5987,7 @@ crbug.com/935064 external/wpt/content-security-policy/unsafe-hashes/javascript_s
crbug.com/936827 external/wpt/fullscreen/api/element-request-fullscreen-and-remove-manual.html [ Failure Pass ] crbug.com/936827 external/wpt/fullscreen/api/element-request-fullscreen-and-remove-manual.html [ Failure Pass ]
# Enable WPT animation-worklet test to run with threaded-compositing # Enable WPT animation-worklet test to run with threaded-compositing
crbug.com/915352 virtual/threaded/external/wpt/animation-worklet/playback-rate.https.html [ Pass Failure ] crbug.com/915352 virtual/threaded/external/wpt/animation-worklet/worklet-animation-pause-resume.https.html [ Pass Failure ]
crbug.com/915352 [ Linux ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-pause-resume.https.html [ Pass Failure ]
crbug.com/915352 [ Mac10.10 Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Pass Failure ] crbug.com/915352 [ Mac10.10 Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline.https.html [ Pass Failure ]
crbug.com/915352 [ Mac10.10 Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Pass Failure ] crbug.com/915352 [ Mac10.10 Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Pass Failure ]
......
...@@ -87,11 +87,11 @@ function setupAndRegisterTests() { ...@@ -87,11 +87,11 @@ function setupAndRegisterTests() {
animation.play(); animation.play();
waitForAnimationFrameWithCondition(_=> { await waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running" return animation.playState == "running"
}); });
// Make sure the current time is not Zero. // Make sure the current time is not Zero.
await waitForNextFrame(); await waitForDocumentTimelineAdvance();
// Set playback rate while the animation is playing. // Set playback rate while the animation is playing.
const prevCurrentTime = animation.currentTime; const prevCurrentTime = animation.currentTime;
...@@ -104,11 +104,11 @@ function setupAndRegisterTests() { ...@@ -104,11 +104,11 @@ function setupAndRegisterTests() {
promise_test(async t => { promise_test(async t => {
const animation = createWorkletAnimation(t); const animation = createWorkletAnimation(t);
const playbackRate = 2; const playbackRate = 0.2;
animation.play(); animation.play();
waitForAnimationFrameWithCondition(_=> { await waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running" return animation.playState == "running"
}); });
...@@ -118,7 +118,7 @@ function setupAndRegisterTests() { ...@@ -118,7 +118,7 @@ function setupAndRegisterTests() {
animation.playbackRate = playbackRate; animation.playbackRate = playbackRate;
// Play the animation some more. // Play the animation some more.
await waitForNextFrame(); await waitForDocumentTimelineAdvance();
const currentTime = animation.currentTime; const currentTime = animation.currentTime;
const currentTimelineTime = document.timeline.currentTime; const currentTimelineTime = document.timeline.currentTime;
...@@ -126,7 +126,7 @@ function setupAndRegisterTests() { ...@@ -126,7 +126,7 @@ function setupAndRegisterTests() {
assert_times_equal( assert_times_equal(
currentTime - prevCurrentTime, currentTime - prevCurrentTime,
(currentTimelineTime - prevTimelineTime) * playbackRate, (currentTimelineTime - prevTimelineTime) * playbackRate,
'The current time should increase two times faster than timeline.'); 'The current time should increase 0.2 times faster than timeline.');
}, 'The playback rate affects the rate of progress of the current time.'); }, 'The playback rate affects the rate of progress of the current time.');
promise_test(async t => { promise_test(async t => {
...@@ -135,13 +135,13 @@ function setupAndRegisterTests() { ...@@ -135,13 +135,13 @@ function setupAndRegisterTests() {
// Set playback rate while the animation is in 'idle' state. // Set playback rate while the animation is in 'idle' state.
animation.playbackRate = playbackRate; animation.playbackRate = playbackRate;
const prevTimelineTime = document.timeline.currentTime;
animation.play(); animation.play();
waitForAnimationFrameWithCondition(_=> {
await waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running" return animation.playState == "running"
}); });
const prevTimelineTime = document.timeline.currentTime; await waitForDocumentTimelineAdvance();
await waitForNextFrame();
const currentTime = animation.currentTime; const currentTime = animation.currentTime;
const timelineTime = document.timeline.currentTime; const timelineTime = document.timeline.currentTime;
...@@ -158,28 +158,48 @@ function setupAndRegisterTests() { ...@@ -158,28 +158,48 @@ function setupAndRegisterTests() {
fill: 'none', fill: 'none',
iterations: 1 iterations: 1
}; };
// TODO(crbug.com/937382): Currently composited
// workletAnimation.currentTime and the corresponding
// effect.getComputedTiming().localTime are computed by main and
// compositing threads respectively and, as a result, don't match.
// To workaround this limitation we compare the output of two identical
// animations that only differ in playback rate. The expectation is that
// their output matches after taking their playback rates into
// consideration. This works since these two animations start at the same
// time on the same thread.
// Once the issue is fixed, this test needs to change so expected
// effect.getComputedTiming().localTime is compared against
// workletAnimation.currentTime.
const target = createDiv(t); const target = createDiv(t);
const targetRef = createDiv(t);
const keyframeEffect = new KeyframeEffect( const keyframeEffect = new KeyframeEffect(
target, { opacity: [0, 1] }, timing); target, { opacity: [1, 0] }, timing);
const keyframeEffectRef = new KeyframeEffect(
targetRef, { opacity: [1, 0] }, timing);
const animation = new WorkletAnimation( const animation = new WorkletAnimation(
'passthrough', keyframeEffect, document.timeline); 'passthrough', keyframeEffect, document.timeline);
const animationRef = new WorkletAnimation(
'passthrough', keyframeEffectRef, document.timeline);
const playbackRate = 2; const playbackRate = 2;
animation.play();
waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running"
});
animation.playbackRate = playbackRate; animation.playbackRate = playbackRate;
animation.play();
animationRef.play();
await waitForNextFrame(); // wait until local times are synced back to the main thread.
await waitForAnimationFrameWithCondition(_ => {
return getComputedStyle(target).opacity != '1';
});
assert_times_equal( assert_times_equal(
keyframeEffect.getComputedTiming().localTime, animation.currentTime, keyframeEffect.getComputedTiming().localTime,
keyframeEffectRef.getComputedTiming().localTime * playbackRate,
'When playback rate is set on WorkletAnimation, the underlying ' + 'When playback rate is set on WorkletAnimation, the underlying ' +
'effect\'s timing should be properly updated.'); 'effect\'s timing should be properly updated.');
assert_approx_equals(Number(getComputedStyle(target).opacity), assert_approx_equals(
animation.currentTime / 100, 0.001, 1 - Number(getComputedStyle(target).opacity),
(1 - Number(getComputedStyle(targetRef).opacity)) * playbackRate,
0.001,
'When playback rate is set on WorkletAnimation, the underlying effect' + 'When playback rate is set on WorkletAnimation, the underlying effect' +
' should produce correct visual result.'); ' should produce correct visual result.');
}, 'When playback rate is updated, the underlying effect is properly ' + }, 'When playback rate is updated, the underlying effect is properly ' +
...@@ -195,7 +215,7 @@ function setupAndRegisterTests() { ...@@ -195,7 +215,7 @@ function setupAndRegisterTests() {
animation.playbackRate = 0.5; animation.playbackRate = 0.5;
animation.play(); animation.play();
waitForAnimationFrameWithCondition(_=> { await waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running" return animation.playState == "running"
}); });
assert_equals(animation.currentTime, 0.2 * timeRange * 0.5, assert_equals(animation.currentTime, 0.2 * timeRange * 0.5,
...@@ -212,9 +232,7 @@ function setupAndRegisterTests() { ...@@ -212,9 +232,7 @@ function setupAndRegisterTests() {
animation.play(); animation.play();
animation.playbackRate = 0.5; animation.playbackRate = 0.5;
waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running"
});
assert_equals(animation.currentTime, 0.2 * timeRange, assert_equals(animation.currentTime, 0.2 * timeRange,
'Initial current time is not affected by playbackRate.'); 'Initial current time is not affected by playbackRate.');
}, 'Initial current time is not affected by playbackRate set while '+ }, 'Initial current time is not affected by playbackRate set while '+
...@@ -229,7 +247,7 @@ function setupAndRegisterTests() { ...@@ -229,7 +247,7 @@ function setupAndRegisterTests() {
animation.play(); animation.play();
scroller.scrollTop = 0.2 * maxScroll; scroller.scrollTop = 0.2 * maxScroll;
waitForAnimationFrameWithCondition(_=> { await waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running" return animation.playState == "running"
}); });
// Set playback rate while the animation is playing. // Set playback rate while the animation is playing.
...@@ -247,7 +265,7 @@ function setupAndRegisterTests() { ...@@ -247,7 +265,7 @@ function setupAndRegisterTests() {
const timeRange = animation.timeline.timeRange; const timeRange = animation.timeline.timeRange;
animation.play(); animation.play();
waitForAnimationFrameWithCondition(_=> { await waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running" return animation.playState == "running"
}); });
scroller.scrollTop = 0.1 * maxScroll; scroller.scrollTop = 0.1 * maxScroll;
...@@ -273,7 +291,7 @@ function setupAndRegisterTests() { ...@@ -273,7 +291,7 @@ function setupAndRegisterTests() {
// Set playback rate while the animation is in 'idle' state. // Set playback rate while the animation is in 'idle' state.
animation.playbackRate = playbackRate; animation.playbackRate = playbackRate;
animation.play(); animation.play();
waitForAnimationFrameWithCondition(_=> { await waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running" return animation.playState == "running"
}); });
scroller.scrollTop = 0.2 * maxScroll; scroller.scrollTop = 0.2 * maxScroll;
...@@ -296,7 +314,7 @@ function setupAndRegisterTests() { ...@@ -296,7 +314,7 @@ function setupAndRegisterTests() {
}; };
const target = createDiv(t); const target = createDiv(t);
const keyframeEffect = new KeyframeEffect( const keyframeEffect = new KeyframeEffect(
target, { opacity: [0, 1] }, timing); target, { opacity: [1, 0] }, timing);
const animation = new WorkletAnimation( const animation = new WorkletAnimation(
'passthrough', keyframeEffect, timeline); 'passthrough', keyframeEffect, timeline);
const playbackRate = 2; const playbackRate = 2;
...@@ -305,12 +323,15 @@ function setupAndRegisterTests() { ...@@ -305,12 +323,15 @@ function setupAndRegisterTests() {
animation.play(); animation.play();
animation.playbackRate = playbackRate; animation.playbackRate = playbackRate;
waitForAnimationFrameWithCondition(_=> { await waitForAnimationFrameWithCondition(_=> {
return animation.playState == "running" return animation.playState == "running"
}); });
scroller.scrollTop = 0.2 * maxScroll; scroller.scrollTop = 0.2 * maxScroll;
await waitForNextFrame(); // wait until local times are synced back to the main thread.
await waitForAnimationFrameWithCondition(_ => {
return getComputedStyle(target).opacity != '1';
});
assert_times_equal( assert_times_equal(
keyframeEffect.getComputedTiming().localTime, keyframeEffect.getComputedTiming().localTime,
...@@ -319,7 +340,7 @@ function setupAndRegisterTests() { ...@@ -319,7 +340,7 @@ function setupAndRegisterTests() {
'effect\'s timing should be properly updated.'); 'effect\'s timing should be properly updated.');
assert_approx_equals( assert_approx_equals(
Number(getComputedStyle(target).opacity), Number(getComputedStyle(target).opacity),
0.2 * timeRange * playbackRate / 1000, 0.001, 1 - 0.2 * timeRange * playbackRate / 1000, 0.001,
'When playback rate is set on WorkletAnimation, the underlying ' + 'When playback rate is set on WorkletAnimation, the underlying ' +
'effect should produce correct visual result.'); 'effect should produce correct visual result.');
}, 'When playback rate is updated, the underlying effect is properly ' + }, 'When playback rate is updated, the underlying effect is properly ' +
......
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