/**
 * @file TestSynchronization.h
 * @date Jul 22, 2008
 * @author Ronald Kluth
 *
 * @brief Contains all helper classes required for testing ODEMx module \b %Synchronization.
 */

#ifndef TESTSYNCHRONIZATION_H_
#define TESTSYNCHRONIZATION_H_

#include <UnitTest++.h>
#include "../Main/Globals.h"

#include <odemx/base/Process.h>
#include <odemx/base/Event.h>
#include <odemx/synchronization/Bin.h>
#include <odemx/synchronization/BinT.h>
#include <odemx/synchronization/CondQ.h>
#include <odemx/synchronization/Memory.h>
#include <odemx/synchronization/Port.h>
#include <odemx/synchronization/Res.h>
#include <odemx/synchronization/ResT.h>
#include <odemx/synchronization/Timer.h>
#include <odemx/synchronization/WaitQ.h>
#include <odemx/synchronization/Wait.h>

/**
 * @namespace Synchronization
 *
 * @brief Contains helpers and tests for module ODEMx %Synchronization
 *
 * The UnitTest++ macro SUITE( Synchronization ) declares namespace
 * Synchronization. Consequently, all helpers for this test suite should
 * be placed in the same namespace.
 */

namespace SuiteSynchronization {

	using namespace odemx;
	using namespace odemx::synchronization;
	using namespace std;

	/***************************** BIN ****************************************/

	/**
	 * @class BinTaker
	 * @brief Simple Process implementation that takes a number of tokens
	 */
	class BinTestTaker:
		public base::Process
	{
	public:
		Bin& bin; ///< reference to the Bin object to work with
		std::size_t number; ///< the amount of tokens to take
		std::size_t received; ///< the amount of tokens received

		/// Constructor
		BinTestTaker( base::Simulation& s, const data::Label& l, Bin& b, std::size_t howMany )
		:	Process( s, l ),
			bin( b ),
			number( howMany ),
			received( 0 )
			{}

		/// minimal implementation of Process behavior to take tokens from Bin
		virtual int main()
		{
			received = bin.take( number );
			return received;
		}
	};

