/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2010-2012 University of Bonn. All rights reserved.
* Copyright (C) 2013 Frederik Heber. All rights reserved.
*
*
* This file is part of MoleCuilder.
*
* MoleCuilder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MoleCuilder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MoleCuilder. If not, see .
*/
/*
* ActionSequenceUnitTest.cpp
*
* Created on: Dec 17, 2009
* Author: crueger
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include "ActionSequenceUnitTest.hpp"
#include "Actions/Action.hpp"
#include "Actions/ActionSequence.hpp"
#include "Actions/MakroAction.hpp"
#include "Actions/ActionHistory.hpp"
#include "Actions/ActionRegistry.hpp"
#include "stubs/DummyUI.hpp"
using namespace MoleCuilder;
#ifdef HAVE_TESTRUNNER
#include "UnitTestMain.hpp"
#endif /*HAVE_TESTRUNNER*/
/********************************************** Test classes **************************************/
// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION( ActionSequenceTest );
/* some neccessary stubs for tests */
class canUndoActionStub : public Action
{
public:
canUndoActionStub(const ActionTrait &_trait):
Action(_trait,false){}
virtual ~canUndoActionStub(){}
virtual Dialog* fillDialog(Dialog *dialog){
ASSERT(dialog,"No Dialog given when filling action dialog");
return dialog;
}
virtual Action::state_ptr performCall(){
return Action::success;
}
virtual Action::state_ptr performUndo(Action::state_ptr){
return Action::success;
}
virtual Action::state_ptr performRedo(Action::state_ptr){
return Action::success;
}
virtual bool canUndo(){
return true;
}
virtual bool shouldUndo(){
return true;
}
};
class cannotUndoActionStub : public Action
{
public:
cannotUndoActionStub(const ActionTrait &_trait) :
Action(_trait,false){}
virtual ~cannotUndoActionStub(){}
virtual Dialog* fillDialog(Dialog *dialog){
ASSERT(dialog,"No Dialog given when filling action dialog");
return dialog;
}
virtual Action::state_ptr performCall(){
return Action::success;
}
virtual Action::state_ptr performUndo(Action::state_ptr){
return Action::success;
}
virtual Action::state_ptr performRedo(Action::state_ptr){
return Action::success;
}
virtual bool canUndo(){
return false;
}
virtual bool shouldUndo(){
return true;
}
};
class wasCalledActionStub : public Action
{
public:
wasCalledActionStub(const ActionTrait &_trait) :
Action(_trait,false),
called(false)
{}
virtual ~wasCalledActionStub(){}
virtual Dialog* fillDialog(Dialog *dialog){
return dialog;
}
virtual Action::state_ptr performCall(){
called = true;
return Action::success;
}
virtual Action::state_ptr performUndo(Action::state_ptr){
called = false;
return Action::success;
}
virtual Action::state_ptr performRedo(Action::state_ptr){
called = true;
return Action::success;
}
virtual bool canUndo(){
return true;
}
virtual bool shouldUndo(){
return true;
}
bool wasCalled(){
return called;
}
private:
bool called;
};
void ActionSequenceTest::setUp(){
hasDescriptor = false;
ActionHistory::init();
// TODO: find a way to really reset the factory to a clean state in tear-down
if(!hasDescriptor){
UIFactory::registerFactory(new DummyUIFactory::description());
hasDescriptor = true;
}
UIFactory::makeUserInterface("Dummy");
// create some necessary stubs used in this test
ActionTrait canUndoTrait("canUndoActionStub");
ActionTrait cannotUndoTrait("cannotUndoActionStub");
positive1 = new canUndoActionStub(canUndoTrait);
positive2 = new canUndoActionStub(canUndoTrait);
negative1 = new cannotUndoActionStub(cannotUndoTrait);
negative2 = new cannotUndoActionStub(cannotUndoTrait);
ActionTrait wasCalledTrait("wasCalledActionStub");
shouldCall1 = new wasCalledActionStub(wasCalledTrait);
shouldCall2 = new wasCalledActionStub(wasCalledTrait);
shouldNotCall1 = new wasCalledActionStub(wasCalledTrait);
shouldNotCall2 = new wasCalledActionStub(wasCalledTrait);
}
void ActionSequenceTest::tearDown(){
delete positive1;
delete positive2;
delete negative1;
delete negative2;
delete shouldCall1;
delete shouldCall2;
delete shouldNotCall1;
delete shouldNotCall2;
ActionHistory::purgeInstance();
ActionRegistry::purgeInstance();
{
UIFactory::purgeInstance();
hasDescriptor = false;
}
}
void ActionSequenceTest::canUndoTest(){
// first section:
{
// test some combinations
{
ActionSequence *sequence = new ActionSequence();
sequence->addAction(positive1);
sequence->addAction(positive2);
CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
delete sequence;
}
{
ActionSequence *sequence = new ActionSequence();
sequence->addAction(positive1);
sequence->addAction(negative2);
CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
delete sequence;
}
{
ActionSequence *sequence = new ActionSequence();
sequence->addAction(negative1);
sequence->addAction(positive2);
CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
delete sequence;
}
{
ActionSequence *sequence = new ActionSequence();
sequence->addAction(negative1);
sequence->addAction(negative2);
CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
delete sequence;
}
}
// second section:
{
// empty sequence can be undone
ActionSequence *sequence = new ActionSequence();
CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
// if only a positive action is contained it can be undone
sequence->addAction(positive1);
CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
// the single negative action should block the process
sequence->addAction(negative1);
CPPUNIT_ASSERT_EQUAL( false, sequence->canUndo() );
// after removing the negative action all is well again
sequence->removeLastAction();
CPPUNIT_ASSERT_EQUAL( true, sequence->canUndo() );
delete sequence;
}
}
void ActionSequenceTest::doesCallTest(){
ActionSequence *sequence = new ActionSequence();
sequence->addAction(shouldCall1);
sequence->addAction(shouldCall2);
sequence->addAction(shouldNotCall1);
sequence->addAction(shouldNotCall2);
sequence->removeLastAction();
sequence->removeLastAction();
sequence->callAll();
CPPUNIT_ASSERT_EQUAL(true,shouldCall1->wasCalled());
CPPUNIT_ASSERT_EQUAL(true,shouldCall2->wasCalled());
CPPUNIT_ASSERT_EQUAL(false,shouldNotCall1->wasCalled());
CPPUNIT_ASSERT_EQUAL(false,shouldNotCall2->wasCalled());
delete sequence;
}
void ActionSequenceTest::doesUndoTest(){
ActionSequence *sequence = new ActionSequence();
ActionTrait wasCalledTrait("wasCalledActionStub");
wasCalledActionStub *wasCalled1 = new wasCalledActionStub(wasCalledTrait);
wasCalledActionStub *wasCalled2 = new wasCalledActionStub(wasCalledTrait);
sequence->addAction(wasCalled1);
sequence->addAction(wasCalled2);
ActionTrait MakroTrait("Test MakroAction");
MakroAction act(MakroTrait,*sequence,false);
act.call();
CPPUNIT_ASSERT_EQUAL(true,wasCalled1->wasCalled());
CPPUNIT_ASSERT_EQUAL(true,wasCalled2->wasCalled());
ActionHistory::getInstance().undoLast();
CPPUNIT_ASSERT_EQUAL(false,wasCalled1->wasCalled());
CPPUNIT_ASSERT_EQUAL(false,wasCalled2->wasCalled());
delete sequence;
}