source: src/unittests/ObserverTest.cpp@ c66537

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 c66537 was bcf653, checked in by Frederik Heber <heber@…>, 15 years ago

Added copyright note to each .cpp file and an extensive one to builder.cpp.

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