source: src/Patterns/Observer/unittests/ObserverUnitTest.cpp@ 75d156

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

Refactored all Observer stuff into own subfolder and split up into distinct modules.

  • Observer/all.hpp is all that's needed.
  • Property mode set to 100644
File size: 8.8 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
34#include "ObserverUnitTest.hpp"
35
36#ifdef HAVE_TESTRUNNER
37#include "UnitTestMain.hpp"
38#endif /*HAVE_TESTRUNNER*/
39
40// Registers the fixture into the 'registry'
41CPPUNIT_TEST_SUITE_REGISTRATION( ObserverTest );
42
43/******************* Test stubs ************************/
44
45
46/******************* actuall tests ***************/
47
48void ObserverTest::setUp() {
49 ASSERT_DO(Assert::Throw);
50 simpleObservable1 = new SimpleObservable();
51 simpleObservable2 = new SimpleObservable();
52 callObservable = new CallObservable();
53 superObservable = new SuperObservable();
54 blockObservable = new BlockObservable();
55 notificationObservable = new NotificationObservable();
56 obsset = new ObservableSet(5);
57 obsmap = new ObservableMap(5);
58
59 observer1 = new UpdateCountObserver();
60 observer2 = new UpdateCountObserver();
61 observer3 = new UpdateCountObserver();
62 observer4 = new UpdateCountObserver();
63
64 notificationObserver1 = new NotificationObserver(
65 notificationObservable->getChannel(NotificationObservable::Operation1Notify));
66 notificationObserver2 = new NotificationObserver(
67 notificationObservable->getChannel(NotificationObservable::Operation2Notify));
68}
69
70void ObserverTest::tearDown() {
71 delete simpleObservable1;
72 delete simpleObservable2;
73 delete callObservable;
74 delete superObservable;
75 delete blockObservable;
76 delete notificationObservable;
77 delete obsset;
78 delete obsmap;
79
80 delete observer1;
81 delete observer2;
82 delete observer3;
83 delete observer4;
84 delete notificationObserver1;
85 delete notificationObserver2;
86}
87
88void ObserverTest::doesUpdateTest()
89{
90 simpleObservable1->signOn(observer1);
91 simpleObservable1->signOn(observer2);
92 simpleObservable1->signOn(observer3);
93
94 simpleObservable2->signOn(observer2);
95 simpleObservable2->signOn(observer4);
96
97 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
98 CPPUNIT_ASSERT_EQUAL( 0, observer2->updates );
99 CPPUNIT_ASSERT_EQUAL( 0, observer3->updates );
100 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
101
102
103 simpleObservable1->changeMethod();
104 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
105 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
106 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
107 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
108
109 simpleObservable1->signOff(observer3);
110
111 simpleObservable1->changeMethod();
112 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
113 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
114 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
115 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
116
117 simpleObservable2->changeMethod();
118 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
119 CPPUNIT_ASSERT_EQUAL( 3, observer2->updates );
120 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
121 CPPUNIT_ASSERT_EQUAL( 1, observer4->updates );
122}
123
124
125void ObserverTest::doesBlockUpdateTest() {
126 callObservable->signOn(observer1);
127 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
128
129 callObservable->changeMethod1();
130 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
131
132 callObservable->changeMethod2();
133 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
134}
135
136void ObserverTest::doesSubObservableTest() {
137 superObservable->signOn(observer1);
138 superObservable->subObservable->signOn(observer2);
139
140 superObservable->subObservable->changeMethod();
141 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
142 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
143
144 superObservable->changeMethod();
145 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
146 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
147}
148
149void ObserverTest::outsideLockTest(){
150 callObservable->signOn(observer1);
151 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
152
153 {
154 LOCK_OBSERVABLE(*callObservable);
155 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
156 }
157 // lock is gone now, observer should have notified
158 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
159}
160
161void ObserverTest::doesNotifyTest(){
162 CPPUNIT_ASSERT_EQUAL(
163 (size_t)NotificationObservable::Operation1Notify,
164 notificationObservable->getChannel(NotificationObservable::Operation1Notify)->getChannelNo());
165 CPPUNIT_ASSERT_EQUAL(
166 (size_t)NotificationObservable::Operation2Notify,
167 notificationObservable->getChannel(NotificationObservable::Operation2Notify)->getChannelNo());
168 notificationObservable->signOn(notificationObserver1,
169 notificationObservable->getChannel(NotificationObservable::Operation1Notify));
170 notificationObservable->signOn(notificationObserver2,
171 notificationObservable->getChannel(NotificationObservable::Operation2Notify));
172
173 notificationObservable->operation1();
174 CPPUNIT_ASSERT(notificationObserver1->wasNotified);
175 CPPUNIT_ASSERT(!notificationObserver2->wasNotified);
176
177 notificationObserver1->wasNotified=false;
178
179 notificationObservable->operation2();
180 CPPUNIT_ASSERT(!notificationObserver1->wasNotified);
181 CPPUNIT_ASSERT(notificationObserver2->wasNotified);
182
183}
184
185void ObserverTest::doesReportTest(){
186 // Actual checks are in the Stub-methods for this
187 blockObservable->changeMethod1();
188 blockObservable->changeMethod2();
189 blockObservable->noChangeMethod();
190}
191
192void ObserverTest::iteratorTest(){
193 int i = 0;
194 // test the general iterator methods
195 for(ObservableSet::iterator iter=obsset->begin(); iter!=obsset->end();++iter){
196 CPPUNIT_ASSERT(i< obsset->num);
197 i++;
198 }
199
200 i=0;
201 for(ObservableSet::const_iterator iter=obsset->begin(); iter!=obsset->end();++iter){
202 CPPUNIT_ASSERT(i<obsset->num);
203 i++;
204 }
205
206 obsset->signOn(observer1);
207 {
208 // we construct this out of the loop, so the iterator dies at the end of
209 // the scope and not the end of the loop (allows more testing)
210 ObservableSet::iterator iter;
211 for(iter=obsset->begin(); iter!=obsset->end(); ++iter){
212 (*iter)->changeMethod();
213 }
214 // At this point no change should have been propagated
215 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates);
216 }
217 // After the Iterator has died the propagation should take place
218 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
219
220 // when using a const_iterator no changes should be propagated
221 for(ObservableSet::const_iterator iter = obsset->begin(); iter!=obsset->end();++iter);
222 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
223
224 // we need to test the operator-> as well
225 obsmap->signOn(observer2);
226 {
227 // we construct this out of the loop, so the iterator dies at the end of
228 // the scope and not the end of the loop (allows more testing)
229 ObservableMap::iterator iter;
230 for(iter=obsmap->begin(); iter!=obsmap->end(); ++iter){
231 iter->second->changeMethod();
232 }
233 // At this point no change should have been propagated
234 CPPUNIT_ASSERT_EQUAL( 0, observer2->updates);
235 }
236 // After the Iterator has died the propagation should take place
237 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates);
238
239
240 obsset->signOff(observer1);
241 obsmap->signOff(observer2);
242}
243
244void ObserverTest::CircleDetectionTest() {
245 std::cout << std::endl << "Warning: the next test involved methods that can produce infinite loops." << std::endl;
246 std::cout << "Errors in this methods can not be checked using the CPPUNIT_ASSERT Macros." << std::endl;
247 std::cout << "Instead tests are run on these methods to see if termination is assured" << std::endl << std::endl;
248 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;
249
250 std::cout << std::endl << std::endl << "The following errors displayed by the observer framework can be ignored" << std::endl;
251
252 // make this Observable its own subject. NEVER DO THIS IN ACTUAL CODE
253 simpleObservable1->signOn(simpleObservable1);
254#ifndef NDEBUG
255 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
256#else
257 simpleObservable1->changeMethod();
258#endif
259
260 // more complex test
261 simpleObservable1->signOff(simpleObservable1);
262 simpleObservable1->signOn(simpleObservable2);
263 simpleObservable2->signOn(simpleObservable1);
264#ifndef NDEBUG
265 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
266#else
267 simpleObservable1->changeMethod();
268#endif
269
270
271 simpleObservable1->signOff(simpleObservable2);
272 simpleObservable2->signOff(simpleObservable1);
273 // when we reach this line, although we broke the DAG assumption the circle check works fine
274 CPPUNIT_ASSERT(true);
275}
Note: See TracBrowser for help on using the repository browser.