source: src/Patterns/Observer/unittests/ObserverUnitTest.cpp@ 2c11c1

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

Modified ObserverLog: Singleton and both output to screen and internal Log.

  • ObserverLog can now either be printed concurrently or later requested as string (e.g. on exit as has been done before). This should ease debugging Observer code.
  • enable/disableLogging() (dis)activate printing to screen.
  • ObserverLog is now a true singleton.

Details:

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