source: src/Patterns/unittests/ObserverUnitTest.cpp@ 56d62f

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

Placed various Observer stubs into own module.

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