ClassCollectionLoaderTest.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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\ClassLoader\Tests;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\ClassLoader\ClassCollectionLoader;
  13. require_once __DIR__.'/Fixtures/ClassesWithParents/GInterface.php';
  14. require_once __DIR__.'/Fixtures/ClassesWithParents/CInterface.php';
  15. require_once __DIR__.'/Fixtures/ClassesWithParents/B.php';
  16. require_once __DIR__.'/Fixtures/ClassesWithParents/A.php';
  17. class ClassCollectionLoaderTest extends TestCase
  18. {
  19. /**
  20. * @requires PHP 5.4
  21. */
  22. public function testTraitDependencies()
  23. {
  24. require_once __DIR__.'/Fixtures/deps/traits.php';
  25. $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
  26. $m = $r->getMethod('getOrderedClasses');
  27. $m->setAccessible(true);
  28. $ordered = $m->invoke(null, array('CTFoo'));
  29. $this->assertEquals(
  30. array('TD', 'TC', 'TB', 'TA', 'TZ', 'CTFoo'),
  31. array_map(function ($class) { return $class->getName(); }, $ordered)
  32. );
  33. $ordered = $m->invoke(null, array('CTBar'));
  34. $this->assertEquals(
  35. array('TD', 'TZ', 'TC', 'TB', 'TA', 'CTBar'),
  36. array_map(function ($class) { return $class->getName(); }, $ordered)
  37. );
  38. }
  39. /**
  40. * @dataProvider getDifferentOrders
  41. */
  42. public function testClassReordering(array $classes)
  43. {
  44. $expected = array(
  45. 'ClassesWithParents\\GInterface',
  46. 'ClassesWithParents\\CInterface',
  47. 'ClassesWithParents\\B',
  48. 'ClassesWithParents\\A',
  49. );
  50. $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
  51. $m = $r->getMethod('getOrderedClasses');
  52. $m->setAccessible(true);
  53. $ordered = $m->invoke(null, $classes);
  54. $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
  55. }
  56. public function getDifferentOrders()
  57. {
  58. return array(
  59. array(array(
  60. 'ClassesWithParents\\A',
  61. 'ClassesWithParents\\CInterface',
  62. 'ClassesWithParents\\GInterface',
  63. 'ClassesWithParents\\B',
  64. )),
  65. array(array(
  66. 'ClassesWithParents\\B',
  67. 'ClassesWithParents\\A',
  68. 'ClassesWithParents\\CInterface',
  69. )),
  70. array(array(
  71. 'ClassesWithParents\\CInterface',
  72. 'ClassesWithParents\\B',
  73. 'ClassesWithParents\\A',
  74. )),
  75. array(array(
  76. 'ClassesWithParents\\A',
  77. )),
  78. );
  79. }
  80. /**
  81. * @dataProvider getDifferentOrdersForTraits
  82. * @requires PHP 5.4
  83. */
  84. public function testClassWithTraitsReordering(array $classes)
  85. {
  86. require_once __DIR__.'/Fixtures/ClassesWithParents/ATrait.php';
  87. require_once __DIR__.'/Fixtures/ClassesWithParents/BTrait.php';
  88. require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php';
  89. require_once __DIR__.'/Fixtures/ClassesWithParents/D.php';
  90. require_once __DIR__.'/Fixtures/ClassesWithParents/E.php';
  91. $expected = array(
  92. 'ClassesWithParents\\GInterface',
  93. 'ClassesWithParents\\CInterface',
  94. 'ClassesWithParents\\ATrait',
  95. 'ClassesWithParents\\BTrait',
  96. 'ClassesWithParents\\CTrait',
  97. 'ClassesWithParents\\B',
  98. 'ClassesWithParents\\A',
  99. 'ClassesWithParents\\D',
  100. 'ClassesWithParents\\E',
  101. );
  102. $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
  103. $m = $r->getMethod('getOrderedClasses');
  104. $m->setAccessible(true);
  105. $ordered = $m->invoke(null, $classes);
  106. $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
  107. }
  108. public function getDifferentOrdersForTraits()
  109. {
  110. return array(
  111. array(array(
  112. 'ClassesWithParents\\E',
  113. 'ClassesWithParents\\ATrait',
  114. )),
  115. array(array(
  116. 'ClassesWithParents\\E',
  117. )),
  118. );
  119. }
  120. /**
  121. * @requires PHP 5.4
  122. */
  123. public function testFixClassWithTraitsOrdering()
  124. {
  125. require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php';
  126. require_once __DIR__.'/Fixtures/ClassesWithParents/F.php';
  127. require_once __DIR__.'/Fixtures/ClassesWithParents/G.php';
  128. $classes = array(
  129. 'ClassesWithParents\\F',
  130. 'ClassesWithParents\\G',
  131. );
  132. $expected = array(
  133. 'ClassesWithParents\\CTrait',
  134. 'ClassesWithParents\\F',
  135. 'ClassesWithParents\\G',
  136. );
  137. $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
  138. $m = $r->getMethod('getOrderedClasses');
  139. $m->setAccessible(true);
  140. $ordered = $m->invoke(null, $classes);
  141. $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
  142. }
  143. /**
  144. * @dataProvider getFixNamespaceDeclarationsData
  145. */
  146. public function testFixNamespaceDeclarations($source, $expected)
  147. {
  148. $this->assertEquals('<?php '.$expected, ClassCollectionLoader::fixNamespaceDeclarations('<?php '.$source));
  149. }
  150. public function getFixNamespaceDeclarationsData()
  151. {
  152. return array(
  153. array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}"),
  154. array("namespace Foo;\nclass Foo {}\n", "namespace Foo\n{\nclass Foo {}\n}"),
  155. array("namespace Bar ;\nclass Foo {}\n", "namespace Bar\n{\nclass Foo {}\n}"),
  156. array("namespace Foo\Bar;\nclass Foo {}\n", "namespace Foo\Bar\n{\nclass Foo {}\n}"),
  157. array("namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n", "namespace Foo\Bar\Bar\n{\nclass Foo {}\n}"),
  158. array("namespace\n{\nclass Foo {}\n}\n", "namespace\n{\nclass Foo {}\n}"),
  159. );
  160. }
  161. /**
  162. * @dataProvider getFixNamespaceDeclarationsDataWithoutTokenizer
  163. */
  164. public function testFixNamespaceDeclarationsWithoutTokenizer($source, $expected)
  165. {
  166. ClassCollectionLoader::enableTokenizer(false);
  167. $this->assertEquals('<?php '.$expected, ClassCollectionLoader::fixNamespaceDeclarations('<?php '.$source));
  168. ClassCollectionLoader::enableTokenizer(true);
  169. }
  170. public function getFixNamespaceDeclarationsDataWithoutTokenizer()
  171. {
  172. return array(
  173. array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}\n"),
  174. array("namespace Foo;\nclass Foo {}\n", "namespace Foo\n{\nclass Foo {}\n}\n"),
  175. array("namespace Bar ;\nclass Foo {}\n", "namespace Bar\n{\nclass Foo {}\n}\n"),
  176. array("namespace Foo\Bar;\nclass Foo {}\n", "namespace Foo\Bar\n{\nclass Foo {}\n}\n"),
  177. array("namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n", "namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n"),
  178. array("\nnamespace\n{\nclass Foo {}\n\$namespace=123;}\n", "\nnamespace\n{\nclass Foo {}\n\$namespace=123;}\n"),
  179. );
  180. }
  181. /**
  182. * @expectedException \InvalidArgumentException
  183. */
  184. public function testUnableToLoadClassException()
  185. {
  186. if (is_file($file = sys_get_temp_dir().'/foo.php')) {
  187. unlink($file);
  188. }
  189. ClassCollectionLoader::load(array('SomeNotExistingClass'), sys_get_temp_dir(), 'foo', false);
  190. }
  191. public function testCommentStripping()
  192. {
  193. if (is_file($file = __DIR__.'/bar.php')) {
  194. unlink($file);
  195. }
  196. spl_autoload_register($r = function ($class) {
  197. if (0 === strpos($class, 'Namespaced') || 0 === strpos($class, 'Pearlike_')) {
  198. @require_once __DIR__.'/Fixtures/'.str_replace(array('\\', '_'), '/', $class).'.php';
  199. }
  200. });
  201. $strictTypes = \defined('HHVM_VERSION') ? '' : "\nnamespace {require __DIR__.'/Fixtures/Namespaced/WithStrictTypes.php';}";
  202. ClassCollectionLoader::load(
  203. array('Namespaced\\WithComments', 'Pearlike_WithComments', 'Namespaced\\WithDirMagic', 'Namespaced\\WithFileMagic', 'Namespaced\\WithHaltCompiler', $strictTypes ? 'Namespaced\\WithStrictTypes' : 'Namespaced\\WithComments'),
  204. __DIR__,
  205. 'bar',
  206. false
  207. );
  208. spl_autoload_unregister($r);
  209. $this->assertEquals(<<<'EOF'
  210. namespace Namespaced
  211. {
  212. class WithComments
  213. {
  214. public static $loaded = true;
  215. }
  216. $string ='string should not be modified {$string}';
  217. $heredoc = (<<<HD
  218. Heredoc should not be modified {$string}
  219. HD
  220. );
  221. $nowdoc =<<<'ND'
  222. Nowdoc should not be modified {$string}
  223. ND
  224. ;
  225. }
  226. namespace
  227. {
  228. class Pearlike_WithComments
  229. {
  230. public static $loaded = true;
  231. }
  232. }
  233. namespace {require __DIR__.'/Fixtures/Namespaced/WithDirMagic.php';}
  234. namespace {require __DIR__.'/Fixtures/Namespaced/WithFileMagic.php';}
  235. namespace {require __DIR__.'/Fixtures/Namespaced/WithHaltCompiler.php';}
  236. EOF
  237. .$strictTypes,
  238. str_replace(array("<?php \n", '\\\\'), array('', '/'), file_get_contents($file))
  239. );
  240. unlink($file);
  241. }
  242. }