4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\ClassLoader\Tests;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\ClassLoader\ClassCollectionLoader;
16 use Symfony\Component\ClassLoader\Tests\Fixtures\DeclaredClass;
17 use Symfony\Component\ClassLoader\Tests\Fixtures\WarmedClass;
19 require_once __DIR__.'/Fixtures/ClassesWithParents/GInterface.php';
20 require_once __DIR__.'/Fixtures/ClassesWithParents/CInterface.php';
21 require_once __DIR__.'/Fixtures/ClassesWithParents/B.php';
22 require_once __DIR__.'/Fixtures/ClassesWithParents/A.php';
24 class ClassCollectionLoaderTest extends TestCase
26 public function testTraitDependencies()
28 require_once __DIR__.'/Fixtures/deps/traits.php';
30 $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
31 $m = $r->getMethod('getOrderedClasses');
32 $m->setAccessible(true);
34 $ordered = $m->invoke(null, array('CTFoo'));
37 array('TD', 'TC', 'TB', 'TA', 'TZ', 'CTFoo'),
38 array_map(function ($class) { return $class->getName(); }, $ordered)
41 $ordered = $m->invoke(null, array('CTBar'));
44 array('TD', 'TZ', 'TC', 'TB', 'TA', 'CTBar'),
45 array_map(function ($class) { return $class->getName(); }, $ordered)
50 * @dataProvider getDifferentOrders
52 public function testClassReordering(array $classes)
55 'ClassesWithParents\\GInterface',
56 'ClassesWithParents\\CInterface',
57 'ClassesWithParents\\B',
58 'ClassesWithParents\\A',
61 $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
62 $m = $r->getMethod('getOrderedClasses');
63 $m->setAccessible(true);
65 $ordered = $m->invoke(null, $classes);
67 $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
70 public function getDifferentOrders()
74 'ClassesWithParents\\A',
75 'ClassesWithParents\\CInterface',
76 'ClassesWithParents\\GInterface',
77 'ClassesWithParents\\B',
80 'ClassesWithParents\\B',
81 'ClassesWithParents\\A',
82 'ClassesWithParents\\CInterface',
85 'ClassesWithParents\\CInterface',
86 'ClassesWithParents\\B',
87 'ClassesWithParents\\A',
90 'ClassesWithParents\\A',
96 * @dataProvider getDifferentOrdersForTraits
98 public function testClassWithTraitsReordering(array $classes)
100 require_once __DIR__.'/Fixtures/ClassesWithParents/ATrait.php';
101 require_once __DIR__.'/Fixtures/ClassesWithParents/BTrait.php';
102 require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php';
103 require_once __DIR__.'/Fixtures/ClassesWithParents/D.php';
104 require_once __DIR__.'/Fixtures/ClassesWithParents/E.php';
107 'ClassesWithParents\\GInterface',
108 'ClassesWithParents\\CInterface',
109 'ClassesWithParents\\ATrait',
110 'ClassesWithParents\\BTrait',
111 'ClassesWithParents\\CTrait',
112 'ClassesWithParents\\B',
113 'ClassesWithParents\\A',
114 'ClassesWithParents\\D',
115 'ClassesWithParents\\E',
118 $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
119 $m = $r->getMethod('getOrderedClasses');
120 $m->setAccessible(true);
122 $ordered = $m->invoke(null, $classes);
124 $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
127 public function getDifferentOrdersForTraits()
131 'ClassesWithParents\\E',
132 'ClassesWithParents\\ATrait',
135 'ClassesWithParents\\E',
140 public function testFixClassWithTraitsOrdering()
142 require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php';
143 require_once __DIR__.'/Fixtures/ClassesWithParents/F.php';
144 require_once __DIR__.'/Fixtures/ClassesWithParents/G.php';
147 'ClassesWithParents\\F',
148 'ClassesWithParents\\G',
152 'ClassesWithParents\\CTrait',
153 'ClassesWithParents\\F',
154 'ClassesWithParents\\G',
157 $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
158 $m = $r->getMethod('getOrderedClasses');
159 $m->setAccessible(true);
161 $ordered = $m->invoke(null, $classes);
163 $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
167 * @dataProvider getFixNamespaceDeclarationsData
169 public function testFixNamespaceDeclarations($source, $expected)
171 $this->assertEquals('<?php '.$expected, ClassCollectionLoader::fixNamespaceDeclarations('<?php '.$source));
174 public function getFixNamespaceDeclarationsData()
177 array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}"),
178 array("namespace Foo;\nclass Foo {}\n", "namespace Foo\n{\nclass Foo {}\n}"),
179 array("namespace Bar ;\nclass Foo {}\n", "namespace Bar\n{\nclass Foo {}\n}"),
180 array("namespace Foo\Bar;\nclass Foo {}\n", "namespace Foo\Bar\n{\nclass Foo {}\n}"),
181 array("namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n", "namespace Foo\Bar\Bar\n{\nclass Foo {}\n}"),
182 array("namespace\n{\nclass Foo {}\n}\n", "namespace\n{\nclass Foo {}\n}"),
187 * @dataProvider getFixNamespaceDeclarationsDataWithoutTokenizer
189 public function testFixNamespaceDeclarationsWithoutTokenizer($source, $expected)
191 ClassCollectionLoader::enableTokenizer(false);
192 $this->assertEquals('<?php '.$expected, ClassCollectionLoader::fixNamespaceDeclarations('<?php '.$source));
193 ClassCollectionLoader::enableTokenizer(true);
196 public function getFixNamespaceDeclarationsDataWithoutTokenizer()
199 array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}\n"),
200 array("namespace Foo;\nclass Foo {}\n", "namespace Foo\n{\nclass Foo {}\n}\n"),
201 array("namespace Bar ;\nclass Foo {}\n", "namespace Bar\n{\nclass Foo {}\n}\n"),
202 array("namespace Foo\Bar;\nclass Foo {}\n", "namespace Foo\Bar\n{\nclass Foo {}\n}\n"),
203 array("namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n", "namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n"),
204 array("\nnamespace\n{\nclass Foo {}\n\$namespace=123;}\n", "\nnamespace\n{\nclass Foo {}\n\$namespace=123;}\n"),
209 * @expectedException \InvalidArgumentException
211 public function testUnableToLoadClassException()
213 if (is_file($file = sys_get_temp_dir().'/foo.php')) {
217 ClassCollectionLoader::load(array('SomeNotExistingClass'), sys_get_temp_dir(), 'foo', false);
220 public function testCommentStripping()
222 if (is_file($file = __DIR__.'/bar.php')) {
225 spl_autoload_register($r = function ($class) {
226 if (0 === strpos($class, 'Namespaced') || 0 === strpos($class, 'Pearlike_')) {
227 @require_once __DIR__.'/Fixtures/'.str_replace(array('\\', '_'), '/', $class).'.php';
231 $strictTypes = defined('HHVM_VERSION') ? '' : "\nnamespace {require __DIR__.'/Fixtures/Namespaced/WithStrictTypes.php';}";
233 ClassCollectionLoader::load(
234 array('Namespaced\\WithComments', 'Pearlike_WithComments', 'Namespaced\\WithDirMagic', 'Namespaced\\WithFileMagic', 'Namespaced\\WithHaltCompiler', $strictTypes ? 'Namespaced\\WithStrictTypes' : 'Namespaced\\WithComments'),
240 spl_autoload_unregister($r);
242 $this->assertEquals(<<<'EOF'
247 public static $loaded = true;
249 $string ='string should not be modified {$string}';
253 Heredoc should not be modified {$string}
261 Nowdoc should not be modified {$string}
269 class Pearlike_WithComments
271 public static $loaded = true;
274 namespace {require __DIR__.'/Fixtures/Namespaced/WithDirMagic.php';}
275 namespace {require __DIR__.'/Fixtures/Namespaced/WithFileMagic.php';}
276 namespace {require __DIR__.'/Fixtures/Namespaced/WithHaltCompiler.php';}
279 str_replace(array("<?php \n", '\\\\'), array('', '/'), file_get_contents($file))
285 public function testInline()
287 $this->assertTrue(class_exists(WarmedClass::class, true));
289 @unlink($cache = sys_get_temp_dir().'/inline.php');
291 $classes = array(WarmedClass::class);
292 $excluded = array(DeclaredClass::class);
294 ClassCollectionLoader::inline($classes, $cache, $excluded);
296 $this->assertSame(<<<'EOTXT'
298 namespace Symfony\Component\ClassLoader\Tests\Fixtures
300 interface WarmedInterface
304 namespace Symfony\Component\ClassLoader\Tests\Fixtures
306 class WarmedClass extends DeclaredClass implements WarmedInterface
311 , file_get_contents($cache)