[TASK] Use Environment API instead of PATH_site in install
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Tests / Unit / FolderStructure / LinkNodeTest.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Install\Tests\Unit\FolderStructure;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17
18 use TYPO3\CMS\Core\Core\Environment;
19 use TYPO3\CMS\Core\Messaging\FlashMessage;
20 use TYPO3\CMS\Install\FolderStructure\Exception\InvalidArgumentException;
21 use TYPO3\CMS\Install\FolderStructure\LinkNode;
22 use TYPO3\CMS\Install\FolderStructure\NodeInterface;
23 use TYPO3\CMS\Install\FolderStructure\RootNodeInterface;
24 use TYPO3\TestingFramework\Core\AccessibleObjectInterface;
25 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
26
27 /**
28 * Test case
29 */
30 class LinkNodeTest extends UnitTestCase
31 {
32 /**
33 * @test
34 */
35 public function constructorThrowsExceptionIfParentIsNull()
36 {
37 $this->expectException(InvalidArgumentException::class);
38 $this->expectExceptionCode(1380485700);
39 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
40 $node = $this->getAccessibleMock(LinkNode::class, ['dummy'], [], '', false);
41 $node->__construct([], null);
42 }
43
44 /**
45 * @test
46 */
47 public function constructorThrowsExceptionIfNameContainsForwardSlash()
48 {
49 $this->expectException(InvalidArgumentException::class);
50 $this->expectExceptionCode(1380546061);
51 $parent = $this->createMock(NodeInterface::class);
52 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
53 $node = $this->getAccessibleMock(LinkNode::class, ['dummy'], [], '', false);
54 $structure = [
55 'name' => 'foo/bar',
56 ];
57 $node->__construct($structure, $parent);
58 }
59
60 /**
61 * @test
62 */
63 public function constructorSetsParent()
64 {
65 $parent = $this->createMock(NodeInterface::class);
66 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
67 $node = $this->getAccessibleMock(LinkNode::class, ['dummy'], [], '', false);
68 $structure = [
69 'name' => 'foo',
70 ];
71 $node->__construct($structure, $parent);
72 $this->assertSame($parent, $node->_call('getParent'));
73 }
74
75 /**
76 * @test
77 */
78 public function constructorSetsName()
79 {
80 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
81 $node = $this->getAccessibleMock(LinkNode::class, ['dummy'], [], '', false);
82 $parent = $this->createMock(RootNodeInterface::class);
83 $name = $this->getUniqueId('test_');
84 $node->__construct(['name' => $name], $parent);
85 $this->assertSame($name, $node->getName());
86 }
87
88 /**
89 * @test
90 */
91 public function constructorSetsNameAndTarget()
92 {
93 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
94 $node = $this->getAccessibleMock(LinkNode::class, ['dummy'], [], '', false);
95 $parent = $this->createMock(RootNodeInterface::class);
96 $name = $this->getUniqueId('test_');
97 $target = '../' . $this->getUniqueId('test_');
98 $node->__construct(['name' => $name, 'target' => $target], $parent);
99 $this->assertSame($target, $node->_call('getTarget'));
100 }
101
102 /**
103 * @test
104 */
105 public function getStatusReturnsArray()
106 {
107 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
108 $node = $this->getAccessibleMock(
109 LinkNode::class,
110 ['isWindowsOs', 'getAbsolutePath', 'exists'],
111 [],
112 '',
113 false
114 );
115 $path = Environment::getVarPath() . '/tests/' . $this->getUniqueId('dir_');
116 $node->expects($this->any())->method('getAbsolutePath')->will($this->returnValue($path));
117 $this->assertInternalType('array', $node->getStatus());
118 }
119
120 /**
121 * @test
122 */
123 public function getStatusReturnsArrayWithInformationStatusIfRunningOnWindows()
124 {
125 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
126 $node = $this->getAccessibleMock(
127 LinkNode::class,
128 ['isWindowsOs', 'getAbsolutePath', 'exists'],
129 [],
130 '',
131 false
132 );
133 $path = Environment::getVarPath() . '/tests/' . $this->getUniqueId('dir_');
134 $node->expects($this->any())->method('getAbsolutePath')->will($this->returnValue($path));
135 $node->expects($this->once())->method('isWindowsOs')->will($this->returnValue(true));
136 $statusArray = $node->getStatus();
137 $this->assertSame(FlashMessage::INFO, $statusArray[0]->getSeverity());
138 }
139
140 /**
141 * @test
142 */
143 public function getStatusReturnsArrayWithErrorStatusIfLinkNotExists()
144 {
145 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
146 $node = $this->getAccessibleMock(
147 LinkNode::class,
148 ['isWindowsOs', 'getAbsolutePath', 'exists'],
149 [],
150 '',
151 false
152 );
153 $path = Environment::getVarPath() . '/tests/' . $this->getUniqueId('dir_');
154 $node->expects($this->any())->method('getAbsolutePath')->will($this->returnValue($path));
155 $node->expects($this->any())->method('isWindowsOs')->will($this->returnValue(false));
156 $node->expects($this->once())->method('exists')->will($this->returnValue(false));
157 $statusArray = $node->getStatus();
158 $this->assertSame(FlashMessage::ERROR, $statusArray[0]->getSeverity());
159 }
160
161 /**
162 * @test
163 */
164 public function getStatusReturnsArrayWithWarningStatusIfNodeIsNotALink()
165 {
166 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
167 $node = $this->getAccessibleMock(
168 LinkNode::class,
169 ['isWindowsOs', 'getAbsolutePath', 'exists', 'isLink', 'getRelativePathBelowSiteRoot'],
170 [],
171 '',
172 false
173 );
174 $node->expects($this->any())->method('getAbsolutePath')->will($this->returnValue(''));
175 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
176 $node->expects($this->once())->method('isLink')->will($this->returnValue(false));
177 $statusArray = $node->getStatus();
178 $this->assertSame(FlashMessage::WARNING, $statusArray[0]->getSeverity());
179 }
180
181 /**
182 * @test
183 */
184 public function getStatusReturnsErrorStatusIfLinkTargetIsNotCorrect()
185 {
186 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
187 $node = $this->getAccessibleMock(
188 LinkNode::class,
189 ['isWindowsOs', 'getAbsolutePath', 'exists', 'isLink', 'isTargetCorrect', 'getCurrentTarget', 'getRelativePathBelowSiteRoot'],
190 [],
191 '',
192 false
193 );
194 $node->expects($this->any())->method('getAbsolutePath')->will($this->returnValue(''));
195 $node->expects($this->any())->method('getCurrentTarget')->will($this->returnValue(''));
196 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
197 $node->expects($this->any())->method('isLink')->will($this->returnValue(true));
198 $node->expects($this->once())->method('isLink')->will($this->returnValue(false));
199 $statusArray = $node->getStatus();
200 $this->assertSame(FlashMessage::ERROR, $statusArray[0]->getSeverity());
201 }
202
203 /**
204 * @test
205 */
206 public function getStatusReturnsOkStatusIfLinkExistsAndTargetIsCorrect()
207 {
208 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
209 $node = $this->getAccessibleMock(
210 LinkNode::class,
211 ['isWindowsOs', 'getAbsolutePath', 'exists', 'isLink', 'isTargetCorrect', 'getRelativePathBelowSiteRoot'],
212 [],
213 '',
214 false
215 );
216 $node->expects($this->any())->method('getAbsolutePath')->will($this->returnValue(''));
217 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
218 $node->expects($this->once())->method('isLink')->will($this->returnValue(true));
219 $node->expects($this->once())->method('isTargetCorrect')->will($this->returnValue(true));
220 $node->expects($this->once())->method('getRelativePathBelowSiteRoot')->will($this->returnValue(''));
221 $statusArray = $node->getStatus();
222 $this->assertSame(FlashMessage::OK, $statusArray[0]->getSeverity());
223 }
224
225 /**
226 * @test
227 */
228 public function fixReturnsEmptyArray()
229 {
230 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
231 $node = $this->getAccessibleMock(
232 LinkNode::class,
233 ['getRelativePathBelowSiteRoot'],
234 [],
235 '',
236 false
237 );
238 $statusArray = $node->fix();
239 $this->assertEmpty($statusArray);
240 }
241
242 /**
243 * @test
244 */
245 public function isLinkThrowsExceptionIfLinkNotExists()
246 {
247 $this->expectException(InvalidArgumentException::class);
248 $this->expectExceptionCode(1380556246);
249 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
250 $node = $this->getAccessibleMock(LinkNode::class, ['exists'], [], '', false);
251 $node->expects($this->once())->method('exists')->will($this->returnValue(false));
252 $this->assertFalse($node->_call('isLink'));
253 }
254
255 /**
256 * @test
257 */
258 public function isLinkReturnsTrueIfNameIsLink()
259 {
260 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
261 $node = $this->getAccessibleMock(LinkNode::class, ['exists', 'getAbsolutePath'], [], '', false);
262 $path = Environment::getVarPath() . '/tests/' . $this->getUniqueId('link_');
263 $target = Environment::getVarPath() . '/tests/' . $this->getUniqueId('linkTarget_');
264 touch($target);
265 symlink($target, $path);
266 $this->testFilesToDelete[] = $path;
267 $this->testFilesToDelete[] = $target;
268 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
269 $node->expects($this->any())->method('getAbsolutePath')->will($this->returnValue($path));
270 $this->assertTrue($node->_call('isLink'));
271 }
272
273 /**
274 * @test
275 */
276 public function isFileReturnsFalseIfNameIsAFile()
277 {
278 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
279 $node = $this->getAccessibleMock(LinkNode::class, ['exists', 'getAbsolutePath'], [], '', false);
280 $path = Environment::getVarPath() . '/tests/' . $this->getUniqueId('file_');
281 touch($path);
282 $this->testFilesToDelete[] = $path;
283 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
284 $node->expects($this->any())->method('getAbsolutePath')->will($this->returnValue($path));
285 $this->assertFalse($node->_call('isLink'));
286 }
287
288 /**
289 * @test
290 */
291 public function isTargetCorrectThrowsExceptionIfLinkNotExists()
292 {
293 $this->expectException(InvalidArgumentException::class);
294 $this->expectExceptionCode(1380556245);
295 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
296 $node = $this->getAccessibleMock(LinkNode::class, ['exists'], [], '', false);
297 $node->expects($this->once())->method('exists')->will($this->returnValue(false));
298 $this->assertFalse($node->_call('isTargetCorrect'));
299 }
300
301 /**
302 * @test
303 */
304 public function isTargetCorrectThrowsExceptionIfNodeIsNotALink()
305 {
306 $this->expectException(InvalidArgumentException::class);
307 $this->expectExceptionCode(1380556247);
308 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
309 $node = $this->getAccessibleMock(LinkNode::class, ['exists', 'isLink', 'getTarget'], [], '', false);
310 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
311 $node->expects($this->once())->method('isLink')->will($this->returnValue(false));
312 $this->assertTrue($node->_call('isTargetCorrect'));
313 }
314
315 /**
316 * @test
317 */
318 public function isTargetCorrectReturnsTrueIfNoExpectedLinkTargetIsSpecified()
319 {
320 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
321 $node = $this->getAccessibleMock(LinkNode::class, ['exists', 'isLink', 'getTarget'], [], '', false);
322 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
323 $node->expects($this->any())->method('isLink')->will($this->returnValue(true));
324 $node->expects($this->once())->method('getTarget')->will($this->returnValue(''));
325 $this->assertTrue($node->_call('isTargetCorrect'));
326 }
327
328 /**
329 * @test
330 */
331 public function isTargetCorrectAcceptsATargetWithATrailingSlash()
332 {
333 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
334 $node = $this->getAccessibleMock(LinkNode::class, ['exists', 'isLink', 'getCurrentTarget', 'getTarget'], [], '', false);
335 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
336 $node->expects($this->any())->method('isLink')->will($this->returnValue(true));
337 $node->expects($this->once())->method('getCurrentTarget')->will($this->returnValue('someLinkTarget/'));
338 $node->expects($this->once())->method('getTarget')->will($this->returnValue('someLinkTarget'));
339 $this->assertTrue($node->_call('isTargetCorrect'));
340 }
341
342 /**
343 * @test
344 * @see https://github.com/mikey179/vfsStream/wiki/Known-Issues - symlink doesn't work with vfsStream
345 */
346 public function isTargetCorrectReturnsTrueIfActualTargetIsIdenticalToSpecifiedTarget()
347 {
348 $path = Environment::getVarPath() . '/tests/' . $this->getUniqueId('link_');
349 $target = Environment::getVarPath() . '/tests/' . $this->getUniqueId('linkTarget_');
350 touch($target);
351 symlink($target, $path);
352 $this->testFilesToDelete[] = $path;
353 $this->testFilesToDelete[] = $target;
354 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
355 $node = $this->getAccessibleMock(
356 LinkNode::class,
357 ['exists', 'isLink', 'getTarget', 'getAbsolutePath'],
358 [],
359 '',
360 false
361 );
362 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
363 $node->expects($this->any())->method('isLink')->will($this->returnValue(true));
364 $node->expects($this->once())->method('getTarget')->will($this->returnValue(str_replace('/', DIRECTORY_SEPARATOR, $target)));
365 $node->expects($this->once())->method('getAbsolutePath')->will($this->returnValue($path));
366 $this->assertTrue($node->_call('isTargetCorrect'));
367 }
368
369 /**
370 * @test
371 * @see https://github.com/mikey179/vfsStream/wiki/Known-Issues - symlink doesn't work with vfsStream
372 */
373 public function isTargetCorrectReturnsFalseIfActualTargetIsNotIdenticalToSpecifiedTarget()
374 {
375 $path = Environment::getVarPath() . '/tests/' . $this->getUniqueId('link_');
376 $target = Environment::getVarPath() . '/tests/' . $this->getUniqueId('linkTarget_');
377 touch($target);
378 symlink($target, $path);
379 $this->testFilesToDelete[] = $path;
380 $this->testFilesToDelete[] = $target;
381 /** @var $node LinkNode|AccessibleObjectInterface|\PHPUnit_Framework_MockObject_MockObject */
382 $node = $this->getAccessibleMock(
383 LinkNode::class,
384 ['exists', 'isLink', 'getTarget', 'getAbsolutePath'],
385 [],
386 '',
387 false
388 );
389 $node->expects($this->any())->method('exists')->will($this->returnValue(true));
390 $node->expects($this->any())->method('isLink')->will($this->returnValue(true));
391 $node->expects($this->once())->method('getTarget')->will($this->returnValue('foo'));
392 $node->expects($this->once())->method('getAbsolutePath')->will($this->returnValue($path));
393 $this->assertFalse($node->_call('isTargetCorrect'));
394 }
395 }