source: src/unittests/ObserverTest.cpp@ 906822

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 906822 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
RevLine 
[63c1f6]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>
[bd58fb]13#include <set>
[63c1f6]14
15#include "Patterns/Observer.hpp"
[bd58fb]16#include "Patterns/ObservedIterator.hpp"
[4fb5a3]17#include "Helpers/Assert.hpp"
[63c1f6]18
19#include <iostream>
20
21using namespace std;
22
[9b6b2f]23#ifdef HAVE_TESTRUNNER
24#include "UnitTestMain.hpp"
25#endif /*HAVE_TESTRUNNER*/
26
[63c1f6]27// Registers the fixture into the 'registry'
28CPPUNIT_TEST_SUITE_REGISTRATION( ObserverTest );
29
30/******************* Test stubs ************************/
31
32class UpdateCountObserver : public Observer {
33public:
34 UpdateCountObserver() :
[cd5047]35 Observer("UpdateCountObserver"),
[63c1f6]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:
[cd5047]48 SimpleObservable() :
49 Observable("SimpleObservable")
50 {}
51
[63c1f6]52 void changeMethod() {
[317df8]53 OBSERVE;
[5e5283]54 int i = 0;
[63c1f6]55 i++;
56 }
57};
58
59class CallObservable : public Observable {
60public:
[cd5047]61 CallObservable() :
62 Observable("CallObservable")
63 {}
64
[63c1f6]65 void changeMethod1() {
[317df8]66 OBSERVE;
[5e5283]67 int i = 0;
[63c1f6]68 i++;
69 }
70
71 void changeMethod2() {
[317df8]72 OBSERVE;
[5e5283]73 int i = 0;
[63c1f6]74 i++;
75 changeMethod1();
76 }
77};
78
[4fb5a3]79class BlockObservable : public Observable {
80public:
[cd5047]81 BlockObservable() :
82 Observable("BlockObservable")
83 {}
84
[4fb5a3]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
[63c1f6]117class SuperObservable : public Observable {
118public:
[cd5047]119 SuperObservable():
120 Observable("SuperObservable")
121 {
[63c1f6]122 subObservable = new SimpleObservable();
123 subObservable->signOn(this);
124 }
125 ~SuperObservable(){
126 delete subObservable;
127 }
128 void changeMethod() {
[317df8]129 OBSERVE;
[5e5283]130 int i = 0;
[63c1f6]131 i++;
132 subObservable->changeMethod();
133 }
134 SimpleObservable *subObservable;
135};
136
[ccacba]137class NotificationObservable : public Observable {
138public:
139 NotificationObservable() :
[cd5047]140 Observable("NotificationObservable"),
141 notification1(new Notification(this)),
142 notification2(new Notification(this))
[ccacba]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) :
[cd5047]167 Observer("NotificationObserver"),
[ccacba]168 requestedNotification(notification),
169 wasNotified(false)
170 {}
171
172 void update(Observable*){}
173 void subjectKilled(Observable*){}
174 void recieveNotification(Observable *publisher, Notification_ptr notification){
[033a05]175 ASSERT(requestedNotification==notification,"Notification received that was not requested");
[ccacba]176 wasNotified = true;
177 }
178
179 Notification_ptr requestedNotification;
180
181 bool wasNotified;
182};
183
[bd58fb]184class ObservableCollection : public Observable {
185public:
186 typedef std::set<SimpleObservable*> set;
187 typedef ObservedIterator<set> iterator;
[a7b761b]188 typedef set::const_iterator const_iterator;
[bd58fb]189
[a7b761b]190 ObservableCollection(int _num) :
[cd5047]191 Observable("ObservableCollection"),
192 num(_num)
[a7b761b]193 {
[bd58fb]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
[a7b761b]216 const int num;
217
[bd58fb]218private:
219 set theSet;
220};
221
[a7b761b]222
[63c1f6]223/******************* actuall tests ***************/
224
225void ObserverTest::setUp() {
[4fb5a3]226 ASSERT_DO(Assert::Throw);
[d5f216]227 simpleObservable1 = new SimpleObservable();
228 simpleObservable2 = new SimpleObservable();
[63c1f6]229 callObservable = new CallObservable();
230 superObservable = new SuperObservable();
[4fb5a3]231 blockObservable = new BlockObservable();
[ccacba]232 notificationObservable = new NotificationObservable();
[a7b761b]233 collection = new ObservableCollection(5);
[63c1f6]234
235 observer1 = new UpdateCountObserver();
236 observer2 = new UpdateCountObserver();
237 observer3 = new UpdateCountObserver();
[d5f216]238 observer4 = new UpdateCountObserver();
[ccacba]239
240 notificationObserver1 = new NotificationObserver(notificationObservable->notification1);
241 notificationObserver2 = new NotificationObserver(notificationObservable->notification2);
[63c1f6]242}
243
244void ObserverTest::tearDown() {
[d5f216]245 delete simpleObservable1;
246 delete simpleObservable2;
[63c1f6]247 delete callObservable;
248 delete superObservable;
[033a05]249 delete blockObservable;
[ccacba]250 delete notificationObservable;
[a7b761b]251 delete collection;
[63c1f6]252
253 delete observer1;
254 delete observer2;
255 delete observer3;
[d5f216]256 delete observer4;
[ccacba]257 delete notificationObserver1;
258 delete notificationObserver2;
[63c1f6]259}
260
261void ObserverTest::doesUpdateTest()
262{
[d5f216]263 simpleObservable1->signOn(observer1);
264 simpleObservable1->signOn(observer2);
265 simpleObservable1->signOn(observer3);
[9b6b2f]266
[d5f216]267 simpleObservable2->signOn(observer2);
268 simpleObservable2->signOn(observer4);
[63c1f6]269
[d5f216]270 simpleObservable1->changeMethod();
[63c1f6]271 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
272 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
273 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
[d5f216]274 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
[63c1f6]275
[d5f216]276 simpleObservable1->signOff(observer3);
[63c1f6]277
[d5f216]278 simpleObservable1->changeMethod();
[63c1f6]279 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
280 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
281 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
[d5f216]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 );
[63c1f6]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
[ccacba]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
[4fb5a3]333void ObserverTest::doesReportTest(){
334 // Actual checks are in the Stub-methods for this
335 blockObservable->changeMethod1();
336 blockObservable->changeMethod2();
337 blockObservable->noChangeMethod();
338}
[63c1f6]339
[bd58fb]340void ObserverTest::iteratorTest(){
[a7b761b]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
[bd58fb]354 collection->signOn(observer1);
355 {
[a7b761b]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)
[bd58fb]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);
[a7b761b]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);
[bd58fb]371 collection->signOff(observer1);
372}
373
[63c1f6]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
[d5f216]380 cout << endl << endl << "The following errors displayed by the observer framework can be ignored" << endl;
[63c1f6]381
382 // make this Observable its own subject. NEVER DO THIS IN ACTUAL CODE
[d5f216]383 simpleObservable1->signOn(simpleObservable1);
[7a176b]384#ifndef NDEBUG
[4fb5a3]385 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
[7a176b]386#else
387 simpleObservable1->changeMethod();
388#endif
[d5f216]389
390 // more complex test
391 simpleObservable1->signOff(simpleObservable1);
392 simpleObservable1->signOn(simpleObservable2);
393 simpleObservable2->signOn(simpleObservable1);
[7a176b]394#ifndef NDEBUG
[4fb5a3]395 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
[7a176b]396#else
397 simpleObservable1->changeMethod();
398#endif
399
400
[d5f216]401 simpleObservable1->signOff(simpleObservable2);
402 simpleObservable2->signOff(simpleObservable1);
[63c1f6]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.