<?php
/**
 * core.framework
 *
 * @category   Core
 * @package    Core_Log_Filter_Throttle
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2013. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 */

/**
 * @category   Core
 * @package    Core_Log_Filter_Throttle
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2013. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 * @group      Core_Log_Filter_Throttle
 */

class Core_Log_Filter_ThrottleTest extends CoreTest_Container_TestCase
{
    /**
     * @var Core_Log_Filter_Throttle
     */
    protected $_object;

    protected function setUp()
    {
        $this->_object  = new Core_Log_Filter_Throttle();
    }

    protected function tearDown()
    {
        Core_Application::resetInstance();
    }

    /**
     * @covers Core_Log_Filter_Throttle::__construct
     */
    public function testConstructReturnsValidObjectAndSetsExpiryTime()
    {
        $filter = new Core_Log_Filter_Throttle(9999);
        $this->assertEquals(9999, $filter->getExpiryTime());
    }


    /**
     * @covers Core_Log_Filter_Throttle::factory
     */
    public function testFactoryReturnsValidObject()
    {
        $filter = Core_Log_Filter_Throttle::factory(array('expiryTime' => 3600));
        $this->assertTrue($filter instanceof Core_Log_Filter_Throttle);
    }

    /**
     * @covers Core_Log_Filter_Throttle::getCache
     * @covers Core_Log_Filter_Throttle::setCache
     */
    public function testCanSetAndGetCache()
    {
        $cacheMock = $this->getMock('Zend_Cache_Core', array(), array());
        $this->_object->setCache($cacheMock);
        $this->assertEquals($cacheMock, $this->_object->getCache());
    }

    /**
     * @covers Core_Log_Filter_Throttle::getCache
     */
    public function testGetCacheWhenNoCacheSetReturnsDefaultCache()
    {
        $cache        = $this->getMock('Zend_Cache_Core');
        $cacheManager = $this->getMock('Core_Cache_Manager', array('getDefaultCache'));
        $cacheManager
            ->expects($this->once())
            ->method('getDefaultCache')
            ->will($this->returnValue($cache));
        $container    = $this->_mockContainer('cacheManager', $cacheManager);
        Core_Application::getInstance()->setContainer($container);

        $this->assertEquals($cache, $this->_object->getCache());
    }


    /**
     * @covers Core_Log_Filter_Throttle::setExpiryTime
     * @covers Core_Log_Filter_Throttle::getExpiryTime
     */
    public function testCanSetAndGetExpiryTime()
    {
        $customExpiryTime = 12*14;
        $this->_object->setExpiryTime($customExpiryTime);
        $this->assertEquals($customExpiryTime, $this->_object->getExpiryTime());
    }

    /**
     * @covers Core_Log_Filter_Throttle::getExpiryTime
     */
    public function testDefaultExpiryTimeIs24Hours()
    {
        $this->assertEquals(86400, $this->_object->getExpiryTime());
    }

    /**
     * @covers Core_Log_Filter_Throttle::setExpiryTime
     *
     * @expectedException InvalidArgumentException
     */
    public function testSetInvalidExpiryTimeThrowsInvalidArgumentException()
    {
        $this->_object->setExpiryTime('!@#');
    }

    /**
     * @covers Core_Log_Filter_Throttle::accept
     */
    public function testThrottlingFirstOccurenceOfExceptionWillEnableLogging()
    {
        // token does not exist, first occurence of this exception
        $mockedTokenData        = null;
        $mockedTokenCounterData = 0;

        $cacheMock  = $this->getMock('Zend_Cache_Core', array('save', 'load'), array());

        // mock loading
        $cacheMock
            ->expects($this->at(0))
            ->method('load')
            ->will($this->returnValue($mockedTokenData));

        $cacheMock
            ->expects($this->at(1))
            ->method('load')
            ->will($this->returnValue($mockedTokenCounterData));

        $this->_object->setCache($cacheMock);

        // return true, logging will happen
        $this->assertTrue($this->_object->accept(array('message' => 'Some Error Exception OMFG')));
    }

    /**
     * @covers Core_Log_Filter_Throttle::accept
     */
    public function testThrottlingConcurringExceptionsWillDisableLoggingAndIncreaseCounter()
    {
        // token does not exist, first occurence of this exception
        $mockedTokenData        = 1;
        $mockedTokenCounterData = 3;

        $cacheMock  = $this->getMock('Zend_Cache_Core', array('save', 'load'), array());

        // mock loading
        $cacheMock
            ->expects($this->at(0))
            ->method('load')
            ->will($this->returnValue($mockedTokenData));

        $cacheMock
            ->expects($this->at(1))
            ->method('load')
            ->will($this->returnValue($mockedTokenCounterData));

        $this->_object->setCache($cacheMock);

        $this->assertFalse($this->_object->accept(array('message' => 'Some Error Exception OMFG')));
    }

    /**
     * @covers Core_Log_Filter_Throttle::accept
     */
    public function testThrottlingNewExceptionWhenCounterExistsWillEnableLoggingAndResetCounter()
    {
        // token does not exist, first occurence of this exception
        $mockedTokenData        = null;
        $mockedTokenCounterData = 3;

        $cacheMock  = $this->getMock('Zend_Cache_Core', array('save', 'load'), array());

        // mock loading
        $cacheMock
            ->expects($this->at(0))
            ->method('load')
            ->will($this->returnValue($mockedTokenData));

        $cacheMock
            ->expects($this->at(1))
            ->method('load')
            ->will($this->returnValue($mockedTokenCounterData));

        $this->_object->setCache($cacheMock);

        $this->assertTrue($this->_object->accept(array('message' => 'Some Error Exception OMFG')));
    }
}
