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

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 caece4 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
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};
98
99class cannotUndoActionStub : public Action
100{
101public:
102 cannotUndoActionStub(const ActionTrait &_trait) :
103 Action(_trait){}
104 virtual ~cannotUndoActionStub(){}
105
106 virtual Dialog* fillDialog(Dialog *dialog){
107 ASSERT(dialog,"No Dialog given when filling action dialog");
108 return dialog;
109 }
110
111 virtual ActionState::ptr performCall(){
112 return Action::success;
113 }
114 virtual ActionState::ptr performUndo(ActionState::ptr){
115 return Action::success;
116 }
117 virtual ActionState::ptr performRedo(ActionState::ptr){
118 return Action::success;
119 }
120 virtual bool canUndo(){
121 return false;
122 }
123 virtual bool shouldUndo(){
124 return true;
125 }
126 Action* clone(enum QueryOptions flag = Interactive) const
127 {
128 return new cannotUndoActionStub(Traits);
129 }
130 void prepare(enum QueryOptions flag = Interactive)
131 {}
132 void outputAsCLI(std::ostream &ost) const
133 {}
134 void outputAsPython(std::ostream &ost, const std::string &prefix) const
135 {}
136};
137
138class wasCalledActionStub : public Action
139{
140public:
141 wasCalledActionStub(const ActionTrait &_trait) :
142 Action(_trait),
143 called(false)
144 {}
145 virtual ~wasCalledActionStub(){}
146
147 virtual Dialog* fillDialog(Dialog *dialog){
148 return dialog;
149 }
150 virtual ActionState::ptr performCall(){
151 called = true;
152 return Action::success;
153 }
154 virtual ActionState::ptr performUndo(ActionState::ptr){
155 called = false;
156 return Action::success;
157 }
158 virtual ActionState::ptr performRedo(ActionState::ptr){
159 called = true;
160 return Action::success;
161 }
162 virtual bool canUndo(){
163 return true;
164 }
165 virtual bool shouldUndo(){
166 return true;
167 }
168 Action* clone(enum QueryOptions flag = Interactive) const
169 {
170 return new wasCalledActionStub(Traits);
171 }
172 void prepare(enum QueryOptions flag = Interactive)
173 {}
174 void outputAsCLI(std::ostream &ost) const
175 {}
176 void outputAsPython(std::ostream &ost, const std::string &prefix) const
177 {}
178 bool wasCalled(){
179 return called;
180 }
181private:
182 bool called;
183};
184
185void ActionSequenceTest::setUp(){
186 hasDescriptor = false;
187 // setup ActionHistory
188 ActionQueue::getInstance();
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");
195 // create some necessary stubs used in this test
196 ActionTrait canUndoTrait("canUndoActionStub");
197 ActionTrait cannotUndoTrait("cannotUndoActionStub");
198 positive1 = new canUndoActionStub(canUndoTrait);
199 positive2 = new canUndoActionStub(canUndoTrait);
200 negative1 = new cannotUndoActionStub(cannotUndoTrait);
201 negative2 = new cannotUndoActionStub(cannotUndoTrait);
202
203 ActionTrait wasCalledTrait("wasCalledActionStub");
204 shouldCall1 = new wasCalledActionStub(wasCalledTrait);
205 shouldCall2 = new wasCalledActionStub(wasCalledTrait);
206 shouldNotCall1 = new wasCalledActionStub(wasCalledTrait);
207 shouldNotCall2 = new wasCalledActionStub(wasCalledTrait);
208
209}
210
211void ActionSequenceTest::tearDown(){
212 delete positive1;
213 delete positive2;
214 delete negative1;
215 delete negative2;
216
217 delete shouldCall1;
218 delete shouldCall2;
219 delete shouldNotCall1;
220 delete shouldNotCall2;
221
222 ActionQueue::purgeInstance();
223 {
224 UIFactory::purgeInstance();
225 hasDescriptor = false;
226 }
227}
228
229void ActionSequenceTest::canUndoTest(){
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 }
279}
280
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
297 delete sequence;
298}
299
300void ActionSequenceTest::doesUndoTest(){
301 ActionSequence *sequence = new ActionSequence();
302 ActionTrait wasCalledTrait("wasCalledActionStub");
303 wasCalledActionStub *wasCalled1 = new wasCalledActionStub(wasCalledTrait);
304 wasCalledActionStub *wasCalled2 = new wasCalledActionStub(wasCalledTrait);
305 sequence->addAction(wasCalled1);
306 sequence->addAction(wasCalled2);
307
308 ActionTrait MakroTrait("Test MakroAction");
309 MakroAction act(MakroTrait,*sequence);
310
311 act.call();
312
313 CPPUNIT_ASSERT_EQUAL(true,wasCalled1->wasCalled());
314 CPPUNIT_ASSERT_EQUAL(true,wasCalled2->wasCalled());
315
316 ActionQueue::getInstance().undoLast();
317
318 CPPUNIT_ASSERT_EQUAL(false,wasCalled1->wasCalled());
319 CPPUNIT_ASSERT_EQUAL(false,wasCalled2->wasCalled());
320
321 delete sequence;
322}
323
324
Note: See TracBrowser for help on using the repository browser.