Index: third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp |
diff --git a/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp b/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp |
index 9b187bab6418a4bea4145294ac7ba78741186ac3..cab0eae17e7bfa9534bedc8db9d0c9e15fc3ece6 100644 |
--- a/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp |
+++ b/third_party/WebKit/Source/core/animation/DocumentTimelineTest.cpp |
@@ -30,32 +30,269 @@ |
#include "core/animation/DocumentTimeline.h" |
+#include <memory> |
+#include "core/animation/AnimationClock.h" |
+#include "core/animation/AnimationEffectReadOnly.h" |
+#include "core/animation/CompositorPendingAnimations.h" |
#include "core/animation/KeyframeEffect.h" |
+#include "core/animation/KeyframeEffectModel.h" |
#include "core/dom/Document.h" |
+#include "core/dom/Element.h" |
+#include "core/dom/QualifiedName.h" |
#include "core/testing/DummyPageHolder.h" |
+#include "platform/weborigin/KURL.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gtest/include/gtest/gtest.h" |
-#include <memory> |
namespace blink { |
+class MockPlatformTiming : public DocumentTimeline::PlatformTiming { |
+ public: |
+ MOCK_METHOD1(WakeAfter, void(double)); |
+ MOCK_METHOD0(ServiceOnNextFrame, void()); |
+ |
+ DEFINE_INLINE_TRACE() { DocumentTimeline::PlatformTiming::Trace(visitor); } |
+}; |
+ |
class AnimationDocumentTimelineTest : public ::testing::Test { |
protected: |
virtual void SetUp() { |
page_holder = DummyPageHolder::Create(); |
document = &page_holder->GetDocument(); |
+ document->GetAnimationClock().ResetTimeForTesting(); |
+ element = Element::Create(QualifiedName::Null(), document.Get()); |
+ platform_timing = new MockPlatformTiming; |
+ timeline = DocumentTimeline::Create(document.Get(), platform_timing); |
+ timeline->ResetForTesting(); |
+ ASSERT_EQ(0, timeline->CurrentTimeInternal()); |
} |
virtual void TearDown() { |
document.Release(); |
+ element.Release(); |
+ timeline.Release(); |
ThreadState::Current()->CollectAllGarbage(); |
} |
+ void UpdateClockAndService(double time) { |
+ document->GetAnimationClock().UpdateTime(time); |
+ document->GetCompositorPendingAnimations().Update( |
+ Optional<CompositorElementIdSet>(), false); |
+ timeline->ServiceAnimations(kTimingUpdateForAnimationFrame); |
+ timeline->ScheduleNextService(); |
+ } |
+ |
std::unique_ptr<DummyPageHolder> page_holder; |
Persistent<Document> document; |
+ Persistent<Element> element; |
Persistent<DocumentTimeline> timeline; |
Timing timing; |
+ Persistent<MockPlatformTiming> platform_timing; |
+ |
+ void Wake() { timeline->Wake(); } |
+ |
+ double MinimumDelay() { return DocumentTimeline::kMinimumDelay; } |
}; |
+TEST_F(AnimationDocumentTimelineTest, EmptyKeyframeAnimation) { |
+ AnimatableValueKeyframeEffectModel* effect = |
+ AnimatableValueKeyframeEffectModel::Create( |
+ AnimatableValueKeyframeVector()); |
+ KeyframeEffect* keyframe_effect = |
+ KeyframeEffect::Create(element.Get(), effect, timing); |
+ |
+ timeline->Play(keyframe_effect); |
+ |
+ UpdateClockAndService(0); |
+ EXPECT_FLOAT_EQ(0, timeline->CurrentTimeInternal()); |
+ EXPECT_FALSE(keyframe_effect->IsInEffect()); |
+ |
+ UpdateClockAndService(100); |
+ EXPECT_FLOAT_EQ(100, timeline->CurrentTimeInternal()); |
+} |
+ |
+TEST_F(AnimationDocumentTimelineTest, EmptyForwardsKeyframeAnimation) { |
+ AnimatableValueKeyframeEffectModel* effect = |
+ AnimatableValueKeyframeEffectModel::Create( |
+ AnimatableValueKeyframeVector()); |
+ timing.fill_mode = Timing::FillMode::FORWARDS; |
+ KeyframeEffect* keyframe_effect = |
+ KeyframeEffect::Create(element.Get(), effect, timing); |
+ |
+ timeline->Play(keyframe_effect); |
+ |
+ UpdateClockAndService(0); |
+ EXPECT_FLOAT_EQ(0, timeline->CurrentTimeInternal()); |
+ EXPECT_TRUE(keyframe_effect->IsInEffect()); |
+ |
+ UpdateClockAndService(100); |
+ EXPECT_FLOAT_EQ(100, timeline->CurrentTimeInternal()); |
+} |
+ |
+TEST_F(AnimationDocumentTimelineTest, ZeroTime) { |
+ bool is_null; |
+ |
+ document->GetAnimationClock().UpdateTime(100); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null)); |
+ EXPECT_FALSE(is_null); |
+ |
+ document->GetAnimationClock().UpdateTime(200); |
+ EXPECT_EQ(200, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(200, timeline->CurrentTimeInternal(is_null)); |
+ EXPECT_FALSE(is_null); |
+} |
+ |
+TEST_F(AnimationDocumentTimelineTest, PlaybackRateNormal) { |
+ double zero_time = timeline->ZeroTime(); |
+ bool is_null; |
+ |
+ timeline->SetPlaybackRate(1.0); |
+ EXPECT_EQ(1.0, timeline->PlaybackRate()); |
+ document->GetAnimationClock().UpdateTime(100); |
+ EXPECT_EQ(zero_time, timeline->ZeroTime()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null)); |
+ EXPECT_FALSE(is_null); |
+ |
+ document->GetAnimationClock().UpdateTime(200); |
+ EXPECT_EQ(zero_time, timeline->ZeroTime()); |
+ EXPECT_EQ(200, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(200, timeline->CurrentTimeInternal(is_null)); |
+ EXPECT_FALSE(is_null); |
+} |
+ |
+TEST_F(AnimationDocumentTimelineTest, PlaybackRatePause) { |
+ bool is_null; |
+ |
+ document->GetAnimationClock().UpdateTime(100); |
+ EXPECT_EQ(0, timeline->ZeroTime()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null)); |
+ EXPECT_FALSE(is_null); |
+ |
+ timeline->SetPlaybackRate(0.0); |
+ EXPECT_EQ(0.0, timeline->PlaybackRate()); |
+ document->GetAnimationClock().UpdateTime(200); |
+ EXPECT_EQ(100, timeline->ZeroTime()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null)); |
+ |
+ timeline->SetPlaybackRate(1.0); |
+ EXPECT_EQ(1.0, timeline->PlaybackRate()); |
+ document->GetAnimationClock().UpdateTime(400); |
+ EXPECT_EQ(100, timeline->ZeroTime()); |
+ EXPECT_EQ(300, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(300, timeline->CurrentTimeInternal(is_null)); |
+ |
+ EXPECT_FALSE(is_null); |
+} |
+ |
+TEST_F(AnimationDocumentTimelineTest, PlaybackRateSlow) { |
+ bool is_null; |
+ |
+ document->GetAnimationClock().UpdateTime(100); |
+ EXPECT_EQ(0, timeline->ZeroTime()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null)); |
+ EXPECT_FALSE(is_null); |
+ |
+ timeline->SetPlaybackRate(0.5); |
+ EXPECT_EQ(0.5, timeline->PlaybackRate()); |
+ document->GetAnimationClock().UpdateTime(300); |
+ EXPECT_EQ(-100, timeline->ZeroTime()); |
+ EXPECT_EQ(200, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(200, timeline->CurrentTimeInternal(is_null)); |
+ |
+ timeline->SetPlaybackRate(1.0); |
+ EXPECT_EQ(1.0, timeline->PlaybackRate()); |
+ document->GetAnimationClock().UpdateTime(400); |
+ EXPECT_EQ(100, timeline->ZeroTime()); |
+ EXPECT_EQ(300, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(300, timeline->CurrentTimeInternal(is_null)); |
+ |
+ EXPECT_FALSE(is_null); |
+} |
+ |
+TEST_F(AnimationDocumentTimelineTest, PlaybackRateFast) { |
+ bool is_null; |
+ |
+ document->GetAnimationClock().UpdateTime(100); |
+ EXPECT_EQ(0, timeline->ZeroTime()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null)); |
+ EXPECT_FALSE(is_null); |
+ |
+ timeline->SetPlaybackRate(2.0); |
+ EXPECT_EQ(2.0, timeline->PlaybackRate()); |
+ document->GetAnimationClock().UpdateTime(300); |
+ EXPECT_EQ(50, timeline->ZeroTime()); |
+ EXPECT_EQ(500, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(500, timeline->CurrentTimeInternal(is_null)); |
+ |
+ timeline->SetPlaybackRate(1.0); |
+ EXPECT_EQ(1.0, timeline->PlaybackRate()); |
+ document->GetAnimationClock().UpdateTime(400); |
+ EXPECT_EQ(-200, timeline->ZeroTime()); |
+ EXPECT_EQ(600, timeline->CurrentTimeInternal()); |
+ EXPECT_EQ(600, timeline->CurrentTimeInternal(is_null)); |
+ |
+ EXPECT_FALSE(is_null); |
+} |
+ |
+TEST_F(AnimationDocumentTimelineTest, PauseForTesting) { |
+ float seek_time = 1; |
+ timing.fill_mode = Timing::FillMode::FORWARDS; |
+ KeyframeEffect* anim1 = |
+ KeyframeEffect::Create(element.Get(), |
+ AnimatableValueKeyframeEffectModel::Create( |
+ AnimatableValueKeyframeVector()), |
+ timing); |
+ KeyframeEffect* anim2 = |
+ KeyframeEffect::Create(element.Get(), |
+ AnimatableValueKeyframeEffectModel::Create( |
+ AnimatableValueKeyframeVector()), |
+ timing); |
+ Animation* animation1 = timeline->Play(anim1); |
+ Animation* animation2 = timeline->Play(anim2); |
+ timeline->PauseAnimationsForTesting(seek_time); |
+ |
+ EXPECT_FLOAT_EQ(seek_time, animation1->CurrentTimeInternal()); |
+ EXPECT_FLOAT_EQ(seek_time, animation2->CurrentTimeInternal()); |
+} |
+ |
+TEST_F(AnimationDocumentTimelineTest, DelayBeforeAnimationStart) { |
+ timing.iteration_duration = 2; |
+ timing.start_delay = 5; |
+ |
+ KeyframeEffect* keyframe_effect = |
+ KeyframeEffect::Create(element.Get(), nullptr, timing); |
+ |
+ timeline->Play(keyframe_effect); |
+ |
+ // TODO: Put the animation startTime in the future when we add the capability |
+ // to change animation startTime |
+ EXPECT_CALL(*platform_timing, WakeAfter(timing.start_delay - MinimumDelay())); |
+ UpdateClockAndService(0); |
+ |
+ EXPECT_CALL(*platform_timing, |
+ WakeAfter(timing.start_delay - MinimumDelay() - 1.5)); |
+ UpdateClockAndService(1.5); |
+ |
+ EXPECT_CALL(*platform_timing, ServiceOnNextFrame()); |
+ Wake(); |
+ |
+ EXPECT_CALL(*platform_timing, ServiceOnNextFrame()); |
+ UpdateClockAndService(4.98); |
+} |
+ |
+TEST_F(AnimationDocumentTimelineTest, UseAnimationAfterTimelineDeref) { |
+ Animation* animation = timeline->Play(0); |
+ timeline.Clear(); |
+ // Test passes if this does not crash. |
+ animation->setStartTime(0, false); |
+} |
+ |
TEST_F(AnimationDocumentTimelineTest, PlayAfterDocumentDeref) { |
timing.iteration_duration = 2; |
timing.start_delay = 5; |