source: src/unittests/ObserverTest.cpp@ 13e3c3

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 13e3c3 was bf3817, checked in by Frederik Heber <heber@…>, 14 years ago

Added ifdef HAVE_CONFIG and config.h include to each and every cpp file.

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