source: src/unittests/ObserverTest.cpp@ 3839e5

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 3839e5 was 8774c5, checked in by Tillmann Crueger <crueger@…>, 14 years ago

Added operator-> for Observed Iterators

  • Property mode set to 100644
File size: 12.2 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 ObservableSet : public Observable {
185public:
186 typedef std::set<SimpleObservable*> set;
187 typedef ObservedIterator<set> iterator;
188 typedef set::const_iterator const_iterator;
189
190 ObservableSet(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 ~ObservableSet(){
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
222class ObservableMap : public Observable {
223public:
224 typedef std::map<int,SimpleObservable*> set;
225 typedef ObservedIterator<set> iterator;
226 typedef set::const_iterator const_iterator;
227
228 ObservableMap(int _num) :
229 Observable("ObservableCollection"),
230 num(_num)
231 {
232 for(int i=0; i<num; ++i){
233 SimpleObservable *content = new SimpleObservable();
234 content->signOn(this);
235 theSet.insert(make_pair(i,content));
236 }
237 }
238
239 ~ObservableMap(){
240 set::iterator iter;
241 for(iter=theSet.begin(); iter!=theSet.end(); ++iter ){
242 delete iter->second;
243 }
244 }
245
246 iterator begin(){
247 return iterator(theSet.begin(),this);
248 }
249
250 iterator end(){
251 return iterator(theSet.end(),this);
252 }
253
254 const int num;
255
256private:
257 set theSet;
258};
259
260
261/******************* actuall tests ***************/
262
263void ObserverTest::setUp() {
264 ASSERT_DO(Assert::Throw);
265 simpleObservable1 = new SimpleObservable();
266 simpleObservable2 = new SimpleObservable();
267 callObservable = new CallObservable();
268 superObservable = new SuperObservable();
269 blockObservable = new BlockObservable();
270 notificationObservable = new NotificationObservable();
271 obsset = new ObservableSet(5);
272 obsmap = new ObservableMap(5);
273
274 observer1 = new UpdateCountObserver();
275 observer2 = new UpdateCountObserver();
276 observer3 = new UpdateCountObserver();
277 observer4 = new UpdateCountObserver();
278
279 notificationObserver1 = new NotificationObserver(notificationObservable->notification1);
280 notificationObserver2 = new NotificationObserver(notificationObservable->notification2);
281}
282
283void ObserverTest::tearDown() {
284 delete simpleObservable1;
285 delete simpleObservable2;
286 delete callObservable;
287 delete superObservable;
288 delete blockObservable;
289 delete notificationObservable;
290 delete obsset;
291 delete obsmap;
292
293 delete observer1;
294 delete observer2;
295 delete observer3;
296 delete observer4;
297 delete notificationObserver1;
298 delete notificationObserver2;
299}
300
301void ObserverTest::doesUpdateTest()
302{
303 simpleObservable1->signOn(observer1);
304 simpleObservable1->signOn(observer2);
305 simpleObservable1->signOn(observer3);
306
307 simpleObservable2->signOn(observer2);
308 simpleObservable2->signOn(observer4);
309
310 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
311 CPPUNIT_ASSERT_EQUAL( 0, observer2->updates );
312 CPPUNIT_ASSERT_EQUAL( 0, observer3->updates );
313 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
314
315
316 simpleObservable1->changeMethod();
317 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
318 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
319 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
320 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
321
322 simpleObservable1->signOff(observer3);
323
324 simpleObservable1->changeMethod();
325 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
326 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
327 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
328 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
329
330 simpleObservable2->changeMethod();
331 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
332 CPPUNIT_ASSERT_EQUAL( 3, observer2->updates );
333 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
334 CPPUNIT_ASSERT_EQUAL( 1, observer4->updates );
335}
336
337
338void ObserverTest::doesBlockUpdateTest() {
339 callObservable->signOn(observer1);
340 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
341
342 callObservable->changeMethod1();
343 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
344
345 callObservable->changeMethod2();
346 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
347}
348
349void ObserverTest::doesSubObservableTest() {
350 superObservable->signOn(observer1);
351 superObservable->subObservable->signOn(observer2);
352
353 superObservable->subObservable->changeMethod();
354 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
355 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
356
357 superObservable->changeMethod();
358 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
359 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
360}
361
362void ObserverTest::outsideLockTest(){
363 callObservable->signOn(observer1);
364 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
365
366 {
367 LOCK_OBSERVABLE(*callObservable);
368 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates );
369 }
370 // lock is gone now, observer should have notified
371 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
372}
373
374void ObserverTest::doesNotifyTest(){
375 notificationObservable->signOn(notificationObserver1,
376 notificationObservable->notification1);
377 notificationObservable->signOn(notificationObserver2,
378 notificationObservable->notification2);
379
380 notificationObservable->operation1();
381 CPPUNIT_ASSERT(notificationObserver1->wasNotified);
382 CPPUNIT_ASSERT(!notificationObserver2->wasNotified);
383
384 notificationObserver1->wasNotified=false;
385
386 notificationObservable->operation2();
387 CPPUNIT_ASSERT(!notificationObserver1->wasNotified);
388 CPPUNIT_ASSERT(notificationObserver2->wasNotified);
389
390}
391
392void ObserverTest::doesReportTest(){
393 // Actual checks are in the Stub-methods for this
394 blockObservable->changeMethod1();
395 blockObservable->changeMethod2();
396 blockObservable->noChangeMethod();
397}
398
399void ObserverTest::iteratorTest(){
400 int i = 0;
401 // test the general iterator methods
402 for(ObservableSet::iterator iter=obsset->begin(); iter!=obsset->end();++iter){
403 CPPUNIT_ASSERT(i< obsset->num);
404 i++;
405 }
406
407 i=0;
408 for(ObservableSet::const_iterator iter=obsset->begin(); iter!=obsset->end();++iter){
409 CPPUNIT_ASSERT(i<obsset->num);
410 i++;
411 }
412
413 obsset->signOn(observer1);
414 {
415 // we construct this out of the loop, so the iterator dies at the end of
416 // the scope and not the end of the loop (allows more testing)
417 ObservableSet::iterator iter;
418 for(iter=obsset->begin(); iter!=obsset->end(); ++iter){
419 (*iter)->changeMethod();
420 }
421 // At this point no change should have been propagated
422 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates);
423 }
424 // After the Iterator has died the propagation should take place
425 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
426
427 // when using a const_iterator no changes should be propagated
428 for(ObservableSet::const_iterator iter = obsset->begin(); iter!=obsset->end();++iter);
429 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
430
431 // we need to test the operator-> as well
432 obsmap->signOn(observer2);
433 {
434 // we construct this out of the loop, so the iterator dies at the end of
435 // the scope and not the end of the loop (allows more testing)
436 ObservableMap::iterator iter;
437 for(iter=obsmap->begin(); iter!=obsmap->end(); ++iter){
438 iter->second->changeMethod();
439 }
440 // At this point no change should have been propagated
441 CPPUNIT_ASSERT_EQUAL( 0, observer2->updates);
442 }
443 // After the Iterator has died the propagation should take place
444 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates);
445
446
447 obsset->signOff(observer1);
448 obsmap->signOff(observer2);
449}
450
451void ObserverTest::CircleDetectionTest() {
452 cout << endl << "Warning: the next test involved methods that can produce infinite loops." << endl;
453 cout << "Errors in this methods can not be checked using the CPPUNIT_ASSERT Macros." << endl;
454 cout << "Instead tests are run on these methods to see if termination is assured" << endl << endl;
455 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;
456
457 cout << endl << endl << "The following errors displayed by the observer framework can be ignored" << endl;
458
459 // make this Observable its own subject. NEVER DO THIS IN ACTUAL CODE
460 simpleObservable1->signOn(simpleObservable1);
461#ifndef NDEBUG
462 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
463#else
464 simpleObservable1->changeMethod();
465#endif
466
467 // more complex test
468 simpleObservable1->signOff(simpleObservable1);
469 simpleObservable1->signOn(simpleObservable2);
470 simpleObservable2->signOn(simpleObservable1);
471#ifndef NDEBUG
472 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
473#else
474 simpleObservable1->changeMethod();
475#endif
476
477
478 simpleObservable1->signOff(simpleObservable2);
479 simpleObservable2->signOff(simpleObservable1);
480 // when we reach this line, although we broke the DAG assumption the circle check works fine
481 CPPUNIT_ASSERT(true);
482}
Note: See TracBrowser for help on using the repository browser.