source: src/Actions/unittests/ActionSequenceUnitTest.cpp@ d93d2c

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 d93d2c was 10aee4, checked in by Frederik Heber <heber@…>, 9 years ago

Cleaned up ActionQueue's interface: Actions are always cloned.

  • Action's dstor needs to be public as we have a clone() function.
  • ActionRegistrys' (and AQ's) getActionByName now returns const ref. We must not return a ptr as it may not get deleted elsewhere. We are handing out prototypes.
  • queueAction(action*,...) is private to prevent leakage, queueAction(string, ...) is the public interface.
  • some other small functions are now private, too.
  • MakroActions now need to clone() the prototype on prepare() and delete them on unprepare().
  • ActionSequence deletes contained actions.
  • FIX: ActionSequenceUnitTest cannot check on not-called property of removed actions anymore as these are gone now (they are deleted on removal and they are cloned on insertion).
  • DOCU: Updated documentation on Actions.
  • Property mode set to 100644
File size: 9.6 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24/*
25 * ActionSequenceUnitTest.cpp
26 *
27 * Created on: Dec 17, 2009
28 * Author: crueger
29 */
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include <cppunit/CompilerOutputter.h>
37#include <cppunit/extensions/TestFactoryRegistry.h>
38#include <cppunit/ui/text/TestRunner.h>
39
40#include "ActionSequenceUnitTest.hpp"
41#include "Actions/Action.hpp"
42#include "Actions/ActionQueue.hpp"
43#include "Actions/ActionSequence.hpp"
44#include "Actions/MakroAction.hpp"
45
46#include "stubs/DummyUI.hpp"
47
48using namespace MoleCuilder;
49
50#ifdef HAVE_TESTRUNNER
51#include "UnitTestMain.hpp"
52#endif /*HAVE_TESTRUNNER*/
53
54/********************************************** Test classes **************************************/
55
56// Registers the fixture into the 'registry'
57CPPUNIT_TEST_SUITE_REGISTRATION( ActionSequenceTest );
58
59/* some neccessary stubs for tests */
60class canUndoActionStub : public Action
61{
62public:
63 canUndoActionStub(const ActionTrait &_trait):
64 Action(_trait){}
65 virtual ~canUndoActionStub(){}
66
67 virtual Dialog* fillDialog(Dialog *dialog){
68 ASSERT(dialog,"No Dialog given when filling action dialog");
69 return dialog;
70 }
71
72 virtual ActionState::ptr performCall(){
73 return Action::success;
74 }
75 virtual ActionState::ptr performUndo(ActionState::ptr){
76 return Action::success;
77 }
78 virtual ActionState::ptr performRedo(ActionState::ptr){
79 return Action::success;
80 }
81 virtual bool canUndo(){
82 return true;
83 }
84 virtual bool shouldUndo(){
85 return true;
86 }
87 Action* clone(enum QueryOptions flag = Interactive) const
88 {
89 return new canUndoActionStub(Traits);
90 }
91 void prepare(enum QueryOptions flag = Interactive)
92 {}
93 void outputAsCLI(std::ostream &ost) const
94 {}
95 void outputAsPython(std::ostream &ost, const std::string &prefix) const
96 {}
97 void setOptionValue(const std::string &_token, const std::string &_value)
98 {}
99};
100
101class cannotUndoActionStub : public Action
102{
103public:
104 cannotUndoActionStub(const ActionTrait &_trait) :
105 Action(_trait){}
106 virtual ~cannotUndoActionStub(){}
107
108 virtual Dialog* fillDialog(Dialog *dialog){
109 ASSERT(dialog,"No Dialog given when filling action dialog");
110 return dialog;
111 }
112
113 virtual ActionState::ptr performCall(){
114 return Action::success;
115 }
116 virtual ActionState::ptr performUndo(ActionState::ptr){
117 return Action::success;
118 }
119 virtual ActionState::ptr performRedo(ActionState::ptr){
120 return Action::success;
121 }
122 virtual bool canUndo(){
123 return false;
124 }
125 virtual bool shouldUndo(){
126 return true;
127 }
128 Action* clone(enum QueryOptions flag = Interactive) const
129 {
130 return new cannotUndoActionStub(Traits);
131 }
132 void prepare(enum QueryOptions flag = Interactive)
133 {}
134 void outputAsCLI(std::ostream &ost) const
135 {}
136 void outputAsPython(std::ostream &ost, const std::string &prefix) const
137 {}
138 void setOptionValue(const std::string &_token, const std::string &_value)
139 {}
140};
141
142class wasCalledActionStub : public Action
143{
144public:
145 wasCalledActionStub(const ActionTrait &_trait) :
146 Action(_trait),
147 called(false)
148 {}
149 virtual ~wasCalledActionStub(){}
150
151 virtual Dialog* fillDialog(Dialog *dialog){
152 return dialog;
153 }
154 virtual ActionState::ptr performCall(){
155 called = true;
156 return Action::success;
157 }
158 virtual ActionState::ptr performUndo(ActionState::ptr){
159 called = false;
160 return Action::success;
161 }
162 virtual ActionState::ptr performRedo(ActionState::ptr){
163 called = true;
164 return Action::success;
165 }
166 virtual bool canUndo(){
167 return true;
168 }
169 virtual bool shouldUndo(){
170 return true;
171 }
172 Action* clone(enum QueryOptions flag = Interactive) const
173 {
174 return new wasCalledActionStub(Traits);
175 }
176 void prepare(enum QueryOptions flag = Interactive)
177 {}
178 void outputAsCLI(std::ostream &ost) const
179 {}
180 void outputAsPython(std::ostream &ost, const std::string &prefix) const
181 {}
182 void setOptionValue(const std::string &_token, const std::string &_value)
183 {}
184 bool wasCalled(){
185 return called;
186 }
187private:
188 bool called;
189};
190
191void ActionSequenceTest::setUp(){
192 hasDescriptor = false;
193 // setup ActionHistory
194 ActionQueue::getInstance();
195 // TODO: find a way to really reset the factory to a clean state in tear-down
196 if(!hasDescriptor){
197 UIFactory::registerFactory(new DummyUIFactory::description());
198 hasDescriptor = true;
199 }
200 UIFactory::makeUserInterface("Dummy");
201 // create some necessary stubs used in this test
202 ActionTrait canUndoTrait("canUndoActionStub");
203 ActionTrait cannotUndoTrait("cannotUndoActionStub");
204 positive1 = new canUndoActionStub(canUndoTrait);
205 positive2 = new canUndoActionStub(canUndoTrait);
206 negative1 = new cannotUndoActionStub(cannotUndoTrait);
207 negative2 = new cannotUndoActionStub(cannotUndoTrait);
208
209 ActionTrait wasCalledTrait("wasCalledActionStub");
210 shouldCall1 = new wasCalledActionStub(wasCalledTrait);
211 shouldCall2 = new wasCalledActionStub(wasCalledTrait);
212 shouldNotCall1 = new wasCalledActionStub(wasCalledTrait);
213 shouldNotCall2 = new wasCalledActionStub(wasCalledTrait);
214
215}
216
217void ActionSequenceTest::tearDown(){
218 delete positive1;
219 delete positive2;
220 delete negative1;
221 delete negative2;
222
223 delete shouldCall1;
224 delete shouldCall2;
225 delete shouldNotCall1;
226 delete shouldNotCall2;
227
228 ActionQueue::purgeInstance();
229 {
230 UIFactory::purgeInstance();
231 hasDescriptor = false;
232 }
233}
234
235void ActionSequenceTest::canUndoTest(){
236 // first section:
237 {
238 // test some combinations
239 {
240 ActionSequence *sequence = new ActionSequence();
241 sequence->addAction(positive1->clone());
242 sequence->addAction(positive2->clone());
243 CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
244 delete sequence;
245 }
246 {
247 ActionSequence *sequence = new ActionSequence();
248 sequence->addAction(positive1->clone());
249 sequence->addAction(negative2->clone());
250 CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
251 delete sequence;
252 }
253 {
254 ActionSequence *sequence = new ActionSequence();
255 sequence->addAction(negative1->clone());
256 sequence->addAction(positive2->clone());
257 CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
258 delete sequence;
259 }
260 {
261 ActionSequence *sequence = new ActionSequence();
262 sequence->addAction(negative1->clone());
263 sequence->addAction(negative2->clone());
264 CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
265 delete sequence;
266 }
267 }
268
269 // second section:
270 {
271 // empty sequence can be undone
272 ActionSequence *sequence = new ActionSequence();
273 CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
274 // if only a positive action is contained it can be undone
275 sequence->addAction(positive1->clone());
276 CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
277 // the single negative action should block the process
278 sequence->addAction(negative1->clone());
279 CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
280 // after removing the negative action all is well again
281 delete sequence->removeLastAction();
282 CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
283 delete sequence;
284 }
285}
286
287void ActionSequenceTest::doesCallTest(){
288 ActionSequence *sequence = new ActionSequence();
289 sequence->addAction(shouldCall1->clone());
290 sequence->addAction(shouldCall2->clone());
291 sequence->addAction(shouldNotCall1->clone());
292 sequence->addAction(shouldNotCall2->clone());
293 delete sequence->removeLastAction();
294 delete sequence->removeLastAction();
295
296 sequence->callAll();
297
298 ActionSequence::actionSet::const_iterator iter = sequence->actions.begin();
299 CPPUNIT_ASSERT_EQUAL(true,dynamic_cast<wasCalledActionStub *>(*iter++)->wasCalled());
300 CPPUNIT_ASSERT_EQUAL(true,dynamic_cast<wasCalledActionStub *>(*iter++)->wasCalled());
301 CPPUNIT_ASSERT( iter == sequence->actions.end() );
302
303 delete sequence;
304}
305
306void ActionSequenceTest::doesUndoTest(){
307 ActionSequence *sequence = new ActionSequence();
308 ActionTrait wasCalledTrait("wasCalledActionStub");
309 sequence->addAction(new wasCalledActionStub(wasCalledTrait));
310 sequence->addAction(new wasCalledActionStub(wasCalledTrait));
311
312 ActionTrait MakroTrait("Test MakroAction");
313 MakroAction act(MakroTrait,*sequence);
314// wasCalledActionStub *wasCalled1 =
315// static_cast<wasCalledActionStub *>(act.actions.actions.front());
316// wasCalledActionStub *wasCalled2 =
317// static_cast<wasCalledActionStub *>(act.actions.actions.back());
318
319 act.call();
320
321 CPPUNIT_ASSERT_EQUAL(true,
322 static_cast<wasCalledActionStub *>(act.actions.actions.front())->wasCalled());
323 CPPUNIT_ASSERT_EQUAL(true,
324 static_cast<wasCalledActionStub *>(act.actions.actions.back())->wasCalled());
325
326 ActionQueue::getInstance().undoLast();
327
328 CPPUNIT_ASSERT_EQUAL(false,
329 static_cast<wasCalledActionStub *>(act.actions.actions.front())->wasCalled());
330 CPPUNIT_ASSERT_EQUAL(false,
331 static_cast<wasCalledActionStub *>(act.actions.actions.back())->wasCalled());
332
333 delete sequence;
334}
335
336
Note: See TracBrowser for help on using the repository browser.