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

/**
 * @category   Core
 * @package    Core_Request
 * @subpackage UnitTests
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 * @group      Core_Request
 */
class Core_RequestTest extends PHPUnit_Framework_TestCase
{
    /**
     * @var Core_Request
     */
    protected $_object;

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

    protected function tearDown()
    {
        $_POST   = array();
        $_GET    = array();
        $_ENV    = array();
        $_SERVER = array();
        $_COOKIE = array();
    }

    /**
     * @covers Core_Request::__construct
     */
    public function testWillAutoUnpackInputIfMethodIsPut()
    {
        $_SERVER['CONTENT_TYPE']       = '+urlencoded';
        $_SERVER['REQUEST_METHOD']     = 'PUT';
        $_ENV['CF_TEST_REQUEST_INPUT'] = 'abc=1&bcd=2';

        $object = new Core_Request;
        $this->assertEquals(1, $object->get('abc'));
    }

    /**
     * @covers Core_Request::__construct
     */
    public function testWillAutoUnpackInputIfMethodIsPatch()
    {
        $_SERVER['CONTENT_TYPE']       = '+urlencoded';
        $_SERVER['REQUEST_METHOD']     = 'PATCH';
        $_ENV['CF_TEST_REQUEST_INPUT'] = 'abc=1&bcd=2';

        $object = new Core_Request;
        $this->assertEquals(2, $object->get('bcd'));
    }

    /**
     * @covers Core_Request::__construct
     */
    public function testWillUnpackJsonInput()
    {
        $_SERVER['CONTENT_TYPE']       = 'text/json';
        $_SERVER['REQUEST_METHOD']     = 'PUT';
        $_ENV['CF_TEST_REQUEST_INPUT'] = '{"abc": "1", "bcd": "2"}';

        $object = new Core_Request;
        $this->assertEquals(2, $object->get('bcd'));
    }

    /**
     * @covers Core_Request::__construct
     */
    public function testWillRecognizeInvalidJsonInput()
    {
        $_SERVER['CONTENT_TYPE']       = 'text/json';
        $_SERVER['REQUEST_METHOD']     = 'PUT';
        $_ENV['CF_TEST_REQUEST_INPUT'] = "{&a}gg1";

        $object = new Core_Request;
        $this->assertFalse($object->isValid());
    }

    /**
     * @covers Core_Request::__construct
     */
    public function testWillRecognizeInvalidXmlInput()
    {
        $_SERVER['CONTENT_TYPE']       = 'text/xml';
        $_SERVER['REQUEST_METHOD']     = 'PUT';
        $_ENV['CF_TEST_REQUEST_INPUT'] = "<a>foo</b>%1";

        $object = new Core_Request;
        $this->assertFalse($object->isValid());
    }

    /**
     * @covers Core_Request::__construct
     */
    public function testWillRecognizeInvalidContentMd5IfSet()
    {
        $_ENV['CF_TEST_REQUEST_INPUT'] = "<a>foo</a>";

        $_SERVER['REQUEST_METHOD']     = 'PUT';
        $_SERVER['CONTENT_TYPE']       = 'text/xml';
        $_SERVER['CONTENT_MD5']        = 'this request checksum is invalid';

        $object = new Core_Request;
        $this->assertFalse($object->isValid());
    }

    /**
     * @covers Core_Request::__construct
     */
    public function testWillAllowProperMd5()
    {
        $_ENV['CF_TEST_REQUEST_INPUT'] = "<a>foo</a>";

        $_SERVER['REQUEST_METHOD']     = 'PUT';
        $_SERVER['CONTENT_TYPE']       = '+xml';
        $_SERVER['CONTENT_MD5']        = 'YjA0NWI5NzMwYzhmY2U3YTViYTFmOWY1NTQ3MWY2ZTU=';

        $object = new Core_Request;
        $this->assertTrue($object->isValid());
    }

    /**
     * @covers Core_Request::getError
     */
    public function testCanAccessRequestErrorDetails()
    {
        $_ENV['CF_TEST_REQUEST_INPUT'] = "<a>foo</a>";

        $_SERVER['REQUEST_METHOD']     = 'PUT';
        $_SERVER['CONTENT_TYPE']       = '+xml';
        $_SERVER['CONTENT_MD5']        = 'invalidMD5123=';

        $object   = new Core_Request;
        $expected = 'Invalid Content-MD5, expected YjA0NWI5NzMwYzhmY2U3YTViYTFmOWY1NTQ3MWY2ZTU=, got invalidMD5123=';
        $this->assertEquals($expected, $object->getError());
    }

    /**
     * @covers Core_Request::__construct
     * @covers Core_Request::<protected>
     */
    public function testWillUnpackXmlInput()
    {
        $_SERVER['CONTENT_TYPE']       = 'text/xml';
        $_SERVER['REQUEST_METHOD']     = 'PUT';
        $_ENV['CF_TEST_REQUEST_INPUT'] = '<root><bcd><inner>2</inner></bcd></root>';

        $object = new Core_Request;
        $this->assertEquals(array('bcd' => array('inner' => 2)), $object->getInput());
    }

    /**
     * @covers Core_Request::__construct
     * @covers Core_Request::<protected>
     */
    public function testIfRequestIsPostAndContentTypeIsNotUrlencodedWillOverwritePostSuperglobalFromPhpInput()
    {
        $_POST                         = null;
        $_SERVER['CONTENT_TYPE']       = 'text/xml';
        $_SERVER['REQUEST_METHOD']     = 'POST';
        $_ENV['CF_TEST_REQUEST_INPUT'] = '<root><bcd><inner>2</inner></bcd></root>';

        $object = new Core_Request;
        $this->assertEquals(array('bcd' => array('inner' => 2)), $_POST);
    }

    /**
     * @covers Core_Request::isValid
     */
    public function testRequestIsValidByDefault()
    {
        $this->assertTrue($this->_object->isValid());
    }

