See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 namespace core; 18 19 use file_archive; 20 use file_progress; 21 use zip_archive; 22 23 defined('MOODLE_INTERNAL') || die(); 24 25 global $CFG; 26 require_once($CFG->libdir . '/filestorage/file_progress.php'); 27 28 /** 29 * Unit tests for /lib/filestorage/zip_packer.php and zip_archive.php 30 * 31 * @package core 32 * @category test 33 * @copyright 2012 Petr Skoda 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class zip_packer_test extends \advanced_testcase implements file_progress { 37 protected $testfile; 38 protected $files; 39 40 /** 41 * @var array Progress information passed to the progress reporter 42 */ 43 protected $progress; 44 45 protected function setUp(): void { 46 parent::setUp(); 47 48 $this->testfile = __DIR__.'/fixtures/test.txt'; 49 50 $fs = get_file_storage(); 51 $context = \context_system::instance(); 52 if (!$file = $fs->get_file($context->id, 'phpunit', 'data', 0, '/', 'test.txt')) { 53 $file = $fs->create_file_from_pathname( 54 array('contextid'=>$context->id, 'component'=>'phpunit', 'filearea'=>'data', 'itemid'=>0, 'filepath'=>'/', 'filename'=>'test.txt'), 55 $this->testfile); 56 } 57 58 $this->files = array( 59 'test.test' => $this->testfile, 60 'testíček.txt' => $this->testfile, 61 'Prüfung.txt' => $this->testfile, 62 '测试.txt' => $this->testfile, 63 '試験.txt' => $this->testfile, 64 'Žluťoučký/Koníček.txt' => $file, 65 ); 66 } 67 68 public function test_get_packer() { 69 $this->resetAfterTest(false); 70 $packer = get_file_packer(); 71 $this->assertInstanceOf('zip_packer', $packer); 72 73 $packer = get_file_packer('application/zip'); 74 $this->assertInstanceOf('zip_packer', $packer); 75 } 76 77 /** 78 * @depends test_get_packer 79 */ 80 public function test_list_files() { 81 $this->resetAfterTest(false); 82 83 $files = array( 84 __DIR__.'/fixtures/test_moodle_22.zip', 85 __DIR__.'/fixtures/test_moodle.zip', 86 __DIR__.'/fixtures/test_tc_8.zip', 87 __DIR__.'/fixtures/test_7zip_927.zip', 88 __DIR__.'/fixtures/test_winzip_165.zip', 89 __DIR__.'/fixtures/test_winrar_421.zip', 90 __DIR__.'/fixtures/test_thumbsdb.zip', 91 ); 92 93 if (function_exists('normalizer_normalize')) { 94 // Unfortunately there is no way to standardise UTF-8 strings without INTL extension. 95 $files[] = __DIR__.'/fixtures/test_infozip_3.zip'; 96 $files[] = __DIR__.'/fixtures/test_osx_1074.zip'; 97 $files[] = __DIR__.'/fixtures/test_osx_compress.zip'; 98 } 99 100 $packer = get_file_packer('application/zip'); 101 102 foreach ($files as $archive) { 103 $archivefiles = $packer->list_files($archive); 104 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); 105 $this->assertTrue(count($this->files) === count($archivefiles) or count($this->files) === count($archivefiles) - 1); // Some zippers create empty dirs. 106 foreach ($archivefiles as $file) { 107 if ($file->pathname === 'Žluťoučký/') { 108 // Some zippers create empty dirs. 109 continue; 110 } 111 $this->assertArrayHasKey($file->pathname, $this->files, "File $file->pathname not extracted properly: ".basename($archive).' '); 112 } 113 } 114 115 // Windows packer supports only DOS encoding. 116 $archive = __DIR__.'/fixtures/test_win8_de.zip'; 117 $archivefiles = $packer->list_files($archive); 118 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); 119 $this->assertEquals(2, count($archivefiles)); 120 foreach ($archivefiles as $file) { 121 $this->assertTrue($file->pathname === 'Prüfung.txt' or $file->pathname === 'test.test'); 122 } 123 124 $zip_archive = new zip_archive(); 125 $zip_archive->open(__DIR__.'/fixtures/test_win8_cz.zip', file_archive::OPEN, 'cp852'); 126 $archivefiles = $zip_archive->list_files(); 127 $this->assertTrue(is_array($archivefiles), "Archive not extracted properly: ".basename($archive).' '); 128 $this->assertEquals(3, count($archivefiles)); 129 foreach ($archivefiles as $file) { 130 $this->assertTrue($file->pathname === 'Žluťoučký/Koníček.txt' or $file->pathname === 'testíček.txt' or $file->pathname === 'test.test'); 131 } 132 $zip_archive->close(); 133 134 // Empty archive extraction. 135 $archive = __DIR__.'/fixtures/empty.zip'; 136 $archivefiles = $packer->list_files($archive); 137 $this->assertSame(array(), $archivefiles); 138 } 139 140 /** 141 * @depends test_list_files 142 */ 143 public function test_archive_to_pathname() { 144 global $CFG; 145 146 $this->resetAfterTest(false); 147 148 $packer = get_file_packer('application/zip'); 149 $archive = "$CFG->tempdir/archive.zip"; 150 151 $this->assertFileDoesNotExist($archive); 152 $result = $packer->archive_to_pathname($this->files, $archive); 153 $this->assertTrue($result); 154 $this->assertFileExists($archive); 155 156 $archivefiles = $packer->list_files($archive); 157 $this->assertTrue(is_array($archivefiles)); 158 $this->assertEquals(count($this->files), count($archivefiles)); 159 foreach ($archivefiles as $file) { 160 $this->assertArrayHasKey($file->pathname, $this->files); 161 } 162 163 // Test invalid files parameter. 164 $archive = "$CFG->tempdir/archive2.zip"; 165 $this->assertFileDoesNotExist($archive); 166 167 $this->assertFileDoesNotExist(__DIR__.'/xx/yy/ee.txt'); 168 $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt'); 169 170 $result = $packer->archive_to_pathname($files, $archive, false); 171 $this->assertFalse($result); 172 $this->assertDebuggingCalled(); 173 $this->assertFileDoesNotExist($archive); 174 175 $result = $packer->archive_to_pathname($files, $archive); 176 $this->assertTrue($result); 177 $this->assertFileExists($archive); 178 $this->assertDebuggingCalled(); 179 $archivefiles = $packer->list_files($archive); 180 $this->assertSame(array(), $archivefiles); 181 unlink($archive); 182 183 $this->assertFileDoesNotExist(__DIR__.'/xx/yy/ee.txt'); 184 $this->assertFileExists(__DIR__.'/fixtures/test.txt'); 185 $files = array('xtest.txt'=>__DIR__.'/xx/yy/ee.txt', 'test.txt'=>__DIR__.'/fixtures/test.txt', 'ytest.txt'=>__DIR__.'/xx/yy/yy.txt'); 186 $result = $packer->archive_to_pathname($files, $archive); 187 $this->assertTrue($result); 188 $this->assertFileExists($archive); 189 $archivefiles = $packer->list_files($archive); 190 $this->assertCount(1, $archivefiles); 191 $this->assertEquals('test.txt', $archivefiles[0]->pathname); 192 $dms = $this->getDebuggingMessages(); 193 $this->assertCount(2, $dms); 194 $this->resetDebugging(); 195 unlink($archive); 196 } 197 198 /** 199 * @depends test_archive_to_pathname 200 */ 201 public function test_archive_to_storage() { 202 $this->resetAfterTest(false); 203 204 $packer = get_file_packer('application/zip'); 205 $fs = get_file_storage(); 206 $context = \context_system::instance(); 207 208 $this->assertFalse($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip')); 209 $result = $packer->archive_to_storage($this->files, $context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 210 $this->assertInstanceOf('stored_file', $result); 211 $this->assertTrue($fs->file_exists($context->id, 'phpunit', 'test', 0, '/', 'archive.zip')); 212 213 $archivefiles = $result->list_files($packer); 214 $this->assertTrue(is_array($archivefiles)); 215 $this->assertEquals(count($this->files), count($archivefiles)); 216 foreach ($archivefiles as $file) { 217 $this->assertArrayHasKey($file->pathname, $this->files); 218 } 219 } 220 221 /** 222 * @depends test_archive_to_storage 223 */ 224 public function test_extract_to_pathname() { 225 global $CFG; 226 227 $this->resetAfterTest(false); 228 229 $packer = get_file_packer('application/zip'); 230 $fs = get_file_storage(); 231 $context = \context_system::instance(); 232 233 $target = "$CFG->tempdir/test/"; 234 $testcontent = file_get_contents($this->testfile); 235 236 @mkdir($target, $CFG->directorypermissions); 237 $this->assertTrue(is_dir($target)); 238 239 $archive = "$CFG->tempdir/archive.zip"; 240 $this->assertFileExists($archive); 241 $result = $packer->extract_to_pathname($archive, $target); 242 $this->assertTrue(is_array($result)); 243 $this->assertEquals(count($this->files), count($result)); 244 foreach ($this->files as $file => $unused) { 245 $this->assertTrue($result[$file]); 246 $this->assertFileExists($target.$file); 247 $this->assertSame($testcontent, file_get_contents($target.$file)); 248 } 249 250 $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 251 $this->assertNotEmpty($archive); 252 $result = $packer->extract_to_pathname($archive, $target); 253 $this->assertTrue(is_array($result)); 254 $this->assertEquals(count($this->files), count($result)); 255 foreach ($this->files as $file => $unused) { 256 $this->assertTrue($result[$file]); 257 $this->assertFileExists($target.$file); 258 $this->assertSame($testcontent, file_get_contents($target.$file)); 259 } 260 } 261 262 /** 263 * Test functionality of {@see zip_packer} for entries with folders ending with dots. 264 * 265 * @link https://bugs.php.net/bug.php?id=77214 266 */ 267 public function test_zip_entry_path_having_folder_ending_with_dot() { 268 global $CFG; 269 270 $this->resetAfterTest(false); 271 272 $packer = get_file_packer('application/zip'); 273 $tmp = make_request_directory(); 274 $now = time(); 275 276 // Create a test archive containing a folder ending with dot. 277 $zippath = $tmp . '/test_archive.zip'; 278 $zipcontents = [ 279 'HOW.TO' => ['Just run tests.'], 280 'README.' => ['This is a test ZIP file'], 281 './Current time' => [$now], 282 'Data/sub1./sub2/1221' => ['1221'], 283 'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt' => [''], 284 ]; 285 286 if ($CFG->ostype === 'WINDOWS') { 287 // File names cannot end with dots on Windows and trailing dots are replaced with underscore. 288 $filenamemap = [ 289 'HOW.TO' => 'HOW.TO', 290 'README.' => 'README_', 291 './Current time' => 'Current time', 292 'Data/sub1./sub2/1221' => 'Data/sub1_/sub2/1221', 293 'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt' => 294 'Data/sub1_/sub2_/Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt', 295 ]; 296 297 } else { 298 $filenamemap = [ 299 'HOW.TO' => 'HOW.TO', 300 'README.' => 'README.', 301 './Current time' => 'Current time', 302 'Data/sub1./sub2/1221' => 'Data/sub1./sub2/1221', 303 'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt' => 304 'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt', 305 ]; 306 } 307 308 // Check that the archive can be created. 309 $result = $packer->archive_to_pathname($zipcontents, $zippath, false); 310 $this->assertTrue($result); 311 312 // Check list of files. 313 $listfiles = $packer->list_files($zippath); 314 $this->assertEquals(count($zipcontents), count($listfiles)); 315 316 foreach ($listfiles as $fileinfo) { 317 $this->assertSame($fileinfo->pathname, $fileinfo->original_pathname); 318 $this->assertArrayHasKey($fileinfo->pathname, $zipcontents); 319 } 320 321 // Check actual extracting. 322 $targetpath = $tmp . '/target'; 323 check_dir_exists($targetpath); 324 $result = $packer->extract_to_pathname($zippath, $targetpath, null, null, true); 325 326 $this->assertTrue($result); 327 328 foreach ($zipcontents as $filename => $filecontents) { 329 $filecontents = reset($filecontents); 330 $this->assertTrue(is_readable($targetpath . '/' . $filenamemap[$filename])); 331 $this->assertEquals($filecontents, file_get_contents($targetpath . '/' . $filenamemap[$filename])); 332 } 333 } 334 335 /** 336 * @depends test_archive_to_storage 337 */ 338 public function test_extract_to_pathname_onlyfiles() { 339 global $CFG; 340 341 $this->resetAfterTest(false); 342 343 $packer = get_file_packer('application/zip'); 344 $fs = get_file_storage(); 345 $context = \context_system::instance(); 346 347 $target = "$CFG->tempdir/onlyfiles/"; 348 $testcontent = file_get_contents($this->testfile); 349 350 @mkdir($target, $CFG->directorypermissions); 351 $this->assertTrue(is_dir($target)); 352 353 $onlyfiles = array('test', 'test.test', 'Žluťoučký/Koníček.txt', 'Idontexist'); 354 $willbeextracted = array_intersect(array_keys($this->files), $onlyfiles); 355 $donotextract = array_diff(array_keys($this->files), $onlyfiles); 356 357 $archive = "$CFG->tempdir/archive.zip"; 358 $this->assertFileExists($archive); 359 $result = $packer->extract_to_pathname($archive, $target, $onlyfiles); 360 $this->assertTrue(is_array($result)); 361 $this->assertEquals(count($willbeextracted), count($result)); 362 363 foreach ($willbeextracted as $file) { 364 $this->assertTrue($result[$file]); 365 $this->assertFileExists($target.$file); 366 $this->assertSame($testcontent, file_get_contents($target.$file)); 367 } 368 foreach ($donotextract as $file) { 369 $this->assertFalse(isset($result[$file])); 370 $this->assertFileDoesNotExist($target.$file); 371 } 372 373 } 374 375 /** 376 * @depends test_archive_to_storage 377 */ 378 public function test_extract_to_pathname_returnvalue_successful() { 379 global $CFG; 380 381 $this->resetAfterTest(false); 382 383 $packer = get_file_packer('application/zip'); 384 385 $target = make_request_directory(); 386 387 $archive = "$CFG->tempdir/archive.zip"; 388 $this->assertFileExists($archive); 389 $result = $packer->extract_to_pathname($archive, $target, null, null, true); 390 $this->assertTrue($result); 391 } 392 393 /** 394 * @depends test_archive_to_storage 395 */ 396 public function test_extract_to_pathname_returnvalue_failure() { 397 global $CFG; 398 399 $this->resetAfterTest(false); 400 401 $packer = get_file_packer('application/zip'); 402 403 $target = make_request_directory(); 404 405 $archive = "$CFG->tempdir/noarchive.zip"; 406 $result = $packer->extract_to_pathname($archive, $target, null, null, true); 407 $this->assertFalse($result); 408 } 409 410 /** 411 * @depends test_archive_to_storage 412 */ 413 public function test_extract_to_storage() { 414 global $CFG; 415 416 $this->resetAfterTest(false); 417 418 $packer = get_file_packer('application/zip'); 419 $fs = get_file_storage(); 420 $context = \context_system::instance(); 421 422 $testcontent = file_get_contents($this->testfile); 423 424 $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 425 $this->assertNotEmpty($archive); 426 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); 427 $this->assertTrue(is_array($result)); 428 $this->assertEquals(count($this->files), count($result)); 429 foreach ($this->files as $file => $unused) { 430 $this->assertTrue($result[$file]); 431 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); 432 $this->assertInstanceOf('stored_file', $stored_file); 433 $this->assertSame($testcontent, $stored_file->get_content()); 434 } 435 436 $archive = "$CFG->tempdir/archive.zip"; 437 $this->assertFileExists($archive); 438 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); 439 $this->assertTrue(is_array($result)); 440 $this->assertEquals(count($this->files), count($result)); 441 foreach ($this->files as $file => $unused) { 442 $this->assertTrue($result[$file]); 443 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); 444 $this->assertInstanceOf('stored_file', $stored_file); 445 $this->assertSame($testcontent, $stored_file->get_content()); 446 } 447 unlink($archive); 448 } 449 450 /** 451 * @depends test_extract_to_storage 452 */ 453 public function test_add_files() { 454 global $CFG; 455 456 $this->resetAfterTest(false); 457 458 $packer = get_file_packer('application/zip'); 459 $archive = "$CFG->tempdir/archive.zip"; 460 461 $this->assertFileDoesNotExist($archive); 462 $packer->archive_to_pathname(array(), $archive); 463 $this->assertFileExists($archive); 464 465 $zip_archive = new zip_archive(); 466 $zip_archive->open($archive, file_archive::OPEN); 467 $this->assertEquals(0, $zip_archive->count()); 468 469 $zip_archive->add_file_from_string('test.txt', 'test'); 470 $zip_archive->close(); 471 $zip_archive->open($archive, file_archive::OPEN); 472 $this->assertEquals(1, $zip_archive->count()); 473 474 $zip_archive->add_directory('test2'); 475 $zip_archive->close(); 476 $zip_archive->open($archive, file_archive::OPEN); 477 $files = $zip_archive->list_files(); 478 $this->assertCount(2, $files); 479 $this->assertEquals('test.txt', $files[0]->pathname); 480 $this->assertEquals('test2/', $files[1]->pathname); 481 482 $result = $zip_archive->add_file_from_pathname('test.txt', __DIR__.'/nonexistent/file.txt'); 483 $this->assertFalse($result); 484 $zip_archive->close(); 485 $zip_archive->open($archive, file_archive::OPEN); 486 $this->assertEquals(2, $zip_archive->count()); 487 $zip_archive->close(); 488 489 unlink($archive); 490 } 491 492 public function test_close_archive() { 493 global $CFG; 494 495 $this->resetAfterTest(true); 496 497 $archive = "$CFG->tempdir/archive.zip"; 498 $textfile = "$CFG->tempdir/textfile.txt"; 499 touch($textfile); 500 501 $this->assertFileDoesNotExist($archive); 502 $this->assertFileExists($textfile); 503 504 // Create archive and close it without files. 505 // (returns true, without any warning). 506 $zip_archive = new zip_archive(); 507 $result = $zip_archive->open($archive, file_archive::CREATE); 508 $this->assertTrue($result); 509 $result = $zip_archive->close(); 510 $this->assertTrue($result); 511 unlink($archive); 512 513 // Create archive and close it with files. 514 // (returns true, without any warning). 515 $zip_archive = new zip_archive(); 516 $result = $zip_archive->open($archive, file_archive::CREATE); 517 $this->assertTrue($result); 518 $result = $zip_archive->add_file_from_string('test.txt', 'test'); 519 $this->assertTrue($result); 520 $result = $zip_archive->add_file_from_pathname('test2.txt', $textfile); 521 $result = $zip_archive->close(); 522 $this->assertTrue($result); 523 unlink($archive); 524 525 // Create archive and close if forcing error. 526 // (returns true for old PHP versions and 527 // false with warnings for new PHP versions). MDL-51863. 528 $zip_archive = new zip_archive(); 529 $result = $zip_archive->open($archive, file_archive::CREATE); 530 $this->assertTrue($result); 531 $result = $zip_archive->add_file_from_string('test.txt', 'test'); 532 $this->assertTrue($result); 533 $result = $zip_archive->add_file_from_pathname('test2.txt', $textfile); 534 $this->assertTrue($result); 535 // Delete the file before closing does force close() to fail. 536 unlink($textfile); 537 // Behavior is different between old PHP versions and new ones. Let's detect it. 538 $result = false; 539 try { 540 // Old PHP versions were not printing any warning. 541 $result = $zip_archive->close(); 542 } catch (\Exception $e) { 543 // New PHP versions print PHP Warning. 544 $this->assertInstanceOf('PHPUnit\Framework\Error\Warning', $e); 545 $this->assertStringContainsString('ZipArchive::close', $e->getMessage()); 546 } 547 // This is crazy, but it shows how some PHP versions do return true. 548 try { 549 // And some PHP versions do return correctly false (5.4.25, 5.6.14...) 550 $this->assertFalse($result); 551 } catch (\Exception $e) { 552 // But others do insist into returning true (5.6.13...). Only can accept them. 553 $this->assertInstanceOf('PHPUnit\Framework\ExpectationFailedException', $e); 554 $this->assertTrue($result); 555 } 556 $this->assertFileDoesNotExist($archive); 557 } 558 559 /** 560 * @depends test_add_files 561 */ 562 public function test_open_archive() { 563 global $CFG; 564 565 $this->resetAfterTest(true); 566 567 $archive = "$CFG->tempdir/archive.zip"; 568 569 $this->assertFileDoesNotExist($archive); 570 571 $zip_archive = new zip_archive(); 572 $result = $zip_archive->open($archive, file_archive::OPEN); 573 $this->assertFalse($result); 574 $this->assertDebuggingCalled(); 575 576 $zip_archive = new zip_archive(); 577 $result = $zip_archive->open($archive, file_archive::CREATE); 578 $this->assertTrue($result); 579 $zip_archive->add_file_from_string('test.txt', 'test'); 580 $zip_archive->close(); 581 $zip_archive->open($archive, file_archive::OPEN); 582 $this->assertEquals(1, $zip_archive->count()); 583 584 $zip_archive = new zip_archive(); 585 $result = $zip_archive->open($archive, file_archive::OVERWRITE); 586 $this->assertTrue($result); 587 $zip_archive->add_file_from_string('test2.txt', 'test'); 588 $zip_archive->close(); 589 $zip_archive->open($archive, file_archive::OPEN); 590 $this->assertEquals(1, $zip_archive->count()); 591 $zip_archive->close(); 592 593 unlink($archive); 594 $zip_archive = new zip_archive(); 595 $result = $zip_archive->open($archive, file_archive::OVERWRITE); 596 $this->assertTrue($result); 597 $zip_archive->add_file_from_string('test2.txt', 'test'); 598 $zip_archive->close(); 599 $zip_archive->open($archive, file_archive::OPEN); 600 $this->assertEquals(1, $zip_archive->count()); 601 $zip_archive->close(); 602 603 unlink($archive); 604 } 605 606 /** 607 * Test opening an encrypted archive 608 */ 609 public function test_open_encrypted_archive() { 610 $this->resetAfterTest(); 611 612 // The archive contains a single encrypted "hello.txt" file. 613 $archive = __DIR__ . '/fixtures/passwordis1.zip'; 614 615 /** @var zip_packer $packer */ 616 $packer = get_file_packer('application/zip'); 617 $result = $packer->extract_to_pathname($archive, make_temp_directory('zip')); 618 619 $this->assertIsArray($result); 620 $this->assertArrayHasKey('hello.txt', $result); 621 $this->assertEquals('Can not read file from zip archive', $result['hello.txt']); 622 } 623 624 /** 625 * Tests the progress reporting. 626 */ 627 public function test_file_progress() { 628 global $CFG; 629 630 // Set up. 631 $this->resetAfterTest(true); 632 $packer = get_file_packer('application/zip'); 633 $archive = "$CFG->tempdir/archive.zip"; 634 $context = \context_system::instance(); 635 636 // Archive to pathname. 637 $this->progress = array(); 638 $result = $packer->archive_to_pathname($this->files, $archive, true, $this); 639 $this->assertTrue($result); 640 // Should send progress at least once per file. 641 $this->assertTrue(count($this->progress) >= count($this->files)); 642 // Each progress will be indeterminate. 643 $this->assertEquals( 644 array(file_progress::INDETERMINATE, file_progress::INDETERMINATE), 645 $this->progress[0]); 646 647 // Archive to pathname using entire folder and subfolder instead of file list. 648 unlink($archive); 649 $folder = make_temp_directory('zip_packer_progress'); 650 file_put_contents($folder . '/test1.txt', 'hello'); 651 $subfolder = $folder . '/sub'; 652 check_dir_exists($subfolder); 653 file_put_contents($subfolder . '/test2.txt', 'world'); 654 file_put_contents($subfolder . '/test3.txt', 'and'); 655 file_put_contents($subfolder . '/test4.txt', 'other'); 656 file_put_contents($subfolder . '/test5.txt', 'worlds'); 657 $this->progress = array(); 658 $result = $packer->archive_to_pathname(array('' => $folder), $archive, true, $this); 659 $this->assertTrue($result); 660 // Should send progress at least once per file. 661 $this->assertTrue(count($this->progress) >= 5); 662 663 // Archive to storage. 664 $this->progress = array(); 665 $archivefile = $packer->archive_to_storage($this->files, $context->id, 666 'phpunit', 'test', 0, '/', 'archive.zip', null, true, $this); 667 $this->assertInstanceOf('stored_file', $archivefile); 668 $this->assertTrue(count($this->progress) >= count($this->files)); 669 $this->assertEquals( 670 array(file_progress::INDETERMINATE, file_progress::INDETERMINATE), 671 $this->progress[0]); 672 673 // Extract to pathname. 674 $this->progress = array(); 675 $target = "$CFG->tempdir/test/"; 676 check_dir_exists($target); 677 $result = $packer->extract_to_pathname($archive, $target, null, $this); 678 remove_dir($target); 679 $this->assertEquals(count($this->files), count($result)); 680 $this->assertTrue(count($this->progress) >= count($this->files)); 681 $this->check_progress_toward_max(); 682 683 // Extract to storage (from storage). 684 $this->progress = array(); 685 $result = $packer->extract_to_storage($archivefile, $context->id, 686 'phpunit', 'target', 0, '/', null, $this); 687 $this->assertEquals(count($this->files), count($result)); 688 $this->assertTrue(count($this->progress) >= count($this->files)); 689 $this->check_progress_toward_max(); 690 691 // Extract to storage (from path). 692 $this->progress = array(); 693 $result = $packer->extract_to_storage($archive, $context->id, 694 'phpunit', 'target', 0, '/', null, $this); 695 $this->assertEquals(count($this->files), count($result)); 696 $this->assertTrue(count($this->progress) >= count($this->files)); 697 $this->check_progress_toward_max(); 698 699 // Wipe created disk file. 700 unlink($archive); 701 } 702 703 /** 704 * Checks that progress reported is numeric rather than indeterminate, 705 * and follows the progress reporting rules. 706 */ 707 private function check_progress_toward_max() { 708 $lastvalue = -1; 709 foreach ($this->progress as $progressitem) { 710 list($value, $max) = $progressitem; 711 $this->assertNotEquals(file_progress::INDETERMINATE, $max); 712 $this->assertTrue($value <= $max); 713 $this->assertTrue($value >= $lastvalue); 714 $lastvalue = $value; 715 } 716 } 717 718 /** 719 * Handles file_progress interface. 720 * 721 * @param int $progress 722 * @param int $max 723 */ 724 public function progress($progress = file_progress::INDETERMINATE, $max = file_progress::INDETERMINATE) { 725 $this->progress[] = array($progress, $max); 726 } 727 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body