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';
27 class ClassCollectionLoaderTest extends TestCase
29 public function testTraitDependencies()
31 require_once __DIR__.'/Fixtures/deps/traits.php';
33 $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
34 $m = $r->getMethod('getOrderedClasses');
35 $m->setAccessible(true);
37 $ordered = $m->invoke(null, array('CTFoo'));
40 array('TD', 'TC', 'TB', 'TA', 'TZ', 'CTFoo'),
41 array_map(function ($class) { return $class->getName(); }, $ordered)
44 $ordered = $m->invoke(null, array('CTBar'));
47 array('TD', 'TZ', 'TC', 'TB', 'TA', 'CTBar'),
48 array_map(function ($class) { return $class->getName(); }, $ordered)
53 * @dataProvider getDifferentOrders
55 public function testClassReordering(array $classes)
58 'ClassesWithParents\\GInterface',
59 'ClassesWithParents\\CInterface',
60 'ClassesWithParents\\B',
61 'ClassesWithParents\\A',
64 $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
65 $m = $r->getMethod('getOrderedClasses');
66 $m->setAccessible(true);
68 $ordered = $m->invoke(null, $classes);
70 $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
73 public function getDifferentOrders()
77 'ClassesWithParents\\A',
78 'ClassesWithParents\\CInterface',
79 'ClassesWithParents\\GInterface',
80 'ClassesWithParents\\B',
83 'ClassesWithParents\\B',
84 'ClassesWithParents\\A',
85 'ClassesWithParents\\CInterface',
88 'ClassesWithParents\\CInterface',
89 'ClassesWithParents\\B',
90 'ClassesWithParents\\A',
93 'ClassesWithParents\\A',
99 * @dataProvider getDifferentOrdersForTraits
101 public function testClassWithTraitsReordering(array $classes)
103 require_once __DIR__.'/Fixtures/ClassesWithParents/ATrait.php';
104 require_once __DIR__.'/Fixtures/ClassesWithParents/BTrait.php';
105 require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php';
106 require_once __DIR__.'/Fixtures/ClassesWithParents/D.php';
107 require_once __DIR__.'/Fixtures/ClassesWithParents/E.php';
110 'ClassesWithParents\\GInterface',
111 'ClassesWithParents\\CInterface',
112 'ClassesWithParents\\ATrait',
113 'ClassesWithParents\\BTrait',
114 'ClassesWithParents\\CTrait',
115 'ClassesWithParents\\B',
116 'ClassesWithParents\\A',
117 'ClassesWithParents\\D',
118 'ClassesWithParents\\E',
121 $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
122 $m = $r->getMethod('getOrderedClasses');
123 $m->setAccessible(true);
125 $ordered = $m->invoke(null, $classes);
127 $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
130 public function getDifferentOrdersForTraits()
134 'ClassesWithParents\\E',
135 'ClassesWithParents\\ATrait',
138 'ClassesWithParents\\E',
143 public function testFixClassWithTraitsOrdering()
145 require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php';
146 require_once __DIR__.'/Fixtures/ClassesWithParents/F.php';
147 require_once __DIR__.'/Fixtures/ClassesWithParents/G.php';
150 'ClassesWithParents\\F',
151 'ClassesWithParents\\G',
155 'ClassesWithParents\\CTrait',
156 'ClassesWithParents\\F',
157 'ClassesWithParents\\G',
160 $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader');
161 $m = $r->getMethod('getOrderedClasses');
162 $m->setAccessible(true);
164 $ordered = $m->invoke(null, $classes);
166 $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered));
170 * @dataProvider getFixNamespaceDeclarationsData
172 public function testFixNamespaceDeclarations($source, $expected)
174 $this->assertEquals('<?php '.$expected, ClassCollectionLoader::fixNamespaceDeclarations('<?php '.$source));
177 public function getFixNamespaceDeclarationsData()
180 array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}"),
181 array("namespace Foo;\nclass Foo {}\n", "namespace Foo\n{\nclass Foo {}\n}"),
182 array("namespace Bar ;\nclass Foo {}\n", "namespace Bar\n{\nclass Foo {}\n}"),
183 array("namespace Foo\Bar;\nclass Foo {}\n", "namespace Foo\Bar\n{\nclass Foo {}\n}"),
184 array("namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n", "namespace Foo\Bar\Bar\n{\nclass Foo {}\n}"),
185 array("namespace\n{\nclass Foo {}\n}\n", "namespace\n{\nclass Foo {}\n}"),
190 * @dataProvider getFixNamespaceDeclarationsDataWithoutTokenizer
192 public function testFixNamespaceDeclarationsWithoutTokenizer($source, $expected)
194 ClassCollectionLoader::enableTokenizer(false);
195 $this->assertEquals('<?php '.$expected, ClassCollectionLoader::fixNamespaceDeclarations('<?php '.$source));
196 ClassCollectionLoader::enableTokenizer(true);
199 public function getFixNamespaceDeclarationsDataWithoutTokenizer()
202 array("namespace;\nclass Foo {}\n", "namespace\n{\nclass Foo {}\n}\n"),
203 array("namespace Foo;\nclass Foo {}\n", "namespace Foo\n{\nclass Foo {}\n}\n"),
204 array("namespace Bar ;\nclass Foo {}\n", "namespace Bar\n{\nclass Foo {}\n}\n"),
205 array("namespace Foo\Bar;\nclass Foo {}\n", "namespace Foo\Bar\n{\nclass Foo {}\n}\n"),
206 array("namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n", "namespace Foo\Bar\Bar\n{\nclass Foo {}\n}\n"),
207 array("\nnamespace\n{\nclass Foo {}\n\$namespace=123;}\n", "\nnamespace\n{\nclass Foo {}\n\$namespace=123;}\n"),
212 * @expectedException \InvalidArgumentException
214 public function testUnableToLoadClassException()
216 if (is_file($file = sys_get_temp_dir().'/foo.php')) {
220 ClassCollectionLoader::load(array('SomeNotExistingClass'), sys_get_temp_dir(), 'foo', false);
223 public function testCommentStripping()
225 if (is_file($file = __DIR__.'/bar.php')) {
228 spl_autoload_register($r = function ($class) {
229 if (0 === strpos($class, 'Namespaced') || 0 === strpos($class, 'Pearlike_')) {
230 @require_once __DIR__.'/Fixtures/'.str_replace(array('\\', '_'), '/', $class).'.php';
234 $strictTypes = \defined('HHVM_VERSION') ? '' : "\nnamespace {require __DIR__.'/Fixtures/Namespaced/WithStrictTypes.php';}";
236 ClassCollectionLoader::load(
237 array('Namespaced\\WithComments', 'Pearlike_WithComments', 'Namespaced\\WithDirMagic', 'Namespaced\\WithFileMagic', 'Namespaced\\WithHaltCompiler', $strictTypes ? 'Namespaced\\WithStrictTypes' : 'Namespaced\\WithComments'),
243 spl_autoload_unregister($r);
245 $this->assertEquals(<<<'EOF'
250 public static $loaded = true;
252 $string ='string should not be modified {$string}';
256 Heredoc should not be modified {$string}
264 Nowdoc should not be modified {$string}
272 class Pearlike_WithComments
274 public static $loaded = true;
277 namespace {require __DIR__.'/Fixtures/Namespaced/WithDirMagic.php';}
278 namespace {require __DIR__.'/Fixtures/Namespaced/WithFileMagic.php';}
279 namespace {require __DIR__.'/Fixtures/Namespaced/WithHaltCompiler.php';}
282 str_replace(array("<?php \n", '\\\\'), array('', '/'), file_get_contents($file))
288 public function testInline()
290 $this->assertTrue(class_exists(WarmedClass::class, true));
292 @unlink($cache = sys_get_temp_dir().'/inline.php');
294 $classes = array(WarmedClass::class);
295 $excluded = array(DeclaredClass::class);
297 ClassCollectionLoader::inline($classes, $cache, $excluded);
299 $this->assertSame(<<<'EOTXT'
301 namespace Symfony\Component\ClassLoader\Tests\Fixtures
303 interface WarmedInterface
307 namespace Symfony\Component\ClassLoader\Tests\Fixtures
309 class WarmedClass extends DeclaredClass implements WarmedInterface
314 , file_get_contents($cache)