source: src/unittests/ObserverTest.cpp@ 05a97c

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 05a97c was b64313, checked in by Tillmann Crueger <crueger@…>, 15 years ago

Improved Observer Framework to include methods to report the state

  • bool Observable::isBlocked() will tell if the Observer is currently updating itself
  • The Circle detection test now uses ASSERT to report when a circle was detected (can be caught by CPPUNIT)
  • Property mode set to 100644
File size: 7.1 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 updates(0)
36 {};
37 void update(Observable *publisher){
38 updates++;
39 }
40 void subjectKilled(Observable *publisher) {
41 }
42 int updates;
43};
44
45class SimpleObservable : public Observable {
46public:
47 void changeMethod() {
48 OBSERVE;
49 int i = 0;
50 i++;
51 }
52};
53
54class CallObservable : public Observable {
55public:
56 void changeMethod1() {
57 OBSERVE;
58 int i = 0;
59 i++;
60 }
61
62 void changeMethod2() {
63 OBSERVE;
64 int i = 0;
65 i++;
66 changeMethod1();
67 }
68};
69
70class BlockObservable : public Observable {
71public:
72 void changeMethod1(){
73 OBSERVE;
74 // test if we report correctly as blocked
75 CPPUNIT_ASSERT(isBlocked());
76 }
77
78 void changeMethod2(){
79 OBSERVE;
80 internalMethod1();
81 internalMethod2();
82 }
83
84 void internalMethod1(){
85 // we did not block, but our caller did...
86 // see if this is found
87 CPPUNIT_ASSERT(isBlocked());
88 }
89
90 void internalMethod2(){
91 OBSERVE;
92 // Both this method and the caller do block
93 // Does the reporting still work as expected?
94 CPPUNIT_ASSERT(isBlocked());
95 }
96
97 void noChangeMethod(){
98 // No Block introduced here
99 // reported correctely?
100 CPPUNIT_ASSERT(!isBlocked());
101 }
102};
103
104class SuperObservable : public Observable {
105public:
106 SuperObservable(){
107 subObservable = new SimpleObservable();
108 subObservable->signOn(this);
109 }
110 ~SuperObservable(){
111 delete subObservable;
112 }
113 void changeMethod() {
114 OBSERVE;
115 int i = 0;
116 i++;
117 subObservable->changeMethod();
118 }
119 SimpleObservable *subObservable;
120};
121
122class ObservableCollection : public Observable {
123public:
124 typedef std::set<SimpleObservable*> set;
125 typedef ObservedIterator<set> iterator;
126
127 ObservableCollection(int num){
128 for(int i=0; i<num; ++i){
129 SimpleObservable *content = new SimpleObservable();
130 content->signOn(this);
131 theSet.insert(content);
132 }
133 }
134
135 ~ObservableCollection(){
136 set::iterator iter;
137 for(iter=theSet.begin(); iter!=theSet.end(); ++iter ){
138 delete (*iter);
139 }
140 }
141
142 iterator begin(){
143 return iterator(theSet.begin(),this);
144 }
145
146 iterator end(){
147 return iterator(theSet.end(),this);
148 }
149
150private:
151 set theSet;
152};
153
154/******************* actuall tests ***************/
155
156void ObserverTest::setUp() {
157 ASSERT_DO(Assert::Throw);
158 simpleObservable1 = new SimpleObservable();
159 simpleObservable2 = new SimpleObservable();
160 callObservable = new CallObservable();
161 superObservable = new SuperObservable();
162 blockObservable = new BlockObservable();
163
164 observer1 = new UpdateCountObserver();
165 observer2 = new UpdateCountObserver();
166 observer3 = new UpdateCountObserver();
167 observer4 = new UpdateCountObserver();
168
169 collection = new ObservableCollection(5);
170}
171
172void ObserverTest::tearDown() {
173 delete simpleObservable1;
174 delete simpleObservable2;
175 delete callObservable;
176 delete superObservable;
177
178 delete observer1;
179 delete observer2;
180 delete observer3;
181 delete observer4;
182
183 delete collection;
184}
185
186void ObserverTest::doesUpdateTest()
187{
188 simpleObservable1->signOn(observer1);
189 simpleObservable1->signOn(observer2);
190 simpleObservable1->signOn(observer3);
191
192 simpleObservable2->signOn(observer2);
193 simpleObservable2->signOn(observer4);
194
195 simpleObservable1->changeMethod();
196 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
197 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
198 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
199 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
200
201 simpleObservable1->signOff(observer3);
202
203 simpleObservable1->changeMethod();
204 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
205 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
206 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
207 CPPUNIT_ASSERT_EQUAL( 0, observer4->updates );
208
209 simpleObservable2->changeMethod();
210 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
211 CPPUNIT_ASSERT_EQUAL( 3, observer2->updates );
212 CPPUNIT_ASSERT_EQUAL( 1, observer3->updates );
213 CPPUNIT_ASSERT_EQUAL( 1, observer4->updates );
214}
215
216
217void ObserverTest::doesBlockUpdateTest() {
218 callObservable->signOn(observer1);
219
220 callObservable->changeMethod1();
221 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
222
223 callObservable->changeMethod2();
224 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
225}
226
227void ObserverTest::doesSubObservableTest() {
228 superObservable->signOn(observer1);
229 superObservable->subObservable->signOn(observer2);
230
231 superObservable->subObservable->changeMethod();
232 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates );
233 CPPUNIT_ASSERT_EQUAL( 1, observer2->updates );
234
235 superObservable->changeMethod();
236 CPPUNIT_ASSERT_EQUAL( 2, observer1->updates );
237 CPPUNIT_ASSERT_EQUAL( 2, observer2->updates );
238}
239
240void ObserverTest::doesReportTest(){
241 // Actual checks are in the Stub-methods for this
242 blockObservable->changeMethod1();
243 blockObservable->changeMethod2();
244 blockObservable->noChangeMethod();
245}
246
247void ObserverTest::iteratorTest(){
248 collection->signOn(observer1);
249 {
250 ObservableCollection::iterator iter;
251 for(iter=collection->begin(); iter!=collection->end(); ++iter){
252 (*iter)->changeMethod();
253 }
254 // At this point no change should have been propagated
255 CPPUNIT_ASSERT_EQUAL( 0, observer1->updates);
256 }
257 // After the Iterator has died the propagation should take place
258 CPPUNIT_ASSERT_EQUAL( 1, observer1->updates);
259 collection->signOff(observer1);
260}
261
262
263void ObserverTest::CircleDetectionTest() {
264 cout << endl << "Warning: the next test involved methods that can produce infinite loops." << endl;
265 cout << "Errors in this methods can not be checked using the CPPUNIT_ASSERT Macros." << endl;
266 cout << "Instead tests are run on these methods to see if termination is assured" << endl << endl;
267 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;
268
269 cout << endl << endl << "The following errors displayed by the observer framework can be ignored" << endl;
270
271 // make this Observable its own subject. NEVER DO THIS IN ACTUAL CODE
272 simpleObservable1->signOn(simpleObservable1);
273 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
274
275 // more complex test
276 simpleObservable1->signOff(simpleObservable1);
277 simpleObservable1->signOn(simpleObservable2);
278 simpleObservable2->signOn(simpleObservable1);
279 CPPUNIT_ASSERT_THROW(simpleObservable1->changeMethod(),Assert::AssertionFailure);
280 simpleObservable1->signOff(simpleObservable2);
281 simpleObservable2->signOff(simpleObservable1);
282 // when we reach this line, although we broke the DAG assumption the circle check works fine
283 CPPUNIT_ASSERT(true);
284}
Note: See TracBrowser for help on using the repository browser.