MDL-41022 cleanup core_files_zip_packer_testcase
[moodle.git] / lib / filestorage / tests / zip_packer_test.php
CommitLineData
79c966cf
PS
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Unit tests for /lib/filestorage/zip_packer.php and zip_archive.php
19 *
20 * @package core_files
21 * @category phpunit
22 * @copyright 2012 Petr Skoda
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28
8252b7c2 29class core_files_zip_packer_testcase extends advanced_testcase {
79c966cf
PS
30 protected $testfile;
31 protected $files;
32
33 protected function setUp() {
34 parent::setUp();
35
36 $this->testfile = __DIR__.'/fixtures/test.txt';
37
38 $fs = get_file_storage();
39 $context = context_system::instance();
40 if (!$file = $fs->get_file($context->id, 'phpunit', 'data', 0, '/', 'test.txt')) {
41 $file = $fs->create_file_from_pathname(
42 array('contextid'=>$context->id, 'component'=>'phpunit', 'filearea'=>'data', 'itemid'=>0, 'filepath'=>'/', 'filename'=>'test.txt'),
43 $this->testfile);
44 }
45
46 $this->files = array(
47 'test.test' => $this->testfile,
48 'testíček.txt' => $this->testfile,
49 'Prüfung.txt' => $this->testfile,
50 '测试.txt' => $this->testfile,
51 '試験.txt' => $this->testfile,
52 'Žluťoučký/Koníček.txt' => $file,
53 );
54 }
55
56 public function test_get_packer() {
57 $this->resetAfterTest(false);
58 $packer = get_file_packer();
59 $this->assertInstanceOf('zip_packer', $packer);
60
61 $packer = get_file_packer('application/zip');
62 $this->assertInstanceOf('zip_packer', $packer);
63 }
64
65 /**
66 * @depends test_get_packer
67 */
68 public function test_list_files() {
69 $this->resetAfterTest(false);
6fb8ae95
PS
70
71 $files = array(
72 __DIR__.'/fixtures/test_moodle_22.zip',
73 __DIR__.'/fixtures/test_moodle.zip',
74 __DIR__.'/fixtures/test_tc_8.zip',
75 __DIR__.'/fixtures/test_7zip_927.zip',
76 __DIR__.'/fixtures/test_winzip_165.zip',
77 __DIR__.'/fixtures/test_winrar_421.zip',
81d9f3d5 78 __DIR__.'/fixtures/test_thumbsdb.zip',
6fb8ae95
PS
79 );
80
81 if (function_exists('normalizer_normalize')) {
5f15f7c9 82 // Unfortunately there is no way to standardise UTF-8 strings without INTL extension.
6fb8ae95
PS
83 $files[] = __DIR__.'/fixtures/test_infozip_3.zip';
84 $files[] = __DIR__.'/fixtures/test_osx_1074.zip';
81d9f3d5 85 $files[] = __DIR__.'/fixtures/test_osx_compress.zip';
6fb8ae95 86 }
79c966cf
PS
87
88 $packer = get_file_packer('application/zip');
89
6fb8ae95
PS
90 foreach ($files as $archive) {
91 $archivefiles = $packer->list_files($archive);
92 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' ');
93 $this->assertTrue(count($this->files) === count($archivefiles) or count($this->files) === count($archivefiles) - 1); // Some zippers create empty dirs.
5f15f7c9 94 foreach ($archivefiles as $file) {
6fb8ae95
PS
95 if ($file->pathname === 'Žluťoučký/') {
96 // Some zippers create empty dirs.
97 continue;
98 }
99 $this->assertArrayHasKey($file->pathname, $this->files, "File $file->pathname not extracted properly: ".basename($archive).' ');
100 }
79c966cf
PS
101 }
102
5f15f7c9 103 // Windows packer supports only DOS encoding.
6fb8ae95
PS
104 $archive = __DIR__.'/fixtures/test_win8_de.zip';
105 $archivefiles = $packer->list_files($archive);
106 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' ');
107 $this->assertEquals(2, count($archivefiles));
5f15f7c9 108 foreach ($archivefiles as $file) {
6fb8ae95
PS
109 $this->assertTrue($file->pathname === 'Prüfung.txt' or $file->pathname === 'test.test');
110 }
111
112 $zip_archive = new zip_archive();
113 $zip_archive->open(__DIR__.'/fixtures/test_win8_cz.zip', file_archive::OPEN, 'cp852');
114 $archivefiles = $zip_archive->list_files();
115 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' ');
116 $this->assertEquals(3, count($archivefiles));
5f15f7c9 117 foreach ($archivefiles as $file) {
6fb8ae95 118 $this->assertTrue($file->pathname === 'Žluťoučký/Koníček.txt' or $file->pathname === 'testíček.txt' or $file->pathname === 'test.test');
79c966cf 119 }
6fb8ae95 120 $zip_archive->close();
01b4040a
PS
121
122 // Empty archive extraction.
123 $archive = __DIR__.'/fixtures/empty.zip';
124 $archivefiles = $packer->list_files($archive);
125 $this->assertSame(array(), $archivefiles);
79c966cf
PS
126 }
127
128 /**
129 * @depends test_list_files
130 */
131 public function test_archive_to_pathname() {
132 global $CFG;
133
134 $this->resetAfterTest(false);
135
136 $packer = get_file_packer('application/zip');
137 $archive = "$CFG->tempdir/archive.zip";
138
01b4040a 139 $this->assertFileNotExists($archive);
79c966cf
PS
140 $result = $packer->archive_to_pathname($this->files, $archive);
141 $this->assertTrue($result);
01b4040a 142 $this->assertFileExists($archive);
79c966cf
PS
143
144 $archivefiles = $packer->list_files($archive);
145 $this->assertTrue(is_array($archivefiles));
146 $this->assertEquals(count($this->files), count($archivefiles));
5f15f7c9 147 foreach ($archivefiles as $file) {
79c966cf
PS
148 $this->assertArrayHasKey($file->pathname, $this->files);
149 }
f6b49abf
PS
150
151 // Test invalid files parameter.
152 $archive = "$CFG->tempdir/archive2.zip";
01b4040a 153 $this->assertFileNotExists($archive);
f6b49abf 154
01b4040a 155 $this->assertFileNotExists(__DIR__.'/xx/yy/ee.txt');
f6b49abf 156 $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt');
1017426c 157
01b4040a 158 $result = $packer->archive_to_pathname($files, $archive, false);
f6b49abf 159 $this->assertFalse($result);
01b4040a
PS
160 $this->assertDebuggingCalled();
161 $this->assertFileNotExists($archive);
162
f6b49abf 163 $result = $packer->archive_to_pathname($files, $archive);
f6b49abf 164 $this->assertTrue($result);
01b4040a
PS
165 $this->assertFileExists($archive);
166 $this->assertDebuggingCalled();
167 $archivefiles = $packer->list_files($archive);
168 $this->assertSame(array(), $archivefiles);
169 unlink($archive);
f6b49abf 170
01b4040a
PS
171 $this->assertFileNotExists(__DIR__.'/xx/yy/ee.txt');
172 $this->assertFileExists(__DIR__.'/fixtures/test.txt');
173 $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt', 'test.txt'=>__DIR__.'/fixtures/test.txt', 'ytest.txt'=>__DIR__.'/xx/yy/yy.txt');
174 $result = $packer->archive_to_pathname($files, $archive);
175 $this->assertTrue($result);
176 $this->assertFileExists($archive);
177 $archivefiles = $packer->list_files($archive);
178 $this->assertCount(1, $archivefiles);
179 $this->assertEquals('test.txt', $archivefiles[0]->pathname);
180 $dms = $this->getDebuggingMessages();
181 $this->assertCount(2, $dms);
182 $this->resetDebugging();
183 unlink($archive);
79c966cf
PS
184 }
185
186 /**
187 * @depends test_archive_to_pathname
188 */
189 public function test_archive_to_storage() {
190 $this->resetAfterTest(false);
191
192 $packer = get_file_packer('application/zip');
193 $fs = get_file_storage();
194 $context = context_system::instance();
195
196 $this->assertFalse($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'));
197 $result = $packer->archive_to_storage($this->files, $context->id, 'phpunit', 'test', 0, '/', 'archive.zip');
198 $this->assertInstanceOf('stored_file', $result);
199 $this->assertTrue($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'));
200
201 $archivefiles = $result->list_files($packer);
202 $this->assertTrue(is_array($archivefiles));
203 $this->assertEquals(count($this->files), count($archivefiles));
5f15f7c9 204 foreach ($archivefiles as $file) {
79c966cf
PS
205 $this->assertArrayHasKey($file->pathname, $this->files);
206 }
207 }
208
209 /**
210 * @depends test_archive_to_storage
211 */
212 public function test_extract_to_pathname() {
213 global $CFG;
214
215 $this->resetAfterTest(false);
216
217 $packer = get_file_packer('application/zip');
218 $fs = get_file_storage();
219 $context = context_system::instance();
220
221 $target = "$CFG->tempdir/test/";
222 $testcontent = file_get_contents($this->testfile);
223
224 @mkdir($target, $CFG->directorypermissions);
225 $this->assertTrue(is_dir($target));
226
227 $archive = "$CFG->tempdir/archive.zip";
01b4040a 228 $this->assertFileExists($archive);
79c966cf
PS
229 $result = $packer->extract_to_pathname($archive, $target);
230 $this->assertTrue(is_array($result));
231 $this->assertEquals(count($this->files), count($result));
5f15f7c9 232 foreach ($this->files as $file => $unused) {
79c966cf 233 $this->assertTrue($result[$file]);
01b4040a 234 $this->assertFileExists($target.$file);
79c966cf
PS
235 $this->assertSame($testcontent, file_get_contents($target.$file));
236 }
237
238 $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip');
239 $this->assertNotEmpty($archive);
240 $result = $packer->extract_to_pathname($archive, $target);
241 $this->assertTrue(is_array($result));
242 $this->assertEquals(count($this->files), count($result));
5f15f7c9 243 foreach ($this->files as $file => $unused) {
79c966cf 244 $this->assertTrue($result[$file]);
01b4040a 245 $this->assertFileExists($target.$file);
79c966cf
PS
246 $this->assertSame($testcontent, file_get_contents($target.$file));
247 }
248 }
249
e462f46b
FM
250 /**
251 * @depends test_archive_to_storage
252 */
253 public function test_extract_to_pathname_onlyfiles() {
254 global $CFG;
255
256 $this->resetAfterTest(false);
257
258 $packer = get_file_packer('application/zip');
259 $fs = get_file_storage();
260 $context = context_system::instance();
261
262 $target = "$CFG->tempdir/onlyfiles/";
263 $testcontent = file_get_contents($this->testfile);
264
265 @mkdir($target, $CFG->directorypermissions);
266 $this->assertTrue(is_dir($target));
267
268 $onlyfiles = array('test', 'test.test', 'Žluťoučký/Koníček.txt', 'Idontexist');
269 $willbeextracted = array_intersect(array_keys($this->files), $onlyfiles);
270 $donotextract = array_diff(array_keys($this->files), $onlyfiles);
271
272 $archive = "$CFG->tempdir/archive.zip";
01b4040a 273 $this->assertFileExists($archive);
e462f46b
FM
274 $result = $packer->extract_to_pathname($archive, $target, $onlyfiles);
275 $this->assertTrue(is_array($result));
276 $this->assertEquals(count($willbeextracted), count($result));
277
5f15f7c9 278 foreach ($willbeextracted as $file) {
e462f46b 279 $this->assertTrue($result[$file]);
01b4040a 280 $this->assertFileExists($target.$file);
e462f46b
FM
281 $this->assertSame($testcontent, file_get_contents($target.$file));
282 }
5f15f7c9 283 foreach ($donotextract as $file) {
e462f46b 284 $this->assertFalse(isset($result[$file]));
01b4040a 285 $this->assertFileNotExists($target.$file);
e462f46b
FM
286 }
287
288 }
289
79c966cf
PS
290 /**
291 * @depends test_archive_to_storage
292 */
293 public function test_extract_to_storage() {
294 global $CFG;
295
01b4040a 296 $this->resetAfterTest(false);
79c966cf
PS
297
298 $packer = get_file_packer('application/zip');
299 $fs = get_file_storage();
300 $context = context_system::instance();
301
302 $testcontent = file_get_contents($this->testfile);
303
304 $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip');
305 $this->assertNotEmpty($archive);
306 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/');
307 $this->assertTrue(is_array($result));
308 $this->assertEquals(count($this->files), count($result));
5f15f7c9 309 foreach ($this->files as $file => $unused) {
79c966cf
PS
310 $this->assertTrue($result[$file]);
311 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file"));
312 $this->assertInstanceOf('stored_file', $stored_file);
313 $this->assertSame($testcontent, $stored_file->get_content());
314 }
315
316 $archive = "$CFG->tempdir/archive.zip";
01b4040a 317 $this->assertFileExists($archive);
79c966cf
PS
318 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/');
319 $this->assertTrue(is_array($result));
320 $this->assertEquals(count($this->files), count($result));
5f15f7c9 321 foreach ($this->files as $file => $unused) {
79c966cf
PS
322 $this->assertTrue($result[$file]);
323 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file"));
324 $this->assertInstanceOf('stored_file', $stored_file);
325 $this->assertSame($testcontent, $stored_file->get_content());
326 }
01b4040a
PS
327 unlink($archive);
328 }
329
330 /**
331 * @depends test_extract_to_storage
332 */
333 public function test_add_files() {
334 global $CFG;
335
336 $this->resetAfterTest(false);
337
338 $packer = get_file_packer('application/zip');
339 $archive = "$CFG->tempdir/archive.zip";
340
341 $this->assertFileNotExists($archive);
342 $packer->archive_to_pathname(array(), $archive);
343 $this->assertFileExists($archive);
344
345 $zip_archive = new zip_archive();
346 $zip_archive->open($archive, file_archive::OPEN);
347 $this->assertEquals(0, $zip_archive->count());
348
349 $zip_archive->add_file_from_string('test.txt', 'test');
350 $zip_archive->close();
351 $zip_archive->open($archive, file_archive::OPEN);
352 $this->assertEquals(1, $zip_archive->count());
353
354 $zip_archive->add_directory('test2');
355 $zip_archive->close();
356 $zip_archive->open($archive, file_archive::OPEN);
357 $files = $zip_archive->list_files();
358 $this->assertCount(2, $files);
359 $this->assertEquals('test.txt', $files[0]->pathname);
360 $this->assertEquals('test2/', $files[1]->pathname);
361
362 $result = $zip_archive->add_file_from_pathname('test.txt', __DIR__.'/nonexistent/file.txt');
363 $this->assertFalse($result);
364 $zip_archive->close();
365 $zip_archive->open($archive, file_archive::OPEN);
366 $this->assertEquals(2, $zip_archive->count());
96846ef1 367 $zip_archive->close();
01b4040a
PS
368
369 unlink($archive);
370 }
371
372 /**
373 * @depends test_add_files
374 */
375 public function test_open_archive() {
376 global $CFG;
377
378 $this->resetAfterTest(true);
379
380 $archive = "$CFG->tempdir/archive.zip";
381
382 $this->assertFileNotExists($archive);
383
384 $zip_archive = new zip_archive();
385 $result = $zip_archive->open($archive, file_archive::OPEN);
386 $this->assertFalse($result);
387 $this->assertDebuggingCalled();
388
389 $zip_archive = new zip_archive();
390 $result = $zip_archive->open($archive, file_archive::CREATE);
391 $this->assertTrue($result);
392 $zip_archive->add_file_from_string('test.txt', 'test');
393 $zip_archive->close();
394 $zip_archive->open($archive, file_archive::OPEN);
395 $this->assertEquals(1, $zip_archive->count());
396
397 $zip_archive = new zip_archive();
398 $result = $zip_archive->open($archive, file_archive::OVERWRITE);
399 $this->assertTrue($result);
400 $zip_archive->add_file_from_string('test2.txt', 'test');
401 $zip_archive->close();
402 $zip_archive->open($archive, file_archive::OPEN);
403 $this->assertEquals(1, $zip_archive->count());
96846ef1 404 $zip_archive->close();
01b4040a
PS
405
406 unlink($archive);
407 $zip_archive = new zip_archive();
408 $result = $zip_archive->open($archive, file_archive::OVERWRITE);
409 $this->assertTrue($result);
410 $zip_archive->add_file_from_string('test2.txt', 'test');
411 $zip_archive->close();
412 $zip_archive->open($archive, file_archive::OPEN);
413 $this->assertEquals(1, $zip_archive->count());
96846ef1
PS
414 $zip_archive->close();
415
416 unlink($archive);
79c966cf
PS
417 }
418}