<?php 
 
/** @noinspection PhpUnhandledExceptionInspection */ 
 
declare(strict_types=1); 
 
namespace MySQLReplication\Tests\Unit\BinaryDataReader; 
 
use MySQLReplication\BinaryDataReader\BinaryDataReader; 
use MySQLReplication\BinaryDataReader\BinaryDataReaderException; 
use PHPUnit\Framework\Attributes\DataProvider; 
use PHPUnit\Framework\TestCase; 
 
class BinaryDataReaderTest extends TestCase 
{ 
    public function testShouldRead(): void 
    { 
        $expected = 'za?ó?? g??l? ja??'; 
        self::assertSame($expected, pack('H*', $this->getBinaryRead(unpack('H*', $expected)[1])->read(52))); 
    } 
 
    public function testShouldReadCodedBinary(): void 
    { 
        self::assertSame(0, $this->getBinaryRead(pack('C', ''))->readCodedBinary()); 
        self::assertNull($this->getBinaryRead(pack('C', BinaryDataReader::NULL_COLUMN))->readCodedBinary()); 
        self::assertSame( 
            0, 
            $this->getBinaryRead(pack('i', BinaryDataReader::UNSIGNED_SHORT_COLUMN))->readCodedBinary() 
        ); 
        self::assertSame( 
            0, 
            $this->getBinaryRead(pack('i', BinaryDataReader::UNSIGNED_INT24_COLUMN))->readCodedBinary() 
        ); 
    } 
 
    public function testShouldThrowErrorOnUnknownCodedBinary(): void 
    { 
        $this->expectException(BinaryDataReaderException::class); 
 
        $this->getBinaryRead(pack('i', 255)) 
            ->readCodedBinary(); 
    } 
 
    public static function dataProviderForUInt(): array 
    { 
        return [ 
            [1, pack('c', 1), 1], 
            [2, pack('v', 9999), 9999], 
            [3, pack('CCC', 160, 190, 15), 1031840], 
            [4, pack('I', 123123543), 123123543], 
            [5, pack('CI', 71, 2570258120), 657986078791], 
            [6, pack('v3', 2570258120, 2570258120, 2570258120), 7456176998088], 
            [7, pack('CSI', 66, 7890, 2570258120), 43121775657013826], 
        ]; 
    } 
 
    public function testShouldReadReadUInt64(): void 
    { 
        $this->assertSame( 
            '18374686483949813760', 
            $this->getBinaryRead(pack('VV', 4278190080, 4278190080)) 
                ->readUInt64() 
        ); 
    } 
 
    #[DataProvider('dataProviderForUInt')] 
    public function testShouldReadUIntBySize(mixed $size, mixed $data, mixed $expected): void 
    { 
        self::assertSame($expected, $this->getBinaryRead($data)->readUIntBySize($size)); 
    } 
 
    public function testShouldThrowErrorOnReadUIntBySizeNotSupported(): void 
    { 
        $this->expectException(BinaryDataReaderException::class); 
 
        $this->getBinaryRead('') 
            ->readUIntBySize(32); 
    } 
 
    public static function dataProviderForBeInt(): array 
    { 
        return [ 
            [1, pack('c', 4), 4], 
            [2, pack('n', 9999), 9999], 
            [3, pack('CCC', 160, 190, 15), -6242801], 
            [4, pack('i', 123123543), 1471632903], 
            [5, pack('NC', 71, 2570258120), 18376], 
        ]; 
    } 
 
    #[DataProvider('dataProviderForBeInt')] public function testShouldReadIntBeBySize( 
        int $size, 
        string $data, 
        int $expected 
    ): void { 
        self::assertSame($expected, $this->getBinaryRead($data)->readIntBeBySize($size)); 
    } 
 
    public function testShouldThrowErrorOnReadIntBeBySizeNotSupported(): void 
    { 
        $this->expectException(BinaryDataReaderException::class); 
 
        $this->getBinaryRead('') 
            ->readIntBeBySize(666); 
    } 
 
    public function testShouldReadInt16(): void 
    { 
        $expected = 1000; 
        self::assertSame($expected, $this->getBinaryRead(pack('s', $expected))->readInt16()); 
    } 
 
    public function testShouldUnreadAdvance(): void 
    { 
        $binaryDataReader = $this->getBinaryRead('123'); 
 
        self::assertEquals('123', $binaryDataReader->getBinaryData()); 
        self::assertEquals(0, $binaryDataReader->getReadBytes()); 
 
        $binaryDataReader->advance(2); 
 
        self::assertEquals('3', $binaryDataReader->getBinaryData()); 
        self::assertEquals(2, $binaryDataReader->getReadBytes()); 
 
        $binaryDataReader->unread('12'); 
 
        self::assertEquals('123', $binaryDataReader->getBinaryData()); 
        self::assertEquals(0, $binaryDataReader->getReadBytes()); 
    } 
 
    public function testShouldReadInt24(): void 
    { 
        self::assertSame(-6513508, $this->getBinaryRead(pack('C3', -100, -100, -100))->readInt24()); 
    } 
 
    public function testShouldReadInt64(): void 
    { 
        self::assertSame('-72057589759737856', $this->getBinaryRead(pack('VV', 4278190080, 4278190080))->readInt64()); 
    } 
 
    public function testShouldReadLengthCodedPascalString(): void 
    { 
        $expected = 255; 
        self::assertSame( 
            $expected, 
            hexdec(bin2hex($this->getBinaryRead(pack('cc', 1, $expected))->readLengthString(1))) 
        ); 
    } 
 
    public function testShouldReadInt32(): void 
    { 
        $expected = 777333; 
        self::assertSame($expected, $this->getBinaryRead(pack('i', $expected))->readInt32()); 
    } 
 
    public function testShouldReadFloat(): void 
    { 
        $expected = 0.001; 
        // we need to add round as php have problem with precision in floats 
        self::assertSame($expected, round($this->getBinaryRead(pack('f', $expected))->readFloat(), 3)); 
    } 
 
    public function testShouldReadDouble(): void 
    { 
        $expected = 1321312312.143567586; 
        self::assertSame($expected, $this->getBinaryRead(pack('d', $expected))->readDouble()); 
    } 
 
    public function testShouldReadTableId(): void 
    { 
        self::assertSame( 
            '7456176998088', 
            $this->getBinaryRead(pack('v3', 2570258120, 2570258120, 2570258120)) 
                ->readTableId() 
        ); 
    } 
 
    public function testShouldCheckIsCompleted(): void 
    { 
        self::assertFalse($this->getBinaryRead('')->isComplete(1)); 
 
        $r = $this->getBinaryRead(str_repeat('-', 30)); 
        $r->advance(21); 
        self::assertTrue($r->isComplete(1)); 
    } 
 
    public function testShouldPack64bit(): void 
    { 
        $expected = 9223372036854775807; 
        self::assertSame((string)$expected, $this->getBinaryRead(BinaryDataReader::pack64bit($expected))->readInt64()); 
    } 
 
    public function testShouldGetBinaryDataLength(): void 
    { 
        self::assertSame(3, $this->getBinaryRead('foo')->getBinaryDataLength()); 
    } 
 
    private function getBinaryRead(string $data): BinaryDataReader 
    { 
        return new BinaryDataReader($data); 
    } 
} 
 
 |