Subversion Repositories SmartDukaan

Rev

Blame | Last modification | View Log | RSS feed

<?php
/**
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://cakephp.org CakePHP Project
 * @since         CakePHP(tm) v 1.2.0.5432
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */

App::uses('Debugger', 'Utility');

/**
 * DebuggerTestCaseDebugger class
 *
 * @package       Cake.Test.Case.Utility
 */
class DebuggerTestCaseDebugger extends Debugger {
}

/**
 * DebuggerTest class
 *
 * !!! Be careful with changing code below as it may
 * !!! change line numbers which are used in the tests
 *
 * @package       Cake.Test.Case.Utility
 */
class DebuggerTest extends CakeTestCase {

        protected $_restoreError = false;

/**
 * setUp method
 *
 * @return void
 */
        public function setUp() {
                parent::setUp();
                Configure::write('debug', 2);
                Configure::write('log', false);
        }

/**
 * tearDown method
 *
 * @return void
 */
        public function tearDown() {
                parent::tearDown();
                Configure::write('log', true);
                if ($this->_restoreError) {
                        restore_error_handler();
                }
        }

/**
 * testDocRef method
 *
 * @return void
 */
        public function testDocRef() {
                ini_set('docref_root', '');
                $this->assertEquals(ini_get('docref_root'), '');
                new Debugger();
                $this->assertEquals(ini_get('docref_root'), 'http://php.net/');
        }

/**
 * test Excerpt writing
 *
 * @return void
 */
        public function testExcerpt() {
                $result = Debugger::excerpt(__FILE__, __LINE__, 2);
                $this->assertTrue(is_array($result));
                $this->assertEquals(5, count($result));
                $this->assertRegExp('/function(.+)testExcerpt/', $result[1]);

                $result = Debugger::excerpt(__FILE__, 2, 2);
                $this->assertTrue(is_array($result));
                $this->assertEquals(4, count($result));

                $pattern = '/<code>.*?<span style\="color\: \#\d+">.*?&lt;\?php/';
                $this->assertRegExp($pattern, $result[0]);

                $result = Debugger::excerpt(__FILE__, 11, 2);
                $this->assertEquals(5, count($result));

                $pattern = '/<span style\="color\: \#\d{6}">\*<\/span>/';
                $this->assertRegExp($pattern, $result[0]);

                $return = Debugger::excerpt('[internal]', 2, 2);
                $this->assertTrue(empty($return));
        }

/**
 * testOutput method
 *
 * @return void
 */
        public function testOutput() {
                set_error_handler('Debugger::showError');
                $this->_restoreError = true;

                $result = Debugger::output(false);
                $this->assertEquals('', $result);
                $out .= '';
                $result = Debugger::output(true);

                $this->assertEquals('Notice', $result[0]['error']);
                $this->assertRegExp('/Undefined variable\:\s+out/', $result[0]['description']);
                $this->assertRegExp('/DebuggerTest::testOutput/i', $result[0]['trace']);

                ob_start();
                Debugger::output('txt');
                $other .= '';
                $result = ob_get_clean();

                $this->assertRegExp('/Undefined variable:\s+other/', $result);
                $this->assertRegExp('/Context:/', $result);
                $this->assertRegExp('/DebuggerTest::testOutput/i', $result);

                ob_start();
                Debugger::output('html');
                $wrong .= '';
                $result = ob_get_clean();
                $this->assertRegExp('/<pre class="cake-error">.+<\/pre>/', $result);
                $this->assertRegExp('/<b>Notice<\/b>/', $result);
                $this->assertRegExp('/variable:\s+wrong/', $result);

                ob_start();
                Debugger::output('js');
                $buzz .= '';
                $result = explode('</a>', ob_get_clean());
                $this->assertTags($result[0], array(
                        'pre' => array('class' => 'cake-error'),
                        'a' => array(
                                'href' => "javascript:void(0);",
                                'onclick' => "preg:/document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display = " .
                                        "\(document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display == 'none'" .
                                        " \? '' \: 'none'\);/"
                        ),
                        'b' => array(), 'Notice', '/b', ' (8)',
                ));

                $this->assertRegExp('/Undefined variable:\s+buzz/', $result[1]);
                $this->assertRegExp('/<a[^>]+>Code/', $result[1]);
                $this->assertRegExp('/<a[^>]+>Context/', $result[2]);
                $this->assertContains('$wrong = &#039;&#039;', $result[3], 'Context should be HTML escaped.');
        }

/**
 * Tests that changes in output formats using Debugger::output() change the templates used.
 *
 * @return void
 */
        public function testChangeOutputFormats() {
                set_error_handler('Debugger::showError');
                $this->_restoreError = true;

                Debugger::output('js', array(
                        'traceLine' => '{:reference} - <a href="txmt://open?url=file://{:file}' .
                                '&line={:line}">{:path}</a>, line {:line}'
                ));
                $result = Debugger::trace();
                $this->assertRegExp('/' . preg_quote('txmt://open?url=file://', '/') . '(\/|[A-Z]:\\\\)' . '/', $result);

                Debugger::output('xml', array(
                        'error' => '<error><code>{:code}</code><file>{:file}</file><line>{:line}</line>' .
                                '{:description}</error>',
                        'context' => "<context>{:context}</context>",
                        'trace' => "<stack>{:trace}</stack>",
                ));
                Debugger::output('xml');

                ob_start();
                $foo .= '';
                $result = ob_get_clean();

                $data = array(
                        'error' => array(),
                        'code' => array(), '8', '/code',
                        'file' => array(), 'preg:/[^<]+/', '/file',
                        'line' => array(), '' . (intval(__LINE__) - 7), '/line',
                        'preg:/Undefined variable:\s+foo/',
                        '/error'
                );
                $this->assertTags($result, $data, true);
        }

/**
 * Test that outputAs works.
 *
 * @return void
 */
        public function testOutputAs() {
                Debugger::outputAs('html');
                $this->assertEquals('html', Debugger::outputAs());
        }

/**
 * Test that choosing a non-existent format causes an exception
 *
 * @expectedException CakeException
 * @return void
 */
        public function testOutputAsException() {
                Debugger::outputAs('Invalid junk');
        }

/**
 * Tests that changes in output formats using Debugger::output() change the templates used.
 *
 * @return void
 */
        public function testAddFormat() {
                set_error_handler('Debugger::showError');
                $this->_restoreError = true;

                Debugger::addFormat('js', array(
                        'traceLine' => '{:reference} - <a href="txmt://open?url=file://{:file}' .
                                '&line={:line}">{:path}</a>, line {:line}'
                ));
                Debugger::outputAs('js');

                $result = Debugger::trace();
                $this->assertRegExp('/' . preg_quote('txmt://open?url=file://', '/') . '(\/|[A-Z]:\\\\)' . '/', $result);

                Debugger::addFormat('xml', array(
                        'error' => '<error><code>{:code}</code><file>{:file}</file><line>{:line}</line>' .
                                '{:description}</error>',
                ));
                Debugger::outputAs('xml');

                ob_start();
                $foo .= '';
                $result = ob_get_clean();

                $data = array(
                        '<error',
                        '<code', '8', '/code',
                        '<file', 'preg:/[^<]+/', '/file',
                        '<line', '' . (intval(__LINE__) - 7), '/line',
                        'preg:/Undefined variable:\s+foo/',
                        '/error'
                );
                $this->assertTags($result, $data, true);
        }

/**
 * Test adding a format that is handled by a callback.
 *
 * @return void
 */
        public function testAddFormatCallback() {
                set_error_handler('Debugger::showError');
                $this->_restoreError = true;

                Debugger::addFormat('callback', array('callback' => array($this, 'customFormat')));
                Debugger::outputAs('callback');

                ob_start();
                $foo .= '';
                $result = ob_get_clean();
                $this->assertContains('Notice: I eated an error', $result);
                $this->assertContains('DebuggerTest.php', $result);
        }

/**
 * Test method for testing addFormat with callbacks.
 *
 * @return void
 */
        public function customFormat($error, $strings) {
                return $error['error'] . ': I eated an error ' . $error['file'];
        }

/**
 * testTrimPath method
 *
 * @return void
 */
        public function testTrimPath() {
                $this->assertEquals('APP' . DS, Debugger::trimPath(APP));
                $this->assertEquals('CORE', Debugger::trimPath(CAKE_CORE_INCLUDE_PATH));
                $this->assertEquals('ROOT', Debugger::trimPath(ROOT));
                $this->assertEquals('CORE' . DS . 'Cake' . DS, Debugger::trimPath(CAKE));
                $this->assertEquals('Some/Other/Path', Debugger::trimPath('Some/Other/Path'));
        }

/**
 * testExportVar method
 *
 * @return void
 */
        public function testExportVar() {
                App::uses('Controller', 'Controller');
                $Controller = new Controller();
                $Controller->helpers = array('Html', 'Form');
                $View = new View($Controller);
                $View->int = 2;
                $View->float = 1.333;

                $result = Debugger::exportVar($View);
                $expected = <<<TEXT
object(View) {
        Helpers => object(HelperCollection) {}
        Blocks => object(ViewBlock) {}
        plugin => null
        name => ''
        passedArgs => array()
        helpers => array(
                (int) 0 => 'Html',
                (int) 1 => 'Form'
        )
        viewPath => ''
        viewVars => array()
        view => null
        layout => 'default'
        layoutPath => null
        autoLayout => true
        ext => '.ctp'
        subDir => null
        theme => null
        cacheAction => false
        validationErrors => array()
        hasRendered => false
        uuids => array()
        request => object(CakeRequest) {}
        response => object(CakeResponse) {}
        elementCache => 'default'
        elementCacheSettings => array()
        Html => object(HtmlHelper) {}
        Form => object(FormHelper) {}
        int => (int) 2
        float => (float) 1.333

TEXT;
                if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
                        $expected .= <<<TEXT
        [protected] _passedVars => array(
                (int) 0 => 'viewVars',
                (int) 1 => 'autoLayout',
                (int) 2 => 'ext',
                (int) 3 => 'helpers',
                (int) 4 => 'view',
                (int) 5 => 'layout',
                (int) 6 => 'name',
                (int) 7 => 'theme',
                (int) 8 => 'layoutPath',
                (int) 9 => 'viewPath',
                (int) 10 => 'request',
                (int) 11 => 'plugin',
                (int) 12 => 'passedArgs',
                (int) 13 => 'cacheAction'
        )
        [protected] _scripts => array()
        [protected] _paths => array()
        [protected] _pathsForPlugin => array()
        [protected] _parents => array()
        [protected] _current => null
        [protected] _currentType => ''
        [protected] _stack => array()
        [protected] _eventManager => object(CakeEventManager) {}
        [protected] _eventManagerConfigured => false

TEXT;
                }
                $expected .= <<<TEXT
}
TEXT;

