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

Unified Diff: cc/scheduler/begin_frame_observer_map_unittest.cc

Issue 1337803002: cc: Adding BeginFrameObserverMap. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase onto master. Created 5 years, 1 month 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
« no previous file with comments | « cc/scheduler/begin_frame_observer_map.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/scheduler/begin_frame_observer_map_unittest.cc
diff --git a/cc/scheduler/begin_frame_observer_map_unittest.cc b/cc/scheduler/begin_frame_observer_map_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..45a4c9cb564c7703a99e27315efe15ecda6e8e1d
--- /dev/null
+++ b/cc/scheduler/begin_frame_observer_map_unittest.cc
@@ -0,0 +1,431 @@
+// 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 "cc/scheduler/begin_frame_observer_map.h"
+
+#include <algorithm>
+
+#include "base/basictypes.h"
+#include "base/gtest_prod_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// We use a macro here so that we get good line number information from gtest.
+#define EXPECT_EMPTY(obmap) \
+ EXPECT_FALSE(obmap.HasObservers()); \
+ for (auto it = obmap.begin(); it != obmap.end(); it++) \
+ NOTREACHED(); \
+ for (auto it = obmap.cbegin(); it != obmap.cend(); it++) \
+ NOTREACHED(); \
+ EXPECT_EQ(GetConstIterators(&obmap), 0U); \
+ EXPECT_EQ(GetIterators(&obmap), 0U);
+
+namespace cc {
+
+// This has to be in the same name space as BeginFrameObserverMap so it is
+// correctly
+// friended.
+class BeginFrameObserverMapTest : public ::testing::Test {
+ public:
+ template <class ObserverType, class ObserverDataType>
+ size_t GetIterators(
+ BeginFrameObserverMap<ObserverType, ObserverDataType>* obmap) {
+ return obmap->iterators_;
+ }
+
+ template <class ObserverType, class ObserverDataType>
+ size_t GetConstIterators(
+ BeginFrameObserverMap<ObserverType, ObserverDataType>* obmap) {
+ return obmap->const_iterators_;
+ }
+};
+
+namespace {
+
+class TestObserver {
+ public:
+ int observe_;
+
+ TestObserver() : observe_(0) {}
+ void Observe() { observe_++; }
+ int GetObserve() const { return observe_; }
+};
+
+struct TestObserverData {
+ TestObserverData() : data(0) {}
+
+ size_t data;
+};
+
+TEST_F(BeginFrameObserverMapTest, Types) {
+ ::testing::StaticAssertTypeEq<
+ BeginFrameObserverMap<TestObserver,
+ TestObserverData>::const_iterator::value_type,
+ std::pair<TestObserver* const, TestObserverData*>>();
+}
+
+TEST_F(BeginFrameObserverMapTest, MapInitiallyEmpty) {
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ EXPECT_EMPTY(obmap);
+}
+
+TEST_F(BeginFrameObserverMapTest, SingleObserver) {
+ size_t data_value1 = __LINE__;
+ size_t data_value2 = __LINE__;
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ TestObserver obs1;
+
+ // Observer not added yet
+ EXPECT_FALSE(obmap.HasObserver(&obs1));
+ EXPECT_EQ(obmap[&obs1], nullptr);
+
+ // Add the observer
+ obmap.AddObserver(&obs1);
+ EXPECT_TRUE(obmap.HasObserver(&obs1));
+ EXPECT_TRUE(obmap.HasObservers());
+ EXPECT_EQ(obmap[&obs1]->data, 0U);
+
+ // Normal iterator
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ EXPECT_EQ(GetIterators(&obmap), 1U);
+ EXPECT_EQ(GetConstIterators(&obmap), 0U);
+ EXPECT_EQ(&obs1, it->first);
+ it->second->data = data_value1;
+ }
+ EXPECT_EQ(GetIterators(&obmap), 0U);
+ EXPECT_EQ(obmap[&obs1]->data, data_value1);
+ // const iterator
+ for (auto it = obmap.cbegin(); it != obmap.cend(); it++) {
+ EXPECT_EQ(GetIterators(&obmap), 0U);
+ EXPECT_EQ(GetConstIterators(&obmap), 1U);
+ EXPECT_EQ(&obs1, it->first);
+ EXPECT_EQ(it->second->data, data_value1);
+ }
+ EXPECT_EQ(GetConstIterators(&obmap), 0U);
+ // Nested iterators
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ for (auto jt = obmap.begin(); jt != obmap.end(); jt++) {
+ EXPECT_EQ(GetIterators(&obmap), 2U);
+ EXPECT_EQ(GetConstIterators(&obmap), 0U);
+ EXPECT_EQ(&obs1, it->first);
+ it->second->data = data_value2;
+ }
+ EXPECT_EQ(GetIterators(&obmap), 1U);
+ }
+ EXPECT_EQ(GetIterators(&obmap), 0U);
+ EXPECT_EQ(obmap[&obs1]->data, data_value2);
+ // Nested const iterator
+ for (auto it = obmap.cbegin(); it != obmap.cend(); it++) {
+ for (auto jt = obmap.cbegin(); jt != obmap.cend(); jt++) {
+ EXPECT_EQ(GetIterators(&obmap), 0U);
+ EXPECT_EQ(GetConstIterators(&obmap), 2U);
+ EXPECT_EQ(&obs1, jt->first);
+ EXPECT_EQ(jt->second->data, data_value2);
+ }
+ EXPECT_EQ(GetConstIterators(&obmap), 1U);
+ }
+ EXPECT_EQ(GetConstIterators(&obmap), 0U);
+
+ // Remove the observer
+ obmap.RemoveObserver(&obs1);
+ EXPECT_EMPTY(obmap);
+}
+
+TEST_F(BeginFrameObserverMapTest, TwoObservers) {
+ size_t data_value1 = __LINE__;
+ size_t data_value2 = __LINE__;
+ size_t data_value3 = __LINE__;
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ TestObserver obs1;
+ TestObserver obs2;
+
+ obmap.AddObserver(&obs1);
+ EXPECT_TRUE(obmap.HasObserver(&obs1));
+ obmap.AddObserver(&obs2);
+ EXPECT_TRUE(obmap.HasObserver(&obs2));
+
+ EXPECT_TRUE(obmap.HasObservers());
+ // Normal iterator
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ EXPECT_EQ(GetIterators(&obmap), 1U);
+ EXPECT_EQ(GetConstIterators(&obmap), 0U);
+ EXPECT_EQ(it->second->data, 0U);
+ it->second->data = data_value1;
+ }
+ EXPECT_EQ(GetIterators(&obmap), 0U);
+ // const iterator
+ for (auto it = obmap.cbegin(); it != obmap.cend(); it++) {
+ EXPECT_EQ(GetIterators(&obmap), 0U);
+ EXPECT_EQ(GetConstIterators(&obmap), 1U);
+ EXPECT_EQ(it->second->data, data_value1);
+ }
+ EXPECT_EQ(GetConstIterators(&obmap), 0U);
+ // operator[]
+ EXPECT_EQ(obmap[&obs1]->data, data_value1);
+ EXPECT_EQ(obmap[&obs2]->data, data_value1);
+
+ // Nested iterators
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ for (auto jt = obmap.begin(); jt != obmap.end(); jt++) {
+ EXPECT_EQ(GetIterators(&obmap), 2U);
+ EXPECT_EQ(GetConstIterators(&obmap), 0U);
+ it->second->data = data_value2;
+ }
+ EXPECT_EQ(GetIterators(&obmap), 1U);
+ }
+ EXPECT_EQ(GetIterators(&obmap), 0U);
+ // Nested const iterator
+ for (auto it = obmap.cbegin(); it != obmap.cend(); it++) {
+ for (auto jt = obmap.cbegin(); jt != obmap.cend(); jt++) {
+ EXPECT_EQ(GetIterators(&obmap), 0U);
+ EXPECT_EQ(GetConstIterators(&obmap), 2U);
+ EXPECT_EQ(jt->second->data, data_value2);
+ }
+ EXPECT_EQ(GetConstIterators(&obmap), 1U);
+ }
+ EXPECT_EQ(GetConstIterators(&obmap), 0U);
+
+ // Remove a single observer
+ obmap.RemoveObserver(&obs2);
+
+ // Repeat the above
+ EXPECT_TRUE(obmap.HasObservers());
+ // Normal iterator
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ EXPECT_EQ(it->second->data, data_value2);
+ it->second->data = data_value3;
+ }
+ // const iterator
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ EXPECT_EQ(it->second->data, data_value3);
+ }
+ // operator[]
+ EXPECT_EQ(obmap[&obs1]->data, data_value3);
+ EXPECT_EQ(obmap[&obs2], nullptr);
+
+ // Remove the other observer
+ obmap.RemoveObserver(&obs1);
+ EXPECT_EMPTY(obmap);
+}
+
+TEST_F(BeginFrameObserverMapTest, AddWhileIterating) {
+ size_t data_value1 = __LINE__;
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ TestObserver obs1;
+ TestObserver obs2;
+ TestObserver obs3;
+ obmap.AddObserver(&obs1);
+ obmap.AddObserver(&obs3);
+
+ obmap[&obs1]->data = data_value1;
+ obmap[&obs3]->data = data_value1;
+
+ int i = 1;
+ for (auto it = obmap.begin(); it != obmap.end(); it++, i++) {
+ // Calling add twice while iterating should be safe
+ obmap.AddObserver(&obs2);
+ // Should be able to access the data right after adding.
+ EXPECT_TRUE(obmap.HasObserver(&obs2));
+ obmap[&obs2]->data = i;
+ }
+ EXPECT_TRUE(obmap.HasObservers());
+
+ EXPECT_EQ(obmap[&obs1]->data, data_value1);
+ EXPECT_EQ(obmap[&obs2]->data, 2U);
+ EXPECT_EQ(obmap[&obs3]->data, data_value1);
+}
+
+TEST_F(BeginFrameObserverMapTest, RemoveOneWhileIterating) {
+ size_t data_value1 = __LINE__;
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ TestObserver obs1;
+ TestObserver obs2;
+ TestObserver obs3;
+ obmap.AddObserver(&obs1);
+ obmap.AddObserver(&obs2);
+ obmap.AddObserver(&obs3);
+
+ obmap[&obs1]->data = data_value1;
+ obmap[&obs2]->data = data_value1;
+ obmap[&obs3]->data = data_value1;
+
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ obmap.RemoveObserver(&obs2);
+ // Observer doesn't go away until the iteration is finished...
+ EXPECT_TRUE(obmap.HasObserver(&obs2));
+ }
+ EXPECT_FALSE(obmap.HasObserver(&obs2));
+ EXPECT_TRUE(obmap.HasObservers());
+
+ EXPECT_EQ(obmap[&obs1]->data, data_value1);
+ EXPECT_EQ(obmap[&obs2], nullptr);
+ EXPECT_EQ(obmap[&obs3]->data, data_value1);
+}
+
+TEST_F(BeginFrameObserverMapTest, NestedRemoveOneWhileIterating) {
+ size_t data_value1 = __LINE__;
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ TestObserver obs1;
+ TestObserver obs2;
+ TestObserver obs3;
+ obmap.AddObserver(&obs1);
+ obmap.AddObserver(&obs2);
+ obmap.AddObserver(&obs3);
+
+ obmap[&obs1]->data = data_value1;
+ obmap[&obs2]->data = data_value1;
+ obmap[&obs3]->data = data_value1;
+
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ for (auto jt = obmap.begin(); jt != obmap.end(); jt++) {
+ obmap.RemoveObserver(&obs2);
+ }
+ }
+ EXPECT_TRUE(obmap.HasObservers());
+
+ EXPECT_EQ(obmap[&obs1]->data, data_value1);
+ EXPECT_EQ(obmap[&obs2], nullptr);
+ EXPECT_EQ(obmap[&obs3]->data, data_value1);
+}
+
+TEST_F(BeginFrameObserverMapTest, RemoveAllWhileIterating) {
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ TestObserver obs1;
+ TestObserver obs2;
+ TestObserver obs3;
+ obmap.AddObserver(&obs1);
+ obmap.AddObserver(&obs2);
+
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ obmap.RemoveObserver(it->first);
+ }
+ EXPECT_EMPTY(obmap);
+}
+
+TEST_F(BeginFrameObserverMapTest, NestedRemoveAllWhileIterating) {
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ TestObserver obs1;
+ TestObserver obs2;
+ TestObserver obs3;
+ obmap.AddObserver(&obs1);
+ obmap.AddObserver(&obs2);
+
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ for (auto jt = obmap.begin(); jt != obmap.end(); jt++) {
+ obmap.RemoveObserver(jt->first);
+ }
+ }
+ EXPECT_EMPTY(obmap);
+}
+
+TEST_F(BeginFrameObserverMapTest, AttemptToRemoveWhileConstIterating) {
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ TestObserver obs1;
+ TestObserver obs2;
+ obmap.AddObserver(&obs1);
+ obmap.AddObserver(&obs2);
+
+ EXPECT_DEATH({
+ for (auto it = obmap.cbegin(); it != obmap.cend(); it++) {
+ obmap.RemoveObserver(const_cast<TestObserver*>(it->first));
+ }
+ }, "");
+
+ const BeginFrameObserverMap<TestObserver, TestObserverData>* cobmap = &obmap;
+ EXPECT_DEATH({
+ for (auto it = cobmap->begin(); it != cobmap->end(); it++) {
+ obmap.RemoveObserver(const_cast<TestObserver*>(it->first));
+ }
+ }, "");
+}
+
+TEST_F(BeginFrameObserverMapTest, AttemptToAddWhileConstIterating) {
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+ TestObserver obs1;
+ TestObserver obs2;
+ TestObserver obs3;
+ obmap.AddObserver(&obs1);
+ obmap.AddObserver(&obs2);
+
+ EXPECT_DEATH({
+ for (auto it = obmap.cbegin(); it != obmap.cend(); it++) {
+ obmap.AddObserver(&obs3);
+ }
+ }, "");
+
+ const BeginFrameObserverMap<TestObserver, TestObserverData>* cobmap = &obmap;
+ EXPECT_DEATH({
+ for (auto it = cobmap->begin(); it != cobmap->end(); it++) {
+ obmap.AddObserver(&obs3);
+ }
+ }, "");
+}
+
+struct TestObserverOwner {
+ TestObserverOwner() : ob1(), ob2(), obmap() {}
+
+ TestObserver ob1;
+ TestObserver ob2;
+ BeginFrameObserverMap<TestObserver, TestObserverData> obmap;
+
+ void Notify() {
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ it->first->Observe();
+ }
+ }
+
+ int LargestObserver() const {
+ int largest = 0;
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ largest = std::max(largest, it->first->GetObserve());
+ }
+ return largest;
+ }
+ size_t LargestData() const {
+ size_t largest1 = 0;
+ size_t largest2 = 0;
+ for (auto it = obmap.begin(); it != obmap.end(); it++) {
+ largest1 = std::max(largest1, it->second->data);
+ largest2 = std::max(largest2, obmap[it->first]->data);
+ }
+ DCHECK_EQ(largest1, largest2);
+ return largest1;
+ }
+};
+
+TEST_F(BeginFrameObserverMapTest, ObserverOwner) {
+ TestObserverOwner owner;
+
+ owner.Notify();
+ EXPECT_EQ(owner.LargestObserver(), 0);
+ EXPECT_EQ(owner.LargestData(), 0U);
+
+ owner.obmap.AddObserver(&owner.ob1);
+ owner.Notify();
+ EXPECT_EQ(owner.LargestObserver(), 1);
+ EXPECT_EQ(owner.LargestData(), 0U);
+
+ owner.obmap[&owner.ob1]->data = 2;
+ EXPECT_EQ(owner.LargestObserver(), 1);
+ EXPECT_EQ(owner.LargestData(), 2U);
+
+ owner.obmap.AddObserver(&owner.ob2);
+ EXPECT_EQ(owner.LargestObserver(), 1);
+ EXPECT_EQ(owner.LargestData(), 2U);
+ owner.Notify();
+ owner.Notify();
+ EXPECT_EQ(owner.LargestObserver(), 3);
+ EXPECT_EQ(owner.LargestData(), 2U);
+
+ owner.obmap[&owner.ob2]->data = 5;
+ EXPECT_EQ(owner.LargestObserver(), 3);
+ EXPECT_EQ(owner.LargestData(), 5U);
+
+ owner.obmap.RemoveObserver(&owner.ob1);
+ EXPECT_EQ(owner.LargestObserver(), 2);
+ EXPECT_EQ(owner.LargestData(), 5U);
+}
+
+} // namespace
+} // namespace cc
« no previous file with comments | « cc/scheduler/begin_frame_observer_map.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698