source: src/Patterns/Observer/unittests/ObserverUnitTest.cpp@ d85532

Last change on this file since d85532 was d85532, checked in by Frederik Heber <heber@…>, 14 years ago

Added unit test on Relay.

  • added new stubs to ObserverStub implementing Relay.
  • Relay is friend of Notification.
  • Property mode set to 100644
File size: 9.5 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * ObserverTest.cpp
10 *
11 * Created on: Jan 19, 2010
12 * Author: crueger
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include <cppunit/CompilerOutputter.h>
21#include <cppunit/extensions/TestFactoryRegistry.h>
22#include <cppunit/ui/text/TestRunner.h>
23#include <set>
24
25#include "Assert.hpp"
26
27#include <iostream>
28
29#include "stubs/ObserverStub.hpp"
30#include "Observer/Notification.hpp"
31#include "Observer/ObservedContainer.hpp"
32#include "Observer/ObservedContainer_impl.hpp"
33#include "Observer/ObserverLog.hpp"
34
35#include "ObserverUnitTest.hpp"
36
37#ifdef HAVE_TESTRUNNER
38#include "UnitTestMain.hpp"
39#endif /*HAVE_TESTRUNNER*/
40
41// Registers the fixture into the 'registry'
42CPPUNIT_TEST_SUITE_REGISTRATION( ObserverTest );
43
44/******************* Test stubs ************************/
45
46
47/******************* actuall tests ***************/
48
49void ObserverTest::setUp() {
50 ASSERT_DO(Assert::Throw);
51
52 simpleObservable1 = new SimpleObservable();
53 simpleObservable2 = new SimpleObservable();
54 callObservable = new CallObservable();
55 superObservable = new SuperObservable();
56 blockObservable = new BlockObservable();
57 notificationObservable = new NotificationObservable();
58 obsset = new ObservableSet(5);
59 obsmap = new ObservableMap(5);
60
61 observer1 = new UpdateCountObserver();
62 observer2 = new UpdateCountObserver();
63 observer3 = new UpdateCountObserver();
64 observer4 = new UpdateCountObserver();
65
66 notificationObserver1 = new NotificationObserver(
67 notificationObservable->getChannel(NotificationObservable::Operation1Notify));
68 notificationObserver2 = new NotificationObserver(
69 notificationObservable->getChannel(NotificationObservable::Operation2Notify));
70
71 RelayObservable = new RelayTest;
72 RelayObserver = new RelayCountObserver(RelayObservable);
73}
74
75void ObserverTest::tearDown() {
76 delete simpleObservable1;
77 delete simpleObservable2;
78 delete callObservable;
79 delete superObservable;
80 delete blockObservable;
81 delete notificationObservable;
82 delete obsset;
83 delete obsmap;
84 delete RelayObservable;
85 delete RelayObserver;
86
87 delete observer1;
88 delete observer2;
89 delete observer3;
90 delete observer4;
91 delete notificationObserver1;
92 delete notificationObserver2;
93#ifdef LOG_OBSERVER
94 ObserverLog::purgeInstance();
95#endif
96}
97
98void ObserverTest::doesUpdateTest()
99{
100 simpleObservable1->signOn(observer1);
101 simpleObservable1->signOn(observer2);
102 simpleObservable1->signOn(observer3);
103
104 simpleObservable2->signOn(observer2);
105 simpleObservable2->signOn(observer4);
106
107 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
108 CPPUNIT_ASSERT_EQUAL( 0, observer2->updates );
109 CPPUNIT_ASSERT_EQUAL( 0, observer3->updates );
110 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
111
112
113 simpleObservable1->changeMethod();
114 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
115 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
116 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
117 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
118
119 simpleObservable1->signOff(observer3);
120
121 simpleObservable1->changeMethod();
122 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
123 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
124 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
125 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
126
127 simpleObservable2->changeMethod();
128 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
129 CPPUNIT_ASSERT_EQUAL( 3, observer2->updates );
130 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
131 CPPUNIT_ASSERT_EQUAL( 1, observer4->updates );
132}
133
134
135void ObserverTest::doesBlockUpdateTest() {
136 callObservable->signOn(observer1);
137 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
138
139 callObservable->changeMethod1();
140 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
141
142 callObservable->changeMethod2();
143 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
144}
145
146void ObserverTest::doesSubObservableTest() {
147 superObservable->signOn(observer1);
148 superObservable->subObservable->signOn(observer2);
149
150 superObservable->subObservable->changeMethod();
151 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
152 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
153
154 superObservable->changeMethod();
155 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
156 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
157}
158
159void ObserverTest::outsideLockTest(){
160 callObservable->signOn(observer1);
161 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
162
163 {
164 LOCK_OBSERVABLE(*callObservable);
165 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
166 }
167 // lock is gone now, observer should have notified
168 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
169}
170
171void ObserverTest::doesNotifyTest(){
172 notificationObservable->signOn(notificationObserver1, NotificationObservable::Operation1Notify);
173 notificationObservable->signOn(notificationObserver2, NotificationObservable::Operation2Notify);
174
175 notificationObservable->operation1();
176 CPPUNIT_ASSERT(notificationObserver1->wasNotified);
177 CPPUNIT_ASSERT(!notificationObserver2->wasNotified);
178
179 notificationObserver1->wasNotified=false;
180
181 notificationObservable->operation2();
182 CPPUNIT_ASSERT(!notificationObserver1->wasNotified);
183 CPPUNIT_ASSERT(notificationObserver2->wasNotified);
184}
185
186void ObserverTest::doesReportTest(){
187 // Actual checks are in the Stub-methods for this
188 blockObservable->changeMethod1();
189 blockObservable->changeMethod2();
190 blockObservable->noChangeMethod();
191}
192
193void ObserverTest::iteratorTest(){
194 int i = 0;
195 // test the general iterator methods
196 for(ObservableSet::iterator iter=obsset->begin(); iter!=obsset->end();++iter){
197 CPPUNIT_ASSERT(i< obsset->num);
198 i++;
199 }
200
201 i=0;
202 for(ObservableSet::const_iterator iter=obsset->begin(); iter!=obsset->end();++iter){
203 CPPUNIT_ASSERT(i<obsset->num);
204 i++;
205 }
206
207 obsset->signOn(observer1);
208 {
209 // we construct this out of the loop, so the iterator dies at the end of
210 // the scope and not the end of the loop (allows more testing)
211 ObservableSet::iterator iter;
212 for(iter=obsset->begin(); iter!=obsset->end(); ++iter){
213 (*iter)->changeMethod();
214 }
215 // At this point no change should have been propagated
216 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates);
217 }
218 // After the Iterator has died the propagation should take place
219 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
220
221 // when using a const_iterator no changes should be propagated
222 for(ObservableSet::const_iterator iter = obsset->begin(); iter!=obsset->end();++iter);
223 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
224
225 // we need to test the operator-> as well
226 obsmap->signOn(observer2);
227 {
228 // we construct this out of the loop, so the iterator dies at the end of
229 // the scope and not the end of the loop (allows more testing)
230 ObservableMap::iterator iter;
231 for(iter=obsmap->begin(); iter!=obsmap->end(); ++iter){
232 iter->second->changeMethod();
233 }
234 // At this point no change should have been propagated
235 CPPUNIT_ASSERT_EQUAL( 0, observer2->updates);
236 }
237 // After the Iterator has died the propagation should take place
238 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates);
239
240 obsset->signOff(observer1);
241 obsmap->signOff(observer2);
242}
243
244void ObserverTest::relayTest()
245{
246 // sign on some observables to the relay
247 simpleObservable1->signOn(RelayObservable);
248 simpleObservable2->signOn(RelayObservable);
249
250 // sign on an observer to the relay
251 RelayObservable->signOn(RelayObserver);
252 simpleObservable1->signOn(observer1);
253
254 // check that all is zero
255 CPPUNIT_ASSERT_EQUAL( 0, RelayObserver->updates );
256 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
257
258 // signal update
259 simpleObservable1->changeMethod();
260
261 // check that both the change
262 // (and RelayObserver checks being called correctly)
263 CPPUNIT_ASSERT_EQUAL( 1, RelayObserver->updates );
264 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
265
266 // signal update through relay only
267 simpleObservable2->changeMethod();
268
269 // check that only one got the change
270 CPPUNIT_ASSERT_EQUAL( 2, RelayObserver->updates );
271 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
272
273 // check on signOff
274 simpleObservable1->signOff(RelayObservable);
275 simpleObservable1->signOff(observer1);
276}
277
278void ObserverTest::CircleDetectionTest() {
279 std::cout << std::endl << "Warning: the next test involved methods that can produce infinite loops." << std::endl;
280 std::cout << "Errors in this methods can not be checked using the CPPUNIT_ASSERT Macros." << std::endl;
281 std::cout << "Instead tests are run on these methods to see if termination is assured" << std::endl << std::endl;
282 std::cout << "If this test does not complete in a few seconds, kill the test-suite and fix the Error in the circle detection mechanism" << std::endl;
283
284 std::cout << std::endl << std::endl << "The following errors displayed by the observer framework can be ignored" << std::endl;
285
286 // make this Observable its own subject. NEVER DO THIS IN ACTUAL CODE
287 simpleObservable1->signOn(simpleObservable1);
288#ifndef NDEBUG
289 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
290#else
291 simpleObservable1->changeMethod();
292#endif
293
294 // more complex test
295 simpleObservable1->signOff(simpleObservable1);
296 simpleObservable1->signOn(simpleObservable2);
297 simpleObservable2->signOn(simpleObservable1);
298#ifndef NDEBUG
299 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
300#else
301 simpleObservable1->changeMethod();
302#endif
303
304
305 simpleObservable1->signOff(simpleObservable2);
306 simpleObservable2->signOff(simpleObservable1);
307 // when we reach this line, although we broke the DAG assumption the circle check works fine
308 CPPUNIT_ASSERT(true);
309}
Note: See TracBrowser for help on using the repository browser.