226 lines
6.3 KiB
C++
226 lines
6.3 KiB
C++
// Copyright 2020 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "base/scoped_multi_source_observation.h"
|
|
|
|
#include "base/containers/contains.h"
|
|
#include "base/ranges/algorithm.h"
|
|
#include "base/scoped_observation_traits.h"
|
|
#include "base/test/gtest_util.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace base {
|
|
namespace {
|
|
|
|
class TestSourceObserver {};
|
|
|
|
class TestSource {
|
|
public:
|
|
void AddObserver(TestSourceObserver* observer);
|
|
void RemoveObserver(TestSourceObserver* observer);
|
|
|
|
bool HasObserver(TestSourceObserver* observer) const;
|
|
size_t num_observers() const { return observers_.size(); }
|
|
|
|
private:
|
|
std::vector<TestSourceObserver*> observers_;
|
|
};
|
|
|
|
void TestSource::AddObserver(TestSourceObserver* observer) {
|
|
observers_.push_back(observer);
|
|
}
|
|
|
|
void TestSource::RemoveObserver(TestSourceObserver* observer) {
|
|
auto it = base::ranges::find(observers_, observer);
|
|
ASSERT_TRUE(it != observers_.end());
|
|
observers_.erase(it);
|
|
}
|
|
|
|
bool TestSource::HasObserver(TestSourceObserver* observer) const {
|
|
return base::Contains(observers_, observer);
|
|
}
|
|
|
|
using TestScopedMultiSourceObservation =
|
|
ScopedMultiSourceObservation<TestSource, TestSourceObserver>;
|
|
|
|
class ScopedMultiSourceObservationTest : public testing::Test {
|
|
public:
|
|
TestSource* s1() { return &s1_; }
|
|
TestSource* s2() { return &s2_; }
|
|
TestSourceObserver* o1() { return &o1_; }
|
|
|
|
private:
|
|
TestSource s1_;
|
|
TestSource s2_;
|
|
TestSourceObserver o1_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
TEST_F(ScopedMultiSourceObservationTest, RemovesSourcesOnDestruction) {
|
|
{
|
|
TestScopedMultiSourceObservation obs(o1());
|
|
EXPECT_EQ(0u, s1()->num_observers());
|
|
EXPECT_FALSE(s1()->HasObserver(o1()));
|
|
|
|
obs.AddObservation(s1());
|
|
EXPECT_EQ(1u, s1()->num_observers());
|
|
EXPECT_TRUE(s1()->HasObserver(o1()));
|
|
|
|
obs.AddObservation(s2());
|
|
EXPECT_EQ(1u, s2()->num_observers());
|
|
EXPECT_TRUE(s2()->HasObserver(o1()));
|
|
}
|
|
|
|
// Test that all observations are removed when it goes out of scope.
|
|
EXPECT_EQ(0u, s1()->num_observers());
|
|
EXPECT_EQ(0u, s2()->num_observers());
|
|
}
|
|
|
|
TEST_F(ScopedMultiSourceObservationTest, RemoveObservation) {
|
|
TestScopedMultiSourceObservation obs(o1());
|
|
EXPECT_EQ(0u, s1()->num_observers());
|
|
EXPECT_FALSE(s1()->HasObserver(o1()));
|
|
EXPECT_EQ(0u, s2()->num_observers());
|
|
EXPECT_FALSE(s2()->HasObserver(o1()));
|
|
|
|
obs.AddObservation(s1());
|
|
EXPECT_EQ(1u, s1()->num_observers());
|
|
EXPECT_TRUE(s1()->HasObserver(o1()));
|
|
|
|
obs.AddObservation(s2());
|
|
EXPECT_EQ(1u, s2()->num_observers());
|
|
EXPECT_TRUE(s2()->HasObserver(o1()));
|
|
|
|
obs.RemoveObservation(s1());
|
|
EXPECT_EQ(0u, s1()->num_observers());
|
|
EXPECT_FALSE(s1()->HasObserver(o1()));
|
|
EXPECT_EQ(1u, s2()->num_observers());
|
|
EXPECT_TRUE(s2()->HasObserver(o1()));
|
|
|
|
obs.RemoveObservation(s2());
|
|
EXPECT_EQ(0u, s1()->num_observers());
|
|
EXPECT_FALSE(s1()->HasObserver(o1()));
|
|
EXPECT_EQ(0u, s2()->num_observers());
|
|
EXPECT_FALSE(s2()->HasObserver(o1()));
|
|
}
|
|
|
|
TEST_F(ScopedMultiSourceObservationTest, RemoveAllObservations) {
|
|
TestScopedMultiSourceObservation obs(o1());
|
|
EXPECT_EQ(0u, s1()->num_observers());
|
|
EXPECT_FALSE(s1()->HasObserver(o1()));
|
|
EXPECT_EQ(0u, s2()->num_observers());
|
|
EXPECT_FALSE(s2()->HasObserver(o1()));
|
|
|
|
obs.AddObservation(s1());
|
|
obs.AddObservation(s2());
|
|
EXPECT_EQ(1u, s1()->num_observers());
|
|
EXPECT_TRUE(s1()->HasObserver(o1()));
|
|
EXPECT_EQ(1u, s2()->num_observers());
|
|
EXPECT_TRUE(s2()->HasObserver(o1()));
|
|
|
|
obs.RemoveAllObservations();
|
|
EXPECT_EQ(0u, s1()->num_observers());
|
|
EXPECT_FALSE(s1()->HasObserver(o1()));
|
|
EXPECT_EQ(0u, s2()->num_observers());
|
|
EXPECT_FALSE(s2()->HasObserver(o1()));
|
|
}
|
|
|
|
TEST_F(ScopedMultiSourceObservationTest, IsObservingSource) {
|
|
TestScopedMultiSourceObservation obs(o1());
|
|
EXPECT_FALSE(obs.IsObservingSource(s1()));
|
|
EXPECT_FALSE(obs.IsObservingSource(s2()));
|
|
|
|
obs.AddObservation(s1());
|
|
EXPECT_TRUE(obs.IsObservingSource(s1()));
|
|
EXPECT_FALSE(obs.IsObservingSource(s2()));
|
|
|
|
obs.AddObservation(s2());
|
|
EXPECT_TRUE(obs.IsObservingSource(s1()));
|
|
EXPECT_TRUE(obs.IsObservingSource(s2()));
|
|
|
|
obs.RemoveObservation(s1());
|
|
EXPECT_FALSE(obs.IsObservingSource(s1()));
|
|
EXPECT_TRUE(obs.IsObservingSource(s2()));
|
|
}
|
|
|
|
TEST_F(ScopedMultiSourceObservationTest, IsObservingAnySource) {
|
|
TestScopedMultiSourceObservation obs(o1());
|
|
EXPECT_FALSE(obs.IsObservingAnySource());
|
|
|
|
obs.AddObservation(s1());
|
|
EXPECT_TRUE(obs.IsObservingAnySource());
|
|
|
|
obs.AddObservation(s2());
|
|
EXPECT_TRUE(obs.IsObservingAnySource());
|
|
|
|
obs.RemoveAllObservations();
|
|
EXPECT_FALSE(obs.IsObservingAnySource());
|
|
}
|
|
|
|
TEST_F(ScopedMultiSourceObservationTest, GetSourcesCount) {
|
|
TestScopedMultiSourceObservation obs(o1());
|
|
EXPECT_EQ(0u, obs.GetSourcesCount());
|
|
|
|
obs.AddObservation(s1());
|
|
EXPECT_EQ(1u, obs.GetSourcesCount());
|
|
|
|
obs.AddObservation(s2());
|
|
EXPECT_EQ(2u, obs.GetSourcesCount());
|
|
|
|
obs.RemoveAllObservations();
|
|
EXPECT_EQ(0u, obs.GetSourcesCount());
|
|
}
|
|
|
|
namespace {
|
|
|
|
// A test source with oddly named Add/Remove functions.
|
|
class TestSourceWithNonDefaultNames {
|
|
public:
|
|
void AddFoo(TestSourceObserver* observer) { impl_.AddObserver(observer); }
|
|
void RemoveFoo(TestSourceObserver* observer) {
|
|
impl_.RemoveObserver(observer);
|
|
}
|
|
|
|
const TestSource& impl() const { return impl_; }
|
|
|
|
private:
|
|
TestSource impl_;
|
|
};
|
|
|
|
using TestScopedMultiSourceObservationWithNonDefaultNames =
|
|
ScopedMultiSourceObservation<TestSourceWithNonDefaultNames,
|
|
TestSourceObserver>;
|
|
|
|
} // namespace
|
|
|
|
template <>
|
|
struct ScopedObservationTraits<TestSourceWithNonDefaultNames,
|
|
TestSourceObserver> {
|
|
static void AddObserver(TestSourceWithNonDefaultNames* source,
|
|
TestSourceObserver* observer) {
|
|
source->AddFoo(observer);
|
|
}
|
|
static void RemoveObserver(TestSourceWithNonDefaultNames* source,
|
|
TestSourceObserver* observer) {
|
|
source->RemoveFoo(observer);
|
|
}
|
|
};
|
|
|
|
TEST_F(ScopedMultiSourceObservationTest, NonDefaultNames) {
|
|
TestSourceWithNonDefaultNames nds1;
|
|
|
|
EXPECT_EQ(0u, nds1.impl().num_observers());
|
|
{
|
|
TestScopedMultiSourceObservationWithNonDefaultNames obs(o1());
|
|
obs.AddObservation(&nds1);
|
|
EXPECT_EQ(1u, nds1.impl().num_observers());
|
|
EXPECT_TRUE(nds1.impl().HasObserver(o1()));
|
|
}
|
|
|
|
EXPECT_EQ(0u, nds1.impl().num_observers());
|
|
}
|
|
|
|
} // namespace base
|