/**
 * @file TestCoroutineContext.cpp
 * @brief Tests for ODEMx class CoroutineContext
 */

#include "TestCoroutine.h"

/// @cond DOXYGEN_SKIP
SUITE( Coro )
{
/// @endcond

	/**
	 * @struct CoroutineContextFixture
	 * @brief Helper struct providing set-up/tear-down of CoroutineContext tests
	 *
	 * @copydetails EventFixture
	 */
	struct CoroutineContextFixture
	{
		/// observer for monitoring CoroutineContext calls
		CoroutineContextTestObserver observer;
		/// a test context pointer
		CoroutineContextTest* context;
		/// a test Coroutine object
		CoroutineTest coro;

		CoroutineContextFixture():
			observer( false ),
			context( new CoroutineContextTest( "CoroutineContextTest", &observer ) ),
			coro( "TestContextCoroutine", context )
			{}

		~CoroutineContextFixture() { if( context ) delete context; }
	};

	/**
	 * @test odemx::CoroutineContext construction and destruction
	 *
	 * Expected observations:
	 * @li initialization of label
	 * @li observation calls of \c onCreate() and \c onDestroy()
	 * @li warning about unfinished coroutines
	 */
	TEST_FIXTURE( CoroutineContextFixture, ConstructionDestruction )
	{
		std::string cAddr = toString( (CoroutineContext*)context );

		CHECK( context->getName() == "CoroutineContextTest" );
		CHECK( observer.observed( "onCreate", cAddr ) );

		delete context; context = 0;
		CHECK( observer.observed( "onDestroy", cAddr ) );
	}

	/**
	 * @test odemx::CoroutineContext::switchTo()
	 *
	 * Precondition: a CoroutineTest object is started to make this call.
	 *
	 * Expected observations after function call:
	 * @li observation call of \c onSwitchTo() from context to Coroutine
	 * @li observation call of \c onChangeActiveCoroutine() from context to Coroutine
	 * @li observation call of \c onChangeActiveCoroutine() from Coroutine to context
	 */
	TEST_FIXTURE( CoroutineContextFixture, SwitchTo )
	{
		coro.switchTo();
		// check for call of CoroutineContext::switchTo()
		CHECK( observer.observed( "onSwitchTo", toString( (CoroutineContext*)context ), toString( &coro ) ) );
		// check start of coroutine, i.e. switch from context to coro
		CHECK( observer.observed( "onChangeActiveCoroutine", toString( (CoroutineContext*)context ), "0", toString( &coro ) ) );
		// check return of coroutine to context
		CHECK( observer.observed( "onChangeActiveCoroutine", toString( (CoroutineContext*)context ), toString( &coro ), "0" ) );
	}

/// @cond DOXYGEN_SKIP
}
/// @endcond
