LUMIERA.clone/tests/components/proc/control/command-use1-test.cpp

393 lines
13 KiB
C++
Raw Normal View History

2009-07-23 03:47:57 +02:00
/*
CommandUse1(Test) - usage aspects I
2010-12-17 23:28:49 +01:00
2009-07-23 03:47:57 +02:00
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
2010-12-17 23:28:49 +01:00
2009-07-23 03:47:57 +02:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
2010-12-17 23:28:49 +01:00
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
2009-07-23 03:47:57 +02:00
This program 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.
2010-12-17 23:28:49 +01:00
2009-07-23 03:47:57 +02:00
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2010-12-17 23:28:49 +01:00
2009-07-23 03:47:57 +02:00
* *****************************************************/
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "proc/control/command-invocation.hpp"
2009-07-23 03:47:57 +02:00
#include "proc/control/command-def.hpp"
#include "lib/format.hpp"
2009-07-23 03:47:57 +02:00
#include "lib/util.hpp"
#include "proc/control/test-dummy-commands.hpp"
#include <iostream>
2009-07-23 03:47:57 +02:00
namespace control {
namespace test {
2009-07-23 03:47:57 +02:00
using util::isSameObject;
2009-08-01 17:14:27 +02:00
using util::contains;
using util::str;
using std::cout;
using std::endl;
2009-07-23 03:47:57 +02:00
/***************************************************************************
* @test command usage aspects I: defining commands in various ways,
* then re-accessing those definitions, create instances,
* invoke them and undo the effect. Clean up finally.
*
* @see Command
* @see command-basic-test.cpp (simple usage example)
2009-07-23 03:47:57 +02:00
*/
class CommandUse1_test : public Test
{
int randVal;
int random() { return randVal = 10 + (rand() % 40); }
2009-07-23 03:47:57 +02:00
virtual void
run (Arg)
{
2009-07-24 17:50:14 +02:00
command1::check_ = 0;
uint cnt_defs = Command::definition_count();
uint cnt_inst = Command::instance_count();
2009-07-23 03:47:57 +02:00
allInOneStep();
standardUse();
statePredicates();
2009-07-23 03:47:57 +02:00
definePrototype();
usePrototype();
2009-08-01 17:14:27 +02:00
preventDuplicates();
stringRepresentation();
undef();
2009-07-23 03:47:57 +02:00
CHECK (0 == command1::check_);
CHECK (cnt_defs == Command::definition_count());
CHECK (cnt_inst == Command::instance_count());
2009-07-23 03:47:57 +02:00
}
void
allInOneStep()
{
CommandDef ("test.command1.1")
.operation (command1::operate)
.captureUndo (command1::capture)
.undoOperation (command1::undoIt)
.bind (random())
.execSync()
2009-07-23 03:47:57 +02:00
;
CHECK (randVal == command1::check_);
2009-07-23 03:47:57 +02:00
Command::get("test.command1.1").undo();
CHECK ( 0 == command1::check_);
}
void
standardUse()
{
{
CommandDef ("test.command1.2")
.operation (command1::operate)
.captureUndo (command1::capture)
.undoOperation (command1::undoIt)
;
}
CHECK (CommandDef("test.command1.2"));
Command com ("test.command1.2");
CHECK (com);
CHECK (com == Command::get("test.command1.2"));
CHECK (contains (str(com), "test.command1.2"));
CHECK (contains (str(com), "{def}"));
CHECK (!com.canExec());
VERIFY_ERROR (UNBOUND_ARGUMENTS, com() );
CHECK ( 0 == command1::check_);
VERIFY_ERROR (INVALID_ARGUMENTS, com.bind ("foo") );
com.bind (random()); // note: run-time type check only
CHECK ( com.canExec());
CHECK (!com.canUndo());
com();
CHECK (randVal == command1::check_);
com.undo();
CHECK ( 0 == command1::check_);
// the following shortcut does the same:
invoke ("test.command1.2") (1234);
CHECK ( 1234 == command1::check_);
// another shortcut, with static type check:
2009-10-06 05:11:30 +02:00
// invoke (command1::operate) (5678); //////////////////TICKET #291 : unimplemented for now (9/09)
// CHECK ( 1234+5678 == command1::check_);
com.undo();
CHECK ( 0 == command1::check_);
2009-07-23 03:47:57 +02:00
}
void
statePredicates()
{
Command::remove("test.command1.2");
VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.2") );
CommandDef def ("test.command1.2");
CHECK (!def);
def.operation (command1::operate)
.captureUndo (command1::capture);
CHECK (!def); // undo functor still missing
VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.2") );
def.operation (command1::operate)
.captureUndo (command1::capture)
.undoOperation (command1::undoIt);
CHECK (def);
CHECK (CommandDef("test.command1.2"));
CHECK (Command::get("test.command1.2"));
CHECK ( Command::defined("test.command1.2"));
CHECK (!Command::canExec("test.command1.2"));
CHECK (!Command::canUndo("test.command1.2"));
Command com = Command::get("test.command1.2");
CHECK (com);
CHECK (!com.canExec());
CHECK (!com.canUndo());
com.bind (11111);
CHECK ( Command::defined("test.command1.2"));
CHECK ( Command::canExec("test.command1.2"));
CHECK (!Command::canUndo("test.command1.2"));
com();
CHECK ( Command::defined("test.command1.2"));
CHECK ( Command::canExec("test.command1.2"));
CHECK ( Command::canUndo("test.command1.2"));
com.undo();
CHECK ( Command::defined("test.command1.2"));
CHECK ( Command::canExec("test.command1.2"));
CHECK ( Command::canUndo("test.command1.2"));
}
2009-07-23 03:47:57 +02:00
void
definePrototype()
{
CommandDef ("test.command1.3")
.operation (command1::operate)
.captureUndo (command1::capture)
.undoOperation (command1::undoIt)
.bind (random())
;
2009-07-23 03:47:57 +02:00
CHECK (Command::get("test.command1.3").canExec());
2009-07-23 03:47:57 +02:00
}
void
usePrototype()
{
Command c1 = Command::get("test.command1.3");
CHECK (c1);
CHECK (c1.canExec());
CHECK (!c1.canUndo());
2009-07-23 03:47:57 +02:00
Command c2 = c1.newInstance();
CHECK (c2);
CHECK (c2.canExec());
CHECK (!c2.canUndo());
2009-07-23 03:47:57 +02:00
CHECK (c1 == c2);
CHECK (!isSameObject(c1, c2));
2009-07-23 03:47:57 +02:00
CHECK (0 == command1::check_);
2009-07-23 03:47:57 +02:00
c1();
CHECK (randVal == command1::check_);
CHECK ( c1.canUndo());
CHECK (!c2.canUndo());
CHECK (c1 != c2);
2009-07-23 03:47:57 +02:00
c2();
CHECK (randVal + randVal == command1::check_);
CHECK (c2.canUndo());
CHECK (c1 != c2);
2009-07-23 03:47:57 +02:00
c1.undo();
CHECK (0 == command1::check_);
2009-07-23 03:47:57 +02:00
c2.undo();
CHECK (randVal == command1::check_);
2009-07-23 03:47:57 +02:00
c2.bind(23);
c2();
CHECK (randVal + 23 == command1::check_);
2009-07-23 03:47:57 +02:00
// you should not use a command more than once (but it works...)
c1();
CHECK (randVal + 23 + randVal == command1::check_);
2009-07-23 03:47:57 +02:00
c1.undo();
CHECK (randVal + 23 == command1::check_);
2009-07-23 03:47:57 +02:00
// note we've overwritten the previous undo state
// and get the sate captured on the second invocation
2009-07-25 19:21:50 +02:00
c2.undo();
CHECK (randVal == command1::check_);
2009-07-23 03:47:57 +02:00
c1.undo();
CHECK (randVal + 23 == command1::check_);
// use the current sate of c2 as Prototype for new command definition
c2.storeDef ("test.command1.4");
2009-08-10 01:30:59 +02:00
Command c4 = Command::get("test.command1.4");
CHECK (c4);
CHECK (c4.canExec());
CHECK (c4.canUndo());
CHECK (c4 == c2);
CHECK (c4 != c1);
2009-08-10 01:30:59 +02:00
c4();
CHECK (c4 != c2); // now lives independently from the original
CHECK (randVal + 2*23 == command1::check_);
c4.bind(int(-command1::check_)); // new command argument binding
2009-08-10 01:30:59 +02:00
c4();
CHECK (0 == command1::check_);
c2();
CHECK (23 == command1::check_);
c2.undo();
CHECK (0 == command1::check_);
}
2009-08-01 17:14:27 +02:00
void
preventDuplicates()
{
#define BUILD_NEW_COMMAND_DEF(_ID_) \
CommandDef (_ID_) \
.operation (command1::operate) \
.captureUndo (command1::capture) \
.undoOperation (command1::undoIt)
CHECK (CommandDef ("test.command1.1"));
VERIFY_ERROR (DUPLICATE_COMMAND, BUILD_NEW_COMMAND_DEF ("test.command1.1") );
CHECK (CommandDef ("test.command1.2"));
VERIFY_ERROR (DUPLICATE_COMMAND, BUILD_NEW_COMMAND_DEF ("test.command1.2") );
CHECK (CommandDef ("test.command1.3"));
VERIFY_ERROR (DUPLICATE_COMMAND, BUILD_NEW_COMMAND_DEF ("test.command1.3") );
CHECK (CommandDef ("test.command1.4"));
VERIFY_ERROR (DUPLICATE_COMMAND, BUILD_NEW_COMMAND_DEF ("test.command1.4") );
2009-08-01 17:14:27 +02:00
}
void
stringRepresentation()
{
cout << string (Command::get("test.command1.1")) << endl;
cout << string (Command::get("test.command1.2")) << endl;
cout << string (Command::get("test.command1.3")) << endl;
cout << string (Command::get("test.command1.4")) << endl;
cout << string (Command() ) << endl;
Command com
= CommandDef ("test.command1.5")
.operation (command1::operate)
.captureUndo (command1::capture)
.undoOperation (command1::undoIt);
cout << string (com) << endl;
com.bind(123);
cout << string (com) << endl;
com();
cout << string (com) << endl;
com.undo();
cout << string (com) << endl;
}
void
undef()
{
CHECK (CommandDef ("test.command1.1"));
CHECK (CommandDef ("test.command1.2"));
CHECK (CommandDef ("test.command1.3"));
CHECK (CommandDef ("test.command1.4"));
CHECK (Command::get("test.command1.1"));
CHECK (Command::get("test.command1.2"));
CHECK (Command::get("test.command1.3"));
CHECK (Command::get("test.command1.4"));
VERIFY_ERROR (INVALID_COMMAND, Command::get("miracle"));
VERIFY_ERROR (INVALID_COMMAND, invoke ("miracle") (1,2,3));
CommandDef unbelievable ("miracle");
CHECK (!unbelievable);
2009-08-01 17:14:27 +02:00
Command miracle;
// but because the miracle isn't yet defined, any use throws
2009-08-01 17:14:27 +02:00
VERIFY_ERROR (INVALID_COMMAND, miracle.bind("abracadabra"));
VERIFY_ERROR (INVALID_COMMAND, miracle.execSync());
VERIFY_ERROR (INVALID_COMMAND, miracle.undo());
VERIFY_ERROR (INVALID_COMMAND, miracle());
CHECK (!miracle.canExec());
CHECK (!miracle.canUndo());
CHECK (!miracle);
Command c5 (Command::get("test.command1.5"));
2009-08-10 01:30:59 +02:00
CHECK (Command::remove("test.command1.1"));
CHECK (Command::remove("test.command1.2"));
CHECK (Command::remove("test.command1.3"));
CHECK (Command::remove("test.command1.4"));
CHECK (Command::remove("test.command1.5"));
CHECK (!Command::remove("miracle")); // there is no such thing...
VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.1"));
VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.2"));
VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.3"));
2009-08-10 01:30:59 +02:00
VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.4"));
VERIFY_ERROR (INVALID_COMMAND, Command::get("test.command1.5"));
VERIFY_ERROR (INVALID_COMMAND, Command::get("miracle"));
2009-08-10 01:30:59 +02:00
// note, removed the registered definitions,
// but existing instances remain valid...
// thus we're free to create new instances...
CHECK (c5.isValid());
CHECK (c5.canExec());
2009-07-23 03:47:57 +02:00
}
};
2009-07-23 03:47:57 +02:00
/** Register this test class... */
LAUNCHER (CommandUse1_test, "function controller");
2009-07-23 03:47:57 +02:00
}} // namespace control::test