diff options
Diffstat (limited to 'test/test_observer_list.cc')
| -rw-r--r-- | test/test_observer_list.cc | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/test/test_observer_list.cc b/test/test_observer_list.cc new file mode 100644 index 0000000..705f701 --- /dev/null +++ b/test/test_observer_list.cc @@ -0,0 +1,119 @@ +#include "common.hh" + +#include "observer_list.hh" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +namespace { + +class Observer { +public: + virtual ~Observer() = default; + virtual void foo() = 0; +}; + +class MockObserver : public Observer { +public: + MOCK_METHOD(void, foo, (), (override)); +}; + +} // namespace + +TEST(observer_list, empty) { + ObserverList<Observer> observers; + EXPECT_TRUE(observers.empty()); + auto it = observers.notify(); + EXPECT_FALSE(it); + ++it; + EXPECT_FALSE(it); +} + +TEST(observer_list, sanity) { + ObserverList<Observer> observers; + MockObserver observer; + observers.add(&observer); + EXPECT_CALL(observer, foo()); + for (auto it = observers.notify(); it; ++it) + it->foo(); +} + +TEST(observer_list, observer_removing_next_observer) { + ObserverList<Observer> observers; + MockObserver observer1; + MockObserver observer2; + observers.add(&observer1); + observers.add(&observer2); + EXPECT_CALL(observer1, foo()) + .WillOnce([&]() { observers.remove(&observer2); }) + .WillOnce(testing::Return()); + EXPECT_CALL(observer2, foo()) + .Times(0); + for (auto it = observers.notify(); it; ++it) + it->foo(); + + for (auto it = observers.notify(); it; ++it) + it->foo(); +} + +TEST(observer_list, observer_removing_previous_observer) { + ObserverList<Observer> observers; + MockObserver observer1; + MockObserver observer2; + observers.add(&observer1); + observers.add(&observer2); + EXPECT_CALL(observer1, foo()); + EXPECT_CALL(observer2, foo()) + .WillOnce([&]() { observers.remove(&observer1); }) + .WillOnce(testing::Return()); + for (auto it = observers.notify(); it; ++it) + it->foo(); + + for (auto it = observers.notify(); it; ++it) + it->foo(); +} + +TEST(observer_list, observer_removing_itself) { + ObserverList<Observer> observers; + MockObserver observer; + observers.add(&observer); + EXPECT_CALL(observer, foo()) + .WillOnce([&]() { observers.remove(&observer); }); + for (auto it = observers.notify(); it; ++it) + it->foo(); + EXPECT_TRUE(observers.empty()); +} + +TEST(observer_list, observer_adding_observer) { + ObserverList<Observer> observers; + MockObserver observer1; + MockObserver observer2; + observers.add(&observer1); + EXPECT_CALL(observer1, foo()) + .WillOnce([&]() { observers.add(&observer2); }) + .WillOnce(testing::Return()); + EXPECT_CALL(observer2, foo()); + for (auto it = observers.notify(); it; ++it) + it->foo(); + + for (auto it = observers.notify(); it; ++it) + it->foo(); +} + +TEST(observer_list, observer_start_new_notify) { + ObserverList<Observer> observers; + MockObserver observer1; + MockObserver observer2; + observers.add(&observer1); + observers.add(&observer2); + EXPECT_CALL(observer1, foo()) + .WillOnce([&]() { + observers.remove(&observer1); + for (auto it = observers.notify(); it; ++it) + it->foo(); + }); + EXPECT_CALL(observer2, foo()) + .Times(2); + for (auto it = observers.notify(); it; ++it) + it->foo(); +} |
