統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Test / Case / Utility / DebuggerTest.php @ 0b1b8047

履歴 | 表示 | アノテート | ダウンロード (15.097 KB)

1
<?php
2
/**
3
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice.
9
 *
10
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 * @link          http://cakephp.org CakePHP Project
12
 * @since         CakePHP(tm) v 1.2.0.5432
13
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
14
 */
15

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

    
18
/**
19
 * DebuggerTestCaseDebugger class
20
 *
21
 * @package       Cake.Test.Case.Utility
22
 */
23
class DebuggerTestCaseDebugger extends Debugger {
24
}
25

    
26
/**
27
 * DebuggerTest class
28
 *
29
 * !!! Be careful with changing code below as it may
30
 * !!! change line numbers which are used in the tests
31
 *
32
 * @package       Cake.Test.Case.Utility
33
 */
34
class DebuggerTest extends CakeTestCase {
35

    
36
        protected $_restoreError = false;
37

    
38
/**
39
 * setUp method
40
 *
41
 * @return void
42
 */
43
        public function setUp() {
44
                parent::setUp();
45
                Configure::write('debug', 2);
46
                Configure::write('log', false);
47
        }
48

    
49
/**
50
 * tearDown method
51
 *
52
 * @return void
53
 */
54
        public function tearDown() {
55
                parent::tearDown();
56
                Configure::write('log', true);
57
                if ($this->_restoreError) {
58
                        restore_error_handler();
59
                }
60
        }
61

    
62
/**
63
 * testDocRef method
64
 *
65
 * @return void
66
 */
67
        public function testDocRef() {
68
                ini_set('docref_root', '');
69
                $this->assertEquals(ini_get('docref_root'), '');
70
                new Debugger();
71
                $this->assertEquals(ini_get('docref_root'), 'http://php.net/');
72
        }
73

    
74
/**
75
 * test Excerpt writing
76
 *
77
 * @return void
78
 */
79
        public function testExcerpt() {
80
                $result = Debugger::excerpt(__FILE__, __LINE__, 2);
81
                $this->assertTrue(is_array($result));
82
                $this->assertEquals(5, count($result));
83
                $this->assertRegExp('/function(.+)testExcerpt/', $result[1]);
84

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

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

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

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

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

    
102
/**
103
 * testOutput method
104
 *
105
 * @return void
106
 */
107
        public function testOutput() {
108
                set_error_handler('Debugger::showError');
109
                $this->_restoreError = true;
110

    
111
                $result = Debugger::output(false);
112
                $this->assertEquals('', $result);
113
                $out .= '';
114
                $result = Debugger::output(true);
115

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

    
120
                ob_start();
121
                Debugger::output('txt');
122
                $other .= '';
123
                $result = ob_get_clean();
124

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

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

    
137
                ob_start();
138
                Debugger::output('js');
139
                $buzz .= '';
140
                $result = explode('</a>', ob_get_clean());
141
                $this->assertTags($result[0], array(
142
                        'pre' => array('class' => 'cake-error'),
143
                        'a' => array(
144
                                'href' => "javascript:void(0);",
145
                                'onclick' => "preg:/document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display = " .
146
                                        "\(document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display == 'none'" .
147
                                        " \? '' \: 'none'\);/"
148
                        ),
149
                        'b' => array(), 'Notice', '/b', ' (8)',
150
                ));
151

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

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

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

    
174
                Debugger::output('xml', array(
175
                        'error' => '<error><code>{:code}</code><file>{:file}</file><line>{:line}</line>' .
176
                                '{:description}</error>',
177
                        'context' => "<context>{:context}</context>",
178
                        'trace' => "<stack>{:trace}</stack>",
179
                ));
180
                Debugger::output('xml');
181

    
182
                ob_start();
183
                $foo .= '';
184
                $result = ob_get_clean();
185

    
186
                $data = array(
187
                        'error' => array(),
188
                        'code' => array(), '8', '/code',
189
                        'file' => array(), 'preg:/[^<]+/', '/file',
190
                        'line' => array(), '' . ((int)__LINE__ - 7), '/line',
191
                        'preg:/Undefined variable:\s+foo/',
192
                        '/error'
193
                );
194
                $this->assertTags($result, $data, true);
195
        }
196

    
197
/**
198
 * Test that outputAs works.
199
 *
200
 * @return void
201
 */
202
        public function testOutputAs() {
203
                Debugger::outputAs('html');
204
                $this->assertEquals('html', Debugger::outputAs());
205
        }
206

    
207
/**
208
 * Test that choosing a non-existent format causes an exception
209
 *
210
 * @expectedException CakeException
211
 * @return void
212
 */
213
        public function testOutputAsException() {
214
                Debugger::outputAs('Invalid junk');
215
        }
216

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

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

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

    
235
                Debugger::addFormat('xml', array(
236
                        'error' => '<error><code>{:code}</code><file>{:file}</file><line>{:line}</line>' .
237
                                '{:description}</error>',
238
                ));
239
                Debugger::outputAs('xml');
240

    
241
                ob_start();
242
                $foo .= '';
243
                $result = ob_get_clean();
244

    
245
                $data = array(
246
                        '<error',
247
                        '<code', '8', '/code',
248
                        '<file', 'preg:/[^<]+/', '/file',
249
                        '<line', '' . ((int)__LINE__ - 7), '/line',
250
                        'preg:/Undefined variable:\s+foo/',
251
                        '/error'
252
                );
253
                $this->assertTags($result, $data, true);
254
        }
255

    
256
/**
257
 * Test adding a format that is handled by a callback.
258
 *
259
 * @return void
260
 */
261
        public function testAddFormatCallback() {
262
                set_error_handler('Debugger::showError');
263
                $this->_restoreError = true;
264

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

    
268
                ob_start();
269
                $foo .= '';
270
                $result = ob_get_clean();
271
                $this->assertContains('Notice: I eated an error', $result);
272
                $this->assertContains('DebuggerTest.php', $result);
273
        }
274

    
275
/**
276
 * Test method for testing addFormat with callbacks.
277
 *
278
 * @return void
279
 */
280
        public function customFormat($error, $strings) {
281
                return $error['error'] . ': I eated an error ' . $error['file'];
282
        }
283

    
284
/**
285
 * testTrimPath method
286
 *
287
 * @return void
288
 */
289
        public function testTrimPath() {
290
                $this->assertEquals('APP' . DS, Debugger::trimPath(APP));
291
                $this->assertEquals('CORE', Debugger::trimPath(CAKE_CORE_INCLUDE_PATH));
292
                $this->assertEquals('ROOT', Debugger::trimPath(ROOT));
293
                $this->assertEquals('CORE' . DS . 'Cake' . DS, Debugger::trimPath(CAKE));
294
                $this->assertEquals('Some/Other/Path', Debugger::trimPath('Some/Other/Path'));
295
        }
296

    
297
/**
298
 * testExportVar method
299
 *
300
 * @return void
301
 */
302
        public function testExportVar() {
303
                App::uses('Controller', 'Controller');
304
                $Controller = new Controller();
305
                $Controller->helpers = array('Html', 'Form');
306
                $View = new View($Controller);
307
                $View->int = 2;
308
                $View->float = 1.333;
309

    
310
                $result = Debugger::exportVar($View);
311
                $expected = <<<TEXT
312
object(View) {
313
        Helpers => object(HelperCollection) {}
314
        Blocks => object(ViewBlock) {}
315
        plugin => null
316
        name => ''
317
        passedArgs => array()
318
        helpers => array(
319
                (int) 0 => 'Html',
320
                (int) 1 => 'Form'
321
        )
322
        viewPath => ''
323
        viewVars => array()
324
        view => null
325
        layout => 'default'
326
        layoutPath => null
327
        autoLayout => true
328
        ext => '.ctp'
329
        subDir => null
330
        theme => null
331
        cacheAction => false
332
        validationErrors => array()
333
        hasRendered => false
334
        uuids => array()
335
        request => object(CakeRequest) {}
336
        response => object(CakeResponse) {}
337
        elementCache => 'default'
338
        elementCacheSettings => array()
339
        Html => object(HtmlHelper) {}
340
        Form => object(FormHelper) {}
341
        int => (int) 2
342
        float => (float) 1.333
343

344
TEXT;
345
                if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
346
                        $expected .= <<<TEXT
347
        [protected] _passedVars => array(
348
                (int) 0 => 'viewVars',
349
                (int) 1 => 'autoLayout',
350
                (int) 2 => 'ext',
351
                (int) 3 => 'helpers',
352
                (int) 4 => 'view',
353
                (int) 5 => 'layout',
354
                (int) 6 => 'name',
355
                (int) 7 => 'theme',
356
                (int) 8 => 'layoutPath',
357
                (int) 9 => 'viewPath',
358
                (int) 10 => 'request',
359
                (int) 11 => 'plugin',
360
                (int) 12 => 'passedArgs',
361
                (int) 13 => 'cacheAction'
362
        )
363
        [protected] _scripts => array()
364
        [protected] _paths => array()
365
        [protected] _pathsForPlugin => array()
366
        [protected] _parents => array()
367
        [protected] _current => null
368
        [protected] _currentType => ''
369
        [protected] _stack => array()
370
        [protected] _eventManager => object(CakeEventManager) {}
371
        [protected] _eventManagerConfigured => false
372

373
TEXT;
374
                }
375
                $expected .= <<<TEXT
376
}
377
TEXT;
378

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

    
381
                $data = array(
382
                        1 => 'Index one',
383
                        5 => 'Index five'
384
                );
385
                $result = Debugger::exportVar($data);
386
                $expected = <<<TEXT
387
array(
388
        (int) 1 => 'Index one',
389
        (int) 5 => 'Index five'
390
)
391
TEXT;
392
                $this->assertTextEquals($expected, $result);
393

    
394
                $data = array(
395
                        'key' => array(
396
                                'value'
397
                        )
398
                );
399
                $result = Debugger::exportVar($data, 1);
400
                $expected = <<<TEXT
401
array(
402
        'key' => array(
403
                [maximum depth reached]
404
        )
405
)
406
TEXT;
407
                $this->assertTextEquals($expected, $result);
408

    
409
                $data = false;
410
                $result = Debugger::exportVar($data);
411
                $expected = <<<TEXT
412
false
413
TEXT;
414
                $this->assertTextEquals($expected, $result);
415

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

    
422
/**
423
 * Test exporting various kinds of false.
424
 *
425
 * @return void
426
 */
427
        public function testExportVarZero() {
428
                $data = array(
429
                        'nothing' => '',
430
                        'null' => null,
431
                        'false' => false,
432
                        'szero' => '0',
433
                        'zero' => 0
434
                );
435
                $result = Debugger::exportVar($data);
436
                $expected = <<<TEXT
437
array(
438
        'nothing' => '',
439
        'null' => null,
440
        'false' => false,
441
        'szero' => '0',
442
        'zero' => (int) 0
443
)
444
TEXT;
445
                $this->assertTextEquals($expected, $result);
446
        }
447

    
448
/**
449
 * testLog method
450
 *
451
 * @return void
452
 */
453
        public function testLog() {
454
                if (file_exists(LOGS . 'debug.log')) {
455
                        unlink(LOGS . 'debug.log');
456
                }
457
                CakeLog::config('file', array('engine' => 'File', 'path' => TMP . 'logs' . DS));
458

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

    
464
                unlink(LOGS . 'debug.log');
465

    
466
                Debugger::log(array('whatever', 'here'));
467
                $result = file_get_contents(LOGS . 'debug.log');
468
                $this->assertContains('DebuggerTest::testLog', $result);
469
                $this->assertContains('[main]', $result);
470
                $this->assertContains('array', $result);
471
                $this->assertContains("'whatever',", $result);
472
                $this->assertContains("'here'", $result);
473
        }
474

    
475
/**
476
 * test log() depth
477
 *
478
 * @return void
479
 */
480
        public function testLogDepth() {
481
                if (file_exists(LOGS . 'debug.log')) {
482
                        unlink(LOGS . 'debug.log');
483
                }
484
                CakeLog::config('file', array('engine' => 'File', 'path' => TMP . 'logs' . DS));
485

    
486
                $val = array(
487
                        'test' => array('key' => 'val')
488
                );
489
                Debugger::log($val, LOG_DEBUG, 0);
490
                $result = file_get_contents(LOGS . 'debug.log');
491
                $this->assertContains('DebuggerTest::testLog', $result);
492
                $this->assertNotContains("/'val'/", $result);
493

    
494
                unlink(LOGS . 'debug.log');
495
        }
496

    
497
/**
498
 * testDump method
499
 *
500
 * @return void
501
 */
502
        public function testDump() {
503
                $var = array('People' => array(
504
                        array(
505
                                'name' => 'joeseph',
506
                                'coat' => 'technicolor',
507
                                'hair_color' => 'brown'
508
                        ),
509
                        array(
510
                                'name' => 'Shaft',
511
                                'coat' => 'black',
512
                                'hair' => 'black'
513
                        )
514
                ));
515
                ob_start();
516
                Debugger::dump($var);
517
                $result = ob_get_clean();
518

    
519
                $open = PHP_SAPI === 'cli' ? "\n" : '<pre>';
520
                $close = PHP_SAPI === 'cli' ? "\n" : '</pre>';
521
                $expected = <<<TEXT
522
{$open}array(
523
        'People' => array(
524
                (int) 0 => array(
525
                        'name' => 'joeseph',
526
                        'coat' => 'technicolor',
527
                        'hair_color' => 'brown'
528
                ),
529
                (int) 1 => array(
530
                        'name' => 'Shaft',
531
                        'coat' => 'black',
532
                        'hair' => 'black'
533
                )
534
        )
535
){$close}
536
TEXT;
537
                $this->assertTextEquals($expected, $result);
538

    
539
                ob_start();
540
                Debugger::dump($var, 1);
541
                $result = ob_get_clean();
542

    
543
                $open = PHP_SAPI === 'cli' ? "\n" : '<pre>';
544
                $close = PHP_SAPI === 'cli' ? "\n" : '</pre>';
545
                $expected = <<<TEXT
546
{$open}array(
547
        'People' => array(
548
                [maximum depth reached]
549
        )
550
){$close}
551
TEXT;
552
                $this->assertTextEquals($expected, $result);
553
        }
554

    
555
/**
556
 * test getInstance.
557
 *
558
 * @return void
559
 */
560
        public function testGetInstance() {
561
                $result = Debugger::getInstance();
562
                $this->assertInstanceOf('Debugger', $result);
563

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

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

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

    
574
/**
575
 * testNoDbCredentials
576
 *
577
 * If a connection error occurs, the config variable is passed through exportVar
578
 * *** our database login credentials such that they are never visible
579
 *
580
 * @return void
581
 */
582
        public function testNoDbCredentials() {
583
                $config = array(
584
                        'datasource' => 'mysql',
585
                        'persistent' => false,
586
                        'host' => 'void.cakephp.org',
587
                        'login' => 'cakephp-user',
588
                        'password' => 'cakephp-password',
589
                        'database' => 'cakephp-database',
590
                        'prefix' => ''
591
                );
592

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

    
595
                $expectedArray = array(
596
                        'datasource' => 'mysql',
597
                        'persistent' => false,
598
                        'host' => '*****',
599
                        'login' => '*****',
600
                        'password' => '*****',
601
                        'database' => '*****',
602
                        'prefix' => ''
603
                );
604
                $expected = Debugger::exportVar($expectedArray);
605

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

    
609
/**
610
 * Test that exportVar() doesn't loop through recursive structures.
611
 *
612
 * @return void
613
 */
614
        public function testExportVarRecursion() {
615
                $output = Debugger::exportVar($GLOBALS);
616
                $this->assertContains("'GLOBALS' => [recursion]", $output);
617
        }
618

    
619
/**
620
 * test trace exclude
621
 *
622
 * @return void
623
 */
624
        public function testTraceExclude() {
625
                $result = Debugger::trace();
626
                $this->assertRegExp('/^DebuggerTest::testTraceExclude/', $result);
627

    
628
                $result = Debugger::trace(array(
629
                        'exclude' => array('DebuggerTest::testTraceExclude')
630
                ));
631
                $this->assertNotRegExp('/^DebuggerTest::testTraceExclude/', $result);
632
        }
633
}