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+">.*?<\?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 = ''', $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 = <<<TEXTobject(View) {Helpers => object(HelperCollection) {}Blocks => object(ViewBlock) {}plugin => nullname => ''passedArgs => array()helpers => array((int) 0 => 'Html',(int) 1 => 'Form')viewPath => ''viewVars => array()view => nulllayout => 'default'layoutPath => nullautoLayout => trueext => '.ctp'subDir => nulltheme => nullcacheAction => falsevalidationErrors => array()hasRendered => falseuuids => array()request => object(CakeRequest) {}response => object(CakeResponse) {}elementCache => 'default'elementCacheSettings => array()Html => object(HtmlHelper) {}Form => object(FormHelper) {}int => (int) 2float => (float) 1.333TEXT;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 => falseTEXT;}$expected .= <<<TEXT}TEXT;$this->assertTextEquals($expected, $result);$data = array(1 => 'Index one',5 => 'Index five');$result = Debugger::exportVar($data);$expected = <<<TEXTarray((int) 1 => 'Index one',(int) 5 => 'Index five')TEXT;$this->assertTextEquals($expected, $result);$data = array('key' => array('value'));$result = Debugger::exportVar($data, 1);$expected = <<<TEXTarray('key' => array([maximum depth reached]))TEXT;$this->assertTextEquals($expected, $result);$data = false;$result = Debugger::exportVar($data);$expected = <<<TEXTfalseTEXT;$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 = <<<TEXTarray('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);}}