source: src/Patterns/unittests/ObserverUnitTest.cpp@ 9e776f

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

Extended Observables by NotificationChannels member variable.

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