8fdd0dde67ba405746d1c25508c77adb1c993f8c
[Packages/TYPO3.CMS.git] / typo3 / sysext / extensionmanager / Tests / Unit / Utility / FileHandlingUtilityTest.php
1 <?php
2 namespace TYPO3\CMS\Extensionmanager\Tests\Unit\Utility;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * Testcase
19 *
20 */
21 class FileHandlingUtilityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
22
23 /**
24 * @var array List of created fake extensions to be deleted in tearDown() again
25 */
26 protected $fakedExtensions = array();
27
28 /**
29 * @var array List of resources (files or empty directories) that need to be removed in tearDown() again
30 */
31 protected $resourcesToRemove = array();
32
33 /**
34 * @return void
35 */
36 public function tearDown() {
37 foreach ($this->fakedExtensions as $extension => $dummy) {
38 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir(PATH_site . 'typo3conf/ext/' . $extension, TRUE);
39 }
40 foreach ($this->resourcesToRemove as $resource) {
41 if (file_exists($resource) && is_file($resource)) {
42 unlink($resource);
43 } elseif(file_exists($resource) && is_dir($resource)) {
44 rmdir($resource);
45 }
46 }
47 parent::tearDown();
48 }
49
50 /**
51 * Creates a fake extension inside typo3temp/. No configuration is created,
52 * just the folder
53 *
54 * @param bool $extkeyOnly
55 * @return string The extension key
56 */
57 protected function createFakeExtension($extkeyOnly = FALSE) {
58 $extKey = strtolower(uniqid('testing'));
59 $absExtPath = PATH_site . 'typo3conf/ext/' . $extKey . '/';
60 $relPath = 'typo3conf/ext/' . $extKey . '/';
61 $this->fakedExtensions[$extKey] = array(
62 'siteRelPath' => $relPath,
63 'siteAbsPath' => $absExtPath
64 );
65 if ($extkeyOnly === TRUE) {
66 return $extKey;
67 }
68 \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir($absExtPath);
69 return $extKey;
70 }
71
72 /**
73 * @test
74 * @return void
75 */
76 public function makeAndClearExtensionDirRemovesExtensionDirIfAlreadyExists() {
77 $extKey = $this->createFakeExtension();
78 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('removeDirectory', 'addDirectory'), array(), '', FALSE);
79 $fileHandlerMock->expects($this->once())->method('removeDirectory')->with(PATH_site . 'typo3conf/ext/' . $extKey . '/');
80 $fileHandlerMock->_call('makeAndClearExtensionDir', $extKey);
81 }
82
83 /**
84 * @return array
85 */
86 public function invalidRelativePathDataProvider() {
87 return array(
88 array('../../'),
89 array('/foo/bar'),
90 array('foo//bar'),
91 array('foo/bar' . chr(0)),
92 );
93 }
94
95 /**
96 * @param string $invalidRelativePath
97 * @test
98 * @dataProvider invalidRelativePathDataProvider
99 * @expectedException \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
100 */
101 public function getAbsolutePathThrowsExceptionForInvalidRelativePaths($invalidRelativePath) {
102 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('dummy'), array());
103 $fileHandlerMock->_call('getAbsolutePath', $invalidRelativePath);
104 }
105
106 /**
107 * @return array
108 */
109 public function validRelativePathDataProvider() {
110 return array(
111 array('foo/../bar', PATH_site . 'bar'),
112 array('bas', PATH_site . 'bas'),
113 );
114 }
115
116 /**
117 * @param string $validRelativePath
118 * @param string $expectedAbsolutePath
119 * @test
120 * @dataProvider validRelativePathDataProvider
121 */
122 public function getAbsolutePathReturnsAbsolutePathForValidRelativePaths($validRelativePath, $expectedAbsolutePath) {
123 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('dummy'));
124 $this->assertSame($expectedAbsolutePath, $fileHandlerMock->_call('getAbsolutePath', $validRelativePath));
125 }
126
127 /**
128 * @test
129 * @return void
130 */
131 public function makeAndClearExtensionDirAddsDir() {
132 $extKey = $this->createFakeExtension();
133 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('removeDirectory', 'addDirectory'));
134 $fileHandlerMock->expects($this->once())->method('addDirectory')->with(PATH_site . 'typo3conf/ext/' . $extKey . '/');
135 $fileHandlerMock->_call('makeAndClearExtensionDir', $extKey);
136 }
137
138 /**
139 * @test
140 * @expectedException \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
141 * @return void
142 */
143 public function makeAndClearExtensionDirThrowsExceptionOnInvalidPath() {
144 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('removeDirectory', 'addDirectory'));
145 $languageServiceMock = $this->getMock('TYPO3\\CMS\\Lang\\LanguageService');
146 $fileHandlerMock->_set('languageService', $languageServiceMock);
147 $fileHandlerMock->_call('makeAndClearExtensionDir', 'testing123', 'fakepath');
148 }
149
150 /**
151 * @test
152 * @return void
153 */
154 public function addDirectoryAddsDirectory() {
155 $extDirPath = $this->fakedExtensions[$this->createFakeExtension(TRUE)]['siteAbsPath'];
156 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('dummy'));
157 $this->assertFalse(is_dir($extDirPath));
158 $fileHandlerMock->_call('addDirectory', $extDirPath);
159 $this->assertTrue(is_dir($extDirPath));
160 }
161
162 /**
163 * @test
164 * @return void
165 */
166 public function removeDirectoryRemovesDirectory() {
167 $extDirPath = $this->fakedExtensions[$this->createFakeExtension()]['siteAbsPath'];
168 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('dummy'));
169 $this->assertTrue(is_dir($extDirPath));
170 $fileHandlerMock->_call('removeDirectory', $extDirPath);
171 $this->assertFalse(is_dir($extDirPath));
172 }
173
174 /**
175 * @test
176 * @return void
177 */
178 public function removeDirectoryRemovesSymlink() {
179 $absoluteSymlinkPath = PATH_site . 'typo3temp/' . uniqid('test_symlink_');
180 $absoluteFilePath = PATH_site . 'typo3temp/' . uniqid('test_file_');
181 touch($absoluteFilePath);
182 $this->resourcesToRemove[] = $absoluteFilePath;
183 symlink($absoluteFilePath, $absoluteSymlinkPath);
184 $fileHandler = new \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility();
185 $fileHandler->removeDirectory($absoluteSymlinkPath);
186 $this->assertFalse(is_link($absoluteSymlinkPath));
187 }
188
189 /**
190 * @test
191 * @return void
192 */
193 public function removeDirectoryDoesNotRemoveContentOfSymlinkedTargetDirectory() {
194 $absoluteSymlinkPath = PATH_site . 'typo3temp/' . uniqid('test_symlink_');
195 $absoluteDirectoryPath = PATH_site . 'typo3temp/' . uniqid('test_dir_') . '/';
196 $relativeFilePath = uniqid('test_file_');
197
198 mkdir($absoluteDirectoryPath);
199 touch($absoluteDirectoryPath . $relativeFilePath);
200
201 $this->resourcesToRemove[] = $absoluteDirectoryPath . $relativeFilePath;
202 $this->resourcesToRemove[] = $absoluteDirectoryPath;
203
204 symlink($absoluteDirectoryPath, $absoluteSymlinkPath);
205
206 $fileHandler = new \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility();
207 $fileHandler->removeDirectory($absoluteSymlinkPath);
208 $this->assertTrue(is_file($absoluteDirectoryPath . $relativeFilePath));
209 }
210
211 /**
212 * @test
213 * @return void
214 */
215 public function unpackExtensionFromExtensionDataArrayCreatesTheExtensionDirectory() {
216 $extensionData = array(
217 'extKey' => 'test'
218 );
219 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array(
220 'makeAndClearExtensionDir',
221 'writeEmConfToFile',
222 'extractFilesArrayFromExtensionData',
223 'extractDirectoriesFromExtensionData',
224 'createDirectoriesForExtensionFiles',
225 'writeExtensionFiles'
226 ));
227 $fileHandlerMock->expects($this->once())->method('extractFilesArrayFromExtensionData')->will($this->returnValue(array()));
228 $fileHandlerMock->expects($this->once())->method('extractDirectoriesFromExtensionData')->will($this->returnValue(array()));
229 $fileHandlerMock->expects($this->once())->method('makeAndClearExtensionDir')->with($extensionData['extKey']);
230 $fileHandlerMock->_call('unpackExtensionFromExtensionDataArray', $extensionData);
231 }
232
233 /**
234 * @test
235 * @return void
236 */
237 public function unpackExtensionFromExtensionDataArrayStripsDirectoriesFromFilesArray() {
238 $extensionData = array(
239 'extKey' => 'test'
240 );
241 $files = array(
242 'ChangeLog' => array(
243 'name' => 'ChangeLog',
244 'size' => 4559,
245 'mtime' => 1219448527,
246 'is_executable' => FALSE,
247 'content' => 'some content to write'
248 ),
249 'doc/' => array(
250 'name' => 'doc/',
251 'size' => 0,
252 'mtime' => 1219448527,
253 'is_executable' => FALSE,
254 'content' => ''
255 ),
256 'doc/ChangeLog' => array(
257 'name' => 'ChangeLog',
258 'size' => 4559,
259 'mtime' => 1219448527,
260 'is_executable' => FALSE,
261 'content' => 'some content to write'
262 ),
263 );
264 $cleanedFiles = array(
265 'ChangeLog' => array(
266 'name' => 'ChangeLog',
267 'size' => 4559,
268 'mtime' => 1219448527,
269 'is_executable' => FALSE,
270 'content' => 'some content to write'
271 ),
272 'doc/ChangeLog' => array(
273 'name' => 'ChangeLog',
274 'size' => 4559,
275 'mtime' => 1219448527,
276 'is_executable' => FALSE,
277 'content' => 'some content to write'
278 ),
279 );
280 $directories = array(
281 'doc/',
282 'mod/doc/'
283 );
284
285 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array(
286 'makeAndClearExtensionDir',
287 'writeEmConfToFile',
288 'extractFilesArrayFromExtensionData',
289 'extractDirectoriesFromExtensionData',
290 'createDirectoriesForExtensionFiles',
291 'writeExtensionFiles'
292 ));
293 $fileHandlerMock->expects($this->once())->method('extractFilesArrayFromExtensionData')->will($this->returnValue($files));
294 $fileHandlerMock->expects($this->once())->method('extractDirectoriesFromExtensionData')->will($this->returnValue($directories));
295 $fileHandlerMock->expects($this->once())->method('createDirectoriesForExtensionFiles')->with($directories);
296 $fileHandlerMock->expects($this->once())->method('writeExtensionFiles')->with($cleanedFiles);
297 $fileHandlerMock->_call('unpackExtensionFromExtensionDataArray', $extensionData);
298 }
299
300 /**
301 * @test
302 * @return void
303 */
304 public function extractFilesArrayFromExtensionDataReturnsFileArray() {
305 $extensionData = array(
306 'key' => 'test',
307 'FILES' => array(
308 'filename1' => 'dummycontent',
309 'filename2' => 'dummycontent2'
310 )
311 );
312 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
313 $extractedFiles = $fileHandlerMock->_call('extractFilesArrayFromExtensionData', $extensionData);
314 $this->assertArrayHasKey('filename1', $extractedFiles);
315 $this->assertArrayHasKey('filename2', $extractedFiles);
316 }
317
318 /**
319 * @test
320 * @return void
321 */
322 public function writeExtensionFilesWritesFiles() {
323 $files = array(
324 'ChangeLog' => array(
325 'name' => 'ChangeLog',
326 'size' => 4559,
327 'mtime' => 1219448527,
328 'is_executable' => FALSE,
329 'content' => 'some content to write'
330 ),
331 'README' => array(
332 'name' => 'README',
333 'size' => 4566,
334 'mtime' => 1219448533,
335 'is_executable' => FALSE,
336 'content' => 'FEEL FREE TO ADD SOME DOCUMENTATION HERE'
337 )
338 );
339 $rootPath = ($extDirPath = $this->fakedExtensions[$this->createFakeExtension()]['siteAbsPath']);
340 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
341 $fileHandlerMock->_call('writeExtensionFiles', $files, $rootPath);
342 $this->assertTrue(file_exists($rootPath . 'ChangeLog'));
343 }
344
345 /**
346 * @test
347 * @return void
348 */
349 public function extractDirectoriesFromExtensionDataExtractsDirectories() {
350 $files = array(
351 'ChangeLog' => array(
352 'name' => 'ChangeLog',
353 'size' => 4559,
354 'mtime' => 1219448527,
355 'is_executable' => FALSE,
356 'content' => 'some content to write'
357 ),
358 'doc/' => array(
359 'name' => 'doc/',
360 'size' => 0,
361 'mtime' => 1219448527,
362 'is_executable' => FALSE,
363 'content' => ''
364 ),
365 'doc/ChangeLog' => array(
366 'name' => 'ChangeLog',
367 'size' => 4559,
368 'mtime' => 1219448527,
369 'is_executable' => FALSE,
370 'content' => 'some content to write'
371 ),
372 'doc/README' => array(
373 'name' => 'README',
374 'size' => 4566,
375 'mtime' => 1219448533,
376 'is_executable' => FALSE,
377 'content' => 'FEEL FREE TO ADD SOME DOCUMENTATION HERE'
378 ),
379 'mod/doc/README' => array(
380 'name' => 'README',
381 'size' => 4566,
382 'mtime' => 1219448533,
383 'is_executable' => FALSE,
384 'content' => 'FEEL FREE TO ADD SOME DOCUMENTATION HERE'
385 )
386 );
387 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
388 $extractedDirectories = $fileHandlerMock->_call('extractDirectoriesFromExtensionData', $files);
389 $expected = array(
390 'doc/',
391 'mod/doc/'
392 );
393 $this->assertSame($expected, array_values($extractedDirectories));
394 }
395
396 /**
397 * @test
398 * @return void
399 */
400 public function createDirectoriesForExtensionFilesCreatesDirectories() {
401 $rootPath = $this->fakedExtensions[$this->createFakeExtension()]['siteAbsPath'];
402 $directories = array(
403 'doc/',
404 'mod/doc/'
405 );
406 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
407 $this->assertFalse(is_dir($rootPath . 'doc/'));
408 $this->assertFalse(is_dir($rootPath . 'mod/doc/'));
409 $fileHandlerMock->_call('createDirectoriesForExtensionFiles', $directories, $rootPath);
410 $this->assertTrue(is_dir($rootPath . 'doc/'));
411 $this->assertTrue(is_dir($rootPath . 'mod/doc/'));
412 }
413
414 /**
415 * @test
416 * @return void
417 */
418 public function writeEmConfWritesEmConfFile() {
419 $extKey = $this->createFakeExtension();
420 $extensionData = array(
421 'extKey' => $extKey,
422 'EM_CONF' => array(
423 'title' => 'Plugin cache engine',
424 'description' => 'Provides an interface to cache plugin content elements based on 4.3 caching framework',
425 'category' => 'Frontend',
426 'shy' => 0
427 )
428 );
429 $rootPath = $this->fakedExtensions[$extKey]['siteAbsPath'];
430 $emConfUtilityMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\EmConfUtility', array('constructEmConf'));
431 $emConfUtilityMock->expects($this->once())->method('constructEmConf')->with($extensionData)->will($this->returnValue(var_export($extensionData['EM_CONF'], TRUE)));
432 $fileHandlerMock = $this->getAccessibleMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('makeAndClearExtensionDir'));
433 $fileHandlerMock->_set('emConfUtility', $emConfUtilityMock);
434 $fileHandlerMock->_call('writeEmConfToFile', $extensionData, $rootPath);
435 $this->assertTrue(file_exists($rootPath . 'ext_emconf.php'));
436 }
437
438 /**
439 * @return \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility
440 */
441 protected function getPreparedFileHandlingMockForDirectoryCreationTests() {
442 /** @var $fileHandlerMock \TYPO3\CMS\Extensionmanager\Utility\FileHandlingUtility|\PHPUnit_Framework_MockObject_MockObject */
443 $fileHandlerMock = $this->getMock('TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility', array('createNestedDirectory', 'getAbsolutePath', 'directoryExists'));
444 $fileHandlerMock->expects($this->any())
445 ->method('getAbsolutePath')
446 ->will($this->returnArgument(0));
447 return $fileHandlerMock;
448 }
449
450 /**
451 * @test
452 */
453 public function uploadFolderIsNotCreatedIfNotRequested() {
454 $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
455 $fileHandlerMock->expects($this->never())
456 ->method('createNestedDirectory');
457 $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
458 'key' => 'foo_bar',
459 'uploadfolder' => 0,
460 )
461 );
462 }
463
464 /**
465 * @test
466 */
467 public function additionalFoldersAreNotCreatedIfNotRequested() {
468 $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
469 $fileHandlerMock->expects($this->never())
470 ->method('createNestedDirectory');
471 $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
472 'key' => 'foo_bar',
473 'createDirs' => '',
474 )
475 );
476 }
477
478 /**
479 * @test
480 */
481 public function configuredUploadFolderIsCreatedIfRequested() {
482 $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
483 $fileHandlerMock->expects($this->once())
484 ->method('createNestedDirectory')
485 ->with('uploads/tx_foobar/');
486 $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
487 'key' => 'foo_bar',
488 'uploadfolder' => 1,
489 )
490 );
491 }
492
493 /**
494 * @test
495 */
496 public function configuredAdditionalDirectoriesAreCreatedIfRequested() {
497 $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
498 $fileHandlerMock->expects($this->exactly(2))
499 ->method('createNestedDirectory')
500 ->will($this->returnCallback(function($path) {
501 if (!in_array($path, array('foo/bar', 'baz/foo'))) {
502 throw new \Exception('Path "' . $path . '" is not expected to be created');
503 }
504
505 })
506 );
507 $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
508 'key' => 'foo_bar',
509 'createDirs' => 'foo/bar, baz/foo',
510 )
511 );
512 }
513
514 /**
515 * @test
516 */
517 public function configuredDirectoriesAreNotCreatedIfTheyAlreadyExist() {
518 $fileHandlerMock = $this->getPreparedFileHandlingMockForDirectoryCreationTests();
519 $fileHandlerMock->expects($this->exactly(3))
520 ->method('directoryExists')
521 ->will($this->returnValue(TRUE));
522 $fileHandlerMock->expects($this->never())
523 ->method('createNestedDirectory');
524 $fileHandlerMock->ensureConfiguredDirectoriesExist(array(
525 'key' => 'foo_bar',
526 'uploadfolder' => 1,
527 'createDirs' => 'foo/bar, baz/foo',
528 )
529 );
530 }
531
532 /**
533 * Warning: This test asserts multiple things at once to keep the setup short.
534 *
535 * @test
536 */
537 public function createZipFileFromExtensionGeneratesCorrectArchive() {
538 // Create extension for testing:
539 $extKey = $this->createFakeExtension();
540 $extensionRoot = $this->fakedExtensions[$extKey]['siteAbsPath'];
541
542 // Build mocked fileHandlingUtility:
543 $fileHandlerMock = $this->getAccessibleMock(
544 'TYPO3\\CMS\\Extensionmanager\\Utility\\FileHandlingUtility',
545 array('getAbsoluteExtensionPath', 'getExtensionVersion')
546 );
547 $fileHandlerMock->expects($this->any())
548 ->method('getAbsoluteExtensionPath')
549 ->will($this->returnValue($extensionRoot));
550 $fileHandlerMock->expects($this->any())
551 ->method('getExtensionVersion')
552 ->will($this->returnValue('0.0.0'));
553
554 // Add files and directories to extension:
555 touch($extensionRoot . 'emptyFile.txt');
556 file_put_contents($extensionRoot . 'notEmptyFile.txt', 'content');
557 touch($extensionRoot . '.hiddenFile');
558 mkdir($extensionRoot . 'emptyDir');
559 mkdir($extensionRoot . 'notEmptyDir');
560 touch($extensionRoot . 'notEmptyDir/file.txt');
561
562 // Create zip-file from extension
563 $filename = $fileHandlerMock->_call('createZipFileFromExtension', $extKey);
564
565 $expectedFilename = PATH_site . 'typo3temp/' . $extKey . '_0.0.0_' . date('YmdHi') . '.zip';
566 $this->assertEquals($expectedFilename, $filename, 'Archive file name differs from expectation');
567
568 // File was created
569 $this->assertTrue(file_exists($filename), 'Zip file not created');
570 $this->resourcesToRemove[] = $filename;
571
572 // Read archive and check its contents
573 $archive = new \ZipArchive();
574 $this->assertTrue($archive->open($filename), 'Unable to open archive');
575 $this->assertEquals($archive->statName('emptyFile.txt')->size, 0, 'Empty file not in archive');
576 $this->assertEquals($archive->getFromName('notEmptyFile.txt'), 'content', 'Expected content not found');
577 $this->assertFalse($archive->statName('.hiddenFile'), 'Hidden file not in archive');
578 $this->assertTrue(is_array($archive->statName('emptyDir/')), 'Empty directory not in archive');
579 $this->assertTrue(is_array($archive->statName('notEmptyDir/')), 'Not empty directory not in archive');
580 $this->assertTrue(is_array($archive->statName('notEmptyDir/file.txt')), 'File within directory not in archive');
581
582 // Check that the archive has no additional content
583 $this->assertEquals($archive->numFiles, 5, 'Too many or too less files in archive');
584 }
585 }