                $this->assertTextEquals($expected, $result);

                $data = array(
                        1 => 'Index one',
                        5 => 'Index five'
                );
                $result = Debugger::exportVar($data);
                $expected = <<<TEXT
array(
        (int) 1 => 'Index one',
        (int) 5 => 'Index five'
)
TEXT;
                $this->assertTextEquals($expected, $result);

                $data = array(
                        'key' => array(
                                'value'
                        )
                );
                $result = Debugger::exportVar($data, 1);
                $expected = <<<TEXT
array(
        'key' => array(
                [maximum depth reached]
        )
)
TEXT;
                $this->assertTextEquals($expected, $result);

                $data = false;
                $result = Debugger::exportVar($data);
                $expected = <<<TEXT
false
TEXT;
                $this->assertTextEquals($expected, $result);

                $file = fopen('php://output', 'w');
                fclose($file);
                $result = Debugger::exportVar($file);
                $this->assertTextEquals('unknown', $result);
        }

/**
 * Test exporting various kinds of false.
 *
 * @return void
 */
        public function testExportVarZero() {
                $data = array(
                        'nothing' => '',
                        'null' => null,
                        'false' => false,
                        'szero' => '0',
                        'zero' => 0
                );
                $result = Debugger::exportVar($data);
                $expected = <<<TEXT
array(
        'nothing' => '',
        'null' => null,
        'false' => false,
        'szero' => '0',
        'zero' => (int) 0
)
TEXT;
                $this->assertTextEquals($expected, $result);
        }

