source: src/unittests/ObserverTest.cpp@ 36166d

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 36166d was 7a176b, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Repaired ObserverUnittest for -DNDEBUG build mode

  • Property mode set to 100644
File size: 10.4 KB
Line 
1/*
2 * ObserverTest.cpp
3 *
4 * Created on: Jan 19, 2010
5 * Author: crueger
6 */
7
8#include "ObserverTest.hpp"
9
10#include <cppunit/CompilerOutputter.h>
11#include <cppunit/extensions/TestFactoryRegistry.h>
12#include <cppunit/ui/text/TestRunner.h>
13#include <set>
14
15#include "Patterns/Observer.hpp"
16#include "Patterns/ObservedIterator.hpp"
17#include "Helpers/Assert.hpp"
18
19#include <iostream>
20
21using namespace std;
22
23#ifdef HAVE_TESTRUNNER
24#include "UnitTestMain.hpp"
25#endif /*HAVE_TESTRUNNER*/
26
27// Registers the fixture into the 'registry'
28CPPUNIT_TEST_SUITE_REGISTRATION( ObserverTest );
29
30/******************* Test stubs ************************/
31
32class UpdateCountObserver : public Observer {
33public:
34 UpdateCountObserver() :
35 Observer("UpdateCountObserver"),
36 updates(0)
37 {};
38 void update(Observable *publisher){
39 updates++;
40 }
41 void subjectKilled(Observable *publisher) {
42 }
43 int updates;
44};
45
46class SimpleObservable : public Observable {
47public:
48 SimpleObservable() :
49 Observable("SimpleObservable")
50 {}
51
52 void changeMethod() {
53 OBSERVE;
54 int i = 0;
55 i++;
56 }
57};
58
59class CallObservable : public Observable {
60public:
61 CallObservable() :
62 Observable("CallObservable")
63 {}
64
65 void changeMethod1() {
66 OBSERVE;
67 int i = 0;
68 i++;
69 }
70
71 void changeMethod2() {
72 OBSERVE;
73 int i = 0;
74 i++;
75 changeMethod1();
76 }
77};
78
79class BlockObservable : public Observable {
80public:
81 BlockObservable() :
82 Observable("BlockObservable")
83 {}
84
85 void changeMethod1(){
86 OBSERVE;
87 // test if we report correctly as blocked
88 CPPUNIT_ASSERT(isBlocked());
89 }
90
91 void changeMethod2(){
92 OBSERVE;
93 internalMethod1();
94 internalMethod2();
95 }
96
97 void internalMethod1(){
98 // we did not block, but our caller did...
99 // see if this is found
100 CPPUNIT_ASSERT(isBlocked());
101 }
102
103 void internalMethod2(){
104 OBSERVE;
105 // Both this method and the caller do block
106 // Does the reporting still work as expected?
107 CPPUNIT_ASSERT(isBlocked());
108 }
109
110 void noChangeMethod(){
111 // No Block introduced here
112 // reported correctely?
113 CPPUNIT_ASSERT(!isBlocked());
114 }
115};
116
117class SuperObservable : public Observable {
118public:
119 SuperObservable():
120 Observable("SuperObservable")
121 {
122 subObservable = new SimpleObservable();
123 subObservable->signOn(this);
124 }
125 ~SuperObservable(){
126 delete subObservable;
127 }
128 void changeMethod() {
129 OBSERVE;
130 int i = 0;
131 i++;
132 subObservable->changeMethod();
133 }
134 SimpleObservable *subObservable;
135};
136
137class NotificationObservable : public Observable {
138public:
139 NotificationObservable() :
140 Observable("NotificationObservable"),
141 notification1(new Notification(this)),
142 notification2(new Notification(this))
143 {}
144
145 ~NotificationObservable(){
146 delete notification1;
147 delete notification2;
148 }
149
150 void operation1(){
151 OBSERVE;
152 NOTIFY(notification1);
153 }
154
155 void operation2(){
156 OBSERVE;
157 NOTIFY(notification2);
158 }
159
160 Notification_ptr notification1;
161 Notification_ptr notification2;
162};
163
164class NotificationObserver : public Observer {
165public:
166 NotificationObserver(Notification_ptr notification) :
167 Observer("NotificationObserver"),
168 requestedNotification(notification),
169 wasNotified(false)
170 {}
171
172 void update(Observable*){}
173 void subjectKilled(Observable*){}
174 void recieveNotification(Observable *publisher, Notification_ptr notification){
175 ASSERT(requestedNotification==notification,"Notification received that was not requested");
176 wasNotified = true;
177 }
178
179 Notification_ptr requestedNotification;
180
181 bool wasNotified;
182};
183
184class ObservableCollection : public Observable {
185public:
186 typedef std::set<SimpleObservable*> set;
187 typedef ObservedIterator<set> iterator;
188 typedef set::const_iterator const_iterator;
189
190 ObservableCollection(int _num) :
191 Observable("ObservableCollection"),
192 num(_num)
193 {
194 for(int i=0; i<num; ++i){
195 SimpleObservable *content = new SimpleObservable();
196 content->signOn(this);
197 theSet.insert(content);
198 }
199 }
200
201 ~ObservableCollection(){
202 set::iterator iter;
203 for(iter=theSet.begin(); iter!=theSet.end(); ++iter ){
204 delete (*iter);
205 }
206 }
207
208 iterator begin(){
209 return iterator(theSet.begin(),this);
210 }
211
212 iterator end(){
213 return iterator(theSet.end(),this);
214 }
215
216 const int num;
217
218private:
219 set theSet;
220};
221
222
223/******************* actuall tests ***************/
224
225void ObserverTest::setUp() {
226 ASSERT_DO(Assert::Throw);
227 simpleObservable1 = new SimpleObservable();
228 simpleObservable2 = new SimpleObservable();
229 callObservable = new CallObservable();
230 superObservable = new SuperObservable();
231 blockObservable = new BlockObservable();
232 notificationObservable = new NotificationObservable();
233 collection = new ObservableCollection(5);
234
235 observer1 = new UpdateCountObserver();
236 observer2 = new UpdateCountObserver();
237 observer3 = new UpdateCountObserver();
238 observer4 = new UpdateCountObserver();
239
240 notificationObserver1 = new NotificationObserver(notificationObservable->notification1);
241 notificationObserver2 = new NotificationObserver(notificationObservable->notification2);
242}
243
244void ObserverTest::tearDown() {
245 delete simpleObservable1;
246 delete simpleObservable2;
247 delete callObservable;
248 delete superObservable;
249 delete blockObservable;
250 delete notificationObservable;
251 delete collection;
252
253 delete observer1;
254 delete observer2;
255 delete observer3;
256 delete observer4;
257 delete notificationObserver1;
258 delete notificationObserver2;
259}
260
261void ObserverTest::doesUpdateTest()
262{
263 simpleObservable1->signOn(observer1);
264 simpleObservable1->signOn(observer2);
265 simpleObservable1->signOn(observer3);
266
267 simpleObservable2->signOn(observer2);
268 simpleObservable2->signOn(observer4);
269
270 simpleObservable1->changeMethod();
271 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
272 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
273 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
274 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
275
276 simpleObservable1->signOff(observer3);
277
278 simpleObservable1->changeMethod();
279 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
280 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
281 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
282 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
283
284 simpleObservable2->changeMethod();
285 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
286 CPPUNIT_ASSERT_EQUAL( 3, observer2->updates );
287 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
288 CPPUNIT_ASSERT_EQUAL( 1, observer4->updates );
289}
290
291
292void ObserverTest::doesBlockUpdateTest() {
293 callObservable->signOn(observer1);
294
295 callObservable->changeMethod1();
296 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
297
298 callObservable->changeMethod2();
299 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
300}
301
302void ObserverTest::doesSubObservableTest() {
303 superObservable->signOn(observer1);
304 superObservable->subObservable->signOn(observer2);
305
306 superObservable->subObservable->changeMethod();
307 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
308 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
309
310 superObservable->changeMethod();
311 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
312 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
313}
314
315void ObserverTest::doesNotifyTest(){
316 notificationObservable->signOn(notificationObserver1,
317 notificationObservable->notification1);
318 notificationObservable->signOn(notificationObserver2,
319 notificationObservable->notification2);
320
321 notificationObservable->operation1();
322 CPPUNIT_ASSERT(notificationObserver1->wasNotified);
323 CPPUNIT_ASSERT(!notificationObserver2->wasNotified);
324
325 notificationObserver1->wasNotified=false;
326
327 notificationObservable->operation2();
328 CPPUNIT_ASSERT(!notificationObserver1->wasNotified);
329 CPPUNIT_ASSERT(notificationObserver2->wasNotified);
330
331}
332
333void ObserverTest::doesReportTest(){
334 // Actual checks are in the Stub-methods for this
335 blockObservable->changeMethod1();
336 blockObservable->changeMethod2();
337 blockObservable->noChangeMethod();
338}
339
340void ObserverTest::iteratorTest(){
341 int i = 0;
342 // test the general iterator methods
343 for(ObservableCollection::iterator iter=collection->begin(); iter!=collection->end();++iter){
344 CPPUNIT_ASSERT(i< collection->num);
345 i++;
346 }
347
348 i=0;
349 for(ObservableCollection::const_iterator iter=collection->begin(); iter!=collection->end();++iter){
350 CPPUNIT_ASSERT(i<collection->num);
351 i++;
352 }
353
354 collection->signOn(observer1);
355 {
356 // we construct this out of the loop, so the iterator dies at the end of
357 // the scope and not the end of the loop (allows more testing)
358 ObservableCollection::iterator iter;
359 for(iter=collection->begin(); iter!=collection->end(); ++iter){
360 (*iter)->changeMethod();
361 }
362 // At this point no change should have been propagated
363 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates);
364 }
365 // After the Iterator has died the propagation should take place
366 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
367
368 // when using a const_iterator no changes should be propagated
369 for(ObservableCollection::const_iterator iter = collection->begin(); iter!=collection->end();++iter);
370 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
371 collection->signOff(observer1);
372}
373
374void ObserverTest::CircleDetectionTest() {
375 cout << endl << "Warning: the next test involved methods that can produce infinite loops." << endl;
376 cout << "Errors in this methods can not be checked using the CPPUNIT_ASSERT Macros." << endl;
377 cout << "Instead tests are run on these methods to see if termination is assured" << endl << endl;
378 cout << "If this test does not complete in a few seconds, kill the test-suite and fix the Error in the circle detection mechanism" << endl;
379
380 cout << endl << endl << "The following errors displayed by the observer framework can be ignored" << endl;
381
382 // make this Observable its own subject. NEVER DO THIS IN ACTUAL CODE
383 simpleObservable1->signOn(simpleObservable1);
384#ifndef NDEBUG
385 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
386#else
387 simpleObservable1->changeMethod();
388#endif
389
390 // more complex test
391 simpleObservable1->signOff(simpleObservable1);
392 simpleObservable1->signOn(simpleObservable2);
393 simpleObservable2->signOn(simpleObservable1);
394#ifndef NDEBUG
395 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
396#else
397 simpleObservable1->changeMethod();
398#endif
399
400
401 simpleObservable1->signOff(simpleObservable2);
402 simpleObservable2->signOff(simpleObservable1);
403 // when we reach this line, although we broke the DAG assumption the circle check works fine
404 CPPUNIT_ASSERT(true);
405}
Note: See TracBrowser for help on using the repository browser.