Index: cc/scheduler/begin_frame_source_unittest.cc |
diff --git a/cc/scheduler/begin_frame_source_unittest.cc b/cc/scheduler/begin_frame_source_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..909bf71d06cd8378cfd3efaa5417e4b383e0d948 |
--- /dev/null |
+++ b/cc/scheduler/begin_frame_source_unittest.cc |
@@ -0,0 +1,792 @@ |
+// Copyright 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <deque> |
+ |
+#include "base/basictypes.h" |
+#include "base/gtest_prod_util.h" |
+#include "base/test/test_simple_task_runner.h" |
+#include "cc/scheduler/begin_frame_source.h" |
+#include "cc/test/begin_frame_args_test.h" |
+#include "cc/test/scheduler_test_common.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+#define EXPECT_BEGIN_FRAME_DROP(obs, ...) \ |
+ { \ |
+ ::testing::Expectation exp = \ |
+ EXPECT_CALL((obs), \ |
+ OnBeginFrame(CreateBeginFrameArgsForTesting(__VA_ARGS__))) \ |
+ .InSequence((obs).sequence); \ |
+ } |
+ |
+#define EXPECT_BEGIN_FRAME_USED(obs, ...) \ |
+ { \ |
+ ::testing::Expectation exp = \ |
+ EXPECT_CALL((obs), \ |
+ OnBeginFrame(CreateBeginFrameArgsForTesting(__VA_ARGS__))) \ |
+ .InSequence((obs).sequence); \ |
+ BeginFrameArgs args = CreateBeginFrameArgsForTesting(__VA_ARGS__); \ |
+ EXPECT_CALL((obs), LastUsedBeginFrameArgs()) \ |
+ .Times(::testing::AnyNumber()) \ |
+ .After(exp) \ |
+ .WillRepeatedly(::testing::Return(args)); \ |
+ } |
+ |
+#define SEND_BEGIN_FRAME_DROP(source, ...) \ |
+ { \ |
+ BeginFrameArgs old_args = (source).TestLastUsedBeginFrameArgs(); \ |
+ BeginFrameArgs new_args = CreateBeginFrameArgsForTesting(__VA_ARGS__); \ |
+ ASSERT_TRUE(!(old_args == new_args)); \ |
+ (source).TestOnBeginFrame(new_args); \ |
+ EXPECT_EQ(old_args, (source).TestLastUsedBeginFrameArgs()); \ |
+ } |
+ |
+#define SEND_BEGIN_FRAME_USED(source, ...) \ |
+ { \ |
+ BeginFrameArgs old_args = (source).TestLastUsedBeginFrameArgs(); \ |
+ BeginFrameArgs new_args = CreateBeginFrameArgsForTesting(__VA_ARGS__); \ |
+ ASSERT_TRUE(!(old_args == new_args)); \ |
+ (source).TestOnBeginFrame(new_args); \ |
+ EXPECT_EQ(new_args, (source).TestLastUsedBeginFrameArgs()); \ |
+ } |
+ |
+namespace cc { |
+namespace { |
+ |
+class MockBeginFrameObserver : public BeginFrameObserver { |
+ public: |
+ MOCK_METHOD1(OnBeginFrame, void(const BeginFrameArgs&)); |
+ MOCK_METHOD1(OnMissedBeginFrame, void(const BeginFrameArgs&)); |
+ MOCK_CONST_METHOD0(LastUsedBeginFrameArgs, const BeginFrameArgs()); |
+ |
+ virtual void AsValueInto(base::debug::TracedValue* dict) const { |
+ dict->SetString("type", "MockBeginFrameObserver"); |
+ dict->BeginDictionary("last_begin_frame_args"); |
+ LastUsedBeginFrameArgs().AsValueInto(dict); |
+ dict->EndDictionary(); |
+ } |
+ |
+ // A value different from the normal default returned by a BeginFrameObserver |
+ // so it is easiable traced back here. |
+ static const BeginFrameArgs kDefaultBeginFrameArgs; |
+ |
+ MockBeginFrameObserver() { |
+ // Set a "default" value returned by LastUsedBeginFrameArgs so that gMock |
+ // doesn't fail an assert and instead returns useful information. |
+ EXPECT_CALL(*this, LastUsedBeginFrameArgs()) |
+ .Times(::testing::AnyNumber()) |
+ .InSequence(sequence) |
+ .WillRepeatedly(::testing::Return(kDefaultBeginFrameArgs)); |
+ } |
+ virtual ~MockBeginFrameObserver() {} |
+ |
+ ::testing::Sequence sequence; |
+}; |
+ |
+TEST(MockBeginFrameObserverTest, ExpectOnBeginFrame) { |
+ ::testing::NiceMock<MockBeginFrameObserver> obs; |
+ EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 400, 600, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 700, 900, 300); |
+ |
+ EXPECT_EQ(obs.LastUsedBeginFrameArgs(), |
+ MockBeginFrameObserver::kDefaultBeginFrameArgs); |
+ |
+ obs.OnBeginFrame(CreateBeginFrameArgsForTesting( |
+ 100, 200, 300)); // One call to LastUsedBeginFrameArgs |
+ EXPECT_EQ(obs.LastUsedBeginFrameArgs(), |
+ CreateBeginFrameArgsForTesting(100, 200, 300)); |
+ |
+ obs.OnBeginFrame(CreateBeginFrameArgsForTesting( |
+ 400, 600, 300)); // Multiple calls to LastUsedBeginFrameArgs |
+ EXPECT_EQ(obs.LastUsedBeginFrameArgs(), |
+ CreateBeginFrameArgsForTesting(400, 600, 300)); |
+ EXPECT_EQ(obs.LastUsedBeginFrameArgs(), |
+ CreateBeginFrameArgsForTesting(400, 600, 300)); |
+ |
+ obs.OnBeginFrame(CreateBeginFrameArgsForTesting( |
+ 700, 900, 300)); // No calls to LastUsedBeginFrameArgs |
+} |
+ |
+TEST(MockBeginFrameObserverTest, ExpectOnBeginFrameStatus) { |
+ ::testing::NiceMock<MockBeginFrameObserver> obs; |
+ EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300); |
+ EXPECT_BEGIN_FRAME_DROP(obs, 400, 600, 300); |
+ EXPECT_BEGIN_FRAME_DROP(obs, 450, 650, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 700, 900, 300); |
+ |
+ EXPECT_EQ(obs.LastUsedBeginFrameArgs(), |
+ MockBeginFrameObserver::kDefaultBeginFrameArgs); |
+ |
+ // Used |
+ obs.OnBeginFrame(CreateBeginFrameArgsForTesting(100, 200, 300)); |
+ EXPECT_EQ(obs.LastUsedBeginFrameArgs(), |
+ CreateBeginFrameArgsForTesting(100, 200, 300)); |
+ |
+ // Dropped |
+ obs.OnBeginFrame(CreateBeginFrameArgsForTesting(400, 600, 300)); |
+ EXPECT_EQ(obs.LastUsedBeginFrameArgs(), |
+ CreateBeginFrameArgsForTesting(100, 200, 300)); |
+ |
+ // Dropped |
+ obs.OnBeginFrame(CreateBeginFrameArgsForTesting(450, 650, 300)); |
+ EXPECT_EQ(obs.LastUsedBeginFrameArgs(), |
+ CreateBeginFrameArgsForTesting(100, 200, 300)); |
+ |
+ // Used |
+ obs.OnBeginFrame(CreateBeginFrameArgsForTesting(700, 900, 300)); |
+ EXPECT_EQ(obs.LastUsedBeginFrameArgs(), |
+ CreateBeginFrameArgsForTesting(700, 900, 300)); |
+} |
+ |
+const BeginFrameArgs MockBeginFrameObserver::kDefaultBeginFrameArgs = |
+ CreateBeginFrameArgsForTesting(-1, -1, -1); |
+ |
+// BeginFrameObserverMixIn testing --------------------------------------- |
+class MockMinimalBeginFrameObserverMixIn : public BeginFrameObserverMixIn { |
+ public: |
+ MOCK_METHOD1(OnBeginFrameMixInDelegate, bool(const BeginFrameArgs&)); |
+ int64_t dropped_begin_frame_args() const { return dropped_begin_frame_args_; } |
+ int64_t dropped_missed_begin_frame_args() const { |
+ return dropped_missed_begin_frame_args_; |
+ } |
+}; |
+ |
+TEST(BeginFrameObserverMixInTest, OnBeginFrameImplementation) { |
+ using ::testing::Return; |
+ MockMinimalBeginFrameObserverMixIn obs; |
+ ::testing::InSequence ordered; // These calls should be ordered |
+ |
+ // Initial conditions |
+ EXPECT_EQ(BeginFrameArgs(), obs.LastUsedBeginFrameArgs()); |
+ EXPECT_EQ(0, obs.dropped_begin_frame_args()); |
+ EXPECT_EQ(0, obs.dropped_missed_begin_frame_args()); |
+ |
+#ifndef NDEBUG |
+ EXPECT_DEATH({ obs.OnBeginFrame(BeginFrameArgs()); }, ""); |
+#endif |
+ |
+ BeginFrameArgs args1 = CreateBeginFrameArgsForTesting(100, 200, 300); |
+ EXPECT_CALL(obs, OnBeginFrameMixInDelegate(args1)).WillOnce(Return(true)); |
+ obs.OnBeginFrame(args1); |
+ EXPECT_EQ(args1, obs.LastUsedBeginFrameArgs()); |
+ EXPECT_EQ(0, obs.dropped_begin_frame_args()); |
+ EXPECT_EQ(0, obs.dropped_missed_begin_frame_args()); |
+ |
+#ifndef NDEBUG |
+ EXPECT_DEATH( |
+ { obs.OnBeginFrame(CreateBeginFrameArgsForTesting(50, 200, 300)); }, ""); |
+#endif |
+ |
+ // Returning false shouldn't update the LastUsedBeginFrameArgs value. |
+ BeginFrameArgs args2 = CreateBeginFrameArgsForTesting(200, 300, 400); |
+ EXPECT_CALL(obs, OnBeginFrameMixInDelegate(args2)).WillOnce(Return(false)); |
+ obs.OnBeginFrame(args2); |
+ EXPECT_EQ(args1, obs.LastUsedBeginFrameArgs()); |
+ EXPECT_EQ(1, obs.dropped_begin_frame_args()); |
+ EXPECT_EQ(0, obs.dropped_missed_begin_frame_args()); |
+ |
+ BeginFrameArgs args3 = CreateBeginFrameArgsForTesting(150, 300, 400); |
+ EXPECT_CALL(obs, OnBeginFrameMixInDelegate(args3)).WillOnce(Return(true)); |
+ obs.OnBeginFrame(args3); |
+ EXPECT_EQ(args3, obs.LastUsedBeginFrameArgs()); |
+ EXPECT_EQ(1, obs.dropped_begin_frame_args()); |
+ EXPECT_EQ(0, obs.dropped_missed_begin_frame_args()); |
+ |
+ // Default missed frame impl drops the frame. |
+ obs.OnMissedBeginFrame(CreateBeginFrameArgsForTesting(300, 400, 500)); |
+ EXPECT_EQ(args3, obs.LastUsedBeginFrameArgs()); |
+ EXPECT_EQ(1, obs.dropped_begin_frame_args()); |
+ EXPECT_EQ(1, obs.dropped_missed_begin_frame_args()); |
+} |
+ |
+class MockFullBeginFrameObserverMixIn |
+ : public MockMinimalBeginFrameObserverMixIn { |
+ public: |
+ MOCK_METHOD1(OnMissedBeginFrameMixInDelegate, bool(const BeginFrameArgs&)); |
+}; |
+ |
+TEST(BeginFrameObserverMixInTest, OnMissedBeginFrameImplementation) { |
+ using ::testing::Return; |
+ MockFullBeginFrameObserverMixIn obs; |
+ ::testing::InSequence ordered; // These calls should be ordered |
+ |
+#ifndef NDEBUG |
+ EXPECT_DEATH({ obs.OnMissedBeginFrame(BeginFrameArgs()); }, ""); |
+#endif |
+ |
+ BeginFrameArgs args1 = CreateBeginFrameArgsForTesting(100, 200, 300); |
+ EXPECT_CALL(obs, OnMissedBeginFrameMixInDelegate(args1)) |
+ .WillOnce(Return(true)); |
+ obs.OnMissedBeginFrame(args1); |
+ EXPECT_EQ(args1, obs.LastUsedBeginFrameArgs()); |
+ EXPECT_EQ(0, obs.dropped_begin_frame_args()); |
+ EXPECT_EQ(0, obs.dropped_missed_begin_frame_args()); |
+ |
+#ifndef NDEBUG |
+ EXPECT_DEATH( |
+ { obs.OnMissedBeginFrame(CreateBeginFrameArgsForTesting(50, 200, 300)); }, |
+ ""); |
+#endif |
+ |
+ // Returning false shouldn't update the LastUsedBeginFrameArgs value. |
+ BeginFrameArgs args2 = CreateBeginFrameArgsForTesting(200, 300, 400); |
+ EXPECT_CALL(obs, OnMissedBeginFrameMixInDelegate(args2)) |
+ .WillOnce(Return(false)); |
+ obs.OnMissedBeginFrame(args2); |
+ EXPECT_EQ(args1, obs.LastUsedBeginFrameArgs()); |
+ EXPECT_EQ(0, obs.dropped_begin_frame_args()); |
+ EXPECT_EQ(1, obs.dropped_missed_begin_frame_args()); |
+ |
+ BeginFrameArgs args3 = CreateBeginFrameArgsForTesting(150, 300, 400); |
+ EXPECT_CALL(obs, OnMissedBeginFrameMixInDelegate(args3)) |
+ .WillOnce(Return(true)); |
+ obs.OnMissedBeginFrame(args3); |
+ EXPECT_EQ(args3, obs.LastUsedBeginFrameArgs()); |
+ EXPECT_EQ(0, obs.dropped_begin_frame_args()); |
+ EXPECT_EQ(1, obs.dropped_missed_begin_frame_args()); |
+} |
+ |
+// BeginFrameSource testing ---------------------------------------------- |
+TEST(BeginFrameSourceTest, ObserverManipulation) { |
+ MockBeginFrameObserver obs; |
+ MockBeginFrameObserver otherObs; |
+ FakeBeginFrameSource source; |
+ |
+ source.AddObserver(&obs); |
+ EXPECT_EQ(&obs, source.GetObserver()); |
+ |
+#ifndef NDEBUG |
+ // Adding an observer when an observer already exists should DCHECK fail. |
+ EXPECT_DEATH({ source.AddObserver(&otherObs); }, ""); |
+ |
+ // Removing wrong observer should DCHECK fail. |
+ EXPECT_DEATH({ source.RemoveObserver(&otherObs); }, ""); |
+ |
+ // Removing an observer when there is no observer should DCHECK fail. |
+ EXPECT_DEATH({ |
+ source.RemoveObserver(&obs); |
+ source.RemoveObserver(&obs); |
+ }, |
+ ""); |
+#endif |
+ source.RemoveObserver(&obs); |
+ |
+ source.AddObserver(&otherObs); |
+ EXPECT_EQ(&otherObs, source.GetObserver()); |
+ source.RemoveObserver(&otherObs); |
+} |
+ |
+TEST(BeginFrameSourceTest, Observer) { |
+ FakeBeginFrameSource source; |
+ MockBeginFrameObserver obs; |
+ source.AddObserver(&obs); |
+ EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300); |
+ EXPECT_BEGIN_FRAME_DROP(obs, 400, 600, 300); |
+ EXPECT_BEGIN_FRAME_DROP(obs, 450, 650, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 700, 900, 300); |
+ |
+ SEND_BEGIN_FRAME_USED(source, 100, 200, 300); |
+ SEND_BEGIN_FRAME_DROP(source, 400, 600, 300); |
+ SEND_BEGIN_FRAME_DROP(source, 450, 650, 300); |
+ SEND_BEGIN_FRAME_USED(source, 700, 900, 300); |
+} |
+ |
+TEST(BeginFrameSourceTest, NoObserver) { |
+ FakeBeginFrameSource source; |
+ SEND_BEGIN_FRAME_DROP(source, 100, 200, 300); |
+} |
+ |
+class LoopingBeginFrameObserver : public BeginFrameObserverMixIn { |
+ public: |
+ BeginFrameSource* source_; |
+ |
+ virtual void AsValueInto(base::debug::TracedValue* dict) const OVERRIDE { |
+ dict->SetString("type", "LoopingBeginFrameObserver"); |
+ dict->BeginDictionary("source"); |
+ source_->AsValueInto(dict); |
+ dict->EndDictionary(); |
+ } |
+ |
+ protected: |
+ // BeginFrameObserverMixIn |
+ virtual bool OnBeginFrameMixInDelegate(const BeginFrameArgs& args) OVERRIDE { |
+ return true; |
+ } |
+}; |
+ |
+TEST(BeginFrameSourceTest, DetectAsValueIntoLoop) { |
+ LoopingBeginFrameObserver obs; |
+ FakeBeginFrameSource source; |
+ |
+ obs.source_ = &source; |
+ source.AddObserver(&obs); |
+ |
+ scoped_refptr<base::debug::TracedValue> state = |
+ new base::debug::TracedValue(); |
+ source.AsValueInto(state.get()); |
+} |
+ |
+// BackToBackBeginFrameSource testing ----------------------------------------- |
+class TestBackToBackBeginFrameSource : public BackToBackBeginFrameSource { |
+ public: |
+ static scoped_ptr<TestBackToBackBeginFrameSource> Create( |
+ scoped_refptr<TestNowSource> now_src, |
+ base::SingleThreadTaskRunner* task_runner) { |
+ return make_scoped_ptr( |
+ new TestBackToBackBeginFrameSource(now_src, task_runner)); |
+ } |
+ |
+ protected: |
+ TestBackToBackBeginFrameSource(scoped_refptr<TestNowSource> now_src, |
+ base::SingleThreadTaskRunner* task_runner) |
+ : BackToBackBeginFrameSource(task_runner), now_src_(now_src) {} |
+ |
+ virtual base::TimeTicks Now() OVERRIDE { return now_src_->Now(); } |
+ |
+ scoped_refptr<TestNowSource> now_src_; |
+}; |
+ |
+class BackToBackBeginFrameSourceTest : public ::testing::Test { |
+ public: |
+ static const int64_t kDeadline; |
+ static const int64_t kInterval; |
+ |
+ scoped_refptr<TestNowSource> now_src_; |
+ scoped_refptr<OrderedSimpleTaskRunner> task_runner_; |
+ scoped_ptr<TestBackToBackBeginFrameSource> source_; |
+ scoped_ptr<MockBeginFrameObserver> obs_; |
+ |
+ virtual void SetUp() OVERRIDE { |
+ now_src_ = TestNowSource::Create(1000); |
+ task_runner_ = |
+ make_scoped_refptr(new OrderedSimpleTaskRunner(now_src_, false)); |
+ task_runner_->SetRunTaskLimit(1); |
+ source_ = |
+ TestBackToBackBeginFrameSource::Create(now_src_, task_runner_.get()); |
+ obs_ = make_scoped_ptr(new ::testing::StrictMock<MockBeginFrameObserver>()); |
+ source_->AddObserver(obs_.get()); |
+ } |
+ |
+ virtual void TearDown() OVERRIDE { obs_.reset(); } |
+}; |
+ |
+const int64_t BackToBackBeginFrameSourceTest::kDeadline = |
+ BeginFrameArgs::DefaultInterval().ToInternalValue(); |
+ |
+const int64_t BackToBackBeginFrameSourceTest::kInterval = |
+ BeginFrameArgs::DefaultInterval().ToInternalValue(); |
+ |
+TEST_F(BackToBackBeginFrameSourceTest, SetNeedsBeginFramesSendsBeginFrame) { |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); |
+ source_->SetNeedsBeginFrames(true); |
+ EXPECT_TRUE(task_runner_->HasPendingTasks()); |
+ task_runner_->RunUntilIdle(); |
+ |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval); |
+ now_src_->AdvanceNowMicroseconds(100); |
+ source_->DidFinishFrame(0); |
+ task_runner_->RunUntilIdle(); |
+} |
+ |
+TEST_F(BackToBackBeginFrameSourceTest, |
+ DidFinishFrameThenSetNeedsBeginFramesProducesNoFrame) { |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); |
+ source_->SetNeedsBeginFrames(true); |
+ task_runner_->RunUntilIdle(); |
+ |
+ source_->SetNeedsBeginFrames(false); |
+ source_->DidFinishFrame(0); |
+ |
+ EXPECT_FALSE(task_runner_->HasPendingTasks()); |
+} |
+ |
+TEST_F(BackToBackBeginFrameSourceTest, |
+ SetNeedsBeginFramesThenDidFinishFrameProducesNoFrame) { |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); |
+ source_->SetNeedsBeginFrames(true); |
+ task_runner_->RunUntilIdle(); |
+ |
+ now_src_->AdvanceNowMicroseconds(100); |
+ source_->DidFinishFrame(0); |
+ source_->SetNeedsBeginFrames(false); |
+ |
+ EXPECT_TRUE(task_runner_->HasPendingTasks()); |
+ task_runner_->RunUntilIdle(); |
+} |
+ |
+TEST_F(BackToBackBeginFrameSourceTest, |
+ DidFinishFrameThenTogglingSetNeedsBeginFramesProducesCorrectFrame) { |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); |
+ source_->SetNeedsBeginFrames(true); |
+ task_runner_->RunUntilIdle(); |
+ |
+ now_src_->AdvanceNowMicroseconds(100); |
+ |
+ source_->SetNeedsBeginFrames(false); |
+ now_src_->AdvanceNowMicroseconds(10); |
+ source_->DidFinishFrame(0); |
+ now_src_->AdvanceNowMicroseconds(10); |
+ source_->SetNeedsBeginFrames(false); |
+ now_src_->AdvanceNowMicroseconds(10); |
+ source_->SetNeedsBeginFrames(true); |
+ |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1130, 1130 + kDeadline, kInterval); |
+ EXPECT_TRUE(task_runner_->HasPendingTasks()); |
+ task_runner_->RunUntilIdle(); |
+} |
+ |
+TEST_F(BackToBackBeginFrameSourceTest, |
+ TogglingSetNeedsBeginFramesThenDidFinishFrameProducesCorrectFrame) { |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); |
+ source_->SetNeedsBeginFrames(true); |
+ task_runner_->RunUntilIdle(); |
+ |
+ now_src_->AdvanceNowMicroseconds(100); |
+ source_->DidFinishFrame(0); |
+ now_src_->AdvanceNowMicroseconds(10); |
+ source_->SetNeedsBeginFrames(false); |
+ now_src_->AdvanceNowMicroseconds(10); |
+ source_->SetNeedsBeginFrames(true); |
+ now_src_->AdvanceNowMicroseconds(10); |
+ |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1130, 1130 + kDeadline, kInterval); |
+ EXPECT_TRUE(task_runner_->HasPendingTasks()); |
+ task_runner_->RunUntilIdle(); |
+} |
+ |
+TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameNeedsBeginFrameFalse) { |
+ source_->SetNeedsBeginFrames(false); |
+ source_->DidFinishFrame(0); |
+ EXPECT_FALSE(task_runner_->RunPendingTasks()); |
+} |
+ |
+TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameRemainingFrames) { |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); |
+ source_->SetNeedsBeginFrames(true); |
+ task_runner_->RunUntilIdle(); |
+ |
+ now_src_->AdvanceNowMicroseconds(100); |
+ |
+ source_->DidFinishFrame(3); |
+ EXPECT_FALSE(task_runner_->HasPendingTasks()); |
+ source_->DidFinishFrame(2); |
+ EXPECT_FALSE(task_runner_->HasPendingTasks()); |
+ source_->DidFinishFrame(1); |
+ EXPECT_FALSE(task_runner_->HasPendingTasks()); |
+ |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval); |
+ source_->DidFinishFrame(0); |
+ EXPECT_EQ(base::TimeDelta(), task_runner_->DelayToNextTaskTime()); |
+ task_runner_->RunUntilIdle(); |
+} |
+ |
+TEST_F(BackToBackBeginFrameSourceTest, DidFinishFrameMultipleCallsIdempotent) { |
+ source_->SetNeedsBeginFrames(true); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); |
+ task_runner_->RunUntilIdle(); |
+ |
+ now_src_->AdvanceNowMicroseconds(100); |
+ source_->DidFinishFrame(0); |
+ source_->DidFinishFrame(0); |
+ source_->DidFinishFrame(0); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1100, 1100 + kDeadline, kInterval); |
+ task_runner_->RunUntilIdle(); |
+ |
+ now_src_->AdvanceNowMicroseconds(100); |
+ source_->DidFinishFrame(0); |
+ source_->DidFinishFrame(0); |
+ source_->DidFinishFrame(0); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1200, 1200 + kDeadline, kInterval); |
+ task_runner_->RunUntilIdle(); |
+} |
+ |
+TEST_F(BackToBackBeginFrameSourceTest, DelayInPostedTaskProducesCorrectFrame) { |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1000, 1000 + kDeadline, kInterval); |
+ source_->SetNeedsBeginFrames(true); |
+ task_runner_->RunUntilIdle(); |
+ |
+ now_src_->AdvanceNowMicroseconds(100); |
+ source_->DidFinishFrame(0); |
+ now_src_->AdvanceNowMicroseconds(50); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 1150, 1150 + kDeadline, kInterval); |
+ |
+ EXPECT_TRUE(task_runner_->HasPendingTasks()); |
+ task_runner_->RunUntilIdle(); |
+} |
+ |
+// SyntheticBeginFrameSource testing ------------------------------------------ |
+class SyntheticBeginFrameSourceTest : public ::testing::Test { |
+ public: |
+ scoped_refptr<TestNowSource> now_src_; |
+ scoped_refptr<OrderedSimpleTaskRunner> task_runner_; |
+ scoped_ptr<TestSyntheticBeginFrameSource> source_; |
+ scoped_ptr<MockBeginFrameObserver> obs_; |
+ |
+ virtual void SetUp() OVERRIDE { |
+ now_src_ = TestNowSource::Create(1000); |
+ task_runner_ = |
+ make_scoped_refptr(new OrderedSimpleTaskRunner(now_src_, false)); |
+ source_ = TestSyntheticBeginFrameSource::Create( |
+ now_src_, task_runner_.get(), base::TimeDelta::FromMicroseconds(10000)); |
+ obs_ = make_scoped_ptr(new MockBeginFrameObserver()); |
+ source_->AddObserver(obs_.get()); |
+ } |
+ |
+ virtual void TearDown() OVERRIDE { obs_.reset(); } |
+}; |
+ |
+TEST_F(SyntheticBeginFrameSourceTest, |
+ SetNeedsBeginFramesCallsOnBeginFrameWithMissedTick) { |
+ now_src_->SetNowMicroseconds(10010); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000); |
+ source_->SetNeedsBeginFrames(true); // Should cause the last tick to be sent |
+ // No tasks should need to be run for this to occur. |
+} |
+ |
+TEST_F(SyntheticBeginFrameSourceTest, |
+ SetNeedsBeginFramesCallsCausesOnBeginFrame) { |
+ source_->SetNeedsBeginFrames(true); |
+ EXPECT_EQ(10000, task_runner_->NextTaskTime().ToInternalValue()); |
+ |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000); |
+ now_src_->SetNowMicroseconds(10010); |
+ task_runner_->RunPendingTasks(); |
+} |
+ |
+TEST_F(SyntheticBeginFrameSourceTest, BasicOperation) { |
+ task_runner_->SetAutoAdvanceNowToPendingTasks(true); |
+ |
+ source_->SetNeedsBeginFrames(true); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 20000, 30000, 10000); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 30000, 40000, 10000); |
+ task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(30001)); |
+ |
+ source_->SetNeedsBeginFrames(false); |
+ // No new frames.... |
+ task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(60000)); |
+} |
+ |
+TEST_F(SyntheticBeginFrameSourceTest, VSyncChanges) { |
+ task_runner_->SetAutoAdvanceNowToPendingTasks(true); |
+ source_->SetNeedsBeginFrames(true); |
+ |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 10000, 20000, 10000); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 20000, 30000, 10000); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 30000, 40000, 10000); |
+ task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(30001)); |
+ |
+ // Update the vsync information |
+ source_->OnUpdateVSyncParameters(base::TimeTicks::FromInternalValue(27500), |
+ base::TimeDelta::FromMicroseconds(10001)); |
+ |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 40000, 47502, 10001); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 47502, 57503, 10001); |
+ EXPECT_BEGIN_FRAME_USED(*obs_, 57503, 67504, 10001); |
+ task_runner_->RunUntilTime(base::TimeTicks::FromInternalValue(60000)); |
+} |
+ |
+// BeginFrameSourceMultiplexer testing ----------------------------------- |
+class BeginFrameSourceMultiplexerTest : public ::testing::Test { |
+ protected: |
+ virtual void SetUp() OVERRIDE { |
+ mux_ = BeginFrameSourceMultiplexer::Create(); |
+ |
+ source1_store_ = make_scoped_ptr(new FakeBeginFrameSource()); |
+ source2_store_ = make_scoped_ptr(new FakeBeginFrameSource()); |
+ source3_store_ = make_scoped_ptr(new FakeBeginFrameSource()); |
+ |
+ source1_ = source1_store_.get(); |
+ source2_ = source2_store_.get(); |
+ source3_ = source3_store_.get(); |
+ } |
+ |
+ virtual void TearDown() OVERRIDE { |
+ // Make sure the mux is torn down before the sources. |
+ mux_.reset(); |
+ } |
+ |
+ scoped_ptr<BeginFrameSourceMultiplexer> mux_; |
+ FakeBeginFrameSource* source1_; |
+ FakeBeginFrameSource* source2_; |
+ FakeBeginFrameSource* source3_; |
+ |
+ private: |
+ scoped_ptr<FakeBeginFrameSource> source1_store_; |
+ scoped_ptr<FakeBeginFrameSource> source2_store_; |
+ scoped_ptr<FakeBeginFrameSource> source3_store_; |
+}; |
+ |
+TEST_F(BeginFrameSourceMultiplexerTest, SourcesManipulation) { |
+ EXPECT_EQ(NULL, mux_->ActiveSource()); |
+ |
+ mux_->AddSource(source1_); |
+ EXPECT_EQ(source1_, mux_->ActiveSource()); |
+ |
+ mux_->SetActiveSource(NULL); |
+ EXPECT_EQ(NULL, mux_->ActiveSource()); |
+ |
+ mux_->SetActiveSource(source1_); |
+ |
+#ifndef NDEBUG |
+ // Setting a source which isn't in the mux as active should DCHECK fail. |
+ EXPECT_DEATH({ mux_->SetActiveSource(source2_); }, ""); |
+ |
+ // Adding a source which is already added should DCHECK fail. |
+ EXPECT_DEATH({ mux_->AddSource(source1_); }, ""); |
+ |
+ // Removing a source which isn't in the mux should DCHECK fail. |
+ EXPECT_DEATH({ mux_->RemoveSource(source2_); }, ""); |
+ |
+ // Removing the active source fails |
+ EXPECT_DEATH({ mux_->RemoveSource(source1_); }, ""); |
+#endif |
+ |
+ // Test manipulation doesn't segfault. |
+ mux_->AddSource(source2_); |
+ mux_->RemoveSource(source2_); |
+ |
+ mux_->AddSource(source2_); |
+ mux_->SetActiveSource(source2_); |
+ EXPECT_EQ(source2_, mux_->ActiveSource()); |
+ |
+ mux_->RemoveSource(source1_); |
+} |
+ |
+TEST_F(BeginFrameSourceMultiplexerTest, NeedsBeginFrames) { |
+ mux_->AddSource(source1_); |
+ mux_->AddSource(source2_); |
+ mux_->SetActiveSource(source1_); |
+ EXPECT_EQ(source1_->needs_begin_frames_, false); |
+ EXPECT_EQ(source2_->needs_begin_frames_, false); |
+ |
+ // Check SetNeedsFrames works |
+ mux_->SetNeedsBeginFrames(true); |
+ EXPECT_EQ(source1_->needs_begin_frames_, true); |
+ EXPECT_EQ(source2_->needs_begin_frames_, false); |
+ |
+ mux_->SetNeedsBeginFrames(false); |
+ EXPECT_EQ(source1_->needs_begin_frames_, false); |
+ EXPECT_EQ(source2_->needs_begin_frames_, false); |
+ |
+ // Checking that switching the source makes SetNeedsFrames on the |
+ // subsources correctly. |
+ mux_->SetNeedsBeginFrames(true); |
+ |
+ mux_->SetActiveSource(source1_); |
+ EXPECT_EQ(source1_->needs_begin_frames_, true); |
+ EXPECT_EQ(source2_->needs_begin_frames_, false); |
+ |
+ mux_->SetActiveSource(source2_); |
+ EXPECT_EQ(source1_->needs_begin_frames_, false); |
+ EXPECT_EQ(source2_->needs_begin_frames_, true); |
+} |
+ |
+TEST_F(BeginFrameSourceMultiplexerTest, BeginFramesSimple) { |
+ mux_->AddSource(source1_); |
+ mux_->AddSource(source2_); |
+ mux_->SetActiveSource(source1_); |
+ |
+ MockBeginFrameObserver obs; |
+ mux_->AddObserver(&obs); |
+ EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 400, 600, 300); |
+ |
+ mux_->SetActiveSource(source1_); |
+ |
+ SEND_BEGIN_FRAME_USED(*source1_, 100, 200, 300); |
+ SEND_BEGIN_FRAME_DROP(*source2_, 200, 500, 300); |
+ |
+ mux_->SetActiveSource(source2_); |
+ SEND_BEGIN_FRAME_USED(*source2_, 400, 600, 300); |
+ SEND_BEGIN_FRAME_DROP(*source1_, 500, 700, 300); |
+} |
+ |
+TEST_F(BeginFrameSourceMultiplexerTest, BeginFramesBackwardsProtection) { |
+ mux_->AddSource(source1_); |
+ mux_->AddSource(source2_); |
+ |
+ MockBeginFrameObserver obs; |
+ mux_->AddObserver(&obs); |
+ EXPECT_BEGIN_FRAME_USED(obs, 400, 600, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 700, 900, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 1000, 1200, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 1001, 1201, 301); |
+ |
+ mux_->SetActiveSource(source1_); |
+ SEND_BEGIN_FRAME_USED(*source1_, 400, 600, 300); |
+ SEND_BEGIN_FRAME_USED(*source1_, 700, 900, 300); |
+ |
+ mux_->SetActiveSource(source2_); |
+ SEND_BEGIN_FRAME_DROP(*source2_, 699, 899, 300); |
+ SEND_BEGIN_FRAME_USED(*source2_, 1000, 1200, 300); |
+ |
+ mux_->SetActiveSource(source1_); |
+ SEND_BEGIN_FRAME_USED(*source1_, 1001, 1201, 301); |
+} |
+ |
+TEST_F(BeginFrameSourceMultiplexerTest, MinimumIntervalNegativeFails) { |
+#ifndef NDEBUG |
+ EXPECT_DEATH( |
+ { mux_->SetMinimumInterval(base::TimeDelta::FromInternalValue(-100)); }, |
+ ""); |
+#endif |
+} |
+ |
+TEST_F(BeginFrameSourceMultiplexerTest, MinimumIntervalZero) { |
+ mux_->SetMinimumInterval(base::TimeDelta()); |
+ mux_->AddSource(source1_); |
+ |
+ MockBeginFrameObserver obs; |
+ mux_->AddObserver(&obs); |
+ EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 400, 600, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 700, 900, 300); |
+ |
+ SEND_BEGIN_FRAME_USED(*source1_, 100, 200, 300); |
+ SEND_BEGIN_FRAME_USED(*source1_, 400, 600, 300); |
+ SEND_BEGIN_FRAME_USED(*source1_, 700, 900, 300); |
+} |
+ |
+TEST_F(BeginFrameSourceMultiplexerTest, MinimumIntervalBasic) { |
+ mux_->SetMinimumInterval(base::TimeDelta::FromInternalValue(600)); |
+ mux_->AddSource(source1_); |
+ |
+ MockBeginFrameObserver obs; |
+ mux_->AddObserver(&obs); |
+ EXPECT_BEGIN_FRAME_USED(obs, 100, 200, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 700, 900, 300); |
+ |
+ SEND_BEGIN_FRAME_USED(*source1_, 100, 200, 300); |
+ SEND_BEGIN_FRAME_DROP(*source1_, 400, 600, 300); |
+ SEND_BEGIN_FRAME_USED(*source1_, 700, 900, 300); |
+} |
+ |
+TEST_F(BeginFrameSourceMultiplexerTest, MinimumIntervalWithMultipleSources) { |
+ mux_->SetMinimumInterval(base::TimeDelta::FromMicroseconds(150)); |
+ mux_->AddSource(source1_); |
+ mux_->AddSource(source2_); |
+ |
+ MockBeginFrameObserver obs; |
+ mux_->AddObserver(&obs); |
+ EXPECT_BEGIN_FRAME_USED(obs, 400, 600, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 700, 900, 300); |
+ EXPECT_BEGIN_FRAME_USED(obs, 1050, 1250, 300); |
+ |
+ mux_->SetActiveSource(source1_); |
+ SEND_BEGIN_FRAME_USED(*source1_, 400, 600, 300); |
+ SEND_BEGIN_FRAME_USED(*source1_, 700, 900, 300); |
+ |
+ mux_->SetActiveSource(source2_); |
+ SEND_BEGIN_FRAME_DROP(*source2_, 750, 1050, 300); |
+ SEND_BEGIN_FRAME_USED(*source2_, 1050, 1250, 300); |
+ |
+ mux_->SetActiveSource(source1_); |
+ SEND_BEGIN_FRAME_DROP(*source2_, 1100, 1400, 300); |
+} |
+ |
+} // namespace |
+} // namespace cc |