/**
 * testLog method
 *
 * @return void
 */
        public function testLog() {
                if (file_exists(LOGS . 'debug.log')) {
                        unlink(LOGS . 'debug.log');
                }
                CakeLog::config('file', array('engine' => 'File', 'path' => TMP . 'logs' . DS));

                Debugger::log('cool');
                $result = file_get_contents(LOGS . 'debug.log');
                $this->assertContains('DebuggerTest::testLog', $result);
                $this->assertContains("'cool'", $result);

                unlink(LOGS . 'debug.log');

                Debugger::log(array('whatever', 'here'));
                $result = file_get_contents(LOGS . 'debug.log');
                $this->assertContains('DebuggerTest::testLog', $result);
                $this->assertContains('[main]', $result);
                $this->assertContains('array', $result);
                $this->assertContains("'whatever',", $result);
                $this->assertContains("'here'", $result);
        }

/**
 * test log() depth
 *
 * @return void
 */
        public function testLogDepth() {
                if (file_exists(LOGS . 'debug.log')) {
                        unlink(LOGS . 'debug.log');
                }
                CakeLog::config('file', array('engine' => 'File', 'path' => TMP . 'logs' . DS));

                $val = array(
                        'test' => array('key' => 'val')
                );
                Debugger::log($val, LOG_DEBUG, 0);
                $result = file_get_contents(LOGS . 'debug.log');
                $this->assertContains('DebuggerTest::testLog', $result);
                $this->assertNotContains("/'val'/", $result);

                unlink(LOGS . 'debug.log');
        }

