Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Unified Diff: cc/scheduler/begin_frame_source_unittest.cc

Issue 267783004: Refactoring the way begin frame sources inside scheduler work. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Very minor fixes. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..20a48784a932cebcedfb2e1465592f5cc473d1a6
--- /dev/null
+++ b/cc/scheduler/begin_frame_source_unittest.cc
@@ -0,0 +1,747 @@
+// 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 <string>
+
+#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"
+
+// Macros to help set up expected calls on the MockBeginFrameObserver.
+#define EXPECT_BEGIN_FRAME_DROP(obs, frame_time, deadline, interval) \
+ { \
+ ::testing::Expectation exp = \
+ EXPECT_CALL((obs), \
+ OnBeginFrame(CreateBeginFrameArgsForTesting( \
+ frame_time, deadline, interval))) \
+ .InSequence((obs).sequence); \
+ }
+
+#define EXPECT_BEGIN_FRAME_USED(obs, frame_time, deadline, interval) \
+ { \
+ BeginFrameArgs args = \
+ CreateBeginFrameArgsForTesting(frame_time, deadline, interval); \
+ ::testing::Expectation exp = \
+ EXPECT_CALL((obs), OnBeginFrame(args)).InSequence((obs).sequence); \
+ EXPECT_CALL((obs), LastUsedBeginFrameArgs()) \
+ .Times(::testing::AnyNumber()) \
+ .After(exp) \
+ .WillRepeatedly(::testing::Return(args)); \
+ }
+
+// Macros to send BeginFrameArgs on a FakeBeginFrameSink (and verify resulting
+// observer behaviour).
+#define SEND_BEGIN_FRAME( \
+ args_equal_to, source, frame_time, deadline, interval) \
+ { \
+ BeginFrameArgs old_args = (source).TestLastUsedBeginFrameArgs(); \
+ BeginFrameArgs new_args = \
+ CreateBeginFrameArgsForTesting(frame_time, deadline, interval); \
+ ASSERT_TRUE(!(old_args == new_args)); \
+ (source).TestOnBeginFrame(new_args); \
+ EXPECT_EQ(args_equal_to, (source).TestLastUsedBeginFrameArgs()); \
+ }
+
+// When dropping LastUsedBeginFrameArgs **shouldn't** change.
+#define SEND_BEGIN_FRAME_DROP(source, frame_time, deadline, interval) \
+ SEND_BEGIN_FRAME(old_args, source, frame_time, deadline, interval);
+
+// When used LastUsedBeginFrameArgs **should** be updated.
+#define SEND_BEGIN_FRAME_USED(source, frame_time, deadline, interval) \
+ SEND_BEGIN_FRAME(new_args, source, frame_time, deadline, interval);
+
+namespace cc {
+namespace {
+
+class MockBeginFrameObserver : public BeginFrameObserver {
+ public:
+ MOCK_METHOD1(OnBeginFrame, 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_; }
+};
+
+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());
+
+#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());
+
+#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());
+
+ 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());
+}
+
+// BeginFrameSource testing ----------------------------------------------
+TEST(BeginFrameSourceMixInTest, 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(BeginFrameSourceMixInTest, 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(BeginFrameSourceMixInTest, NoObserver) {
+ FakeBeginFrameSource source;
+ SEND_BEGIN_FRAME_DROP(source, 100, 200, 300);
+}
+
+TEST(BeginFrameSourceMixInTest, NeedsBeginFrames) {
+ FakeBeginFrameSource source;
+ EXPECT_FALSE(source.NeedsBeginFrames());
+ source.SetNeedsBeginFrames(true);
+ EXPECT_TRUE(source.NeedsBeginFrames());
+ source.SetNeedsBeginFrames(false);
+ EXPECT_FALSE(source.NeedsBeginFrames());
+}
+
+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(BeginFrameSourceMixInTest, 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_CALL((*obs_),
+ OnBeginFrame(CreateTypedBeginFrameArgsForTesting(
+ 10000, 20000, 10000, BeginFrameArgs::MISSED)));
+ 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_->NeedsBeginFrames(), false);
+ EXPECT_EQ(source2_->NeedsBeginFrames(), false);
+
+ // Check SetNeedsFrames works
+ mux_->SetNeedsBeginFrames(true);
+ EXPECT_EQ(source1_->NeedsBeginFrames(), true);
+ EXPECT_EQ(source2_->NeedsBeginFrames(), false);
+
+ mux_->SetNeedsBeginFrames(false);
+ EXPECT_EQ(source1_->NeedsBeginFrames(), false);
+ EXPECT_EQ(source2_->NeedsBeginFrames(), false);
+
+ // Checking that switching the source makes SetNeedsFrames on the
+ // subsources correctly.
+ mux_->SetNeedsBeginFrames(true);
+
+ mux_->SetActiveSource(source1_);
+ EXPECT_EQ(source1_->NeedsBeginFrames(), true);
+ EXPECT_EQ(source2_->NeedsBeginFrames(), false);
+
+ mux_->SetActiveSource(source2_);
+ EXPECT_EQ(source1_->NeedsBeginFrames(), false);
+ EXPECT_EQ(source2_->NeedsBeginFrames(), 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

Powered by Google App Engine
This is Rietveld 408576698