    /**
     * @covers Core_Request::isPost
     */
    public function testCanTellIfRequestIsPost()
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertTrue($this->_object->isPost());
    }

    /**
     * @covers Core_Request::isPost
     */
    public function testCanTellIfRequestIsNotPost()
    {
        $_SERVER['REQUEST_METHOD'] = 'GET';

        $this->assertFalse($this->_object->isPost());
    }

    /**
     * @covers Core_Request::isGet
     */
    public function testCanTellIfRequestIsGet()
    {
        $_SERVER['REQUEST_METHOD'] = 'GET';

        $this->assertTrue($this->_object->isGet());
    }

    /**
     * @covers Core_Request::isGet
     */
    public function testCanTellIfRequestIsNotGet()
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertFalse($this->_object->isGet());
    }

    /**
     * @covers Core_Request::isPut
     */
    public function testCanTellIfRequestIsPut()
    {
        $_SERVER['REQUEST_METHOD'] = 'PUT';

        $this->assertTrue($this->_object->isPut());
    }

    /**
     * @covers Core_Request::isPut
     */
    public function testCanTellIfRequestIsNotPut()
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertFalse($this->_object->isPut());
    }

    /**
     * @covers Core_Request::isPatch
     */
    public function testCanTellIfRequestIsPatch()
    {
        $_SERVER['REQUEST_METHOD'] = 'PATCH';

        $this->assertTrue($this->_object->isPatch());
    }

    /**
     * @covers Core_Request::isPatch
     */
    public function testCanTellIfRequestIsNotPatch()
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertFalse($this->_object->isPut());
    }

    /**
     * @covers Core_Request::isDelete
     */
    public function testCanTellIfRequestIsDelete()
    {
        $_SERVER['REQUEST_METHOD'] = 'DELETE';

        $this->assertTrue($this->_object->isDelete());
    }

    /**
     * @covers Core_Request::isDelete
     */
    public function testCanTellIfRequestIsNotDelete()
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertFalse($this->_object->isDelete());
    }

    /**
     * @covers Core_Request::isHead
     */
    public function testCanTellIfRequestIsHead()
    {
        $_SERVER['REQUEST_METHOD'] = 'HEAD';

        $this->assertTrue($this->_object->isHead());
    }

    /**
     * @covers Core_Request::isHead
     */
    public function testCanTellIfRequestIsNotHead()
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertFalse($this->_object->isHead());
    }

    /**
     * @covers Core_Request::isOptions
     */
    public function testCanTellIfRequestIsOptions()
    {
        $_SERVER['REQUEST_METHOD'] = 'OPTIONS';

        $this->assertTrue($this->_object->isOptions());
    }

    /**
     * @covers Core_Request::isOptions
     */
    public function testCanTellIfRequestIsNotOptions()
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertFalse($this->_object->isOptions());
    }

    /**
     * @covers Core_Request::isTrace
     */
    public function testCanTellIfRequestIsTrace()
    {
        $_SERVER['REQUEST_METHOD'] = 'TRACE';

        $this->assertTrue($this->_object->isTrace());
    }

    /**
     * @covers Core_Request::isOptions
     */
    public function testCanTellIfRequestIsNotTrace()
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertFalse($this->_object->isTrace());
    }

    /**
     * @covers Core_Request::isMethod
     */
    public function testCanTestForRequestMethodByNameIgnoringCase()
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertTrue($this->_object->isMethod('post'));
    }

    /**
     * @covers Core_Request::isXMLHTTPRequest
     */
    public function testCanTellIfRequestIsAnXMLHTTPRequest()
    {
        $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';

        $this->assertTrue($this->_object->isXmlHttpRequest());
    }

    /**
     * @covers Core_Request::isXMLHTTPRequest
     */
    public function testCanTellIfRequestIsNotAnXMLHTTPRequest()
    {
        $this->assertFalse($this->_object->isXmlHttpRequest());
    }

    /**
     * @covers Core_Request::isXMLHTTPRequest
     */
    public function testCanTellIfRequestIsABotRequest()
    {
        $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)';
        
        $this->assertTrue($this->_object->isBot());
    }
    
    /**
     * @covers Core_Request::isXMLHTTPRequest
     */
    public function testCanTellIfRequestIsNotABotRequest()
    {
        $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:32.0) Gecko/20100101 Firefox/32.0';
        
        $this->assertFalse($this->_object->isBot());
    }

    /**
     * @covers Core_Request::isSecure
     */
    public function testCanTellIfRequestIsSecure()
    {
        $_SERVER['HTTPS'] = 'on';

        $this->assertTrue($this->_object->isSecure());
    }

    /**
     * @covers Core_Request::isSecure
     */
    public function testCanTellIfRequestIsNotSecure()
    {
        $this->assertFalse($this->_object->isSecure());
    }

    /**
     * @covers Core_Request::getRawInput
     */
    public function testRawInputIsAnEmptyStringByDefault()
    {
        $this->assertEquals('', $this->_object->getRawInput());
    }

    /**
     * @covers Core_Request::getRawInput
     */
    public function testCanAccessRawInput()
    {
        $_ENV['CF_TEST_REQUEST_INPUT'] = 'raw_input';

        $this->assertEquals('raw_input', $this->_object->getRawInput());
    }

    /**
     * @covers Core_Request::getContentType
     * @covers Core_Request::<protected>
     */
    public function testDefaultContentTypeIsTextPlain()
    {
        $this->assertEquals('text/plain', $this->_object->getContentType());
    }

    /**
     * @covers Core_Request::getContentCharset
     */
    public function testDefaultContentEncodingIsUTF8()
    {
        $_SERVER['CONTENT_TYPE'] = 'application/json';

        $this->assertEquals('UTF-8', $this->_object->getContentCharset());
    }

    /**
     * @covers Core_Request::getContentFormat
     */
    public function testDefaultContentFormatIsUrlencoded()
    {
        $this->assertEquals('urlencoded', $this->_object->getContentFormat());
    }

    /**
     * @covers Core_Request::getContentFormat
     * @covers Core_Request::<protected>
     */
    public function testWill()
    {
        $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';

        $this->assertEquals('urlencoded', $this->_object->getContentFormat());
    }

    /**
     * @covers Core_Request::getContentParams
     * @covers Core_Request::<protected>
     */
    public function testCanExtractContentParams()
    {
        $_SERVER['CONTENT_TYPE'] = 'application/json; a=123;b=234; c=345';

        $this->assertEquals(array('a' => 123, 'b' => 234, 'c' => 345), $this->_object->getContentParams());
    }

    /**
     * @covers Core_Request::getContentParam
     */
    public function testCanExtractContentParamByName()
    {
        $_SERVER['CONTENT_TYPE'] = 'application/json; a=123;b=234; c=345';

        $this->assertEquals(234, $this->_object->getContentParam('b'));
    }

    /**
     * @covers Core_Request::getContentParam
     */
    public function testWillReturnDefaultValueIfNoContentParamProvided()
    {
        $_SERVER['CONTENT_TYPE'] = 'application/json';

        $this->assertEquals(234, $this->_object->getContentParam('no-such-param', 234));
    }

    /**
     * @param string $cType    Content MIME type
     * @param string $type     Content type (normalized)
     * @param string $encoding Content encoding
     * @param string $format   Content serialization format
     * @param array  $params   Embedded params
     *
     * @covers Core_Request::<protected>
     *
     * @dataProvider contentTypeToTypeEncodingAndFormat
     */
    public function testCanGetContentTypeEncodingAndFormat($cType, $type, $encoding, $format, array $params = array())
    {
        $_SERVER['CONTENT_TYPE'] = $cType;

        $this->assertEquals($type,     $this->_object->getContentType());
        $this->assertEquals($encoding, $this->_object->getContentCharset());
        $this->assertEquals($format,   $this->_object->getContentFormat());
        $this->assertEquals($params,   $this->_object->getContentParams());
    }

    /**
     * @return array
     */
    public function contentTypeToTypeEncodingAndFormat()
    {
        return array(
            // contentType, type, encoding, format, params
            array(
                'application/json',
                'application/json',
                'UTF-8',
                'json'
            ),
            array(
                'application/json; charset=windows-1250',
                'application/json',
                'windows-1250',
                'json',
                array('charset' => 'windows-1250')
            ),
            array(
                'text/xml; charset=UTF-8' ,
                'text/xml',
                'UTF-8',
                'xml',
                array('charset' => 'UTF-8')
            ),
            array(
                'application/x-www-form-urlencoded',
                'application/x-www-form-urlencoded',
                'UTF-8',
                'urlencoded'
            ),
            array(
                'application/vnd.misc.example+json',
                'application/vnd.misc.example',
                'UTF-8',
                'json'
            ),
            array(
                'application/vnd.misc.example+XML;charset=windows-1250',
                'application/vnd.misc.example',
                'windows-1250',
                'xml',
                array('charset' => 'windows-1250')
            ),
            array(
                'application/vnd.misc.example+XML;charset=windows-1250;foo=bar; bla=bla',
                'application/vnd.misc.example',
                'windows-1250',
                'xml',
                array('foo' => 'bar', 'bla' => 'bla', 'charset' => 'windows-1250')
            ),
        );
    }

    /**
     * @covers Core_Request::getContentCharset
     */
    public function testDefaultAcceptEncodingIsUTF8()
    {
        $this->assertEquals('UTF-8', $this->_object->getAcceptCharset());
    }


    /**
     * @covers Core_Request::getAcceptParams
     */
    public function testCanExtractAcceptParams()
    {
        $_SERVER['ACCEPT'] = 'application/json; a=123;b=234; c=345';

        $this->assertEquals(array('a' => 123, 'b' => 234, 'c' => 345), $this->_object->getAcceptParams());
    }

    /**
     * @covers Core_Request::getAcceptParam
     */
    public function testCanExtractAcceptParamByName()
    {
        $_SERVER['ACCEPT'] = 'application/json; a=123;b=234; c=345';

        $this->assertEquals(234, $this->_object->getAcceptParam('b'));
    }

    /**
     * @covers Core_Request::getAcceptParam
     */
    public function testWillReturnDefaultValueIfNoAcceptParamProvided()
    {
        $_SERVER['ACCEPT'] = 'application/json';

        $this->assertEquals(234, $this->_object->getContentParam('no-such-param', 234));
    }

    /**
     * @param array  $headers  Request headers to set
     * @param string $type     Accept content type
     * @param string $encoding Accept content encoding
     * @param string $format   Accept content serialization format
     *
     * @covers Core_Request::getAcceptType
     * @covers Core_Request::getAcceptCharset
     * @covers Core_Request::getAcceptFormat
     *
     * @dataProvider acceptToTypeEncodingAndFormat
     */
    public function testCanGetAcceptTypeEncodingAndFormat(array $headers, $type, $encoding, $format)
    {
        foreach ($headers as $name => $value) {
            $_SERVER['HTTP_'. strtoupper($name)] = $value;
        }

        $this->assertEquals($type,     $this->_object->getAcceptType());
        $this->assertEquals($encoding, $this->_object->getAcceptCharset());
        $this->assertEquals($format,   $this->_object->getAcceptFormat());
    }

    /**
     * @return array
     */
    public function acceptToTypeEncodingAndFormat()
    {
        return array(
            // headers, type, encoding, format
            array(
                array(
                    'ACCEPT' => 'application/json',
                ),
                'application/json', 'UTF-8',  'json'
            ),
            array(
                array(
                    'ACCEPT'           => 'application/json',
                    'ACCEPT_ENCODING'  => 'windows-1250'
                ),
                'application/json', 'windows-1250',  'json'
            ),
            array(
                array(
                    'ACCEPT' => 'text/xml',
                ),
                'text/xml', 'UTF-8', 'xml'
            ),
            array(
                array(
                    'ACCEPT' => 'application/vnd.misc.example+json',
                ),
                'application/vnd.misc.example', 'UTF-8',  'json'
            ),
            array(
                array(
                    'ACCEPT'          => 'application/vnd.misc.example+XML',
                    'ACCEPT_ENCODING' => 'windows-1250'
                ),
                'application/vnd.misc.example', 'windows-1250',  'xml'
            ),
        );
    }
    
    /**
     * @covers Core_Request::getAcceptLanguage
     * @covers Core_Request::<protected>
     */
    public function testCanGetAcceptLanguage()
    {
        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en-US,en;q=0.5';
        
        $this->assertEquals('en-US', $this->_object->getAcceptLanguage());
    }
    
    /**
     * @covers Core_Request::getAcceptLanguage
     * @covers Core_Request::<protected>
     */
    public function testWillPickTheMostAcceptableApplicationAvailableLanguage()
    {
        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en-US,hr;q=0.5';
        
        $this->assertEquals('hr', $this->_object->getAcceptLanguage(array('hr')));
    }
    
    /**
     * @covers Core_Request::getAcceptLanguage
     * @covers Core_Request::<protected>
     */
    public function testWillPickTheFirstApplicationAvailableLanguageIfNothingBetterFoundAndNoDefaultProvided()
    {
        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-DE,de;q=0.5';
        
        $this->assertEquals('hr', $this->_object->getAcceptLanguage(array('en', 'hr'), 'hr'));
    }
    
    /**
     * @covers Core_Request::getAcceptLanguage
     * @covers Core_Request::<protected>
     */
    public function testWillPickTheDefaultAcceptableLanguageIfNothingBetterFoundAndDefaultProvided()
    {
        $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-DE,de;q=0.5';
        
        $this->assertEquals('en', $this->_object->getAcceptLanguage(array('en', 'hr')));
    }

    /**
     * @covers Core_Request::setParam
     * @covers Core_Request::getParam
     * @covers Core_Request::getParams
     */
    public function testCanSetAndGetParams()
    {
        $this->_object->setParam('foo', 'baz');

        $this->assertEquals('baz', $this->_object->getParam('foo'));
        $this->assertEquals(array('foo' => 'baz'), $this->_object->getParams());
    }

    /**
     * @covers Core_Request::getParam
     */
    public function testFetchingAnUnknownParamReturnsNull()
    {
        $this->assertNull($this->_object->getParam('foo'));
    }

    /**
     * @covers Core_Request::get
     */
    public function testGettingAnUnknownVariableReturnsNull()
    {
        $this->assertNull($this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::get
     */
    public function testGettingAnUnknownVariableReturnsTheDefault()
    {
        $this->assertEquals('abc', $this->_object->get('foo', 'abc'));
    }

    /**
     * @covers Core_Request::get
     */
    public function testGettingAVariableWillFirstTryParams()
    {
        $this->_object->setParam('foo', 'baz1');

        $this->assertEquals('baz1', $this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::get
     * @covers Core_Request::<protected>
     */
    public function testGettingAVariableWillSecondTry_GET()
    {
        $_GET['foo'] = 'baz2';

        $this->assertEquals('baz2', $this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::get
     * @covers Core_Request::<protected>
     */
    public function testGettingAVariableWillThirdTry_POST()
    {
        $_POST['foo'] = 'baz3';

        $this->assertEquals('baz3', $this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::get
     * @covers Core_Request::<protected>
     */
    public function testGettingAVariableWillFourtyTryPhpInput()
    {
        $_ENV['CF_TEST_REQUEST_INPUT'] = array('foo' => 'baz4');
        $this->_object->getRawInput();

        $this->assertEquals('baz4', $this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::get
     * @covers Core_Request::<protected>
     */
    public function testGettingAVariableWillFifthTry_COOKIE()
    {
        $_COOKIE['foo'] = 'baz5';

        $this->assertEquals('baz5', $this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::get
     */
    public function testGettingAVariableWillSixthTry_SERVER()
    {
        $_SERVER['foo'] = 'baz6';

        $this->assertEquals('baz6', $this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::get
     */
    public function testGettingAVariableWillSeventhTry_ENV()
    {
        $_ENV['foo'] = 'baz7';

        $this->assertEquals('baz7', $this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::__get
     */
    public function testAccessingRequestPropertyWillProxyToGetMethod()
    {
        $this->_object->setParam('foo', 'bazz');

        $this->assertEquals($this->_object->foo, $this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::getValue
     */
    public function testGetValueMethodWillProxyToGetMethod()
    {
        $this->_object->setParam('foo', 'bazzt');

        $this->assertEquals($this->_object->getValue('foo'), $this->_object->get('foo'));
    }

    /**
     * @covers Core_Request::set
     */
    public function testSetMethodWillProxyToSetParam()
    {
        $this->_object->set('foo', 'sbla');

        $this->assertEquals('sbla', $this->_object->getParam('foo'));
    }

    /**
     * @covers Core_Request::__set
     */
    public function testSettingRequestPropertyWillProxyToSetMethod()
    {
        $this->_object->baz = 'buzz';

        $this->assertEquals('buzz', $this->_object->get('baz'));
    }

    /**
     * @covers Core_Request::setValue
     */
    public function testSetValueMethodWillProxyToSetParam()
    {
        $this->_object->setValue('foo', 'svbla');

        $this->assertEquals('svbla', $this->_object->getParam('foo'));
    }

    /**
     * @covers Core_Request::hasParam
     */
    public function testCanCheckIfNamedUserParamExists()
    {
        $this->_object->setParam('foo', 1);

        $this->assertTrue($this->_object->hasParam('foo'));
    }

    /**
     * @covers Core_Request::has
     */
    public function testCheckingForExistanceOfANonExistantVariableWillReturnFalse()
    {
        $this->assertFalse($this->_object->has('foo'));
    }

    /**
     * @covers Core_Request::has
     */
    public function testCheckingForExistanceOfAVariableWillCheckUserParamsFirst()
    {
        $this->_object->setParam('blabla1', 23);

        $this->assertTrue($this->_object->has('blabla1'));
    }

    /**
     * @covers Core_Request::has
     */
    public function testCheckingForExistanceOfAVariableWillCheck_GETSecond()
    {
        $_GET['blabla2'] = 23;

        $this->assertTrue($this->_object->has('blabla2'));
    }

    /**
     * @covers Core_Request::has
     */
    public function testCheckingForExistanceOfAVariableWillCheck_POSTThird()
    {
        $_POST['blabla3'] = 23;

        $this->assertTrue($this->_object->has('blabla3'));
    }


    /**
     * @covers Core_Request::has
     */
    public function testCheckingForExistanceOfAVariableWillCheckPhpInputFourth()
    {
        $_ENV['CF_TEST_REQUEST_INPUT'] = array('blabla4' => 23);
        $this->_object->getRawInput();

        $this->assertTrue($this->_object->has('blabla4'));
    }

    /**
     * @covers Core_Request::has
     */
    public function testCheckingForExistanceOfAVariableWillCheck_COOKIEFifth()
    {
        $_COOKIE['blabla5'] = 23;

        $this->assertTrue($this->_object->has('blabla5'));
    }

    /**
     * @covers Core_Request::has
     */
    public function testCheckingForExistanceOfAVariableWillCheck_SERVERSixth()
    {
        $_SERVER['blabla6'] = 23;

        $this->assertTrue($this->_object->has('blabla6'));
    }

    /**
     * @covers Core_Request::has
     */
    public function testCheckingForExistanceOfAVariableWillCheck_ENVSeventh()
    {
        $_ENV['blabla7'] = 23;

        $this->assertTrue($this->_object->has('blabla7'));
    }

    /**
     * @covers Core_Request::__isset
     */
    public function testTestingForRequestPropertyWillProxyToHasMethod()
    {
        $this->_object->setParam('foo', 99);

        $this->assertTrue(isset($this->_object->foo));
    }

    /**
     * @covers Core_Request::getValues
     */
    public function testCanGetValuesForGETRequest()
    {
        $_GET   = array('a' => 1, 'b' => 2);
        $_SERVER['REQUEST_METHOD'] = 'GET';

        $this->assertEquals($_GET, $this->_object->getValues());
    }

    /**
     * @covers Core_Request::getValues
     */
    public function testCanGetValuesForPOSTRequest()
    {
        $_POST = array('a' => 1, 'b' => 2);
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertEquals($_POST, $this->_object->getValues());
    }

    /**
     * @covers Core_Request::getValues
     */
    public function testCanGetValuesForPUTRequest()
    {
        $_SERVER['REQUEST_METHOD']     = 'PUT';
        $_ENV['CF_TEST_REQUEST_INPUT'] = array('a' => 1, 'b' => 2);
        $this->_object->getRawInput();

        $this->assertEquals(array('a' => 1, 'b' => 2), $this->_object->getValues());
    }

    /**
     * @covers Core_Request::getValues
     */
    public function testCanGetValuesForPATCHRequest()
    {
        $_SERVER['REQUEST_METHOD']     = 'PATCH';
        $_ENV['CF_TEST_REQUEST_INPUT'] = array('a' => 2, 'b' => 1);
        $this->_object->getRawInput();

        $this->assertEquals(array('a' => 2, 'b' => 1), $this->_object->getValues());
    }

    /**
     * @covers Core_Request::getValues
     */
    public function testCallingGetValuesMethodOnRequestsNotPostGetPutOrPatchReturnsAnEmptyArray()
    {
        $_SERVER['REQUEST_METHOD'] = 'OPTIONS';

        $this->assertEmpty($this->_object->getValues());
    }

    /**
     * @covers Core_Request::getValues
     */
    public function testCanSpecifyValuesToFetchAsAnArray()
    {
        $_POST = array('a' => 1, 'b' => 2, 'c' => 3);
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertEquals(array('a' => 1, 'b' => 2), $this->_object->getValues(array('a', 'b')));
    }

    /**
     * @covers Core_Request::toArray
     */
    public function testToArrayMethodProxiesToGetValues()
    {
        $_POST = array('a' => 1, 'b' => 2);
        $_SERVER['REQUEST_METHOD'] = 'POST';

        $this->assertEquals($_POST, $this->_object->toArray());
    }

    /**
     * @covers Core_Request::getQuery
     * @covers Core_Request::<protected>
     */
    public function testGetQueryWithoutParamsWillReturn_GETWithStrippedSlashes()
    {
        $_GET = array('a' => '\"bla\"');
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertEquals(array('a' => '"bla"'), $this->_object->getQuery());
    }

    /**
     * @covers Core_Request::getQuery
     */
    public function testGetQueryWithArrayOfKeysWillReturnThoseKeysWithDefaultForMissingKeys()
    {
        $_GET = array('a' => 1, 'b' => 2);
        $this->assertEquals(array('a' => 1, 'c' => 'nope'), $this->_object->getQuery(array('a', 'c'), 'nope'));
    }

    /**
     * @covers Core_Request::getQuery
     * @covers Core_Request::<protected>
     */
    public function testGetQueryWillReturnNamedVariableWithStrippedSlashes()
    {
        $_GET = array('a' => '\"bla\"');
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertEquals('"bla"', $this->_object->getQuery('a'));
    }

    /**
     * @covers Core_Request::getQuery
     * @covers Core_Request::<protected>
     */
    public function testGetQueryWillReturnDefaultValueIfVariableNotFound()
    {
        $this->assertEquals('"bla"', $this->_object->getQuery('a', '"bla"'));
    }

    /**
     * @covers Core_Request::getPost
     * @covers Core_Request::<protected>
     */
    public function testGetPostWithoutParamsWillReturn_POSTWithStrippedSlashes()
    {
        $_POST = array('a' => '\"bla\"');
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertEquals(array('a' => '"bla"'), $this->_object->getPost());
    }

    /**
     * @covers Core_Request::getPost
     */
    public function testGetPostWithArrayOfKeysWillReturnThoseKeysWithDefaultForMissingKeys()
    {
        $_POST = array('a' => 1, 'b' => 2);
        $this->assertEquals(array('a' => 1, 'c' => 'nope'), $this->_object->getPost(array('a', 'c'), 'nope'));
    }

    /**
     * @covers Core_Request::getPost
     * @covers Core_Request::<protected>
     */
    public function testGetPostWillReturnNamedVariableWithStrippedSlashes()
    {
        $_POST = array('a' => '\"bla\"');
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertEquals('"bla"', $this->_object->getPost('a'));
    }

    /**
     * @covers Core_Request::getPost
     * @covers Core_Request::<protected>
     */
    public function testGetPostWillReturnDefaultValueIfVariableNotFound()
    {
        $this->assertEquals('"bla"', $this->_object->getPost('a', '"bla"'));
    }

    /**
     * @covers Core_Request::getInput
     * @covers Core_Request::<protected>
     */
    public function testGetInputWithoutParamsWillReturnPhpInputWithStrippedSlashes()
    {
        $_ENV['CF_TEST_REQUEST_INPUT'] = array('a' => '\"bla\"');
        $this->_object->getRawInput();
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertEquals(array('a' => '"bla"'), $this->_object->getInput());
    }

    /**
     * @covers Core_Request::getInput
     */
    public function testGetInputWithArrayOfKeysWillReturnThoseKeysWithDefaultForMissingKeys()
    {
        $_ENV['CF_TEST_REQUEST_INPUT'] = array('a' => 1, 'b' => 2);
        $this->_object->getRawInput();

        $this->assertEquals(array('a' => 1, 'c' => 'nope'), $this->_object->getInput(array('a', 'c'), 'nope'));
    }

    /**
     * @covers Core_Request::getInput
     * @covers Core_Request::<protected>
     */
    public function testGetInputWillReturnNamedVariableWithStrippedSlashes()
    {
        $_ENV['CF_TEST_REQUEST_INPUT'] = array('a' => '\"bla\"');
        $this->_object->getRawInput();
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertEquals('"bla"', $this->_object->getInput('a'));
    }

    /**
     * @covers Core_Request::getInput
     * @covers Core_Request::<protected>
     */
    public function testGetInputWillReturnDefaultValueIfVariableNotFound()
    {
        $this->assertEquals('"bla"', $this->_object->getInput('a', '"bla"'));
    }

    /**
     * @covers Core_Request::getCookie
     * @covers Core_Request::<protected>
     */
    public function testGetCookieWithoutParamsWillReturn_COOKIEWithStrippedSlashes()
    {
        $_COOKIE = array('a' => '\"bla\"');
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertEquals(array('a' => '"bla"'), $this->_object->getCookie());
    }

    /**
     * @covers Core_Request::getCookie
     * @covers Core_Request::<protected>
     */
    public function testGetCookieWillReturnNamedVariableWithStrippedSlashes()
    {
        $_COOKIE = array('a' => '\"bla\"');
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertEquals('"bla"', $this->_object->getCookie('a'));
    }

    /**
     * @covers Core_Request::getCookie
     */
    public function testGetCookieWithArrayOfKeysWillReturnThoseKeysWithDefaultForMissingKeys()
    {
        $_COOKIE = array('a' => 1, 'b' => 2);

        $this->assertEquals(array('a' => 1, 'c' => 'nope'), $this->_object->getCookie(array('a', 'c'), 'nope'));
    }

    /**
     * @covers Core_Request::getCookie
     * @covers Core_Request::<protected>
     */
    public function testGetCookieWillReturnDefaultValueIfVariableNotFound()
    {
        $this->assertEquals('"bla"', $this->_object->getCookie('a', '"bla"'));
    }

    /**
     * @covers Core_Request::getServer
     */
    public function testGetServerWithoutParamsWillReturn_SERVER()
    {
        $_SERVER = array('a' => 'bla');

        $this->assertEquals(array('a' => 'bla'), $this->_object->getServer());
    }

    /**
     * @covers Core_Request::getServer
     */
    public function testGetServerWithArrayOfKeysWillReturnThoseKeysWithDefaultForMissingKeys()
    {
        $_SERVER = array('a' => 1, 'b' => 2);

        $this->assertEquals(array('a' => 1, 'c' => 'nope'), $this->_object->getServer(array('a', 'c'), 'nope'));
    }

    /**
     * @covers Core_Request::getServer
     */
    public function testGetServerWillReturnNamedVariable()
    {
        $_SERVER = array('a' => '"bla"');

        $this->assertEquals('"bla"', $this->_object->getServer('a'));
    }

    /**
     * @covers Core_Request::getServer
     */
    public function testGetServerWillReturnDefaultValueIfVariableNotFound()
    {
        $this->assertEquals('"bla"', $this->_object->getServer('a', '"bla"'));
    }

    /**
     * @covers Core_Request::getEnv
     */
    public function testGetEnvWithoutParamsWillReturn_ENV()
    {
        $_ENV= array('a' => 'bla');

        $this->assertEquals(array('a' => 'bla'), $this->_object->getEnv());
    }

    /**
     * @covers Core_Request::getEnv
     */
    public function testGetEnvWithArrayOfKeysWillReturnThoseKeysWithDefaultForMissingKeys()
    {
        $_ENV = array('a' => 1, 'b' => 2);

        $this->assertEquals(array('a' => 1, 'c' => 'nope'), $this->_object->getEnv(array('a', 'c'), 'nope'));
    }

    /**
     * @covers Core_Request::getEnv
     */
    public function testGetEnvWillReturnNamedVariable()
    {
        $_ENV = array('a' => '"bla"');

        $this->assertEquals('"bla"', $this->_object->getEnv('a'));
    }

    /**
     * @covers Core_Request::getEnv
     */
    public function testGetEnvWillReturnDefaultValueIfVariableNotFound()
    {
        $this->assertEquals('"bla"', $this->_object->getEnv('a', '"bla"'));
    }

    /**
     * @covers Core_Request::getHeader
     */
    public function testFetchingAnUnnamedHeaderThrowsAnInvalidArgumentException()
    {
        $this->setExpectedException('InvalidArgumentException');

        $this->_object->getHeader('');
    }

    /**
     * @covers Core_Request::getHeader
     */
    public function testHeaderNameToFetchWillBePrependedByHTTPAndUppercased()
    {
        $_SERVER['HTTP_THIS_IS_THE_NAME_TO_FIND'] = 99;

        $this->assertEquals(99, $this->_object->getHeader('This-is_the_NaMe-To_find'));
    }

    /**
     * @covers Core_Request::getHeader
     */
    public function testFetchingAnUnknownHeaderWillReturnNull()
    {
        $this->assertNull($this->_object->getHeader('no-such-header'));
    }
    
    /**
     * @covers Core_Request::isHeader
     */
    public function testCanTestForHeaderValue()
    {
        $_SERVER['HTTP_THIS_IS_THE_NAME_TO_FIND'] = 99;
        
        $this->assertTrue($this->_object->isHeader('This-is_the_NaMe-To_find', 99));
    }
    
    /**
     * @covers Core_Request::isHeader
     */
    public function testHeaderTestIsCaseInsensitive()
    {
        $_SERVER['HTTP_THIS_IS_THE_NAME_TO_FIND'] = 'SomeThinG';
        
        $this->assertTrue($this->_object->isHeader('This-is_the_NaMe-To_find', 'something'));
    }
    
    /**
     * @covers Core_Request::isHeaderRegexMatch
     */
    public function testCanTestHeaderAgainstARegex()
    {
        $_SERVER['HTTP_THIS_IS_THE_NAME_TO_FIND'] = 'SomeThing on the inside';
        
        $this->assertTrue($this->_object->isHeaderRegexMatch('This-is_the_NaMe-To_find', '/thing/'));
    }
    
    /**
     * @covers Core_Request::isHeaderRegexMatch
     */
    public function testHeaderRegexTestIsCaseInsensitive()
    {
        $_SERVER['HTTP_THIS_IS_THE_NAME_TO_FIND'] = 'SomeThing on the inside';
        
        $this->assertTrue($this->_object->isHeaderRegexMatch('This-is_the_NaMe-To_find', '/thing/'));
    }
    
    /**
     * @covers Core_Request::isHeaderRegexMatch
     */
    public function testHeaderRegexTestWillNotFailIfWeProvideOvnCaseInsensitveFlagForRegex()
    {
        $_SERVER['HTTP_THIS_IS_THE_NAME_TO_FIND'] = 'SomeThing on the inside';
        
        $this->assertTrue($this->_object->isHeaderRegexMatch('This-is_the_NaMe-To_find', '/thing/i'));
    }
    
    /**
     * @covers Core_Request::isHeaderRegexMatch
     */
    public function testHeaderRegexTestRegexCanUseAnyDelimeter()
    {
        $_SERVER['HTTP_THIS_IS_THE_NAME_TO_FIND'] = 'SomeThing on the inside';
        
        $this->assertTrue($this->_object->isHeaderRegexMatch('This-is_the_NaMe-To_find', '#thing#i'));
    }

    /**
     * @covers Core_Request::setMagicQuotesEnabled
     * @covers Core_Request::hasMagicQuotesEnabled
     */
    public function testCanSetAndGetMagicQuotesEnabled()
    {
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertTrue($this->_object->hasMagicQuotesEnabled());
    }

    /**
     * @covers Core_Request::hasMagicQuotesEnabled
     */
    public function testGetMagicQuotesEnabledDefaultsToEnvironmentSetting()
    {
        $magicQuotesEnabled = (bool) ini_get('magic_quotes_gpc');

        $this->assertEquals($magicQuotesEnabled, $this->_object->hasMagicQuotesEnabled());
    }

    /**
     * @covers Core_Request::getClientIp
     */
    public function testCanGetClientIP()
    {
        $_SERVER['REMOTE_ADDR'] = '10.20.30.40';

        $this->assertEquals('10.20.30.40', $this->_object->getClientIp());
    }

    /**
     * @covers Core_Request::getClientIp
     */
    public function testCanGetClientIPForProxiedRequests()
    {
        // HTTP_CLIENT_IP variant
        $_SERVER = array(
            'HTTP_CLIENT_IP' => '10.20.20.10',
            'REMOTE_ADDR'    => '10.20.30.40',
        );
        $this->assertEquals('10.20.20.10', $this->_object->getClientIp());

        // HTTP_X_FORWARDED_FOR variant
        $_SERVER = array(
            'HTTP_X_FORWARDED_FOR' => '10.30.30.10',
            'REMOTE_ADDR'          => '10.20.30.40',
        );
        $this->assertEquals('10.30.30.10', $this->_object->getClientIp());
    }

    /**
     * @covers Core_Request::getReferrer
     */
    public function testCanGetHTTPReferrer()
    {
        $_SERVER = array(
            'HTTP_REFERER' => 'http://example.com',
        );

        $this->assertEquals('http://example.com', $this->_object->getReferrer());
    }

    /**
     * @covers Core_Request::getMethod
     */
    public function testCanGetRequestMethod()
    {
        $_SERVER = array(
            'REQUEST_METHOD' => 'POST',
        );

        $this->assertEquals('POST', $this->_object->getMethod());
    }

    /**
     * @covers Core_Request::getMethod
     */
    public function testRequestMethodIsUppercased()
    {
        $_SERVER = array(
            'REQUEST_METHOD' => 'Get',
        );

        $this->assertEquals('GET', $this->_object->getMethod());
    }

    /**
     * @covers Core_Request::getMethod
     */
    public function testWillAllowForHttpMethodOverrideHeader()
    {
        $_SERVER = array(
            'REQUEST_METHOD'              => 'POST',
            'HTTP_X_HTTP_METHOD_OVERRIDE' => 'PUT',
        );

        $this->assertEquals('PUT', $this->_object->getMethod());
    }

    /**
     * @covers Core_Request::getMethod
     */
    public function testWillNotAllowForHttpMethodOverrideIfOriginalMethodIsNotPost()
    {
        $_SERVER = array(
            'REQUEST_METHOD'              => 'GET',
            'HTTP_X_HTTP_METHOD_OVERRIDE' => 'PUT',
        );

        $this->assertEquals('GET', $this->_object->getMethod());
    }

    /**
     * @covers Core_Request::getProtocol
     */
    public function testCanTellIfProtocolIsHTTP()
    {
        $this->assertEquals('http', $this->_object->getProtocol());
    }

    /**
     * @covers Core_Request::getProtocol
     */
    public function testCanTellIfProtocolIsHTTPS()
    {
        $_SERVER = array('HTTPS' => 'on');

        $this->assertEquals('https', $this->_object->getProtocol());
    }

    /**
     * @covers Core_Request::getHostname
     */
    public function testCanGetVhostHostname()
    {
        $_SERVER = array(
            'HTTP_HOST' => 'example.com',
        );

        $this->assertEquals('example.com', $this->_object->getHostname());
    }

    /**
     * @covers Core_Request::getHostname
     */
    public function testIfNoOtherHostnameCanBeFoundWillReturnLocalhost()
    {
        $this->assertEquals('localhost', $this->_object->getHostname());
    }

    /**
     * @covers Core_Request::getHostname
     */
    public function testCanGetVhostHostnameWithoutPort()
    {
        $_SERVER = array(
            'HTTP_HOST' => 'example.com:9999',
        );

        $this->assertEquals('example.com', $this->_object->getHostname());
    }

    /**
     * @covers Core_Request::getHostname
     */
    public function testCanGetGlobalHostname()
    {
        $_SERVER = array(
            'SERVER_NAME' => 'global.example.com',
        );

        $this->assertEquals('global.example.com', $this->_object->getHostname());
    }

    /**
     * @covers Core_Request::getPort
     */
    public function testCanGetPort()
    {
        $_SERVER = array(
            'SERVER_PORT' => 23
        );

        $this->assertEquals(23, $this->_object->getPort());
    }

    /**
     * @covers Core_Request::getPort
     */
    public function testDefaultPortIs80()
    {
        $this->assertEquals(80, $this->_object->getPort());
    }

    /**
     * @covers Core_Request::getHost
     */
    public function testHostIsHostnameAndPort()
    {
        $_SERVER = array(
            'SERVER_NAME' => 'example.com',
            'SERVER_PORT' => 23,
        );

        $this->assertEquals('example.com:23', $this->_object->getHost());
    }

    /**
     * @covers Core_Request::getHost
     */
    public function testHostViaHTTPOnPort80DoesNotIncludePort()
    {
        $_SERVER = array(
            'SERVER_NAME' => 'example.com',
            'SERVER_PORT' => 80,
        );

        $this->assertEquals('example.com', $this->_object->getHost());
    }

    /**
     * @covers Core_Request::getHost
     */
    public function testHostViaHTTPSOnPort443DoesNotIncludePort()
    {
        $_SERVER = array(
            'HTTPS'       => 'on',
            'SERVER_NAME' => 'example.com',
            'SERVER_PORT' => 443,
        );

        $this->assertEquals('example.com', $this->_object->getHost());
    }

    /**
     * @covers Core_Request::getQueryString
     */
    public function testCanGetQueryString()
    {
        $_SERVER = array(
            'QUERY_STRING' => 'test=a&bla=23',
        );

        $this->assertEquals('test=a&bla=23', $this->_object->getQueryString());
    }

    /**
     * @covers Core_Request::getPathName
     */
    public function testCanGetPathName()
    {
        $_SERVER = array(
            'REQUEST_URI' => '/abc/bcd/'
        );

        $this->assertEquals('/abc/bcd/', $this->_object->getPathName());
    }

    /**
     * @covers Core_Request::getPathName
     */
    public function testPathNameDoesNotIncludeQueryString()
    {
        $_SERVER = array(
            'REQUEST_URI'  => '/abc/bcd/?foo=23',
        );

        $this->assertEquals('/abc/bcd/', $this->_object->getPathName());
    }


    /**
     * @covers Core_Request::getPath
     */
    public function testCanGetPath()
    {
        $_SERVER = array(
            'REQUEST_URI' => '/abc/bcd/'
        );

        $this->assertEquals('/abc/bcd/', $this->_object->getPath());
    }

    /**
     * @covers Core_Request::getPath
     */
    public function testPathIncludesQueryString()
    {
        $_SERVER = array(
            'REQUEST_URI'  => '/abc/bcd/',
            'QUERY_STRING' => 'foo=23',
        );

        $this->assertEquals('/abc/bcd/?foo=23', $this->_object->getPath());
    }

    /**
     * @covers Core_Request::getUriBase
     */
    public function testCanGetUriBase()
    {
        $_SERVER = array(
            'HTTPS'       => 'on',
            'HTTP_HOST'   => 'secure-example.com',
            'SERVER_PORT' => 1111,
        );

        $this->assertEquals('https://secure-example.com:1111', $this->_object->getUri());
    }

    /**
     * @covers Core_Request::getUriPathName
     */
    public function testCanGetUriPathName()
    {
        $_SERVER = array(
            'HTTPS'       => 'on',
            'HTTP_HOST'   => 'secure-example.com',
            'SERVER_PORT' => 1111,
            'REQUEST_URI' => '/abc/bcd/?foo=23'
        );

        $this->assertEquals('https://secure-example.com:1111/abc/bcd/', $this->_object->getUriPathName());
    }

    /**
     * @covers Core_Request::getUri
     */
    public function testCanGetUri()
    {
        $_SERVER = array(
            'HTTPS'        => 'on',
            'HTTP_HOST'    => 'secure-example.com',
            'SERVER_PORT'  => 1111,
            'REQUEST_URI'  => '/abc/bcd/',
            'QUERY_STRING' => 'foo=23'
        );

        $this->assertEquals('https://secure-example.com:1111/abc/bcd/?foo=23', $this->_object->getUri());
    }

    /**
     * @covers Core_Request::<protected>
     */
    public function testWhenFetchingArraysFromRequestsWillStripSlashesRecursively()
    {
        $_POST = array(
            'titles' => array(
                'No more "I Love You\"\'s',
                'Robocop' => array(
                    'Robocop',
                    'Robocop \"Two\"'
                )
            ),
        );
        $this->_object->setMagicQuotesEnabled(true);

        $this->assertEquals(
            array(
                'titles' => array(
                    // note that \' is to escape the outer string delimeter
                    'No more "I Love You"\'s',
                    'Robocop' => array(
                        'Robocop',
                        'Robocop "Two"',
                    )
                ),
            ),
            $this->_object->getPost()
        );
    }


    /**
     * @covers Core_Request::getServer
     */
    public function testCanGetRequestUriWithNonUrlencodedCyrillicString()
    {
        $_SERVER = array(
            'REQUEST_URI' => '/abc/%D0%BA%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82/'
        );

        $this->assertEquals('/abc/контакт/', $this->_object->getServer('REQUEST_URI'));
    }

    /**
     * @covers Core_Request::getPathName
     */
    public function testCanGetPathNameWithNonUrlencodedCyrillicRequestUri()
    {
        $_SERVER = array(
            'REQUEST_URI' => '/abc/%D0%BA%D0%BE%D0%BD%D1%82%D0%B0%D0%BA%D1%82/?test=mirko'
        );

        $this->assertEquals('/abc/контакт/', $this->_object->getPathName());
    }
    
    /**
     * @covers Core_Request::setProxied
     * @covers Core_Request::isProxied
     */
    public function testCanSetAndGetProxied()
    {
        $this->_object->setProxied(true);
        $this->assertTrue($this->_object->isProxied());
    }
    
    /**
     * @covers Core_Request::isProxied
     */
    public function testIsNotProxiedByDefault()
    {
        $this->assertFalse($this->_object->isProxied());
    }
    
    /**
     * @covers Core_Request::getProtocol
     */
    public function testWillObeyXForwardedProtoIfProxied()
    {
        $this->_object->setProxied(true);
        $_SERVER['HTTP_X_FORWARDED_PROTO'] = 'https';
        
        $this->assertEquals(Core_Request::PROTOCOL_HTTPS, $this->_object->getProtocol());
    }
    
    /**
     * @covers Core_Request::getProtocol
     */
    public function testWillNotObeyXForwardedProtoIfNotProxied()
    {
        $this->_object->setProxied(false);
        $_SERVER['HTTP_X_FORWARDED_PROTO'] = 'https';
        
        $this->assertEquals(Core_Request::PROTOCOL_HTTP, $this->_object->getProtocol());
    }
    
    /**
     * @covers Core_Request::getProtocol
     */
    public function testCanHandleNonNormalizedXForwardedProto()
    {
        $this->_object->setProxied(true);
        $_SERVER['HTTP_X_FORWARDED_PROTO'] = 'hTtPs';
        
        $this->assertEquals(Core_Request::PROTOCOL_HTTPS, $this->_object->getProtocol());
    }
    
    /**
     * @covers Core_Request::getProtocol
     */
    public function testSettingAnUnknownProtocolForXForwardedProtoThrowsAnRuntimeException()
    {
        $this->_object->setProxied(true);
        $_SERVER['HTTP_X_FORWARDED_PROTO'] = 'something unknown';
        $this->setExpectedException('RuntimeException');
        
        $this->_object->getProtocol();
    }
}
