[!!!][FEATURE] Discard TYPO3 class loader
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Package / PackageManagerTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Package;
3
4 /* *
5 * This script belongs to the TYPO3 Flow framework. *
6 * *
7 * It is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU Lesser General Public License, either version 3 *
9 * of the License, or (at your option) any later version. *
10 * *
11 * The TYPO3 project - inspiring people to share! *
12 * */
13
14 use TYPO3\CMS\Core\Package\PackageInterface;
15 use org\bovigo\vfs\vfsStream;
16
17 /**
18 * Testcase for the default package manager
19 *
20 */
21 class PackageManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
22
23 /**
24 * @var \TYPO3\CMS\Core\Package\PackageManager
25 */
26 protected $packageManager;
27
28 /**
29 * Sets up this test case
30 *
31 */
32 protected function setUp() {
33 vfsStream::setup('Test');
34 $mockBootstrap = $this->getMock(\TYPO3\CMS\Core\Core\Bootstrap::class, array(), array(), '', FALSE);
35 $mockCache = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\PhpFrontend::class, array('has', 'set', 'getBackend'), array(), '', FALSE);
36 $mockCacheBackend = $this->getMock(\TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend::class, array('has', 'set', 'getBackend'), array(), '', FALSE);
37 $mockCache->expects($this->any())->method('has')->will($this->returnValue(FALSE));
38 $mockCache->expects($this->any())->method('set')->will($this->returnValue(TRUE));
39 $mockCache->expects($this->any())->method('getBackend')->will($this->returnValue($mockCacheBackend));
40 $mockCacheBackend->expects($this->any())->method('getCacheDirectory')->will($this->returnValue('vfs://Test/Cache'));
41 $this->packageManager = $this->getAccessibleMock(\TYPO3\CMS\Core\Package\PackageManager::class, array('sortAndSavePackageStates', 'sortAvailablePackagesByDependencies', 'registerAutoloadInformationInClassLoader'));
42
43 mkdir('vfs://Test/Packages/Application', 0700, TRUE);
44 mkdir('vfs://Test/Configuration');
45 file_put_contents('vfs://Test/Configuration/PackageStates.php', "<?php return array ('packages' => array(), 'version' => 4); ");
46
47 $composerNameToPackageKeyMap = array(
48 'typo3/flow' => 'TYPO3.Flow'
49 );
50
51 $this->packageManager->injectCoreCache($mockCache);
52 $this->inject($this->packageManager, 'composerNameToPackageKeyMap', $composerNameToPackageKeyMap);
53 $this->packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
54 $this->packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
55 $this->packageManager->initialize($mockBootstrap);
56 }
57
58 /**
59 * @param string $packageKey
60 * @return \TYPO3\CMS\Core\Package\Package
61 */
62 protected function createPackage($packageKey) {
63 $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
64 mkdir($packagePath, 0770, TRUE);
65 file_put_contents($packagePath . 'ext_emconf.php', '');
66 file_put_contents($packagePath . 'composer.json', '');
67 $package = new \TYPO3\CMS\Core\Package\Package($this->packageManager, $packageKey, $packagePath);
68 $this->packageManager->registerPackage($package);
69 $this->packageManager->activatePackage($packageKey);
70
71 return $package;
72 }
73
74 /**
75 * @test
76 */
77 public function getPackageReturnsTheSpecifiedPackage() {
78 $this->createPackage('TYPO3.Flow');
79 $package = $this->packageManager->getPackage('TYPO3.Flow');
80
81 $this->assertInstanceOf(\TYPO3\CMS\Core\Package\PackageInterface::class, $package, 'The result of getPackage() was no valid package object.');
82 }
83
84 /**
85 * @test
86 * @expectedException \TYPO3\CMS\Core\Package\Exception\UnknownPackageException
87 */
88 public function getPackageThrowsExceptionOnUnknownPackage() {
89 $this->packageManager->getPackage('PrettyUnlikelyThatThisPackageExists');
90 }
91
92
93 /**
94 * @test
95 */
96 public function scanAvailablePackagesTraversesThePackagesDirectoryAndRegistersPackagesItFinds() {
97 $expectedPackageKeys = array(
98 $this->getUniqueId('TYPO3.CMS'),
99 $this->getUniqueId('TYPO3.CMS.Test'),
100 $this->getUniqueId('TYPO3.YetAnotherTestPackage'),
101 $this->getUniqueId('Lolli.Pop.NothingElse')
102 );
103
104 foreach ($expectedPackageKeys as $packageKey) {
105 $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
106
107 mkdir($packagePath, 0770, TRUE);
108 mkdir($packagePath . 'Classes');
109 file_put_contents($packagePath . 'composer.json', '{"name": "' . $packageKey . '", "type": "typo3-test"}');
110 }
111
112 $packageManager = $this->getAccessibleMock(\TYPO3\CMS\Core\Package\PackageManager::class, array('sortAndSavePackageStates'));
113 $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
114 $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
115
116 $packageManager->_set('packages', array());
117 $packageManager->_call('scanAvailablePackages');
118
119 $packageStates = require('vfs://Test/Configuration/PackageStates.php');
120 $actualPackageKeys = array_keys($packageStates['packages']);
121 $this->assertEquals(sort($expectedPackageKeys), sort($actualPackageKeys));
122 }
123
124 /**
125 * @test
126 */
127 public function scanAvailablePackagesKeepsExistingPackageConfiguration() {
128 $expectedPackageKeys = array(
129 $this->getUniqueId('TYPO3.CMS'),
130 $this->getUniqueId('TYPO3.CMS.Test'),
131 $this->getUniqueId('TYPO3.YetAnotherTestPackage'),
132 $this->getUniqueId('Lolli.Pop.NothingElse')
133 );
134
135 foreach ($expectedPackageKeys as $packageKey) {
136 $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
137
138 mkdir($packagePath, 0770, TRUE);
139 mkdir($packagePath . 'Classes');
140 file_put_contents($packagePath . 'composer.json', '{"name": "' . $packageKey . '", "type": "typo3-cms-test"}');
141 file_put_contents($packagePath . 'ext_emconf.php', '');
142 }
143
144 $packageManager = $this->getAccessibleMock(\TYPO3\CMS\Core\Package\PackageManager::class, array('dummy'));
145 $packageManager->_set('packagesBasePaths', array('local' => 'vfs://Test/Packages/Application'));
146 $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
147 $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
148
149 $dependencyResolver = $this->getMock(\TYPO3\CMS\Core\Package\DependencyResolver::class, array('dummy'));
150 $packageManager->injectDependencyResolver($dependencyResolver);
151
152 $packageManager->_set('packageStatesConfiguration', array(
153 'packages' => array(
154 $packageKey => array(
155 'state' => 'inactive',
156 'packagePath' => 'Application/' . $packageKey . '/'
157 )
158 ),
159 'version' => 4
160 ));
161 $packageManager->_call('scanAvailablePackages');
162 $packageManager->_call('sortAndSavePackageStates');
163
164 $packageStates = require('vfs://Test/Configuration/PackageStates.php');
165 $this->assertEquals('inactive', $packageStates['packages'][$packageKey]['state']);
166 }
167
168
169 /**
170 * @test
171 */
172 public function packageStatesConfigurationContainsRelativePaths() {
173 $packageKeys = array(
174 $this->getUniqueId('Lolli.Pop.NothingElse'),
175 $this->getUniqueId('TYPO3.Package'),
176 $this->getUniqueId('TYPO3.YetAnotherTestPackage')
177 );
178
179 foreach ($packageKeys as $packageKey) {
180 $packagePath = 'vfs://Test/Packages/Application/' . $packageKey . '/';
181
182 mkdir($packagePath, 0770, TRUE);
183 mkdir($packagePath . 'Classes');
184 file_put_contents($packagePath . 'composer.json', '{"name": "' . $packageKey . '", "type": "typo3-cms-test"}');
185 file_put_contents($packagePath . 'ext_emconf.php', '');
186 }
187
188 $packageManager = $this->getAccessibleMock(\TYPO3\CMS\Core\Package\PackageManager::class, array('dummy'));
189 $packageManager->_set('packagesBasePaths', array('local' => 'vfs://Test/Packages/Application'));
190 $packageManager->_set('packagesBasePath', 'vfs://Test/Packages/');
191 $packageManager->_set('packageStatesPathAndFilename', 'vfs://Test/Configuration/PackageStates.php');
192
193 $dependencyResolver = $this->getMock(\TYPO3\CMS\Core\Package\DependencyResolver::class, array('dummy'));
194 $packageManager->injectDependencyResolver($dependencyResolver);
195
196 $packageManager->_set('packages', array());
197 $packageManager->_call('scanAvailablePackages');
198
199 $expectedPackageStatesConfiguration = array();
200 foreach ($packageKeys as $packageKey) {
201 $expectedPackageStatesConfiguration[$packageKey] = array(
202 'state' => 'inactive',
203 'packagePath' => 'Application/' . $packageKey . '/',
204 'composerName' => $packageKey,
205 'suggestions' => array(),
206 );
207 }
208
209 $actualPackageStatesConfiguration = $packageManager->_get('packageStatesConfiguration');
210 $this->assertEquals($expectedPackageStatesConfiguration, $actualPackageStatesConfiguration['packages']);
211 }
212
213 /**
214 * Data Provider returning valid package keys and the corresponding path
215 *
216 * @return array
217 */
218 public function packageKeysAndPaths() {
219 return array(
220 array('TYPO3.YetAnotherTestPackage', 'vfs://Test/Packages/Application/TYPO3.YetAnotherTestPackage/'),
221 array('Lolli.Pop.NothingElse', 'vfs://Test/Packages/Application/Lolli.Pop.NothingElse/')
222 );
223 }
224
225 /**
226 * @test
227 * @dataProvider packageKeysAndPaths
228 */
229 public function createPackageCreatesPackageFolderAndReturnsPackage($packageKey, $expectedPackagePath) {
230 $actualPackage = $this->createPackage($packageKey);
231 $actualPackagePath = $actualPackage->getPackagePath();
232
233 $this->assertEquals($expectedPackagePath, $actualPackagePath);
234 $this->assertTrue(is_dir($actualPackagePath), 'Package path should exist after createPackage()');
235 $this->assertEquals($packageKey, $actualPackage->getPackageKey());
236 $this->assertTrue($this->packageManager->isPackageAvailable($packageKey));
237 }
238
239 /**
240 * @test
241 */
242 public function activatePackageAndDeactivatePackageActivateAndDeactivateTheGivenPackage() {
243 $packageKey = 'Acme.YetAnotherTestPackage';
244
245 $this->createPackage($packageKey);
246
247 $this->packageManager->deactivatePackage($packageKey);
248 $this->assertFalse($this->packageManager->isPackageActive($packageKey));
249
250 $this->packageManager->activatePackage($packageKey);
251 $this->assertTrue($this->packageManager->isPackageActive($packageKey));
252 }
253
254 /**
255 * @test
256 * @expectedException \TYPO3\CMS\Core\Package\Exception\ProtectedPackageKeyException
257 */
258 public function deactivatePackageThrowsAnExceptionIfPackageIsProtected() {
259 $package = $this->createPackage('Acme.YetAnotherTestPackage');
260 $package->setProtected(TRUE);
261 $this->packageManager->deactivatePackage('Acme.YetAnotherTestPackage');
262 }
263
264 /**
265 * @test
266 * @expectedException \TYPO3\CMS\Core\Package\Exception\UnknownPackageException
267 */
268 public function deletePackageThrowsErrorIfPackageIsNotAvailable() {
269 $this->packageManager->deletePackage('PrettyUnlikelyThatThisPackageExists');
270 }
271
272 /**
273 * @test
274 * @expectedException \TYPO3\CMS\Core\Package\Exception\ProtectedPackageKeyException
275 */
276 public function deletePackageThrowsAnExceptionIfPackageIsProtected() {
277 $package = $this->createPackage('Acme.YetAnotherTestPackage');
278 $package->setProtected(TRUE);
279 $this->packageManager->deletePackage('Acme.YetAnotherTestPackage');
280 }
281
282 /**
283 * @test
284 */
285 public function deletePackageRemovesPackageFromAvailableAndActivePackagesAndDeletesThePackageDirectory() {
286 $this->createPackage('Acme.YetAnotherTestPackage');
287
288 $this->assertTrue($this->packageManager->isPackageActive('Acme.YetAnotherTestPackage'));
289 $this->assertTrue($this->packageManager->isPackageAvailable('Acme.YetAnotherTestPackage'));
290
291 $this->packageManager->deletePackage('Acme.YetAnotherTestPackage');
292
293 $this->assertFalse($this->packageManager->isPackageActive('Acme.YetAnotherTestPackage'));
294 $this->assertFalse($this->packageManager->isPackageAvailable('Acme.YetAnotherTestPackage'));
295 }
296
297 /**
298 * @return array
299 */
300 public function composerNamesAndPackageKeys() {
301 return array(
302 array('imagine/Imagine', 'imagine.Imagine'),
303 array('imagine/imagine', 'imagine.Imagine'),
304 array('typo3/cms', 'TYPO3.CMS'),
305 array('TYPO3/CMS', 'TYPO3.CMS')
306 );
307 }
308
309 /**
310 * @test
311 * @dataProvider composerNamesAndPackageKeys
312 */
313 public function getPackageKeyFromComposerNameIgnoresCaseDifferences($composerName, $packageKey) {
314 $packageStatesConfiguration = array('packages' =>
315 array(
316 'TYPO3.CMS' => array(
317 'composerName' => 'typo3/cms'
318 ),
319 'imagine.Imagine' => array(
320 'composerName' => 'imagine/Imagine'
321 )
322 )
323 );
324
325 $packageManager = $this->getAccessibleMock(\TYPO3\CMS\Core\Package\PackageManager::class, array('resolvePackageDependencies'));
326 $packageManager->_set('packageStatesConfiguration', $packageStatesConfiguration);
327
328 $this->assertEquals($packageKey, $packageManager->_call('getPackageKeyFromComposerName', $composerName));
329 }
330
331 }