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

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 e9e86f was af5384, checked in by Frederik Heber <heber@…>, 11 years ago

Actions can now clone() and split off prepare() from call().

  • ActionQueue now separates call phase into clone(), prepare(), and call().
  • ActionQueue's dstor releases Actions in deque.
  • CurrentAction is an index as push_back always invalidates iterator.
  • ActionQueue_t is now a simple vector of ptrs.
  • call() is now non-interactive, (maybe) interactive part is placed in prepare() where dialogs are used to fill parameters.
  • only fully prepared Actions are placed in ActionQueue.
  • ActionQueue obtains action instances from Registry, copies, prepares them, and places them in the queue.
  • Action::clone() gets QueryOptions as param. This lets us either clone without params or really copy the instance.
  • If action is called as COMMAND, params have been filled already.
  • Reactions require a ActionQueue::getLastAction() to actually obtain result of (cloned) Action.
  • FIX: Calculation now has const has...() and getResult().
  • Property mode set to 100644
File size: 8.8 KB
RevLine 
[bcf653]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
[0aa122]4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
[5aaa43]5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
[94d5ac6]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/>.
[bcf653]22 */
23
[147339]24/*
[f7c0c4]25 * ActionSequenceUnitTest.cpp
[147339]26 *
27 * Created on: Dec 17, 2009
28 * Author: crueger
29 */
30
[bf3817]31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
[147339]36#include <cppunit/CompilerOutputter.h>
37#include <cppunit/extensions/TestFactoryRegistry.h>
38#include <cppunit/ui/text/TestRunner.h>
39
[f7c0c4]40#include "ActionSequenceUnitTest.hpp"
[147339]41#include "Actions/Action.hpp"
[628577]42#include "Actions/ActionQueue.hpp"
[147339]43#include "Actions/ActionSequence.hpp"
[2efa90]44#include "Actions/MakroAction.hpp"
[147339]45
[fdcd1b]46#include "stubs/DummyUI.hpp"
[112f90]47
[ce7fdc]48using namespace MoleCuilder;
49
[9b6b2f]50#ifdef HAVE_TESTRUNNER
51#include "UnitTestMain.hpp"
52#endif /*HAVE_TESTRUNNER*/
53
54/********************************************** Test classes **************************************/
55
[147339]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:
[3139b2]63 canUndoActionStub(const ActionTrait &_trait):
[126867]64 Action(_trait){}
[147339]65 virtual ~canUndoActionStub(){}
66
[047878]67 virtual Dialog* fillDialog(Dialog *dialog){
68 ASSERT(dialog,"No Dialog given when filling action dialog");
69 return dialog;
[80951de]70 }
71
[b5b01e]72 virtual ActionState::ptr performCall(){
[67e2b3]73 return Action::success;
74 }
[b5b01e]75 virtual ActionState::ptr performUndo(ActionState::ptr){
[67e2b3]76 return Action::success;
77 }
[b5b01e]78 virtual ActionState::ptr performRedo(ActionState::ptr){
[67e2b3]79 return Action::success;
80 }
[147339]81 virtual bool canUndo(){
82 return true;
83 }
[67e2b3]84 virtual bool shouldUndo(){
85 return true;
86 }
[af5384]87 Action* clone(enum QueryOptions flag = Interactive) const
88 {
89 return new canUndoActionStub(Traits);
90 }
91 void prepare(enum QueryOptions flag = Interactive)
92 {}
[46b181]93 void outputAsCLI(std::ostream &ost) const
94 {}
[477012]95 void outputAsPython(std::ostream &ost, const std::string &prefix) const
96 {}
[147339]97};
98
99class cannotUndoActionStub : public Action
100{
101public:
[3139b2]102 cannotUndoActionStub(const ActionTrait &_trait) :
[126867]103 Action(_trait){}
[147339]104 virtual ~cannotUndoActionStub(){}
105
[047878]106 virtual Dialog* fillDialog(Dialog *dialog){
107 ASSERT(dialog,"No Dialog given when filling action dialog");
108 return dialog;
[80951de]109 }
110
[b5b01e]111 virtual ActionState::ptr performCall(){
[67e2b3]112 return Action::success;
113 }
[b5b01e]114 virtual ActionState::ptr performUndo(ActionState::ptr){
[67e2b3]115 return Action::success;
116 }
[b5b01e]117 virtual ActionState::ptr performRedo(ActionState::ptr){
[67e2b3]118 return Action::success;
119 }
[147339]120 virtual bool canUndo(){
121 return false;
122 }
[67e2b3]123 virtual bool shouldUndo(){
124 return true;
125 }
[af5384]126 Action* clone(enum QueryOptions flag = Interactive) const
127 {
128 return new cannotUndoActionStub(Traits);
129 }
130 void prepare(enum QueryOptions flag = Interactive)
131 {}
[46b181]132 void outputAsCLI(std::ostream &ost) const
133 {}
[477012]134 void outputAsPython(std::ostream &ost, const std::string &prefix) const
135 {}
[147339]136};
137
[0229f9]138class wasCalledActionStub : public Action
139{
140public:
[3139b2]141 wasCalledActionStub(const ActionTrait &_trait) :
[126867]142 Action(_trait),
[0229f9]143 called(false)
144 {}
145 virtual ~wasCalledActionStub(){}
[147339]146
[047878]147 virtual Dialog* fillDialog(Dialog *dialog){
148 return dialog;
[80951de]149 }
[b5b01e]150 virtual ActionState::ptr performCall(){
[0229f9]151 called = true;
[67e2b3]152 return Action::success;
[0229f9]153 }
[b5b01e]154 virtual ActionState::ptr performUndo(ActionState::ptr){
[0229f9]155 called = false;
[67e2b3]156 return Action::success;
157 }
[b5b01e]158 virtual ActionState::ptr performRedo(ActionState::ptr){
[67e2b3]159 called = true;
160 return Action::success;
[0229f9]161 }
162 virtual bool canUndo(){
163 return true;
164 }
[67e2b3]165 virtual bool shouldUndo(){
166 return true;
167 }
[af5384]168 Action* clone(enum QueryOptions flag = Interactive) const
169 {
170 return new wasCalledActionStub(Traits);
171 }
172 void prepare(enum QueryOptions flag = Interactive)
173 {}
[46b181]174 void outputAsCLI(std::ostream &ost) const
175 {}
[477012]176 void outputAsPython(std::ostream &ost, const std::string &prefix) const
177 {}
[0229f9]178 bool wasCalled(){
179 return called;
180 }
181private:
182 bool called;
183};
[147339]184
[0229f9]185void ActionSequenceTest::setUp(){
[694d84]186 hasDescriptor = false;
[6367dd]187 // setup ActionHistory
188 ActionQueue::getInstance();
[112f90]189 // TODO: find a way to really reset the factory to a clean state in tear-down
190 if(!hasDescriptor){
191 UIFactory::registerFactory(new DummyUIFactory::description());
192 hasDescriptor = true;
193 }
194 UIFactory::makeUserInterface("Dummy");
[147339]195 // create some necessary stubs used in this test
[3139b2]196 ActionTrait canUndoTrait("canUndoActionStub");
197 ActionTrait cannotUndoTrait("cannotUndoActionStub");
[e4afb4]198 positive1 = new canUndoActionStub(canUndoTrait);
199 positive2 = new canUndoActionStub(canUndoTrait);
200 negative1 = new cannotUndoActionStub(cannotUndoTrait);
201 negative2 = new cannotUndoActionStub(cannotUndoTrait);
202
[3139b2]203 ActionTrait wasCalledTrait("wasCalledActionStub");
[e4afb4]204 shouldCall1 = new wasCalledActionStub(wasCalledTrait);
205 shouldCall2 = new wasCalledActionStub(wasCalledTrait);
206 shouldNotCall1 = new wasCalledActionStub(wasCalledTrait);
207 shouldNotCall2 = new wasCalledActionStub(wasCalledTrait);
[0229f9]208
209}
210
211void ActionSequenceTest::tearDown(){
212 delete positive1;
213 delete positive2;
214 delete negative1;
215 delete negative2;
[147339]216
[0229f9]217 delete shouldCall1;
218 delete shouldCall2;
219 delete shouldNotCall1;
220 delete shouldNotCall2;
221
[628577]222 ActionQueue::purgeInstance();
[694d84]223 {
224 UIFactory::purgeInstance();
225 hasDescriptor = false;
226 }
[0229f9]227}
228
229void ActionSequenceTest::canUndoTest(){
[147339]230 // first section:
231 {
232 // test some combinations
233 {
234 ActionSequence *sequence = new ActionSequence();
235 sequence->addAction(positive1);
236 sequence->addAction(positive2);
237 CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
238 delete sequence;
239 }
240 {
241 ActionSequence *sequence = new ActionSequence();
242 sequence->addAction(positive1);
243 sequence->addAction(negative2);
244 CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
245 delete sequence;
246 }
247 {
248 ActionSequence *sequence = new ActionSequence();
249 sequence->addAction(negative1);
250 sequence->addAction(positive2);
251 CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
252 delete sequence;
253 }
254 {
255 ActionSequence *sequence = new ActionSequence();
256 sequence->addAction(negative1);
257 sequence->addAction(negative2);
258 CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
259 delete sequence;
260 }
261 }
262
263 // second section:
264 {
265 // empty sequence can be undone
266 ActionSequence *sequence = new ActionSequence();
267 CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
268 // if only a positive action is contained it can be undone
269 sequence->addAction(positive1);
270 CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
271 // the single negative action should block the process
272 sequence->addAction(negative1);
273 CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
274 // after removing the negative action all is well again
275 sequence->removeLastAction();
276 CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
277 delete sequence;
278 }
[0229f9]279}
[147339]280
[0229f9]281void ActionSequenceTest::doesCallTest(){
282 ActionSequence *sequence = new ActionSequence();
283 sequence->addAction(shouldCall1);
284 sequence->addAction(shouldCall2);
285 sequence->addAction(shouldNotCall1);
286 sequence->addAction(shouldNotCall2);
287 sequence->removeLastAction();
288 sequence->removeLastAction();
289
290 sequence->callAll();
291
292 CPPUNIT_ASSERT_EQUAL(true,shouldCall1->wasCalled());
293 CPPUNIT_ASSERT_EQUAL(true,shouldCall2->wasCalled());
294 CPPUNIT_ASSERT_EQUAL(false,shouldNotCall1->wasCalled());
295 CPPUNIT_ASSERT_EQUAL(false,shouldNotCall2->wasCalled());
296
[f59d81]297 delete sequence;
[0229f9]298}
299
300void ActionSequenceTest::doesUndoTest(){
301 ActionSequence *sequence = new ActionSequence();
[3139b2]302 ActionTrait wasCalledTrait("wasCalledActionStub");
[e4afb4]303 wasCalledActionStub *wasCalled1 = new wasCalledActionStub(wasCalledTrait);
304 wasCalledActionStub *wasCalled2 = new wasCalledActionStub(wasCalledTrait);
[2efa90]305 sequence->addAction(wasCalled1);
306 sequence->addAction(wasCalled2);
[0229f9]307
[3139b2]308 ActionTrait MakroTrait("Test MakroAction");
[126867]309 MakroAction act(MakroTrait,*sequence);
[0229f9]310
[2efa90]311 act.call();
[0229f9]312
[2efa90]313 CPPUNIT_ASSERT_EQUAL(true,wasCalled1->wasCalled());
[ec149d]314 CPPUNIT_ASSERT_EQUAL(true,wasCalled2->wasCalled());
[0229f9]315
[6367dd]316 ActionQueue::getInstance().undoLast();
[2efa90]317
318 CPPUNIT_ASSERT_EQUAL(false,wasCalled1->wasCalled());
[ec149d]319 CPPUNIT_ASSERT_EQUAL(false,wasCalled2->wasCalled());
[147339]320
[22b786]321 delete sequence;
[147339]322}
323
324
Note: See TracBrowser for help on using the repository browser.