CRC64 class and fixes for ACL Login unit tests
This commit is contained in:
1 parent
13df70acd4
commit
979bf17748
11 files changed
+4573
-8
No files matched your search
File diff suppressed because it is too large.
Load diff
+1999
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AUTHOR: Clemens Schwaighofer
|
||||
* CREATED: 2026/10/15
|
||||
* DESCRIPTION:
|
||||
* AWS CRC64 Implementation
|
||||
* This can be replaced by:
|
||||
* https://github.com/awesomized/crc-fast-php-ext
|
||||
* This this needs: https://github.com/awesomized/crc-fast-rust
|
||||
* installed, and there is no easy binary package available.
|
||||
*
|
||||
* NOTE: for anything larger than 10MB this is absolutely NOT recommended
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CoreLibs\Create;
|
||||
|
||||
class Crc64
|
||||
{
|
||||
/**
|
||||
* Internal CRC64 calculation for a given data string.
|
||||
*
|
||||
* @param string $data
|
||||
* @param int $crc
|
||||
* @return int
|
||||
*/
|
||||
private function crc64Calc(string $data, int $crc = 0): int
|
||||
{
|
||||
static $table = null;
|
||||
if ($table === null) {
|
||||
// reflected poly 0x9A6C9329AC4BC9B5 (built from halves, too big for a PHP int literal)
|
||||
$poly = (0x9A6C9329 << 32) | 0xAC4BC9B5;
|
||||
$table = [];
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
$c = $i;
|
||||
for ($k = 0; $k < 8; $k++) {
|
||||
// logical right shift: PHP >> is arithmetic, so mask off the sign bit
|
||||
$c = ($c & 1)
|
||||
? ((($c >> 1) & PHP_INT_MAX) ^ $poly)
|
||||
: (($c >> 1) & PHP_INT_MAX);
|
||||
}
|
||||
$table[$i] = $c;
|
||||
}
|
||||
}
|
||||
$crc = ~$crc; // xor 0xFFFFFFFFFFFFFFFF
|
||||
foreach (unpack('C*', $data) ?: [] as $b) {
|
||||
$crc = $table[($crc ^ $b) & 0xFF] ^ (($crc >> 8) & 0x00FFFFFFFFFFFFFF);
|
||||
}
|
||||
return ~$crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns int value of the CRC64 checksum for the given file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int<1,16777216> $chunkSize
|
||||
* @return int
|
||||
*/
|
||||
private function crc64CalcFile(string $path, int $chunkSize = 8 * 1024 * 1024): int
|
||||
{
|
||||
$fh = fopen($path, 'rb');
|
||||
if ($fh === false) {
|
||||
throw new \RuntimeException("Cannot open $path");
|
||||
}
|
||||
$crc = 0;
|
||||
try {
|
||||
while (!feof($fh)) {
|
||||
$chunk = fread($fh, $chunkSize);
|
||||
if ($chunk === false) {
|
||||
throw new \RuntimeException("Read error on $path");
|
||||
}
|
||||
$crc = $this->crc64Calc($chunk, $crc);
|
||||
}
|
||||
} finally {
|
||||
fclose($fh);
|
||||
}
|
||||
return $crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Base64-encoded CRC64 checksum for the given file.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public static function crc64(string $path): string
|
||||
{
|
||||
return base64_encode(pack('J', (new self())->crc64CalcFile($path))); // J = uint64 big-endian
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 16-character lowercase hexadecimal CRC64 checksum for the given file.
|
||||
* Same as base64.b64decode(...).hex()
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public static function crc64hex(string $path): string
|
||||
{
|
||||
return sprintf('%016x', (new self())->crc64CalcFile($path));
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
@@ -46,7 +46,8 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
// database/CoreLibsACLLogin_database_create_data.sql
|
||||
$load_sql_file = __DIR__
|
||||
. DIRECTORY_SEPARATOR
|
||||
. 'database/CoreLibsACLLogin_database_create_data.sql';
|
||||
. 'database' . DIRECTORY_SEPARATOR
|
||||
. 'CoreLibsACLLogin_database_create_data.sql';
|
||||
if (!is_file($load_sql_file)) {
|
||||
self::markTestIncomplete(
|
||||
'Missing ACL\Login database load SQL file'
|
||||
@@ -63,6 +64,7 @@ final class CoreLibsACLLoginTest extends TestCase
|
||||
. "CoreLibsACLLogin_database_prepare.sh "
|
||||
. "$load_sql_file "
|
||||
. "$db_user "
|
||||
. "$db_password "
|
||||
. "$db_name "
|
||||
. "$db_host ";
|
||||
exec($command, $ouput, $result);
|
||||
|
||||
@@ -22,31 +22,32 @@ if ! command -v dropdb &> /dev/null || ! command -v createdb &> /dev/null || ! c
|
||||
fi;
|
||||
|
||||
db_user="${2}";
|
||||
db_name="${3}";
|
||||
db_host="${4}";
|
||||
db_password="${3}";
|
||||
db_name="${4}";
|
||||
db_host="${5}";
|
||||
# empty db name or db user -> exit with 2
|
||||
if [ -z "${db_user}" ] || [ -z "${db_name}" ] || [ -z "${db_host}" ]; then
|
||||
if [ -z "${db_user}" ] || [ -z "${db_name}" ] || [ -z "${db_password}" ] || [ -z "${db_host}" ]; then
|
||||
echo 2;
|
||||
exit 2;
|
||||
fi;
|
||||
# drop database, on error exit with 3
|
||||
dropdb -U "${db_user}" -h "${db_host}" "${db_name}" 2>&1;
|
||||
PGPASSWORD="${db_password}" dropdb -U "${db_user}" -h "${db_host}" "${db_name}" 2>&1;
|
||||
if [ ! $? ]; then
|
||||
echo 3;
|
||||
exit 3;
|
||||
fi;
|
||||
# create database, on error exit with 4
|
||||
createdb -U "${db_user}" -O "${db_user}" -h "${db_host}" -E utf8 "${db_name}" 2>&1;
|
||||
PGPASSWORD="${db_password}" createdb -U "${db_user}" -O "${db_user}" -h "${db_host}" -E utf8 "${db_name}" 2>&1;
|
||||
if [ ! $? ]; then
|
||||
echo 4;
|
||||
exit 4;
|
||||
fi;
|
||||
# if error 5 thrown, test with enabled below
|
||||
if [ -n "${5}" ]; then
|
||||
psql -U "${db_user}" -h "${db_host}" -f "${load_sql}" "${db_name}";
|
||||
PGPASSWORD="${db_password}" psql -U "${db_user}" -h "${db_host}" -f "${load_sql}" "${db_name}";
|
||||
else
|
||||
# load data (redirect ALL error to null), on error exit with 5
|
||||
psql -U "${db_user}" -h "${db_host}" -f "${load_sql}" "${db_name}" 2>&1 1>/dev/null 2>/dev/null;
|
||||
PGPASSWORD="${db_password}" psql -U "${db_user}" -h "${db_host}" -f "${load_sql}" "${db_name}" 2>&1 1>/dev/null 2>/dev/null;
|
||||
fi;
|
||||
if [ ! $? ]; then
|
||||
echo 5;
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test class for Create\Crc64
|
||||
* @coversDefaultClass \CoreLibs\Create\Crc64
|
||||
* @testdox \CoreLibs\Create\Crc64 method tests
|
||||
*/
|
||||
final class CoreLibsCreateCrc64Test extends TestCase
|
||||
{
|
||||
public function providerFiles(): array
|
||||
{
|
||||
return [
|
||||
'10kb' => [
|
||||
'file' => __DIR__ . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . 'random_10KB.bin',
|
||||
'crc64_base64' => 'oMgkUkGrDME=',
|
||||
'crc64_hex' => 'a0c8245241ab0cc1',
|
||||
],
|
||||
'100kb' => [
|
||||
'file' => __DIR__ . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . 'random_100KB.bin',
|
||||
'crc64_base64' => 'i9Lpf3Y3D3M=',
|
||||
'crc64_hex' => '8bd2e97f76370f73',
|
||||
],
|
||||
'1mb' => [
|
||||
'file' => __DIR__ . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . 'random_1MB.bin',
|
||||
'crc64_base64' => 'WqYAirRJ0q8=',
|
||||
'crc64_hex' => '5aa6008ab449d2af',
|
||||
],
|
||||
'5mb' => [
|
||||
'file' => __DIR__ . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . 'random_5MB.bin',
|
||||
'crc64_base64' => '9hS5kUxbgR0=',
|
||||
'crc64_hex' => 'f614b9914c5b811d',
|
||||
],
|
||||
'10mb' => [
|
||||
'file' => __DIR__ . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . 'random_10MB.bin',
|
||||
'crc64_base64' => 'xDmtkk1JhjM=',
|
||||
'crc64_hex' => 'c439ad924d498633',
|
||||
],
|
||||
// everything above 10MB is too slow, sow do not check this
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @covers ::crc64
|
||||
* @covers ::crc64hex
|
||||
* @dataProvider providerFiles
|
||||
* @testdox generate crc64 for $file and expecting $crc64_base64 and $crc64_hex [$_dataName]
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCrc64(string $file, string $crc64_base64, string $crc64_hex): void
|
||||
{
|
||||
$this->assertSame(
|
||||
$crc64_base64,
|
||||
\CoreLibs\Create\Crc64::crc64($file),
|
||||
"Failed asserting base64 CRC64 for $file"
|
||||
);
|
||||
$this->assertSame(
|
||||
$crc64_hex,
|
||||
\CoreLibs\Create\Crc64::crc64hex($file),
|
||||
"Failed asserting hex CRC64 for $file"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// __END__
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user