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