1 //
2 // test_Observable.cc for pekwm
3 // Copyright (C) 2021 Claes Nästén <pekdon@gmail.com>
4 //
5 // This program is licensed under the GNU GPL.
6 // See the LICENSE file for more information.
7 //
8 
9 #include "test.hh"
10 
11 #include "Observable.hh"
12 
13 class TestObservable : public Observable {
14 public:
15 	virtual ~TestObservable(void);
16 };
17 
18 class TestObservation : public Observation {
19 public:
20 	virtual ~TestObservation(void);
21 };
22 
23 class TestObserver : public Observer {
24 public:
25 	virtual ~TestObserver(void);
26 	virtual void notify(Observable* observable, Observation* observation);
27 
28 	std::vector<TestObservation*> observations;
29 };
30 
31 class TestObserverMapping : public TestSuite {
32 public:
33 	TestObserverMapping(void);
34 	~TestObserverMapping(void);
35 
36 	virtual bool run_test(TestSpec spec, bool status);
37 
38 private:
39 	static void testNotify(void);
40 	static void testRemoveObservable(void);
41 	static void testDestructObservable(void);
42 };
43 
~TestObservable(void)44 TestObservable::~TestObservable(void)
45 {
46 }
47 
~TestObservation(void)48 TestObservation::~TestObservation(void)
49 {
50 }
51 
~TestObserver(void)52 TestObserver::~TestObserver(void)
53 {
54 }
55 
56 void
notify(Observable * observable,Observation * observation)57 TestObserver::notify(Observable* observable, Observation* observation)
58 {
59 	TestObservation *test_observation =
60 		dynamic_cast<TestObservation*>(observation);
61 	observations.push_back(test_observation);
62 }
63 
TestObserverMapping(void)64 TestObserverMapping::TestObserverMapping(void)
65 	: TestSuite("ObserverMapping")
66 {
67 }
68 
~TestObserverMapping(void)69 TestObserverMapping::~TestObserverMapping(void)
70 {
71 }
72 
73 bool
run_test(TestSpec spec,bool status)74 TestObserverMapping::run_test(TestSpec spec, bool status)
75 {
76 	TEST_FN(spec, "notify", testNotify());
77 	TEST_FN(spec, "removeObservable", testRemoveObservable());
78 	TEST_FN(spec, "destructObservable", testDestructObservable());
79 	return status;
80 }
81 
82 void
testNotify(void)83 TestObserverMapping::testNotify(void)
84 {
85 	ObserverMapping om;
86 	TestObservable observable;
87 	TestObserver observer1;
88 	TestObserver observer2;
89 	TestObservation observation;
90 
91 	// notify no observers
92 	om.notifyObservers(&observable, nullptr);
93 	ASSERT_EQUAL("no observer", 0, om.size());
94 	ASSERT_EQUAL("no observer", 0, observer1.observations.size());
95 	ASSERT_EQUAL("no observer", 0, observer2.observations.size());
96 
97 	// notify one observer
98 	om.addObserver(&observable, &observer1);
99 	ASSERT_EQUAL("one observer", 1, om.size());
100 	om.notifyObservers(&observable, &observation);
101 	ASSERT_EQUAL("one observer", 1, observer1.observations.size());
102 	ASSERT_EQUAL("one observer", 0, observer2.observations.size());
103 
104 	// notify multiple observers
105 	om.addObserver(&observable, &observer2);
106 	ASSERT_EQUAL("two observers", 1, om.size());
107 	om.notifyObservers(&observable, &observation);
108 	ASSERT_EQUAL("two observers", 2, observer1.observations.size());
109 	ASSERT_EQUAL("two observers", 1, observer2.observations.size());
110 
111 	// remove observer
112 	om.removeObserver(&observable, &observer1);
113 	ASSERT_EQUAL("remove observers", 1, om.size());
114 	om.notifyObservers(&observable, &observation);
115 	ASSERT_EQUAL("remove observers", 2, observer1.observations.size());
116 	ASSERT_EQUAL("remove observers", 2, observer2.observations.size());
117 
118 	// no observers
119 	om.removeObserver(&observable, &observer2);
120 	ASSERT_EQUAL("no observers", 0, om.size());
121 	om.notifyObservers(&observable, &observation);
122 	ASSERT_EQUAL("no observers", 2, observer1.observations.size());
123 	ASSERT_EQUAL("no observers", 2, observer2.observations.size());
124 }
125 
126 void
testRemoveObservable(void)127 TestObserverMapping::testRemoveObservable(void)
128 {
129 	ObserverMapping om;
130 	TestObservable observable;
131 	TestObserver observer1;
132 	TestObserver observer2;
133 	TestObservation observation;
134 
135 	om.addObserver(&observable, &observer1);
136 	om.addObserver(&observable, &observer2);
137 	// removing the observable should remove the observers from its
138 	// list as well.
139 	om.removeObservable(&observable);
140 	om.notifyObservers(&observable, &observation);
141 
142 	ASSERT_EQUAL("removed observable", 0, observer1.observations.size());
143 	ASSERT_EQUAL("removed observable", 0, observer2.observations.size());
144 }
145 
146 void
testDestructObservable(void)147 TestObserverMapping::testDestructObservable(void)
148 {
149 	TestObserver observer;
150 
151 	ObserverMapping *om = pekwm::observerMapping();
152 	{
153 		TestObservable observable;
154 		om->addObserver(&observable, &observer);
155 		ASSERT_EQUAL("destruct observable", 1, om->size());
156 	}
157 
158 	ASSERT_EQUAL("destruct observable", 0, om->size());
159 }
160