/**
 * testDump method
 *
 * @return void
 */
        public function testDump() {
                $var = array('People' => array(
                        array(
                                'name' => 'joeseph',
                                'coat' => 'technicolor',
                                'hair_color' => 'brown'
                        ),
                        array(
                                'name' => 'Shaft',
                                'coat' => 'black',
                                'hair' => 'black'
                        )
                ));
                ob_start();
                Debugger::dump($var);
                $result = ob_get_clean();

                $open = php_sapi_name() === 'cli' ? "\n" : '<pre>';
                $close = php_sapi_name() === 'cli' ? "\n" : '</pre>';
                $expected = <<<TEXT
{$open}array(
        'People' => array(
                (int) 0 => array(
                        'name' => 'joeseph',
                        'coat' => 'technicolor',
                        'hair_color' => 'brown'
                ),
                (int) 1 => array(
                        'name' => 'Shaft',
                        'coat' => 'black',
                        'hair' => 'black'
                )
        )
){$close}
TEXT;
                $this->assertTextEquals($expected, $result);

                ob_start();
                Debugger::dump($var, 1);
                $result = ob_get_clean();

                $open = php_sapi_name() == 'cli' ? "\n" : '<pre>';
                $close = php_sapi_name() == 'cli' ? "\n" : '</pre>';
                $expected = <<<TEXT
{$open}array(
        'People' => array(
                [maximum depth reached]
        )
){$close}
TEXT;
                $this->assertTextEquals($expected, $result);
        }

/**
 * test getInstance.
 *
 * @return void
 */
        public function testGetInstance() {
                $result = Debugger::getInstance();
                $this->assertInstanceOf('Debugger', $result);

                $result = Debugger::getInstance('DebuggerTestCaseDebugger');
                $this->assertInstanceOf('DebuggerTestCaseDebugger', $result);

                $result = Debugger::getInstance();
                $this->assertInstanceOf('DebuggerTestCaseDebugger', $result);

                $result = Debugger::getInstance('Debugger');
                $this->assertInstanceOf('Debugger', $result);
        }

/**
 * testNoDbCredentials
 *
 * If a connection error occurs, the config variable is passed through exportVar
 * *** our database login credentials such that they are never visible
 *
 * @return void
 */
        public function testNoDbCredentials() {
                $config = array(
                        'datasource' => 'mysql',
                        'persistent' => false,
                        'host' => 'void.cakephp.org',
                        'login' => 'cakephp-user',
                        'password' => 'cakephp-password',
                        'database' => 'cakephp-database',
                        'prefix' => ''
                );

                $output = Debugger::exportVar($config);

                $expectedArray = array(
                        'datasource' => 'mysql',
                        'persistent' => false,
                        'host' => '*****',
                        'login' => '*****',
                        'password' => '*****',
                        'database' => '*****',
                        'prefix' => ''
                );
                $expected = Debugger::exportVar($expectedArray);

                $this->assertEquals($expected, $output);
        }

/**
 * Test that exportVar() doesn't loop through recursive structures.
 *
 * @return void
 */
        public function testExportVarRecursion() {
                $output = Debugger::exportVar($GLOBALS);
                $this->assertContains("'GLOBALS' => [recursion]", $output);
        }

/**
 * test trace exclude
 *
 * @return void
 */
        public function testTraceExclude() {
                $result = Debugger::trace();
                $this->assertRegExp('/^DebuggerTest::testTraceExclude/', $result);

                $result = Debugger::trace(array(
                        'exclude' => array('DebuggerTest::testTraceExclude')
                ));
                $this->assertNotRegExp('/^DebuggerTest::testTraceExclude/', $result);
        }
}