	/**
	 * @class BinTestObserver
	 * @brief Implements BinObserver to validate execution of Bin methods
	 */
	class BinTestObserver:
		public BinObserver,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		BinTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(Bin* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(Bin* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onTakeFail(Bin* sender, std::size_t n)
		{ ObserverBase::saw( "onTakeFail", sender, toString( n ) ); }
		virtual void onTakeSucceed(Bin* sender, std::size_t n)
		{ ObserverBase::saw( "onTakeSucceed", sender, toString( n ) ); }
		virtual void onGive(Bin* sender, std::size_t n)
		{ ObserverBase::saw( "onGive", sender, toString( n ) ); }
		virtual void onChangeTokenNumber(Bin* sender, std::size_t oldTokenNumber,
			std::size_t newTokenNumber)
		{ ObserverBase::saw( "onChangeTokenNumber", sender, toString( oldTokenNumber ), toString( newTokenNumber ) ); }
		//@}
	};

	/************************ BIN TEMPLATE ************************************/

	/**
	 * @struct TokenTest
	 * @brief Simple implementation of a Token type
	 */
	struct TokenTest
	{
		/// Constructor
		TokenTest( short i, const data::Label& l )
		:	id( i ),
			label( l )
			{}

		short id; ///< the token ID
		data::Label label; ///< the token label
	};

	/// allows to compare TokenTest objects
	extern bool operator== ( const TokenTest& t1, const TokenTest& t2 );

	/// makes TokenTest objects streamable
	extern std::ostream& operator<< ( std::ostream& stream, const TokenTest& t );

	/**
	 * @class BinTTaker
	 * @brief Simple Process implementation that takes a number of tokens
	 */
	class BinTTaker:
		public base::Process
	{
	public:
		BinT< TokenTest >& theBin; ///< reference to the Bin object to work with
		std::size_t number; ///< the amount of tokens to take
		std::auto_ptr< std::vector< TokenTest > > received; ///< the received token objects

		/// Constructor
		BinTTaker( base::Simulation& s, const data::Label& l, BinT< TokenTest >& b, std::size_t howMany )
		:	Process( s, l ),
			theBin( b ),
			number( howMany ),
			received( 0 )
			{}

		/// minimal implementation of Process behavior to take tokens from Bin
		virtual int main()
		{
			received = theBin.take( number );
			return received.get() ? received->size() : 0;
		}
	};

	/**
	 * @class BinTTestObserver
	 * @brief Implements BinTObserver to validate execution of BinT methods
	 */
	class BinTTestObserver:
		public BinTObserver< TokenTest >,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		BinTTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(BinT< TokenTest >* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(BinT< TokenTest >* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onTakeFail(BinT< TokenTest >* sender, std::size_t n)
		{ ObserverBase::saw( "onTakeFail", sender, toString( n ) ); }
		virtual void onTakeSucceed(BinT< TokenTest >* sender, std::size_t n)
		{ ObserverBase::saw( "onTakeSucceed", sender, toString( n ) ); }
		virtual void onGive(BinT< TokenTest >* sender, std::size_t n)
		{ ObserverBase::saw( "onGive", sender, toString( n ) ); }
		virtual void onChangeTokenNumber(BinT< TokenTest >* sender, std::size_t oldTokenNumber,
			std::size_t newTokenNumber)
		{ ObserverBase::saw( "onChangeTokenNumber", sender, toString( oldTokenNumber ), toString( newTokenNumber ) ); }
		//@}
	};

	/***************************** CONDQ **************************************/

	/**
	 * @class CondQSignal
	 * @brief Simple Process that is used to call CondQ::signal()
	 */
	class CondQSignal:
		public base::Process
	{
	public:
		CondQ& condQ; ///< reference to the CondQ object to be called

		/// Constructor
		CondQSignal( base::Simulation& s, const data::Label& l, CondQ& c )
		:	Process( s, l ),
			condQ( c )
			{}
		/// Process behavior is just calling signal() and then finish
		virtual int main()
		{
			condQ.signal();
			return 0;
		}
	};

	/**
	 * @class CondQTestProcess
	 * @brief Simple Process implementation using a CondQ to wait for fulfilment
	 * of a condition
	 */
	class CondQTestProcess:
		public base::Process
	{
	public:
		CondQ& condQ; ///< a reference to the condition queue to be used
		bool conditionValue; ///< boolean representing a condition to be fulfilled
		bool running; ///< a boolean to check if main was called
		bool reactivated; ///< a boolean to check if the process has been reactivated
		bool waitReturnValue; ///< a boolean to test the return value of CondQ::wait()

		/// Constructor
		CondQTestProcess( base::Simulation& sim, const data::Label& l, CondQ& q )
		:	Process( sim, l ),
			condQ( q ),
			conditionValue( false ),
			running( false ),
			reactivated( false ),
			waitReturnValue( false )
			{}

		/// Simple implementation of Process behavior for using a wait condition
		virtual int main()
		{
			running = true;
			waitReturnValue = condQ.wait( (base::Condition)&CondQTestProcess::condition );
			reactivated = true;
			return 0;
		}

		/// Simple condition function, returns a boolean that can be set elsewhere
		bool condition() { return conditionValue; }
	};

	/**
	 * @class CondQTestObserver
	 * @brief Implements CondQObserver to validate execution of CondQ methods
	 */
	class CondQTestObserver:
		public CondQObserver,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		CondQTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(CondQ* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(CondQ* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onWait(CondQ* sender, base::Process* process)
		{ ObserverBase::saw( "onWait", sender, process ); }
		virtual void onContinue(CondQ* sender, base::Process* process)
		{ ObserverBase::saw( "onContinue", sender, process ); }
		virtual void onSignal(CondQ* sender, base::Process* process)
		{ ObserverBase::saw( "onSignal", sender, process ); }
		//@}
	};

	/**************************** MEMORY **************************************/

	/**
	 * @class MemoryTestProcess
	 * @brief Simple Process helper class without behavior specification
	 */
	class MemoryTestProcess:
		public base::Process
	{
	public:
		/// Constructor
		MemoryTestProcess( base::Simulation& sim, const data::Label& l )
		:	Process( sim, l )
		{}
		/// required (but empty) implementation of process behavior
		virtual int main() { return 0; }
	};

	/**
	 * @class MemoryTestEvent
	 * @brief Simple Event helper class without action specification
	 */
	class MemoryTestEvent:
		public base::Event
	{
	public:
		/// Constructor
		MemoryTestEvent( base::Simulation& sim, const data::Label& l )
		:	Event( sim, l )
		{}
		/// required (but empty) implementation of event action
		virtual void eventAction() {}
	};

	/**
	 * @class MemoryTest
	 * @brief Helper class that implements a pure virtual function, used for
	 * testing class Memory
	 */
	class MemoryTest: public Memory
	{
	public:
		/// Constructor for user-defined simulation
		MemoryTest( base::Simulation& sim, const data::Label& l, Memory::Type t, MemoryObserver* mo = 0 )
		:	Memory( sim, l, t, mo )
		{}
		/// required implementation of pure virtual function
		virtual bool available() { return true; }
		/// makes the protected function public for testing
		virtual void alert() { Memory::alert(); }
	};

	/**
	 * @class MemoryTestObserver
	 * @brief Implements MemoryObserver to validate execution of Memory methods
	 */
	class MemoryTestObserver:
		public MemoryObserver,
		public ObserverBase
	{
	public:
		bool onCreateMemory; ///< boolean for checking constructor call
		bool onDestroyMemory; ///< boolean for checking destructor call
		Memory* createdMemoryObject; ///< pointer to check for the correct observation sender
		Memory* destroyedMemoryObject; ///< pointer to check for the correct observation sender

		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		MemoryTestObserver( bool output ):
			ObserverBase( output ),
			onCreateMemory( false ),
			onDestroyMemory( false ),
			createdMemoryObject( 0 ),
			destroyedMemoryObject( 0 )
			{}

		/// reset observation history and member data
		void clear()
		{
			onCreateMemory = false;
			onDestroyMemory = false;
			createdMemoryObject = 0;
			destroyedMemoryObject = 0;
			history.clear();
		}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(Memory* sender)
		{
			// different implementation to avoid pure virtual function call
			// to getLabel() because MemoryTest is not fully constructed
			onCreateMemory = true; createdMemoryObject = sender;
		}
		virtual void onDestroy(Memory* sender)
		{
			// different implementation to avoid pure virtual function call
			// to getLabel() because MemoryTest part is already destroyed
			onDestroyMemory = true; destroyedMemoryObject = sender;
		}
		virtual void onRemember(Memory* sender, base::Sched* s)
		{ ObserverBase::saw( "onRemember", dynamic_cast< MemoryTest* >( sender ), s ); }
		virtual void onForget(Memory* sender, base::Sched* s)
		{ ObserverBase::saw( "onForget", dynamic_cast< MemoryTest* >( sender ), s ); }
		virtual void onAlert(Memory* sender)
		{ ObserverBase::saw( "onAlert", dynamic_cast< MemoryTest* >( sender ) ); }
		//@}
	};

	/****************************** PORT HEAD *********************************/

	/**
	 * @struct PortTestElement
	 * @brief Simple user-defined Port data type
	 */
	struct PortTestElement
	{
		unsigned int id; ///< data element id for checking correct data handling
	};

	/// make PortTestElement objects streamable
	extern std::ostream& operator<< ( std::ostream& stream, const PortTestElement& e );

	/// compare PortTestElement objects
	extern bool operator== ( const PortTestElement& e1, const PortTestElement& e2 );

	/**
	 * @class PortHeadTTestGetProcess
	 * @brief A simple Process class for accessing a WAITING_MODE PortHeadT
	 */
	class PortHeadTTestGetProcess:
		public base::Process
	{
	public:
		PortHeadT< PortTestElement >::Ptr port; ///< reference to the PortHeadT to read from
		PortTestElement received; ///< the element received from the Port

		/// Constructor
		PortHeadTTestGetProcess( base::Simulation& sim, const data::Label& l, PortHeadT< PortTestElement >::Ptr port )
		:	Process( sim, l ),
			port( port )
			{
				received.id = 0;
			}

		/// Simple Process behavior implementation to get data from a port
		virtual int main()
		{
			std::auto_ptr< PortTestElement > pointer = port->get();
			if( pointer.get() != 0 ) received = *pointer;
			return 0;
		}
	};

  /**
   * @class PortHeadTTestGetCriterionProcess
   * @brief A simple Process class for accessing a WAITING_MODE PortHeadT with a given
   * criterion.
   */
  class PortHeadTTestGetCriterionProcess: 
    public base::Process
  {

	public:
		PortHeadT< PortTestElement >::Ptr port; ///< reference to the PortHeadT to read from
		PortTestElement received; ///< the element received from the Port

		/// Constructor
		PortHeadTTestGetCriterionProcess( base::Simulation& sim, const data::Label& l, PortHeadT< PortTestElement >::Ptr port )
		:	Process( sim, l ),
			port( port )
			{
				received.id = 0;
			}

    /// Criterion - check if el.id != 0
    bool ElementCondition ( PortTestElement el )
    {
      return el.id == 1;
    }

		/// Simple Process behavior implementation to get data from a port
		virtual int main()
		{
			std::auto_ptr< PortTestElement > pointer = port->get( 
         ( PortHeadT< PortTestElement >::ElementCondition ) &PortHeadTTestGetCriterionProcess::ElementCondition);
			if( pointer.get() != 0 ) received = *pointer;
			return 0;
		}
  };

	/**
	 * @class PortHeadTTestGetEvent
	 * @brief An Event used for accessing a PortHeadT in WAITING_MODE
	 */
	class PortHeadTTestGetEvent:
		public base::Event
	{
	public:
		PortHeadT< PortTestElement >::Ptr port; ///< a reference to the PortHeadT
		std::auto_ptr< PortTestElement > received; ///< pointer to hold the return value of get()

		/// Constructor
		PortHeadTTestGetEvent( base::Simulation& sim, const data::Label& l, PortHeadT< PortTestElement >::Ptr port )
		:	Event( sim, l ),
			port( port ),
			received( 0 )
			{}

		/// Simple action implementation for accessing a Port
		virtual void eventAction()
		{
			std::auto_ptr< PortTestElement > pointer = port->get();
			received = pointer;
		}
	};

	/**
	 * @class PortHeadTTestObserver
	 * @brief Implements PortHeadTObserver to validate execution of PortHeadT methods
	 */
	class PortHeadTTestObserver:
		public PortHeadTObserver< PortTestElement >,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		PortHeadTTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(PortHeadT< PortTestElement >* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(PortHeadT< PortTestElement >* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onGet(PortHeadT< PortTestElement >* sender)
		{ ObserverBase::saw( "onGet", sender ); }
		virtual void onUnGet(PortHeadT< PortTestElement >* sender, const PortTestElement& newElement)
		{ ObserverBase::saw( "onUnGet", sender, toString( newElement.id ) ); }
		virtual void onCut(PortHeadT< PortTestElement >* sender)
		{ ObserverBase::saw( "onCut", sender ); }
		virtual void onSplice(PortHeadT< PortTestElement >* sender, PortHeadT< PortTestElement >::TailPtr oldTail)
		{ ObserverBase::saw( "onSplice", sender, oldTail->getLabel() ); }
		virtual void onCppSplice(PortHeadT< PortTestElement >* sender, PortHeadT< PortTestElement >::TailPtr tail, bool append)
		{ ObserverBase::saw( "onCppSplice", sender, tail->getLabel(), toString( append ) ); }
		virtual void onAlert(PortHeadT< PortTestElement >* sender, base::Sched* alerted)
		{ ObserverBase::saw( "onAlert", sender, alerted->getLabel() ); }
		virtual void onChangeMode(PortHeadT< PortTestElement >* sender, PortMode oldMode, PortMode newMode)
		{
			std::string from, to;
			switch( oldMode )
			{
			case ERROR_MODE: from = "ERROR_MODE"; break;
			case WAITING_MODE: from = "WAITING_MODE"; break;
			case ZERO_MODE: from = "ZERO_MODE"; break;
			}
			switch( newMode )
			{
			case ERROR_MODE: to = "ERROR_MODE"; break;
			case WAITING_MODE: to = "WAITING_MODE"; break;
			case ZERO_MODE: to = "ZERO_MODE"; break;
			}
			ObserverBase::saw( "onChangeMode", sender, from, to );
		}
		virtual void onChangeMaxCapacity(PortHeadT< PortTestElement >* sender, SizeType oldMax, SizeType newMax)
		{ ObserverBase::saw( "onChangeMaxCapacity", sender, toString( oldMax ), toString( newMax ) ); }
		//@}
	};

	/**************************** PORT TAIL ***********************************/

	/**
	 * @class PortTailTTestPutProcess
	 * @brief A Process used for accessing a PortTailT
	 */
	class PortTailTTestPutProcess:
		public base::Process
	{
	public:
		PortTailT< PortTestElement >::Ptr port; ///< the Port to put data into
		unsigned int elementId;  ///< holds the id value for the data to add
		int putReturnValue; ///< holds the return value of the put() call

		/// Constructor
		PortTailTTestPutProcess( base::Simulation& sim, const data::Label& l, PortTailT< PortTestElement >::Ptr port, unsigned int elementId )
		:	Process( sim, l ),
			port( port ),
			elementId( elementId ),
			putReturnValue( 100 )
			{}

		/// Simple implementation of Process behavior for accessing a PortTailT
		virtual int main()
		{
			PortTestElement element = { elementId };
			putReturnValue = port->put( element );
			return 0;
		}
	};

	/**
	 * @class PortTailTTestGetEvent
	 * @brief An Event used for accessing a PortTailT in WAITING_MODE
	 */
	class PortTailTTestPutEvent:
		public base::Event
	{
	public:
		PortTailT< PortTestElement >::Ptr port; ///< a reference to the PortTailT
		unsigned int elementId;  ///< holds the id value for the data to add
		int putReturnValue; ///<  holds the return value of put()

		/// Constructor
		PortTailTTestPutEvent( base::Simulation& sim, const data::Label& l, PortTailT< PortTestElement >::Ptr port, unsigned int elementId )
		:	Event( sim, l ),
			port( port ),
			elementId( elementId ),
			putReturnValue( 100 )
			{}

		/// Simple action implementation for accessing a PortTailT
		virtual void eventAction()
		{
			PortTestElement element = { elementId };
			putReturnValue = port->put( element );
		}
	};

	/**
	 * @class PortTailTTestObserver
	 * @brief Implements PortTailTObserver to validate execution of PortTailT methods
	 */
	class PortTailTTestObserver:
		public PortTailTObserver< PortTestElement >,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		PortTailTTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(PortTailT< PortTestElement >* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(PortTailT< PortTestElement >* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onPut(PortTailT< PortTestElement >* sender, const PortTestElement& newElement)
		{ ObserverBase::saw( "onPut", sender, toString( newElement.id ) ); }
		virtual void onCut(PortTailT< PortTestElement >* sender)
		{ ObserverBase::saw( "onCut", sender ); }
		virtual void onSplice(PortTailT< PortTestElement >* sender, PortHeadT< PortTestElement >::Ptr oldHead)
		{ ObserverBase::saw( "onSplice", sender, oldHead->getLabel() ); }
		virtual void onCppSplice(PortTailT< PortTestElement >* sender, PortHeadT< PortTestElement >::Ptr oldHead, bool append)
		{ ObserverBase::saw( "onCppSplice", sender, oldHead->getLabel(), toString( append ) ); }
		virtual void onAlert(PortTailT< PortTestElement >* sender, base::Sched* alerted)
		{ ObserverBase::saw( "onAlert", sender, alerted->getLabel() ); }
		virtual void onChangeMode(PortTailT< PortTestElement >* sender, PortMode oldMode, PortMode newMode)
		{
			std::string from, to;
			switch( oldMode )
			{
			case ERROR_MODE: from = "ERROR_MODE"; break;
			case WAITING_MODE: from = "WAITING_MODE"; break;
			case ZERO_MODE: from = "ZERO_MODE"; break;
			}
			switch( newMode )
			{
			case ERROR_MODE: to = "ERROR_MODE"; break;
			case WAITING_MODE: to = "WAITING_MODE"; break;
			case ZERO_MODE: to = "ZERO_MODE"; break;
			}
			ObserverBase::saw( "onChangeMode", sender, from, to );
		}
		virtual void onChangeMaxCapacity(PortTailT< PortTestElement >* sender, SizeType oldMax, SizeType newMax)
		{ ObserverBase::saw( "onChangeMaxCapacity", sender, toString( oldMax ), toString( newMax ) ); }
		//@}
	};

	/***************************** RES ****************************************/

	/**
	 * @class ResTaker
	 * @brief Simple Process implementation that takes a number of tokens
	 */
	class ResTaker:
		public base::Process
	{
	public:
		Res& theRes; ///< reference to the Res object to work with
		unsigned int number; ///< the amount of tokens to take
		unsigned int received; ///< the amount of tokens received

		/// Constructor
		ResTaker( base::Simulation& s, const data::Label& l, Res& r, unsigned int howMany )
		:	Process( s, l ),
			theRes( r ),
			number( howMany ),
			received( 0 )
			{}

		/// minimal implementation of Process behavior to take tokens from Res
		virtual int main()
		{
			received = theRes.acquire( number );
			return received;
		}
	};

	/**
	 * @class ResTestUnControlProcess
	 * @brief Simple Process implementation that lowers the Res token limit
	 */
	class ResTestUnControlProcess:
		public base::Process
	{
	public:
		Res& theRes; ///< reference to the Res object to work with
		unsigned int number; ///< the amount of tokens to remove from the resource
		int unControlReturnValue; ///< the amount of tokens removed, or 0 on interrupt

		/// Constructor
		ResTestUnControlProcess( base::Simulation& s, const data::Label& l, Res& r, unsigned int howMany )
		:	Process( s, l ),
			theRes( r ),
			number( howMany ),
			unControlReturnValue( -1 )
			{}

		/// minimal implementation of Process behavior to lower the Res token limit
		virtual int main()
		{
			unControlReturnValue = theRes.unControl( number );
			return unControlReturnValue;
		}
	};

	/**
	 * @class ResTestObserver
	 * @brief Implements ResObserver to validate execution of Res methods
	 */
	class ResTestObserver:
		public ResObserver,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		ResTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(Res* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(Res* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onAcquireFail(Res* sender, std::size_t n)
		{ ObserverBase::saw( "onAcquireFail", sender, toString( n ) ); }
		virtual void onAcquireSucceed(Res* sender, std::size_t n)
		{ ObserverBase::saw( "onAcquireSucceed", sender, toString( n ) ); }
		virtual void onReleaseFail(Res* sender, std::size_t n)
		{ ObserverBase::saw( "onReleaseFail", sender, toString( n ) ); }
		virtual void onReleaseSucceed(Res* sender, std::size_t n)
		{ ObserverBase::saw( "onReleaseSucceed", sender, toString( n ) ); }
		virtual void onControl(Res* sender, std::size_t n)
		{ ObserverBase::saw( "onControl", sender, toString( n ) ); }
		virtual void onUnControl(Res* sender, std::size_t n)
		{ ObserverBase::saw( "onUnControl", sender, toString( n ) ); }
		virtual void onChangeTokenNumber(Res* sender, std::size_t oldTokenNumber,
			std::size_t newTokenNumber)
		{ ObserverBase::saw( "onChangeTokenNumber", sender, toString( oldTokenNumber ), toString( newTokenNumber ) ); }
		//@}
	};

	/**************************** RES TEMPLATE ********************************/

	/**
	 * @class ResTTaker
	 * @brief Simple Process implementation that takes a number of tokens
	 */
	class ResTTaker:
		public base::Process
	{
	public:
		ResT< TokenTest >& theRes; ///< reference to the Bin object to work with
		std::size_t number; ///< the amount of tokens to take
		std::vector< TokenTest* > receivedTokens; ///< vector of received token objects
		TokenTest* token; ///< a single received token
		bool release; ///< a boolean value to control the token release

		/// Constructor
		ResTTaker( base::Simulation& s, const data::Label& l, ResT< TokenTest >& r, std::size_t howMany, bool rel = false )
		:	Process( s, l ),
			theRes( r ),
			number( howMany ),
			receivedTokens( 0 ),
			token( 0 ),
			release( rel )
			{}

		/// Process behavior to take and release tokens from ResT
		virtual int main()
		{
			// test single acquire
			if( number == 1 )
			{
				token = theRes.acquire();

				if( release )
				{
					hold();
					theRes.release( token );
				}
			}
			// test multiple-token acquire
			else
			{
				receivedTokens = theRes.acquire( number );

				if( release )
				{
					hold();
					theRes.release( receivedTokens );
				}
			}
			// return the number of received tokens
			return token ? 1 : receivedTokens.size();
		}
	};

	/**
	 * @class ResTTestUnControl
	 * @brief Simple Process implementation that permanently removes a number of
	 * tokens from a resource
	 */
	class ResTTestUnControl:
		public base::Process
	{
	public:
		ResT< TokenTest >& theRes; ///< reference to the Bin object to work with
		std::size_t number; ///< the amount of tokens to take
		std::vector< TokenTest > receivedTokens; ///< vector of received token objects

		/// Constructor
		ResTTestUnControl( base::Simulation& s, const data::Label& l, ResT< TokenTest >& r, std::size_t howMany )
		:	Process( s, l ),
			theRes( r ),
			number( howMany )
			{}

		/// Simple implementation of Process behavior to evoke ResT::unControl()
		virtual int main()
		{
			receivedTokens = theRes.unControl( number );
			return receivedTokens.size();
		}
	};


	/**
	 * @class ResTTestObserver
	 * @brief Implements ResTObserver to validate execution of ResT methods
	 */
	class ResTTestObserver:
		public ResTObserver< TokenTest >,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		ResTTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(ResType* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(ResType* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onAcquireFail(ResType* sender, std::size_t n)
		{ ObserverBase::saw( "onAcquireFail", sender, toString( n ) ); }
		virtual void onAcquireSucceed(ResType* sender, std::size_t n)
		{ ObserverBase::saw( "onAcquireSucceed", sender, toString( n ) ); }
		virtual void onReleaseFail(ResType* sender, std::size_t n)
		{ ObserverBase::saw( "onReleaseFail", sender, toString( n ) ); }
		virtual void onReleaseSucceed(ResType* sender, std::size_t n)
		{ ObserverBase::saw( "onReleaseSucceed", sender, toString( n ) ); }
		virtual void onTransfer(ResType* sender, std::size_t n,
				base::Process* oldOwner, base::Process* newOwner)
		{ ObserverBase::saw( "onTransfer", sender, toString( n ), oldOwner->getLabel(), newOwner->getLabel() );}
		virtual void onControl(ResType* sender, std::size_t n)
		{ ObserverBase::saw( "onControl", sender, toString( n ) ); }
		virtual void onUnControl(ResType* sender, std::size_t n)
		{ ObserverBase::saw( "onUnControl", sender, toString( n ) ); }
		virtual void onChangeTokenNumber(ResType* sender, std::size_t oldTokenNumber, std::size_t newTokenNumber)
		{ ObserverBase::saw( "onChangeTokenNumber", sender, toString( oldTokenNumber ), toString( newTokenNumber ) ); }
		//@}
	};

	/****************** RES TEMPLATE WITH CHOICE ******************************/

	/**
	 * @class ResTChoiceTaker
	 * @brief Simple Process implementation that takes a number of tokens
	 * according to a selection function
	 */
	class ResTChoiceTaker:
		public base::Process
	{
	public:
		ResTChoice< TokenTest >& theRes; ///< reference to the Bin object to work with
		std::size_t number; ///< the amount of tokens to take
		short tokenSelectId; ///< border value used in selection function
		std::vector< TokenTest* > receivedTokens; ///< vector of received token objects
		TokenTest* token; ///< a single received token
		ResTChoice< TokenTest >::Selection select; ///< selection function pointer
		bool release; ///< a boolean value to control the token release

		/// Constructor
		ResTChoiceTaker( base::Simulation& s, const data::Label& l, ResTChoice< TokenTest >& r,
				std::size_t howMany, ResTChoice< TokenTest >::Selection sel,
				short choice, bool rel = false )
		:	Process( s, l ),
			theRes( r ),
			number( howMany ),
			tokenSelectId( choice ),
			receivedTokens( 0 ),
			token( 0 ),
			select( sel ),
			release( rel )
			{}

		/// Process behavior to take and release tokens from ResTChoice
		virtual int main()
		{
			// test single acquire
			if( number == 1 )
			{
				token = theRes.acquire( select );

				if( release )
				{
					holdFor(1);
					theRes.release( token );
				}
			}
			// test multiple-token acquire
			else
			{
				receivedTokens = theRes.acquire( select, number );

				if( release )
				{
					holdFor(1);
					theRes.release( receivedTokens );
				}
			}
			// return the number of received tokens
			return token ? 1 : receivedTokens.size();
		}
	};

	/**
	 * @brief Token selection function used by ResTChoiceTaker
	 *
	 * This function is used for selecting specific tokens from the resource.
	 * This simple implementation merely checks if a token's id value is less
	 * than a limit value stored as a member of the calling ResTChoiceTaker
	 * object.
	 */
	extern bool tokenSelect( base::Process* resTaker, TokenTest* t );

	/**
	 * @class ResTChoiceTestObserver
	 * @brief Implements ResTChoiceObserver to validate execution of ResTChoice methods
	 */
	class ResTChoiceTestObserver:
		public ResTChoiceObserver< TokenTest >,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		ResTChoiceTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(ResTBase< TokenTest >* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(ResTBase< TokenTest >* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onAcquireFail(ResTBase< TokenTest >* sender, std::size_t n)
		{ ObserverBase::saw( "onAcquireFail", sender, toString( n ) ); }
		virtual void onAcquireSucceed(ResTBase< TokenTest >* sender, std::size_t n)
		{ ObserverBase::saw( "onAcquireSucceed", sender, toString( n ) ); }
		virtual void onReleaseFail(ResTBase< TokenTest >* sender, std::size_t n)
		{ ObserverBase::saw( "onReleaseFail", sender, toString( n ) ); }
		virtual void onReleaseSucceed(ResTBase< TokenTest >* sender, std::size_t n)
		{ ObserverBase::saw( "onReleaseSucceed", sender, toString( n ) ); }
		virtual void onChangeTokenNumber(ResTBase< TokenTest >* sender, std::size_t oldTokenNumber, std::size_t newTokenNumber)
		{ ObserverBase::saw( "onChangeTokenNumber", sender, toString( oldTokenNumber ), toString( newTokenNumber ) ); }
		//@}
	};

	/******************************** TIMER ***********************************/

	/**
	 * @class TimerTestObserver
	 * @brief Implements TimerObserver to validate execution of Timer methods
	 */
	class TimerTestObserver:
		public TimerObserver,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		TimerTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(Timer* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(Timer* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onSetIn( Timer* sender, base::SimTime t )
		{ ObserverBase::saw( "onSetIn", sender, toString( t ) ); }
		virtual void onSetAt( Timer* sender, base::SimTime t )
		{ ObserverBase::saw( "onSetAt", sender, toString( t ) ); }
		virtual void onReset(Timer* sender, base::SimTime oldTime, base::SimTime newTime)
		{ ObserverBase::saw( "onReset", sender, toString( oldTime ), toString( newTime ) ); }
		virtual void onStop(Timer* sender)
		{ ObserverBase::saw( "onStop", sender ); }
		virtual void onRegisterProcess(Timer* sender, base::Process* p)
		{ ObserverBase::saw( "onRegisterProcess", sender, p ); }
		virtual void onRemoveProcess(Timer* sender, base::Process* p)
		{ ObserverBase::saw( "onRemoveProcess", sender, p ); }
		virtual void onTimeout(Timer* sender)
		{ ObserverBase::saw( "onTimeout", sender ); }
		//@}
	};

	/******************************** WAITQ ***********************************/

	/**
	 * @class WaitQTestSlave
	 * @brief Simple slave Process implementation for using a WaitQ
	 */
	class WaitQTestSlave:
		public base::Process
	{
	public:
		WaitQ& waitQ; ///< a reference to the condition queue to be used
		int selectionValue; ///< integer for modeling a selection property
		int weightValue; ///< the weight value of this process
		base::Weight weightFct; ///< the weight function to be used
		bool running; ///< a boolean to check if main was called
		bool reactivated; ///< a boolean to check if the process has been reactivated
		bool waitReturnValue; ///< a boolean to test the return value of WaitQ::wait()

		/// Constructor
		WaitQTestSlave( base::Simulation& sim, const data::Label& l, WaitQ& q, int sel = 0, base::Weight w = 0 )
		:	Process( sim, l ),
			waitQ( q ),
			selectionValue( sel ),
			weightValue( 0 ),
			weightFct( w ),
			running( false ),
			reactivated( false ),
			waitReturnValue( false )
			{}

		/// Simple implementation of Process behavior for using a wait condition
		virtual int main()
		{
			running = true;
			if( weightFct )
			{
				waitReturnValue = waitQ.wait( weightFct );
			}
			else
			{
				waitReturnValue = waitQ.wait();
			}
			reactivated = true;
			return 0;
		}
	};

	/**
	 * @class WaitQTestMaster
	 * @brief Simple master Process implementation for using a WaitQ
	 */
	class WaitQTestMaster:
		public base::Process
	{
	public:
		WaitQ& waitQ; ///< a reference to the condition queue to be used
		int selectionValue; ///< integer for modeling a selection property
		int weightValue; ///< the weight value of this process
		bool weighted; ///< specifies whether to use the weight function
		bool running; ///< a boolean to check if main was called
		bool reactivated; ///< a boolean to check if the process has been reactivated
		Process* slave; ///< the Process acquired by coopt

		/// Constructor
		WaitQTestMaster( base::Simulation& sim, const data::Label& l, WaitQ& q, int sel = 0, bool w = false )
		:	Process( sim, l ),
			waitQ( q ),
			selectionValue( sel ),
			weightValue( 0 ),
			weighted( w ),
			running( false ),
			reactivated( false ),
			slave( 0 )
			{}

		/// Simple implementation of Process behavior for using a wait condition
		virtual int main()
		{
			running = true;
			if( selectionValue )
			{
				slave = waitQ.coopt( (base::Selection) &WaitQTestMaster::select );
			}
			else if( weighted )
			{
				slave = waitQ.coopt( (base::Weight) &WaitQTestMaster::weight );
			}
			else
			{
				slave = waitQ.coopt();
			}
			reactivated = true;
			return 0;
		}

		bool select( Process* partner )
		{
			return ( static_cast< WaitQTestSlave* >( partner )->selectionValue
					== this->selectionValue );
		}

		double weight( Process* partner )
		{
			return static_cast< WaitQTestSlave* >( partner )->weightValue + this->weightValue;
		}
	};

	/**
	 * @class WaitQTestAvail
	 * @brief Simple master Process implementation for using a WaitQ
	 */
	class WaitQTestAvail:
		public base::Process
	{
	public:
		WaitQ& waitQ; ///< a reference to the condition queue to be used
		int selectionValue; ///< integer for modeling a selection property
		bool running; ///< a boolean to check if main was called
		bool reactivated; ///< a boolean to check if the process has been reactivated
		Process* slave; ///< the Process acquired by coopt

		/// Constructor
		WaitQTestAvail( base::Simulation& sim, const data::Label& l, WaitQ& q, int sel = 0 )
		:	Process( sim, l ),
			waitQ( q ),
			selectionValue( sel ),
			running( false ),
			reactivated( false ),
			slave( 0 )
			{}

		/// Simple implementation of Process behavior for using a wait condition
		virtual int main()
		{
			running = true;
			if( selectionValue )
			{
				slave = waitQ.avail( (base::Selection) &WaitQTestAvail::select );
			}
			else
			{
				slave = waitQ.avail();
			}
			reactivated = true;
			return 0;
		}

		bool select( Process* partner )
		{
			return ( static_cast< WaitQTestSlave* >( partner )->selectionValue
					== this->selectionValue );
		}
	};

	/**
	 * @class WaitQTestObserver
	 * @brief Implements WaitQObserver to validate execution of WaitQ methods
	 */
	class WaitQTestObserver:
		public WaitQObserver,
		public ObserverBase
	{
	public:
		/**
		 * @brief Constructor
		 * @param output determines whether Observations are sent to stdout
		 */
		WaitQTestObserver( bool output ):
			ObserverBase( output )
			{}

		/**
		 * @name Implementation of virtual Observer functions
		 *
		 * Most ODEMx classes define an Observer interface with empty
		 * implementation. These virtual functions are re-implemented here in
		 * order to observe the behavior of test objects. All of them call
		 * ObserverBase::saw() to store events with parameters in the
		 * observation history which can then be used to verify expected
		 * behavior of objects.
		 *
		 * @{
		 */
		virtual void onCreate(WaitQ* sender)
		{ ObserverBase::saw( "onCreate", sender ); }
		virtual void onDestroy(WaitQ* sender)
		{ ObserverBase::saw( "onDestroy", sender ); }
		virtual void onWait(WaitQ* sender, base::Process* slave)
		{ ObserverBase::saw( "onWait", sender, slave ); }
		virtual void onWaitWeight(WaitQ* sender, base::Process* slave)
		{ ObserverBase::saw( "onWaitWeight", sender, slave ); }
		virtual void onAvailFail(WaitQ* sender, base::Process* master)
		{ ObserverBase::saw( "onAvailFail", sender, master ); }
		virtual void onAvailSucceed(WaitQ* sender, base::Process* master, base::Process* slave)
		{ ObserverBase::saw( "onAvailSucceed", sender, master, slave ); }
		virtual void onAvailSelFail(WaitQ* sender, base::Process* master)
		{ ObserverBase::saw( "onAvailSelFail", sender, master ); }
		virtual void onAvailSelSucceed(WaitQ* sender, base::Process* master, base::Process* slave)
		{ ObserverBase::saw( "onAvailSelSucceed", sender, master, slave ); }
		virtual void onCooptFail(WaitQ* sender, base::Process* master)
		{ ObserverBase::saw( "onCooptFail", sender, master ); }
		virtual void onCooptSucceed(WaitQ* sender, base::Process* master, base::Process* slave)
		{ ObserverBase::saw( "onCooptSucceed", sender, master, slave ); }
		virtual void onCooptSelFail(WaitQ* sender, base::Process* master)
		{ ObserverBase::saw( "onCooptSelFail", sender, master ); }
		virtual void onCooptSelSucceed(WaitQ* sender, base::Process* master, base::Process* slave)
		{ ObserverBase::saw( "onCooptSelSucceed", sender, master, slave ); }
		virtual void onCooptWeightFail(WaitQ* sender, base::Process* master)
		{ ObserverBase::saw( "onCooptWeightFail", sender, master ); }
		virtual void onCooptWeightSucceed(WaitQ* sender, base::Process* master, base::Process* slave)
		{ ObserverBase::saw( "onCooptWeightSucceed", sender, master, slave ); }
		//@}
	};

	/************************** WAIT ******************************************/

	/**
	 * @class WaitQTestAvail
	 * @brief Simple waiting Process that uses odemx::Wait
	 */
	class Waiter:
		public base::Process
	{
	public:
		Wait& wait; ///< reference to the wait object
		bool waitReturnValue; ///< the return value of the wait function

		/// Constructor
		Waiter( base::Simulation& s, const data::Label& l, Wait& w )
		:	Process( s, l ),
			wait( w ),
			waitReturnValue( false )
			{}

		/// Simple Process behavior that waits for other processes' termination
		virtual int main()
		{
			waitReturnValue = wait.wait();
			return 0;
		}
	};
} // namespace SuiteSynchronization

#endif /* TESTSYNCHRONIZATION_H_ */
