You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
227 lines
7.1 KiB
227 lines
7.1 KiB
<?php
|
|
|
|
include_once dirname(__FILE__).'/../zipinfo.php';
|
|
|
|
/**
|
|
* Test case for ZipInfo.
|
|
*
|
|
* @group zip
|
|
*/
|
|
class ZipInfoTest extends PHPUnit_Framework_TestCase
|
|
{
|
|
protected $fixturesDir;
|
|
|
|
/**
|
|
* This method is called before each test is executed.
|
|
*/
|
|
protected function setUp()
|
|
{
|
|
$this->fixturesDir = realpath(dirname(__FILE__).'/fixtures/zip');
|
|
}
|
|
|
|
/**
|
|
* ZIP files consist of a series of records with headers and optional bodies.
|
|
* The main info is divided between Local File and Central File records. We
|
|
* should be able to report an accurate list of all records in summmary form.
|
|
*
|
|
* @dataProvider providerTestFixtures
|
|
* @param string $filename sample zip filename
|
|
* @param string $records expected list of valid records
|
|
*/
|
|
public function testStoresListOfAllValidRecords($filename, $records)
|
|
{
|
|
$zip = new ZipInfo;
|
|
$zip->open($filename, true);
|
|
|
|
$this->assertEmpty($zip->error, $zip->error);
|
|
$recordList = $zip->getRecords();
|
|
$this->assertEquals(count($records), count($recordList));
|
|
$this->assertEquals($records, $recordList);
|
|
}
|
|
|
|
/**
|
|
* Provides test data from sample files.
|
|
*/
|
|
public function providerTestFixtures()
|
|
{
|
|
$ds = DIRECTORY_SEPARATOR;
|
|
$fixturesDir = realpath(dirname(__FILE__).'/fixtures/zip');
|
|
$fixtures = array();
|
|
|
|
foreach (glob($fixturesDir.$ds.'*.zip') as $rarfile) {
|
|
$fname = pathinfo($rarfile, PATHINFO_BASENAME).'.records';
|
|
$fpath = $fixturesDir.$ds.$fname;
|
|
if (file_exists($fpath)) {
|
|
$records = include $fpath;
|
|
$fixtures[] = array('filename' => $rarfile, 'records' => $records);
|
|
}
|
|
}
|
|
|
|
return $fixtures;
|
|
}
|
|
|
|
/**
|
|
* We should be able to report on the contents of the ZIP file, with some
|
|
* simple processing of the raw File blocks to make them human-readable.
|
|
*/
|
|
public function testListsAllArchiveFiles()
|
|
{
|
|
$zip = new ZipInfo;
|
|
$zip->open($this->fixturesDir.'/pecl_test.zip');
|
|
|
|
$files = $zip->getFileList();
|
|
$this->assertCount(4, $files);
|
|
|
|
$this->assertSame('bar', $files[0]['name']);
|
|
$this->assertSame(4, $files[0]['size']);
|
|
$this->assertSame(1123171908, $files[0]['date']);
|
|
$this->assertSame(0, $files[0]['pass']);
|
|
$this->assertSame(0, $files[0]['compressed']);
|
|
$this->assertSame('54-57', $files[0]['range']);
|
|
$this->assertSame('4a2b3e9', $files[0]['crc32']);
|
|
$this->assertArrayNotHasKey('is_dir', $files[0]);
|
|
|
|
$this->assertSame('foobar/', $files[1]['name']);
|
|
$this->assertSame(0, $files[1]['size']);
|
|
$this->assertSame(1123171948, $files[1]['date']);
|
|
$this->assertSame(0, $files[1]['pass']);
|
|
$this->assertSame(0, $files[1]['compressed']);
|
|
$this->assertArrayNotHasKey('range', $files[1]);
|
|
$this->assertArrayNotHasKey('crc32', $files[1]);
|
|
$this->assertArrayHasKey('is_dir', $files[1]);
|
|
|
|
$this->assertSame('foobar/baz', $files[2]['name']);
|
|
$this->assertSame(27, $files[2]['size']);
|
|
$this->assertSame(1123171948, $files[2]['date']);
|
|
$this->assertSame(0, $files[2]['pass']);
|
|
$this->assertSame(1, $files[2]['compressed']);
|
|
$this->assertSame('177-203', $files[2]['range']);
|
|
$this->assertSame('1dc53e58', $files[2]['crc32']);
|
|
$this->assertArrayNotHasKey('is_dir', $files[2]);
|
|
|
|
$this->assertSame('entry1.txt', $files[3]['name']);
|
|
$this->assertSame(8, $files[3]['size']);
|
|
$this->assertSame(1152216782, $files[3]['date']);
|
|
$this->assertSame(0, $files[3]['pass']);
|
|
$this->assertSame(1, $files[3]['compressed']);
|
|
$this->assertSame('241-248', $files[3]['range']);
|
|
$this->assertSame('f40c64db', $files[3]['crc32']);
|
|
$this->assertArrayNotHasKey('is_dir', $files[3]);
|
|
|
|
// Encrypted files should be reported
|
|
$zip->open($this->fixturesDir.'/encrypted_file.zip');
|
|
$files = $zip->getFileList();
|
|
$this->assertCount(1, $files);
|
|
$this->assertSame('test_date.txt', $files[0]['name']);
|
|
$this->assertSame(1, $files[0]['pass']);
|
|
$this->assertSame(0, $files[0]['compressed']);
|
|
$this->assertArrayNotHasKey('is_dir', $files[0]);
|
|
}
|
|
|
|
/**
|
|
* The End of Central Directory record keeps a count of files in the current
|
|
* volume, but if it's missing we should count the Local File records instead.
|
|
*/
|
|
public function testCountsLocalFileRecordsIfCentralDirectoryIsMissing()
|
|
{
|
|
$zip = new ZipInfo;
|
|
|
|
// Missing CDR, but has Local File record:
|
|
$zip->open($this->fixturesDir.'/large_file_start.zip');
|
|
$summary = $zip->getSummary();
|
|
$this->assertSame($zip->file, $summary['file_name']);
|
|
$this->assertSame($zip->fileCount, $summary['file_count']);
|
|
$this->assertSame(1, $summary['file_count']);
|
|
|
|
// Missing Local File record, but has CDR:
|
|
$zip->open($this->fixturesDir.'/large_file_end.zip');
|
|
$summary = $zip->getSummary();
|
|
$this->assertSame($zip->file, $summary['file_name']);
|
|
$this->assertSame($zip->fileCount, $summary['file_count']);
|
|
$this->assertSame(1, $summary['file_count']);
|
|
}
|
|
|
|
/**
|
|
* If the archive files aren't compressed, we should just be able to extract
|
|
* the file data and use it as is.
|
|
*/
|
|
public function testExtractsUncompressedFileData()
|
|
{
|
|
$zip = new ZipInfo;
|
|
$zip->open($this->fixturesDir.'/little_file.zip');
|
|
|
|
$files = $zip->getFileList();
|
|
$this->assertCount(1, $files);
|
|
$this->assertSame(0, $files[0]['compressed']);
|
|
|
|
$data = $zip->getFileData($files[0]['name']);
|
|
$this->assertSame($files[0]['size'], strlen($data));
|
|
$this->assertSame($files[0]['crc32'], dechex(crc32(($data))));
|
|
$this->assertSame("Some text.\n", $data);
|
|
}
|
|
|
|
/**
|
|
* Provides the path to the external client executable, or false if it
|
|
* doesn't exist in the given directory.
|
|
*
|
|
* @return string|boolean the absolute path to the executable, or false
|
|
*/
|
|
protected function getUnzipPath()
|
|
{
|
|
$unzip = DIRECTORY_SEPARATOR === '\\'
|
|
? dirname(__FILE__).'\bin\7z\7za.exe'
|
|
: dirname(__FILE__).'/bin/7z/7za';
|
|
|
|
if (file_exists($unzip))
|
|
return $unzip;
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Decompression of archive contents should be possible by using an external
|
|
* client to read the current file, or temporary files for data sources. The
|
|
* test should be skipped if no external client is available.
|
|
*
|
|
* @group external
|
|
*/
|
|
public function testDecompressesWithExternalClient()
|
|
{
|
|
if (!($unzip = $this->getUnzipPath())) {
|
|
$this->markTestSkipped();
|
|
}
|
|
$zip = new ZipInfo;
|
|
|
|
// From a file source
|
|
$zipfile = $this->fixturesDir.'/pecl_test.zip';
|
|
$zip->open($zipfile);
|
|
$this->assertEmpty($zip->error);
|
|
|
|
$files = $zip->getFileList();
|
|
$file = $files[3];
|
|
$this->assertSame('entry1.txt', $file['name']);
|
|
$this->assertSame(1, $file['compressed']);
|
|
|
|
$data = $zip->extractFile($file['name']);
|
|
$this->assertNotEmpty($zip->error);
|
|
$this->assertContains('external client', $zip->error);
|
|
$this->assertFalse($data);
|
|
|
|
$zip->setExternalClient($unzip);
|
|
$data = $zip->extractFile($file['name']);
|
|
$this->assertEmpty($zip->error,$zip->error);
|
|
$this->assertSame($file['size'], strlen($data));
|
|
$this->assertSame($file['crc32'], dechex(crc32(($data))));
|
|
$this->assertSame("entry #1", $data);
|
|
|
|
// From a data source (via temp file)
|
|
$zip->setData(file_get_contents($zipfile));
|
|
$this->assertEmpty($zip->error);
|
|
$summary = $zip->getSummary(true);
|
|
$this->assertSame(filesize($zipfile), $summary['data_size']);
|
|
$data = $zip->extractFile($file['name']);
|
|
$this->assertEmpty($zip->error);
|
|
$this->assertSame($file['size'], strlen($data));
|
|
}
|
|
|
|
} // End ZipInfoTest
|
|
|