Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]
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(): void { 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 * Test functionality of {@see zip_packer} for entries with folders ending with dots. 259 * 260 * @link https://bugs.php.net/bug.php?id=77214 261 */ 262 public function test_zip_entry_path_having_folder_ending_with_dot() { 263 global $CFG; 264 265 $this->resetAfterTest(false); 266 267 $packer = get_file_packer('application/zip'); 268 $tmp = make_request_directory(); 269 $now = time(); 270 271 // Create a test archive containing a folder ending with dot. 272 $zippath = $tmp . '/test_archive.zip'; 273 $zipcontents = [ 274 'HOW.TO' => ['Just run tests.'], 275 'README.' => ['This is a test ZIP file'], 276 './Current time' => [$now], 277 'Data/sub1./sub2/1221' => ['1221'], 278 'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt' => [''], 279 ]; 280 281 if ($CFG->ostype === 'WINDOWS') { 282 // File names cannot end with dots on Windows and trailing dots are replaced with underscore. 283 $filenamemap = [ 284 'HOW.TO' => 'HOW.TO', 285 'README.' => 'README_', 286 './Current time' => 'Current time', 287 'Data/sub1./sub2/1221' => 'Data/sub1_/sub2/1221', 288 'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt' => 289 'Data/sub1_/sub2_/Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt', 290 ]; 291 292 } else { 293 $filenamemap = [ 294 'HOW.TO' => 'HOW.TO', 295 'README.' => 'README.', 296 './Current time' => 'Current time', 297 'Data/sub1./sub2/1221' => 'Data/sub1./sub2/1221', 298 'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt' => 299 'Data/sub1./sub2./Příliš žluťoučký kůň úpěl Ďábelské Ódy.txt', 300 ]; 301 } 302 303 // Check that the archive can be created. 304 $result = $packer->archive_to_pathname($zipcontents, $zippath, false); 305 $this->assertTrue($result); 306 307 // Check list of files. 308 $listfiles = $packer->list_files($zippath); 309 $this->assertEquals(count($zipcontents), count($listfiles)); 310 311 foreach ($listfiles as $fileinfo) { 312 $this->assertSame($fileinfo->pathname, $fileinfo->original_pathname); 313 $this->assertArrayHasKey($fileinfo->pathname, $zipcontents); 314 } 315 316 // Check actual extracting. 317 $targetpath = $tmp . '/target'; 318 check_dir_exists($targetpath); 319 $result = $packer->extract_to_pathname($zippath, $targetpath, null, null, true); 320 321 $this->assertTrue($result); 322 323 foreach ($zipcontents as $filename => $filecontents) { 324 $filecontents = reset($filecontents); 325 $this->assertTrue(is_readable($targetpath . '/' . $filenamemap[$filename])); 326 $this->assertEquals($filecontents, file_get_contents($targetpath . '/' . $filenamemap[$filename])); 327 } 328 } 329 330 /** 331 * @depends test_archive_to_storage 332 */ 333 public function test_extract_to_pathname_onlyfiles() { 334 global $CFG; 335 336 $this->resetAfterTest(false); 337 338 $packer = get_file_packer('application/zip'); 339 $fs = get_file_storage(); 340 $context = context_system::instance(); 341 342 $target = "$CFG->tempdir/onlyfiles/"; 343 $testcontent = file_get_contents($this->testfile); 344 345 @mkdir($target, $CFG->directorypermissions); 346 $this->assertTrue(is_dir($target)); 347 348 $onlyfiles = array('test', 'test.test', 'Žluťoučký/Koníček.txt', 'Idontexist'); 349 $willbeextracted = array_intersect(array_keys($this->files), $onlyfiles); 350 $donotextract = array_diff(array_keys($this->files), $onlyfiles); 351 352 $archive = "$CFG->tempdir/archive.zip"; 353 $this->assertFileExists($archive); 354 $result = $packer->extract_to_pathname($archive, $target, $onlyfiles); 355 $this->assertTrue(is_array($result)); 356 $this->assertEquals(count($willbeextracted), count($result)); 357 358 foreach ($willbeextracted as $file) { 359 $this->assertTrue($result[$file]); 360 $this->assertFileExists($target.$file); 361 $this->assertSame($testcontent, file_get_contents($target.$file)); 362 } 363 foreach ($donotextract as $file) { 364 $this->assertFalse(isset($result[$file])); 365 $this->assertFileNotExists($target.$file); 366 } 367 368 } 369 370 /** 371 * @depends test_archive_to_storage 372 */ 373 public function test_extract_to_pathname_returnvalue_successful() { 374 global $CFG; 375 376 $this->resetAfterTest(false); 377 378 $packer = get_file_packer('application/zip'); 379 380 $target = make_request_directory(); 381 382 $archive = "$CFG->tempdir/archive.zip"; 383 $this->assertFileExists($archive); 384 $result = $packer->extract_to_pathname($archive, $target, null, null, true); 385 $this->assertTrue($result); 386 } 387 388 /** 389 * @depends test_archive_to_storage 390 */ 391 public function test_extract_to_pathname_returnvalue_failure() { 392 global $CFG; 393 394 $this->resetAfterTest(false); 395 396 $packer = get_file_packer('application/zip'); 397 398 $target = make_request_directory(); 399 400 $archive = "$CFG->tempdir/noarchive.zip"; 401 $result = $packer->extract_to_pathname($archive, $target, null, null, true); 402 $this->assertFalse($result); 403 } 404 405 /** 406 * @depends test_archive_to_storage 407 */ 408 public function test_extract_to_storage() { 409 global $CFG; 410 411 $this->resetAfterTest(false); 412 413 $packer = get_file_packer('application/zip'); 414 $fs = get_file_storage(); 415 $context = context_system::instance(); 416 417 $testcontent = file_get_contents($this->testfile); 418 419 $archive = $fs->get_file($context->id, 'phpunit', 'test', 0, '/', 'archive.zip'); 420 $this->assertNotEmpty($archive); 421 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); 422 $this->assertTrue(is_array($result)); 423 $this->assertEquals(count($this->files), count($result)); 424 foreach ($this->files as $file => $unused) { 425 $this->assertTrue($result[$file]); 426 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); 427 $this->assertInstanceOf('stored_file', $stored_file); 428 $this->assertSame($testcontent, $stored_file->get_content()); 429 } 430 431 $archive = "$CFG->tempdir/archive.zip"; 432 $this->assertFileExists($archive); 433 $result = $packer->extract_to_storage($archive, $context->id, 'phpunit', 'target', 0, '/'); 434 $this->assertTrue(is_array($result)); 435 $this->assertEquals(count($this->files), count($result)); 436 foreach ($this->files as $file => $unused) { 437 $this->assertTrue($result[$file]); 438 $stored_file = $fs->get_file_by_hash(sha1("/$context->id/phpunit/target/0/$file")); 439 $this->assertInstanceOf('stored_file', $stored_file); 440 $this->assertSame($testcontent, $stored_file->get_content()); 441 } 442 unlink($archive); 443 } 444 445 /** 446 * @depends test_extract_to_storage 447 */ 448 public function test_add_files() { 449 global $CFG; 450 451 $this->resetAfterTest(false); 452 453 $packer = get_file_packer('application/zip'); 454 $archive = "$CFG->tempdir/archive.zip"; 455 456 $this->assertFileNotExists($archive); 457 $packer->archive_to_pathname(array(), $archive); 458 $this->assertFileExists($archive); 459 460 $zip_archive = new zip_archive(); 461 $zip_archive->open($archive, file_archive::OPEN); 462 $this->assertEquals(0, $zip_archive->count()); 463 464 $zip_archive->add_file_from_string('test.txt', 'test'); 465 $zip_archive->close(); 466 $zip_archive->open($archive, file_archive::OPEN); 467 $this->assertEquals(1, $zip_archive->count()); 468 469 $zip_archive->add_directory('test2'); 470 $zip_archive->close(); 471 $zip_archive->open($archive, file_archive::OPEN); 472 $files = $zip_archive->list_files(); 473 $this->assertCount(2, $files); 474 $this->assertEquals('test.txt', $files[0]->pathname); 475 $this->assertEquals('test2/', $files[1]->pathname); 476 477 $result = $zip_archive->add_file_from_pathname('test.txt', __DIR__.'/nonexistent/file.txt'); 478 $this->assertFalse($result); 479 $zip_archive->close(); 480 $zip_archive->open($archive, file_archive::OPEN); 481 $this->assertEquals(2, $zip_archive->count()); 482 $zip_archive->close(); 483 484 unlink($archive); 485 } 486 487 public function test_close_archive() { 488 global $CFG; 489 490 $this->resetAfterTest(true); 491 492 $archive = "$CFG->tempdir/archive.zip"; 493 $textfile = "$CFG->tempdir/textfile.txt"; 494 touch($textfile); 495 496 $this->assertFileNotExists($archive); 497 $this->assertFileExists($textfile); 498 499 // Create archive and close it without files. 500 // (returns true, without any warning). 501 $zip_archive = new zip_archive(); 502 $result = $zip_archive->open($archive, file_archive::CREATE); 503 $this->assertTrue($result); 504 $result = $zip_archive->close(); 505 $this->assertTrue($result); 506 unlink($archive); 507 508 // Create archive and close it with files. 509 // (returns true, without any warning). 510 $zip_archive = new zip_archive(); 511 $result = $zip_archive->open($archive, file_archive::CREATE); 512 $this->assertTrue($result); 513 $result = $zip_archive->add_file_from_string('test.txt', 'test'); 514 $this->assertTrue($result); 515 $result = $zip_archive->add_file_from_pathname('test2.txt', $textfile); 516 $result = $zip_archive->close(); 517 $this->assertTrue($result); 518 unlink($archive); 519 520 // Create archive and close if forcing error. 521 // (returns true for old PHP versions and 522 // false with warnings for new PHP versions). MDL-51863. 523 $zip_archive = new zip_archive(); 524 $result = $zip_archive->open($archive, file_archive::CREATE); 525 $this->assertTrue($result); 526 $result = $zip_archive->add_file_from_string('test.txt', 'test'); 527 $this->assertTrue($result); 528 $result = $zip_archive->add_file_from_pathname('test2.txt', $textfile); 529 $this->assertTrue($result); 530 // Delete the file before closing does force close() to fail. 531 unlink($textfile); 532 // Behavior is different between old PHP versions and new ones. Let's detect it. 533 $result = false; 534 try { 535 // Old PHP versions were not printing any warning. 536 $result = $zip_archive->close(); 537 } catch (Exception $e) { 538 // New PHP versions print PHP Warning. 539 $this->assertInstanceOf('PHPUnit\Framework\Error\Warning', $e); 540 $this->assertStringContainsString('ZipArchive::close', $e->getMessage()); 541 } 542 // This is crazy, but it shows how some PHP versions do return true. 543 try { 544 // And some PHP versions do return correctly false (5.4.25, 5.6.14...) 545 $this->assertFalse($result); 546 } catch (Exception $e) { 547 // But others do insist into returning true (5.6.13...). Only can accept them. 548 $this->assertInstanceOf('PHPUnit\Framework\ExpectationFailedException', $e); 549 $this->assertTrue($result); 550 } 551 $this->assertFileNotExists($archive); 552 } 553 554 /** 555 * @depends test_add_files 556 */ 557 public function test_open_archive() { 558 global $CFG; 559 560 $this->resetAfterTest(true); 561 562 $archive = "$CFG->tempdir/archive.zip"; 563 564 $this->assertFileNotExists($archive); 565 566 $zip_archive = new zip_archive(); 567 $result = $zip_archive->open($archive, file_archive::OPEN); 568 $this->assertFalse($result); 569 $this->assertDebuggingCalled(); 570 571 $zip_archive = new zip_archive(); 572 $result = $zip_archive->open($archive, file_archive::CREATE); 573 $this->assertTrue($result); 574 $zip_archive->add_file_from_string('test.txt', 'test'); 575 $zip_archive->close(); 576 $zip_archive->open($archive, file_archive::OPEN); 577 $this->assertEquals(1, $zip_archive->count()); 578 579 $zip_archive = new zip_archive(); 580 $result = $zip_archive->open($archive, file_archive::OVERWRITE); 581 $this->assertTrue($result); 582 $zip_archive->add_file_from_string('test2.txt', 'test'); 583 $zip_archive->close(); 584 $zip_archive->open($archive, file_archive::OPEN); 585 $this->assertEquals(1, $zip_archive->count()); 586 $zip_archive->close(); 587 588 unlink($archive); 589 $zip_archive = new zip_archive(); 590 $result = $zip_archive->open($archive, file_archive::OVERWRITE); 591 $this->assertTrue($result); 592 $zip_archive->add_file_from_string('test2.txt', 'test'); 593 $zip_archive->close(); 594 $zip_archive->open($archive, file_archive::OPEN); 595 $this->assertEquals(1, $zip_archive->count()); 596 $zip_archive->close(); 597 598 unlink($archive); 599 } 600 601 /** 602 * Test opening an encrypted archive 603 */ 604 public function test_open_encrypted_archive() { 605 $this->resetAfterTest(); 606 607 // The archive contains a single encrypted "hello.txt" file. 608 $archive = __DIR__ . '/fixtures/passwordis1.zip'; 609 610 /** @var zip_packer $packer */ 611 $packer = get_file_packer('application/zip'); 612 $result = $packer->extract_to_pathname($archive, make_temp_directory('zip')); 613 614 $this->assertIsArray($result); 615 $this->assertArrayHasKey('hello.txt', $result); 616 $this->assertEquals('Can not read file from zip archive', $result['hello.txt']); 617 } 618 619 /** 620 * Tests the progress reporting. 621 */ 622 public function test_file_progress() { 623 global $CFG; 624 625 // Set up. 626 $this->resetAfterTest(true); 627 $packer = get_file_packer('application/zip'); 628 $archive = "$CFG->tempdir/archive.zip"; 629 $context = context_system::instance(); 630 631 // Archive to pathname. 632 $this->progress = array(); 633 $result = $packer->archive_to_pathname($this->files, $archive, true, $this); 634 $this->assertTrue($result); 635 // Should send progress at least once per file. 636 $this->assertTrue(count($this->progress) >= count($this->files)); 637 // Each progress will be indeterminate. 638 $this->assertEquals( 639 array(file_progress::INDETERMINATE, file_progress::INDETERMINATE), 640 $this->progress[0]); 641 642 // Archive to pathname using entire folder and subfolder instead of file list. 643 unlink($archive); 644 $folder = make_temp_directory('zip_packer_progress'); 645 file_put_contents($folder . '/test1.txt', 'hello'); 646 $subfolder = $folder . '/sub'; 647 check_dir_exists($subfolder); 648 file_put_contents($subfolder . '/test2.txt', 'world'); 649 file_put_contents($subfolder . '/test3.txt', 'and'); 650 file_put_contents($subfolder . '/test4.txt', 'other'); 651 file_put_contents($subfolder . '/test5.txt', 'worlds'); 652 $this->progress = array(); 653 $result = $packer->archive_to_pathname(array('' => $folder), $archive, true, $this); 654 $this->assertTrue($result); 655 // Should send progress at least once per file. 656 $this->assertTrue(count($this->progress) >= 5); 657 658 // Archive to storage. 659 $this->progress = array(); 660 $archivefile = $packer->archive_to_storage($this->files, $context->id, 661 'phpunit', 'test', 0, '/', 'archive.zip', null, true, $this); 662 $this->assertInstanceOf('stored_file', $archivefile); 663 $this->assertTrue(count($this->progress) >= count($this->files)); 664 $this->assertEquals( 665 array(file_progress::INDETERMINATE, file_progress::INDETERMINATE), 666 $this->progress[0]); 667 668 // Extract to pathname. 669 $this->progress = array(); 670 $target = "$CFG->tempdir/test/"; 671 check_dir_exists($target); 672 $result = $packer->extract_to_pathname($archive, $target, null, $this); 673 remove_dir($target); 674 $this->assertEquals(count($this->files), count($result)); 675 $this->assertTrue(count($this->progress) >= count($this->files)); 676 $this->check_progress_toward_max(); 677 678 // Extract to storage (from storage). 679 $this->progress = array(); 680 $result = $packer->extract_to_storage($archivefile, $context->id, 681 'phpunit', 'target', 0, '/', null, $this); 682 $this->assertEquals(count($this->files), count($result)); 683 $this->assertTrue(count($this->progress) >= count($this->files)); 684 $this->check_progress_toward_max(); 685 686 // Extract to storage (from path). 687 $this->progress = array(); 688 $result = $packer->extract_to_storage($archive, $context->id, 689 'phpunit', 'target', 0, '/', null, $this); 690 $this->assertEquals(count($this->files), count($result)); 691 $this->assertTrue(count($this->progress) >= count($this->files)); 692 $this->check_progress_toward_max(); 693 694 // Wipe created disk file. 695 unlink($archive); 696 } 697 698 /** 699 * Checks that progress reported is numeric rather than indeterminate, 700 * and follows the progress reporting rules. 701 */ 702 private function check_progress_toward_max() { 703 $lastvalue = -1; 704 foreach ($this->progress as $progressitem) { 705 list($value, $max) = $progressitem; 706 $this->assertNotEquals(file_progress::INDETERMINATE, $max); 707 $this->assertTrue($value <= $max); 708 $this->assertTrue($value >= $lastvalue); 709 $lastvalue = $value; 710 } 711 } 712 713 /** 714 * Handles file_progress interface. 715 * 716 * @param int $progress 717 * @param int $max 718 */ 719 public function progress($progress = file_progress::INDETERMINATE, $max = file_progress::INDETERMINATE) { 720 $this->progress[] = array($progress, $max); 721 } 722 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body