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