/*
 *  UT_Timer.cpp
 *  OMA-DM Client
 *
 *  Created by Mykola Bilovus on 03/03/10.
 *  Copyright 2010. All rights reserved.
 *
 */


#include <boost/test/unit_test.hpp>
#include "Event.h"
#include "PortableThread.h"
#include "Timer.h"


using namespace NS_DM_Client;
using namespace NS_DM_Client::NS_Common;


BOOST_AUTO_TEST_SUITE(SuiteCommonLib)


class Sleeper : public Thread
{
public:
	int seconds;
	Sleeper(int sec) : seconds(sec) {
		start();
		wait();
	}
	virtual ~Sleeper() {};
	
protected:
	virtual void run() {
		sleep(1000*seconds);
	}
};


class MockCallback : public Callback
{
private:
	int  expectedTicks;
	int  ticks;
	Event event;

public:
	MockCallback(int expTicks = 1) : expectedTicks(expTicks), ticks(0) {};
	virtual ~MockCallback ()  {};
	
	void Call() {
		if (expectedTicks == ++ticks)
			event.signal();
	}
	
	int ticksReceived() {
		return ticks;
	}
	
	void wait() {
		if (expectedTicks > ticks)
			event.wait();
	}
};


BOOST_AUTO_TEST_CASE(TestCase_TimerCreate)
{
	// test timer's initial state
	Timer timer;
	BOOST_CHECK( !timer.IsRunning() );
}


BOOST_AUTO_TEST_CASE(TestCase_TimerPlainStart)
{
	// test timer's state after start
	Timer timer;
	
	timer.Start();
	BOOST_CHECK( !timer.IsRunning() );
}


BOOST_AUTO_TEST_CASE(TestCase_TimerTick1)
{
	// test timer is able to tick once
	const int ticksToTest = 1;
	MockCallback callback(ticksToTest);
	Timer timer;
	
	timer.SetCallback(&callback);
	timer.SetInterval(1);
	timer.SetTicksCount(ticksToTest);
	timer.Start();
	
	callback.wait();
	Sleeper sleeper(3);
	
	BOOST_CHECK( ticksToTest == callback.ticksReceived() );
	BOOST_CHECK( !timer.IsRunning() );
}


BOOST_AUTO_TEST_CASE(TestCase_TimerTick5)
{
	// test timer is able to tick 5 times
	const int ticksToTest = 5;
	MockCallback callback(ticksToTest);
	Timer timer;
	
	timer.SetCallback(&callback);
	timer.SetInterval(1);
	timer.SetTicksCount(ticksToTest);
	timer.Start();
	
	callback.wait();
	// wait for 3 seconnds for the timer's close 
	Sleeper sleeper(3);

	BOOST_CHECK( ticksToTest == callback.ticksReceived() );
	BOOST_CHECK( !timer.IsRunning() );
}


BOOST_AUTO_TEST_CASE(TestCase_TimerRepeatedStart)
{
	// test that timer is able to be restarted after it completes all tick from the previous start
	const int ticksToTest = 3;
	MockCallback callback(ticksToTest);
	Timer timer;
	
	timer.SetCallback(&callback);
	timer.SetInterval(1);
	timer.SetTicksCount(ticksToTest);
	timer.Start();
	
	callback.wait();
	Sleeper sleeper(3);
	
	BOOST_CHECK( ticksToTest == callback.ticksReceived() );
	BOOST_CHECK( !timer.IsRunning() );



	MockCallback callback2(ticksToTest);
	timer.SetCallback(&callback2);
	timer.Start();
	
	callback2.wait();
	// wait for 3 seconnds for the timer's close 
	Sleeper sleeper2(3);
	
	BOOST_CHECK( ticksToTest == callback.ticksReceived() );
	BOOST_CHECK( !timer.IsRunning() );
}


BOOST_AUTO_TEST_CASE(TestCase_TimerStop)
{
	// test that timer is able to stop ticking
	const int ticksToTest = 10;
	MockCallback callback(ticksToTest);
	Timer timer;
	
	timer.SetCallback(&callback);
	timer.SetInterval(1);
	timer.SetTicksCount(ticksToTest);

	timer.Start();
	Sleeper sleeper(3);

	timer.Stop();
	Sleeper sleeper2(3);
	
	BOOST_CHECK( !timer.IsRunning() );
}


BOOST_AUTO_TEST_SUITE_END()
