/**
 * @file TestLayer.cpp
 * @date May 5, 2010
 * @author ron
 *
 * @brief
 */

#include "TestProtocol.h"
#include "../TestBase/TestBase.h"

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

	/**
	 * @struct LayerFixture
	 * @brief Helper struct providing set-up/tear-down of Layer tests
	 *
	 * @copydetails EventFixture
	 */
	struct LayerFixture
	{
		SuiteBase::SimulationTest sim;
		TestLogConsumer::Ptr log;
		Layer layer;
		data::TypeInfo type;

		LayerFixture()
		:	sim( "LayerTestSim" )
		,	log( TestLogConsumer::create() )
		,	layer( sim, "LayerTest" )
		,	type( typeid(Layer) )
		{
			sim.addConsumer( log );
		}
	};

	TEST_FIXTURE( LayerFixture, ConstructionDestruction )
	{
		data::Label label = "LayerTestConstructionDestruction";
		{
			Layer layer( sim, label );
			CHECK_EQUAL( (Layer*) 0, layer.getUpperLayer() );
			CHECK_EQUAL( (Layer*) 0, layer.getLowerLayer() );
			CHECK( layer.getSaps().empty() );
			CHECK( layer.getServiceProviders().empty() );
			CHECK( log->getTraceRecord( "create", type ) );

			layer.addServiceProvider( new ServiceProviderTest( sim, "LayerTestSP" ) );
		}
		CHECK( log->getTraceRecord( "destroy", type ) );
		CHECK( log->getTraceRecord( "destroy", typeid(ServiceProvider) ) );
	}

	TEST_FIXTURE( LayerFixture, AddServiceProvider )
	{
		ServiceProviderTest* sp = new ServiceProviderTest( sim, "LayerTestSP" );
		layer.addServiceProvider( sp );
		Sap* sap = sp->addSap( "SAP" );

		CHECK_EQUAL( &layer, sp->getLayer() );
		CHECK_EQUAL( sap, layer.getSap( "SAP" ) );
		CHECK( log->getTraceRecord( "add service provider", type ) );
		CHECK_EQUAL( (std::size_t) 1, layer.getServiceProviders().size() );
	}

	TEST_FIXTURE( LayerFixture, AddSap )
	{
		Sap* sap = new Sap( sim, "LayerTestAddSap", "SAP" );

		layer.addSap( sap );
		CHECK_EQUAL( (std::size_t) 1, layer.getSaps().size() );
		CHECK( log->getTraceRecord( "add SAP", type ) );

		layer.addSap( sap );
		CHECK_EQUAL( (std::size_t) 1, layer.getSaps().size() );
		CHECK( log->getWarningRecord( "Layer::addSap(): SAP already in map, insertion failed", type ) );
	}

	TEST_FIXTURE( LayerFixture, GetSap )
	{
		Sap* found = layer.getSap( "SAP" );
		CHECK_EQUAL( (Sap*) 0, found );

		std::auto_ptr< Sap > sap( new Sap( sim, "LayerTestGetSap", "SAP" ) );
		layer.addSap( sap.get() );

		found = layer.getSap( "SAP" );
		CHECK_EQUAL( sap.get(), found );
	}

	TEST_FIXTURE( LayerFixture, RemoveSap )
	{
		bool success = layer.removeSap( "NotInMap" );
		CHECK( ! success );
		CHECK( log->getWarningRecord( "Layer::removeSap(): SAP not found", type ) );

		Sap* sap = new Sap( sim, "LayerTestRemoveSap", "SAP" );
		layer.addSap( sap );
		CHECK_EQUAL( (std::size_t) 1, layer.getSaps().size() );
		success = layer.removeSap( "SAP" );
		CHECK( success );
		CHECK( layer.getSaps().empty() );
		CHECK( log->getTraceRecord( "remove SAP", type ) );
	}

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