<?php
/**
 * @copyright NetMonsters <team@netmonsters.ru>
 * @link http://netmonsters.ru
 * @package Majestic
 * @subpackage Tests app
 * @since 10.07.12
 *
 */

require_once __DIR__ . '/../../util/profiler/Profiler.php';
require_once __DIR__ . '/../../exception/GeneralException.php';
require_once __DIR__ . '/../../exception/ErrorHTTPException.php';
require_once __DIR__ . '/../../exception/Error404Exception.php';
require_once __DIR__ . '/../../exception/ErrorHandler.php';
require_once __DIR__ . '/../../app/CliController.php';
require_once __DIR__ . '/../../Registry.php';
require_once __DIR__ . '/../../Config.php';
require_once __DIR__ . '/../../app/iCli.php';
require_once __DIR__ . '/../../logger/Logger.php';
require_once __DIR__ . '/../../logger/CliLogger.php';

/**
 * @desc CliController tests
 * @author Aleksandr Demidov
 */
class CliControllerTest extends PHPUnit_Framework_TestCase
{
    protected $stream;

    public function testGetInstance()
    {
        $instance = CliController::getInstance();
        $this->assertInstanceOf('CliController', $instance);
    }

    public function testExecute()
    {
        Config::set('PROFILER', false);
        $cli_class = $this->getMockForAbstractClass('iCli', array(), '', '', '', '', array('run'));
        $cli_class->expects($this->once())
                ->method('run')
                ->with();
        CliController::getInstance()->execute($cli_class);
    }

    public function testExecuteWithProfiler()
    {
        ob_start();
        Config::set('PROFILER', true);
        $cli_class = $this->getMockForAbstractClass('iCli', array(), '', '', '', '', array('run'));
        $cli_class->expects($this->once())
                ->method('run')
                ->with();
        CliController::getInstance()->execute($cli_class);
        $output = ob_get_clean();
        $this->assertContains('Elapsed time:', $output);
    }


    public function testExecuteWithLogger()
    {
        ob_start();
        Config::set('PROFILER', true);
        Config::set('LOGGING', true);
        Config::set('Logger', array('logger' => 'CliLogger'));
        $cli_class = $this->getMockForAbstractClass('iCli', array(), '', '', '', '', array('run'));
        $cli_class->expects($this->once())
                ->method('run')
                ->with();
        CliController::getInstance()->execute($cli_class);
        $output = ob_get_clean();
        $this->assertContains('Elapsed time:', $output);
    }

    /**
     * @runInSeparateProcess
     */
    public function testExecuteImplementErrorToFile()
    {
        Config::set('ErrorStream', __DIR__ . '/temp.txt');
        touch(Config::get('ErrorStream'));
        $cli_class = new StdClass();
        CliController::getInstance()->execute($cli_class);
        $this->assertContains('Runner "' . get_class($cli_class) . '" need implement of "iCli" interface.', file_get_contents(Config::get('ErrorStream')));
        unlink(Config::get('ErrorStream'));
    }

    /**
     * @runInSeparateProcess
     */
    public function testExecuteImplementErrorToConsole()
    {
        Config::set('ErrorStream', 'php://output');
        $cli_class = new StdClass();
        $this->expectOutputRegex('/.*Runner "' . get_class($cli_class) . '" need implement of "iCli" interface\..*/');
        CliController::getInstance()->execute($cli_class);
    }
    /**
     * @runInSeparateProcess
     */
    public function testExecuteWithRunThrowError()
    {
        Config::set('ErrorStream', 'php://output');
        Config::set('PROFILER', false);
        $cli_class = $this->getMockForAbstractClass('iCli', array(), '', '', '', '', array('run'));
        $cli_class->expects($this->once())
                ->method('run')
                ->with()
                ->will($this->returnCallback(array($this, 'callbackWithThrow')));
        
        $this->expectOutputRegex('/.*Error from callback\..*/');
        CliController::getInstance()->execute($cli_class);
    }

    public function callbackWithThrow()
    {
        throw new ErrorException('Error from callback.');
    }
}