No Description

DebugClassLoaderTest.php 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Debug\Tests;
  11. use Symfony\Component\Debug\DebugClassLoader;
  12. use Symfony\Component\Debug\ErrorHandler;
  13. use Symfony\Component\Debug\Exception\ContextErrorException;
  14. class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
  15. {
  16. /**
  17. * @var int Error reporting level before running tests.
  18. */
  19. private $errorReporting;
  20. private $loader;
  21. protected function setUp()
  22. {
  23. $this->errorReporting = error_reporting(E_ALL | E_STRICT);
  24. $this->loader = new ClassLoader();
  25. spl_autoload_register(array($this->loader, 'loadClass'), true, true);
  26. DebugClassLoader::enable();
  27. }
  28. protected function tearDown()
  29. {
  30. DebugClassLoader::disable();
  31. spl_autoload_unregister(array($this->loader, 'loadClass'));
  32. error_reporting($this->errorReporting);
  33. }
  34. public function testIdempotence()
  35. {
  36. DebugClassLoader::enable();
  37. $functions = spl_autoload_functions();
  38. foreach ($functions as $function) {
  39. if (is_array($function) && $function[0] instanceof DebugClassLoader) {
  40. $reflClass = new \ReflectionClass($function[0]);
  41. $reflProp = $reflClass->getProperty('classLoader');
  42. $reflProp->setAccessible(true);
  43. $this->assertNotInstanceOf('Symfony\Component\Debug\DebugClassLoader', $reflProp->getValue($function[0]));
  44. return;
  45. }
  46. }
  47. $this->fail('DebugClassLoader did not register');
  48. }
  49. public function testUnsilencing()
  50. {
  51. ob_start();
  52. $this->iniSet('log_errors', 0);
  53. $this->iniSet('display_errors', 1);
  54. // See below: this will fail with parse error
  55. // but this should not be @-silenced.
  56. @class_exists(__NAMESPACE__.'\TestingUnsilencing', true);
  57. $output = ob_get_clean();
  58. $this->assertStringMatchesFormat('%aParse error%a', $output);
  59. }
  60. public function testStacking()
  61. {
  62. // the ContextErrorException must not be loaded to test the workaround
  63. // for https://bugs.php.net/65322.
  64. if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) {
  65. $this->markTestSkipped('The ContextErrorException class is already loaded.');
  66. }
  67. ErrorHandler::register();
  68. try {
  69. // Trigger autoloading + E_STRICT at compile time
  70. // which in turn triggers $errorHandler->handle()
  71. // that again triggers autoloading for ContextErrorException.
  72. // Error stacking works around the bug above and everything is fine.
  73. eval('
  74. namespace '.__NAMESPACE__.';
  75. class ChildTestingStacking extends TestingStacking { function foo($bar) {} }
  76. ');
  77. $this->fail('ContextErrorException expected');
  78. } catch (\ErrorException $exception) {
  79. // if an exception is thrown, the test passed
  80. restore_error_handler();
  81. restore_exception_handler();
  82. $this->assertEquals(E_STRICT, $exception->getSeverity());
  83. $this->assertStringStartsWith(__FILE__, $exception->getFile());
  84. $this->assertRegexp('/^Runtime Notice: Declaration/', $exception->getMessage());
  85. } catch (\Exception $exception) {
  86. restore_error_handler();
  87. restore_exception_handler();
  88. throw $exception;
  89. }
  90. }
  91. /**
  92. * @expectedException \RuntimeException
  93. */
  94. public function testNameCaseMismatch()
  95. {
  96. class_exists(__NAMESPACE__.'\TestingCaseMismatch', true);
  97. }
  98. /**
  99. * @expectedException \RuntimeException
  100. */
  101. public function testFileCaseMismatch()
  102. {
  103. if (!file_exists(__DIR__.'/Fixtures/CaseMismatch.php')) {
  104. $this->markTestSkipped('Can only be run on case insensitive filesystems');
  105. }
  106. class_exists(__NAMESPACE__.'\Fixtures\CaseMismatch', true);
  107. }
  108. /**
  109. * @expectedException \RuntimeException
  110. */
  111. public function testPsr4CaseMismatch()
  112. {
  113. class_exists(__NAMESPACE__.'\Fixtures\Psr4CaseMismatch', true);
  114. }
  115. public function testNotPsr0()
  116. {
  117. $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\NotPSR0', true));
  118. }
  119. public function testNotPsr0Bis()
  120. {
  121. $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\NotPSR0bis', true));
  122. }
  123. public function testClassAlias()
  124. {
  125. $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\ClassAlias', true));
  126. }
  127. }
  128. class ClassLoader
  129. {
  130. public function loadClass($class)
  131. {
  132. }
  133. public function getClassMap()
  134. {
  135. return array(__NAMESPACE__.'\Fixtures\NotPSR0bis' => __DIR__.'/Fixtures/notPsr0Bis.php');
  136. }
  137. public function findFile($class)
  138. {
  139. if (__NAMESPACE__.'\TestingUnsilencing' === $class) {
  140. eval('-- parse error --');
  141. } elseif (__NAMESPACE__.'\TestingStacking' === $class) {
  142. eval('namespace '.__NAMESPACE__.'; class TestingStacking { function foo() {} }');
  143. } elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) {
  144. eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}');
  145. } elseif (__NAMESPACE__.'\Fixtures\CaseMismatch' === $class) {
  146. return __DIR__.'/Fixtures/CaseMismatch.php';
  147. } elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) {
  148. return __DIR__.'/Fixtures/psr4/Psr4CaseMismatch.php';
  149. } elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) {
  150. return __DIR__.'/Fixtures/reallyNotPsr0.php';
  151. } elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) {
  152. return __DIR__.'/Fixtures/notPsr0Bis.php';
  153. }
  154. }
  155. }