source: src/unittests/ObserverTest.cpp@ 4c1230

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 4c1230 was bcf653, checked in by Frederik Heber <heber@…>, 14 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
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 "ObserverTest.hpp"
21
22#include <cppunit/CompilerOutputter.h>
23#include <cppunit/extensions/TestFactoryRegistry.h>
24#include <cppunit/ui/text/TestRunner.h>
25#include <set>
26
27#include "Patterns/Observer.hpp"
28#include "Patterns/ObservedIterator.hpp"
29#include "Helpers/Assert.hpp"
30
31#include <iostream>
32
33using namespace std;
34
35#ifdef HAVE_TESTRUNNER
36#include "UnitTestMain.hpp"
37#endif /*HAVE_TESTRUNNER*/
38
39// Registers the fixture into the 'registry'
40CPPUNIT_TEST_SUITE_REGISTRATION( ObserverTest );
41
42/******************* Test stubs ************************/
43
44class UpdateCountObserver : public Observer {
45public:
46 UpdateCountObserver() :
47 Observer("UpdateCountObserver"),
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:
60 SimpleObservable() :
61 Observable("SimpleObservable")
62 {}
63
64 void changeMethod() {
65 OBSERVE;
66 int i = 0;
67 i++;
68 }
69};
70
71class CallObservable : public Observable {
72public:
73 CallObservable() :
74 Observable("CallObservable")
75 {}
76
77 void changeMethod1() {
78 OBSERVE;
79 int i = 0;
80 i++;
81 }
82
83 void changeMethod2() {
84 OBSERVE;
85 int i = 0;
86 i++;
87 changeMethod1();
88 }
89};
90
91class BlockObservable : public Observable {
92public:
93 BlockObservable() :
94 Observable("BlockObservable")
95 {}
96
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
129class SuperObservable : public Observable {
130public:
131 SuperObservable():
132 Observable("SuperObservable")
133 {
134 subObservable = new SimpleObservable();
135 subObservable->signOn(this);
136 }
137 ~SuperObservable(){
138 delete subObservable;
139 }
140 void changeMethod() {
141 OBSERVE;
142 int i = 0;
143 i++;
144 subObservable->changeMethod();
145 }
146 SimpleObservable *subObservable;
147};
148
149class NotificationObservable : public Observable {
150public:
151 NotificationObservable() :
152 Observable("NotificationObservable"),
153 notification1(new Notification(this)),
154 notification2(new Notification(this))
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) :
179 Observer("NotificationObserver"),
180 requestedNotification(notification),
181 wasNotified(false)
182 {}
183
184 void update(Observable*){}
185 void subjectKilled(Observable*){}
186 void recieveNotification(Observable *publisher, Notification_ptr notification){
187 ASSERT(requestedNotification==notification,"Notification received that was not requested");
188 wasNotified = true;
189 }
190
191 Notification_ptr requestedNotification;
192
193 bool wasNotified;
194};
195
196class ObservableSet : public Observable {
197public:
198 typedef std::set<SimpleObservable*> set;
199 typedef ObservedIterator<set> iterator;
200 typedef set::const_iterator const_iterator;
201
202 ObservableSet(int _num) :
203 Observable("ObservableCollection"),
204 num(_num)
205 {
206 for(int i=0; i<num; ++i){
207 SimpleObservable *content = new SimpleObservable();
208 content->signOn(this);
209 theSet.insert(content);
210 }
211 }
212
213 ~ObservableSet(){
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
228 const int num;
229
230private:
231 set theSet;
232};
233
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
272
273/******************* actuall tests ***************/
274
275void ObserverTest::setUp() {
276 ASSERT_DO(Assert::Throw);
277 simpleObservable1 = new SimpleObservable();
278 simpleObservable2 = new SimpleObservable();
279 callObservable = new CallObservable();
280 superObservable = new SuperObservable();
281 blockObservable = new BlockObservable();
282 notificationObservable = new NotificationObservable();
283 obsset = new ObservableSet(5);
284 obsmap = new ObservableMap(5);
285
286 observer1 = new UpdateCountObserver();
287 observer2 = new UpdateCountObserver();
288 observer3 = new UpdateCountObserver();
289 observer4 = new UpdateCountObserver();
290
291 notificationObserver1 = new NotificationObserver(notificationObservable->notification1);
292 notificationObserver2 = new NotificationObserver(notificationObservable->notification2);
293}
294
295void ObserverTest::tearDown() {
296 delete simpleObservable1;
297 delete simpleObservable2;
298 delete callObservable;
299 delete superObservable;
300 delete blockObservable;
301 delete notificationObservable;
302 delete obsset;
303 delete obsmap;
304
305 delete observer1;
306 delete observer2;
307 delete observer3;
308 delete observer4;
309 delete notificationObserver1;
310 delete notificationObserver2;
311}
312
313void ObserverTest::doesUpdateTest()
314{
315 simpleObservable1->signOn(observer1);
316 simpleObservable1->signOn(observer2);
317 simpleObservable1->signOn(observer3);
318
319 simpleObservable2->signOn(observer2);
320 simpleObservable2->signOn(observer4);
321
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
328 simpleObservable1->changeMethod();
329 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
330 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
331 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
332 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
333
334 simpleObservable1->signOff(observer3);
335
336 simpleObservable1->changeMethod();
337 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
338 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
339 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
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 );
347}
348
349
350void ObserverTest::doesBlockUpdateTest() {
351 callObservable->signOn(observer1);
352 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
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
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
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
404void ObserverTest::doesReportTest(){
405 // Actual checks are in the Stub-methods for this
406 blockObservable->changeMethod1();
407 blockObservable->changeMethod2();
408 blockObservable->noChangeMethod();
409}
410
411void ObserverTest::iteratorTest(){
412 int i = 0;
413 // test the general iterator methods
414 for(ObservableSet::iterator iter=obsset->begin(); iter!=obsset->end();++iter){
415 CPPUNIT_ASSERT(i< obsset->num);
416 i++;
417 }
418
419 i=0;
420 for(ObservableSet::const_iterator iter=obsset->begin(); iter!=obsset->end();++iter){
421 CPPUNIT_ASSERT(i<obsset->num);
422 i++;
423 }
424
425 obsset->signOn(observer1);
426 {
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)
429 ObservableSet::iterator iter;
430 for(iter=obsset->begin(); iter!=obsset->end(); ++iter){
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);
438
439 // when using a const_iterator no changes should be propagated
440 for(ObservableSet::const_iterator iter = obsset->begin(); iter!=obsset->end();++iter);
441 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
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);
461}
462
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
469 cout << endl << endl << "The following errors displayed by the observer framework can be ignored" << endl;
470
471 // make this Observable its own subject. NEVER DO THIS IN ACTUAL CODE
472 simpleObservable1->signOn(simpleObservable1);
473#ifndef NDEBUG
474 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
475#else
476 simpleObservable1->changeMethod();
477#endif
478
479 // more complex test
480 simpleObservable1->signOff(simpleObservable1);
481 simpleObservable1->signOn(simpleObservable2);
482 simpleObservable2->signOn(simpleObservable1);
483#ifndef NDEBUG
484 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
485#else
486 simpleObservable1->changeMethod();
487#endif
488
489
490 simpleObservable1->signOff(simpleObservable2);
491 simpleObservable2->signOff(simpleObservable1);
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.