[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
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 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 require_once($CFG->libdir . '/filestorage/file_progress.php'); 30 31 class core_files_zip_packer_testcase extends advanced_testcase implements file_progress { 32 protected $testfile; 33 protected $files; 34 35 /** 36 * @var array Progress information passed to the progress reporter 37 */ 38 protected $progress; 39 40 protected function setUp() { 41 parent::setUp(); 42 43 $this->testfile = __DIR__.'/fixtures/test.txt'; 44 45 $fs = get_file_storage(); 46 $context = context_system::instance(); 47 if (!$file = $fs->get_file($context->id, 'phpunit', 'data', 0, '/', 'test.txt')) { 48 $file = $fs->create_file_from_pathname( 49 array('contextid'=>$context->id, 'component'=>'phpunit', 'filearea'=>'data', 'itemid'=>0, 'filepath'=>'/', 'filename'=>'test.txt'), 50 $this->testfile); 51 } 52 53 $this->files = array( 54 'test.test' => $this->testfile, 55 'testíček.txt' => $this->testfile, 56 'Prüfung.txt' => $this->testfile, 57 '测试.txt' => $this->testfile, 58 '試験.txt' => $this->testfile, 59 'Žluťoučký/Koníček.txt' => $file, 60 ); 61 } 62 63 public function test_get_packer() { 64 $this->resetAfterTest(false); 65 $packer = get_file_packer(); 66 $this->assertInstanceOf('zip_packer', $packer); 67 68 $packer = get_file_packer('application/zip'); 69 $this->assertInstanceOf('zip_packer', $packer); 70 } 71 72 /** 73 * @depends test_get_packer 74 */ 75 public function test_list_files() { 76 $this->resetAfterTest(false); 77 78 $files = array( 79 __DIR__.'/fixtures/test_moodle_22.zip', 80 __DIR__.'/fixtures/test_moodle.zip', 81 __DIR__.'/fixtures/test_tc_8.zip', 82 __DIR__.'/fixtures/test_7zip_927.zip', 83 __DIR__.'/fixtures/test_winzip_165.zip', 84 __DIR__.'/fixtures/test_winrar_421.zip', 85 __DIR__.'/fixtures/test_thumbsdb.zip', 86 ); 87 88 if (function_exists('normalizer_normalize')) { 89 // Unfortunately there is no way to standardise UTF-8 strings without INTL extension. 90 $files[] = __DIR__.'/fixtures/test_infozip_3.zip'; 91 $files[] = __DIR__.'/fixtures/test_osx_1074.zip'; 92 $files[] = __DIR__.'/fixtures/test_osx_compress.zip'; 93 } 94 95 $packer = get_file_packer('application/zip'); 96 97 foreach ($files as $archive) { 98 $archivefiles = $packer->list_files($archive); 99 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); 100 $this->assertTrue(count($this->files) === count($archivefiles) or count($this->files) === count($archivefiles) - 1); // Some zippers create empty dirs. 101 foreach ($archivefiles as $file) { 102 if ($file->pathname === 'Žluťoučký/') { 103 // Some zippers create empty dirs. 104 continue; 105 } 106 $this->assertArrayHasKey($file->pathname, $this->files, "File $file->pathname not extracted properly: ".basename($archive).' '); 107 } 108 } 109 110 // Windows packer supports only DOS encoding. 111 $archive = __DIR__.'/fixtures/test_win8_de.zip'; 112 $archivefiles = $packer->list_files($archive); 113 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); 114 $this->assertEquals(2, count($archivefiles)); 115 foreach ($archivefiles as $file) { 116 $this->assertTrue($file->pathname === 'Prüfung.txt' or $file->pathname === 'test.test'); 117 } 118 119 $zip_archive = new zip_archive(); 120 $zip_archive->open(__DIR__.'/fixtures/test_win8_cz.zip', file_archive::OPEN, 'cp852'); 121 $archivefiles = $zip_archive->list_files(); 122 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); 123 $this->assertEquals(3, count($archivefiles)); 124 foreach ($archivefiles as $file) { 125 $this->assertTrue($file->pathname === 'Žluťoučký/Koníček.txt' or $file->pathname === 'testíček.txt' or $file->pathname === 'test.test'); 126 } 127 $zip_archive->close(); 128 129 // Empty archive extraction. 130 $archive = __DIR__.'/fixtures/empty.zip'; 131 $archivefiles = $packer->list_files($archive); 132 $this->assertSame(array(), $archivefiles); 133 } 134 135 /** 136 * @depends test_list_files 137 */ 138 public function test_archive_to_pathname() { 139 global $CFG; 140 141 $this->resetAfterTest(false); 142 143 $packer = get_file_packer('application/zip'); 144 $archive = "$CFG->tempdir/archive.zip"; 145 146 $this->assertFileNotExists($archive); 147 $result = $packer->archive_to_pathname($this->files, $archive); 148 $this->assertTrue($result); 149 $this->assertFileExists($archive); 150 151 $archivefiles = $packer->list_files($archive); 152 $this->assertTrue(is_array($archivefiles)); 153 $this->assertEquals(count($this->files), count($archivefiles)); 154 foreach ($archivefiles as $file) { 155 $this->assertArrayHasKey($file->pathname, $this->files); 156 } 157 158 // Test invalid files parameter. 159 $archive = "$CFG->tempdir/archive2.zip"; 160 $this->assertFileNotExists($archive); 161 162 $this->assertFileNotExists(__DIR__.'/xx/yy/ee.txt'); 163 $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt'); 164 165 $result = $packer->archive_to_pathname($files, $archive, false); 166 $this->assertFalse($result); 167 $this->assertDebuggingCalled(); 168 $this->assertFileNotExists($archive); 169 170 $result = $packer->archive_to_pathname($files, $archive); 171 $this->assertTrue($result); 172 $this->assertFileExists($archive); 173 $this->assertDebuggingCalled(); 174 $archivefiles = $packer->list_files($archive); 175 $this->assertSame(array(), $archivefiles); 176 unlink($archive); 177 178 $this->assertFileNotExists(__DIR__.'/xx/yy/ee.txt'); 179 $this->assertFileExists(__DIR__.'/fixtures/test.txt'); 180 $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt', 'test.txt'=>__DIR__.'/fixtures/test.txt', 'ytest.txt'=>__DIR__.'/xx/yy/yy.txt'); 181 $result = $packer->archive_to_pathname($files, $archive); 182 $this->assertTrue($result); 183 $this->assertFileExists($archive); 184 $archivefiles = $packer->list_files($archive); 185 $this->assertCount(1, $archivefiles); 186 $this->assertEquals('test.txt', $archivefiles[0]->pathname); 187 $dms = $this->getDebuggingMessages(); 188 $this->assertCount(2, $dms); 189 $this->resetDebugging(); 190 unlink($archive); 191 } 192 193 /** 194 * @depends test_archive_to_pathname 195 */ 196 public function test_archive_to_storage() { 197 $this->resetAfterTest(false); 198 199 $packer = get_file_packer('application/zip'); 200 $fs = get_file_storage(); 201 $context = context_system::instance(); 202 203 $this->assertFalse($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip')); 204 $result = $packer->archive_to_storage($this->files, $context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 205 $this->assertInstanceOf('stored_file', $result); 206 $this->assertTrue($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip')); 207 208 $archivefiles = $result->list_files($packer); 209 $this->assertTrue(is_array($archivefiles)); 210 $this->assertEquals(count($this->files), count($archivefiles)); 211 foreach ($archivefiles as $file) { 212 $this->assertArrayHasKey($file->pathname, $this->files); 213 } 214 } 215 216 /** 217 * @depends test_archive_to_storage 218 */ 219 public function test_extract_to_pathname() { 220 global $CFG; 221 222 $this->resetAfterTest(false); 223 224 $packer = get_file_packer('application/zip'); 225 $fs = get_file_storage(); 226 $context = context_system::instance(); 227 228 $target = "$CFG->tempdir/test/"; 229 $testcontent = file_get_contents($this->testfile); 230 231 @mkdir($target, $CFG->directorypermissions); 232 $this->assertTrue(is_dir($target)); 233 234 $archive = "$CFG->tempdir/archive.zip"; 235 $this->assertFileExists($archive); 236 $result = $packer->extract_to_pathname($archive, $target); 237 $this->assertTrue(is_array($result)); 238 $this->assertEquals(count($this->files), count($result)); 239 foreach ($this->files as $file => $unused) { 240 $this->assertTrue($result[$file]); 241 $this->assertFileExists($target.$file); 242 $this->assertSame($testcontent, file_get_contents($target.$file)); 243 } 244 245 $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 246 $this->assertNotEmpty($archive); 247 $result = $packer->extract_to_pathname($archive, $target); 248 $this->assertTrue(is_array($result)); 249 $this->assertEquals(count($this->files), count($result)); 250 foreach ($this->files as $file => $unused) { 251 $this->assertTrue($result[$file]); 252 $this->assertFileExists($target.$file); 253 $this->assertSame($testcontent, file_get_contents($target.$file)); 254 } 255 } 256 257 /** 258 * @depends test_archive_to_storage 259 */ 260 public function test_extract_to_pathname_onlyfiles() { 261 global $CFG; 262 263 $this->resetAfterTest(false); 264 265 $packer = get_file_packer('application/zip'); 266 $fs = get_file_storage(); 267 $context = context_system::instance(); 268 269 $target = "$CFG->tempdir/onlyfiles/"; 270 $testcontent = file_get_contents($this->testfile); 271 272 @mkdir($target, $CFG->directorypermissions); 273 $this->assertTrue(is_dir($target)); 274 275 $onlyfiles = array('test', 'test.test', 'Žluťoučký/Koníček.txt', 'Idontexist'); 276 $willbeextracted = array_intersect(array_keys($this->files), $onlyfiles); 277 $donotextract = array_diff(array_keys($this->files), $onlyfiles); 278 279 $archive = "$CFG->tempdir/archive.zip"; 280 $this->assertFileExists($archive); 281 $result = $packer->extract_to_pathname($archive, $target, $onlyfiles); 282 $this->assertTrue(is_array($result)); 283 $this->assertEquals(count($willbeextracted), count($result)); 284 285 foreach ($willbeextracted as $file) { 286 $this->assertTrue($result[$file]); 287 $this->assertFileExists($target.$file); 288 $this->assertSame($testcontent, file_get_contents($target.$file)); 289 } 290 foreach ($donotextract as $file) { 291 $this->assertFalse(isset($result[$file])); 292 $this->assertFileNotExists($target.$file); 293 } 294 295 } 296 297 /** 298 * @depends test_archive_to_storage 299 */ 300 public function test_extract_to_storage() { 301 global $CFG; 302 303 $this->resetAfterTest(false); 304 305 $packer = get_file_packer('application/zip'); 306 $fs = get_file_storage(); 307 $context = context_system::instance(); 308 309 $testcontent = file_get_contents($this->testfile); 310 311 $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 312 $this->assertNotEmpty($archive); 313 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); 314 $this->assertTrue(is_array($result)); 315 $this->assertEquals(count($this->files), count($result)); 316 foreach ($this->files as $file => $unused) { 317 $this->assertTrue($result[$file]); 318 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); 319 $this->assertInstanceOf('stored_file', $stored_file); 320 $this->assertSame($testcontent, $stored_file->get_content()); 321 } 322 323 $archive = "$CFG->tempdir/archive.zip"; 324 $this->assertFileExists($archive); 325 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); 326 $this->assertTrue(is_array($result)); 327 $this->assertEquals(count($this->files), count($result)); 328 foreach ($this->files as $file => $unused) { 329 $this->assertTrue($result[$file]); 330 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); 331 $this->assertInstanceOf('stored_file', $stored_file); 332 $this->assertSame($testcontent, $stored_file->get_content()); 333 } 334 unlink($archive); 335 } 336 337 /** 338 * @depends test_extract_to_storage 339 */ 340 public function test_add_files() { 341 global $CFG; 342 343 $this->resetAfterTest(false); 344 345 $packer = get_file_packer('application/zip'); 346 $archive = "$CFG->tempdir/archive.zip"; 347 348 $this->assertFileNotExists($archive); 349 $packer->archive_to_pathname(array(), $archive); 350 $this->assertFileExists($archive); 351 352 $zip_archive = new zip_archive(); 353 $zip_archive->open($archive, file_archive::OPEN); 354 $this->assertEquals(0, $zip_archive->count()); 355 356 $zip_archive->add_file_from_string('test.txt', 'test'); 357 $zip_archive->close(); 358 $zip_archive->open($archive, file_archive::OPEN); 359 $this->assertEquals(1, $zip_archive->count()); 360 361 $zip_archive->add_directory('test2'); 362 $zip_archive->close(); 363 $zip_archive->open($archive, file_archive::OPEN); 364 $files = $zip_archive->list_files(); 365 $this->assertCount(2, $files); 366 $this->assertEquals('test.txt', $files[0]->pathname); 367 $this->assertEquals('test2/', $files[1]->pathname); 368 369 $result = $zip_archive->add_file_from_pathname('test.txt', __DIR__.'/nonexistent/file.txt'); 370 $this->assertFalse($result); 371 $zip_archive->close(); 372 $zip_archive->open($archive, file_archive::OPEN); 373 $this->assertEquals(2, $zip_archive->count()); 374 $zip_archive->close(); 375 376 unlink($archive); 377 } 378 379 /** 380 * @depends test_add_files 381 */ 382 public function test_open_archive() { 383 global $CFG; 384 385 $this->resetAfterTest(true); 386 387 $archive = "$CFG->tempdir/archive.zip"; 388 389 $this->assertFileNotExists($archive); 390 391 $zip_archive = new zip_archive(); 392 $result = $zip_archive->open($archive, file_archive::OPEN); 393 $this->assertFalse($result); 394 $this->assertDebuggingCalled(); 395 396 $zip_archive = new zip_archive(); 397 $result = $zip_archive->open($archive, file_archive::CREATE); 398 $this->assertTrue($result); 399 $zip_archive->add_file_from_string('test.txt', 'test'); 400 $zip_archive->close(); 401 $zip_archive->open($archive, file_archive::OPEN); 402 $this->assertEquals(1, $zip_archive->count()); 403 404 $zip_archive = new zip_archive(); 405 $result = $zip_archive->open($archive, file_archive::OVERWRITE); 406 $this->assertTrue($result); 407 $zip_archive->add_file_from_string('test2.txt', 'test'); 408 $zip_archive->close(); 409 $zip_archive->open($archive, file_archive::OPEN); 410 $this->assertEquals(1, $zip_archive->count()); 411 $zip_archive->close(); 412 413 unlink($archive); 414 $zip_archive = new zip_archive(); 415 $result = $zip_archive->open($archive, file_archive::OVERWRITE); 416 $this->assertTrue($result); 417 $zip_archive->add_file_from_string('test2.txt', 'test'); 418 $zip_archive->close(); 419 $zip_archive->open($archive, file_archive::OPEN); 420 $this->assertEquals(1, $zip_archive->count()); 421 $zip_archive->close(); 422 423 unlink($archive); 424 } 425 426 /** 427 * Tests the progress reporting. 428 */ 429 public function test_file_progress() { 430 global $CFG; 431 432 // Set up. 433 $this->resetAfterTest(true); 434 $packer = get_file_packer('application/zip'); 435 $archive = "$CFG->tempdir/archive.zip"; 436 $context = context_system::instance(); 437 438 // Archive to pathname. 439 $this->progress = array(); 440 $result = $packer->archive_to_pathname($this->files, $archive, true, $this); 441 $this->assertTrue($result); 442 // Should send progress at least once per file. 443 $this->assertTrue(count($this->progress) >= count($this->files)); 444 // Each progress will be indeterminate. 445 $this->assertEquals( 446 array(file_progress::INDETERMINATE, file_progress::INDETERMINATE), 447 $this->progress[0]); 448 449 // Archive to pathname using entire folder and subfolder instead of file list. 450 unlink($archive); 451 $folder = make_temp_directory('zip_packer_progress'); 452 file_put_contents($folder . '/test1.txt', 'hello'); 453 $subfolder = $folder . '/sub'; 454 check_dir_exists($subfolder); 455 file_put_contents($subfolder . '/test2.txt', 'world'); 456 file_put_contents($subfolder . '/test3.txt', 'and'); 457 file_put_contents($subfolder . '/test4.txt', 'other'); 458 file_put_contents($subfolder . '/test5.txt', 'worlds'); 459 $this->progress = array(); 460 $result = $packer->archive_to_pathname(array('' => $folder), $archive, true, $this); 461 $this->assertTrue($result); 462 // Should send progress at least once per file. 463 $this->assertTrue(count($this->progress) >= 5); 464 465 // Archive to storage. 466 $this->progress = array(); 467 $archivefile = $packer->archive_to_storage($this->files, $context->id, 468 'phpunit', 'test', 0, '/', 'archive.zip', null, true, $this); 469 $this->assertInstanceOf('stored_file', $archivefile); 470 $this->assertTrue(count($this->progress) >= count($this->files)); 471 $this->assertEquals( 472 array(file_progress::INDETERMINATE, file_progress::INDETERMINATE), 473 $this->progress[0]); 474 475 // Extract to pathname. 476 $this->progress = array(); 477 $target = "$CFG->tempdir/test/"; 478 check_dir_exists($target); 479 $result = $packer->extract_to_pathname($archive, $target, null, $this); 480 remove_dir($target); 481 $this->assertEquals(count($this->files), count($result)); 482 $this->assertTrue(count($this->progress) >= count($this->files)); 483 $this->check_progress_toward_max(); 484 485 // Extract to storage (from storage). 486 $this->progress = array(); 487 $result = $packer->extract_to_storage($archivefile, $context->id, 488 'phpunit', 'target', 0, '/', null, $this); 489 $this->assertEquals(count($this->files), count($result)); 490 $this->assertTrue(count($this->progress) >= count($this->files)); 491 $this->check_progress_toward_max(); 492 493 // Extract to storage (from path). 494 $this->progress = array(); 495 $result = $packer->extract_to_storage($archive, $context->id, 496 'phpunit', 'target', 0, '/', null, $this); 497 $this->assertEquals(count($this->files), count($result)); 498 $this->assertTrue(count($this->progress) >= count($this->files)); 499 $this->check_progress_toward_max(); 500 501 // Wipe created disk file. 502 unlink($archive); 503 } 504 505 /** 506 * Checks that progress reported is numeric rather than indeterminate, 507 * and follows the progress reporting rules. 508 */ 509 private function check_progress_toward_max() { 510 $lastvalue = -1; 511 foreach ($this->progress as $progressitem) { 512 list($value, $max) = $progressitem; 513 $this->assertNotEquals(file_progress::INDETERMINATE, $max); 514 $this->assertTrue($value <= $max); 515 $this->assertTrue($value >= $lastvalue); 516 $lastvalue = $value; 517 } 518 } 519 520 /** 521 * Handles file_progress interface. 522 * 523 * @param int $progress 524 * @param int $max 525 */ 526 public function progress($progress = file_progress::INDETERMINATE, $max = file_progress::INDETERMINATE) { 527 $this->progress[] = array($progress, $max); 528 } 529 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |