blob: e0d8f4ba43cf8a097dfa27f1faea55ceb7310acd [file]
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
declare(strict_types=1);
namespace Test\Thrift\Unit\Lib\Protocol;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use Thrift\Exception\TProtocolException;
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Protocol\TProtocol;
use Thrift\Transport\TMemoryBuffer;
use Thrift\Type\TType;
class TProtocolTest extends TestCase
{
#[DataProvider('skipScalarDataProvider')]
public function testSkipScalarValues(int $type, string $writerMethod, $value): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol) use ($writerMethod, $value): void {
$protocol->{$writerMethod}($value);
}
);
$transport = new TMemoryBuffer($buffer);
$protocol = new TBinaryProtocol($transport);
$this->assertSame(strlen($buffer), $protocol->skip($type));
$this->assertSame(0, (int)$transport->available());
}
public static function skipScalarDataProvider(): iterable
{
yield 'bool' => [
TType::BOOL,
'writeBool',
true,
];
yield 'byte' => [
TType::BYTE,
'writeByte',
7,
];
yield 'i16' => [
TType::I16,
'writeI16',
1024,
];
yield 'i32' => [
TType::I32,
'writeI32',
65536,
];
yield 'i64' => [
TType::I64,
'writeI64',
1099511627776,
];
yield 'double' => [
TType::DOUBLE,
'writeDouble',
3.14,
];
yield 'string' => [
TType::STRING,
'writeString',
'skip me',
];
yield 'uuid' => [
TType::UUID,
'writeUuid',
'12345678-1234-5678-1234-567812345678',
];
}
public function testSkipStruct(): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol): void {
$protocol->writeStructBegin('Example');
$protocol->writeFieldBegin('flag', TType::BOOL, 1);
$protocol->writeBool(true);
$protocol->writeFieldEnd();
$protocol->writeFieldBegin('name', TType::STRING, 2);
$protocol->writeString('value');
$protocol->writeFieldEnd();
$protocol->writeFieldStop();
$protocol->writeStructEnd();
}
);
$transport = new TMemoryBuffer($buffer);
$protocol = new TBinaryProtocol($transport);
$this->assertSame(strlen($buffer), $protocol->skip(TType::STRUCT));
$this->assertSame(0, (int)$transport->available());
}
public function testSkipMap(): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol): void {
$protocol->writeMapBegin(TType::I32, TType::STRING, 2);
$protocol->writeI32(1);
$protocol->writeString('a');
$protocol->writeI32(2);
$protocol->writeString('bc');
$protocol->writeMapEnd();
}
);
$transport = new TMemoryBuffer($buffer);
$protocol = new TBinaryProtocol($transport);
$this->assertSame(strlen($buffer), $protocol->skip(TType::MAP));
$this->assertSame(0, (int)$transport->available());
}
public function testSkipSet(): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol): void {
$protocol->writeSetBegin(TType::I16, 2);
$protocol->writeI16(10);
$protocol->writeI16(20);
$protocol->writeSetEnd();
}
);
$transport = new TMemoryBuffer($buffer);
$protocol = new TBinaryProtocol($transport);
$this->assertSame(strlen($buffer), $protocol->skip(TType::SET));
$this->assertSame(0, (int)$transport->available());
}
public function testSkipList(): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol): void {
$protocol->writeListBegin(TType::STRING, 2);
$protocol->writeString('first');
$protocol->writeString('second');
$protocol->writeListEnd();
}
);
$transport = new TMemoryBuffer($buffer);
$protocol = new TBinaryProtocol($transport);
$this->assertSame(strlen($buffer), $protocol->skip(TType::LST));
$this->assertSame(0, (int)$transport->available());
}
public function testSkipThrowsForUnknownType(): void
{
$protocol = new TBinaryProtocol(new TMemoryBuffer());
$this->expectException(TProtocolException::class);
$this->expectExceptionCode(TProtocolException::INVALID_DATA);
$protocol->skip(999);
}
#[DataProvider('skipScalarDataProvider')]
public function testSkipBinaryScalarValues(int $type, string $writerMethod, $value): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol) use ($writerMethod, $value): void {
$protocol->{$writerMethod}($value);
}
);
$this->assertSkipBinaryConsumesBuffer($buffer, $type);
}
public function testSkipBinaryStruct(): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol): void {
$protocol->writeStructBegin('Example');
$protocol->writeFieldBegin('flag', TType::BOOL, 1);
$protocol->writeBool(true);
$protocol->writeFieldEnd();
$protocol->writeFieldBegin('name', TType::STRING, 2);
$protocol->writeString('value');
$protocol->writeFieldEnd();
$protocol->writeFieldStop();
$protocol->writeStructEnd();
}
);
$this->assertSkipBinaryConsumesBuffer($buffer, TType::STRUCT);
}
public function testSkipBinaryMap(): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol): void {
$protocol->writeMapBegin(TType::I32, TType::STRING, 2);
$protocol->writeI32(1);
$protocol->writeString('a');
$protocol->writeI32(2);
$protocol->writeString('bc');
$protocol->writeMapEnd();
}
);
$this->assertSkipBinaryConsumesBuffer($buffer, TType::MAP);
}
public function testSkipBinaryList(): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol): void {
$protocol->writeListBegin(TType::STRING, 2);
$protocol->writeString('first');
$protocol->writeString('second');
$protocol->writeListEnd();
}
);
$this->assertSkipBinaryConsumesBuffer($buffer, TType::LST);
}
public function testSkipBinarySet(): void
{
$buffer = $this->buildBinaryBuffer(
function (TBinaryProtocol $protocol): void {
$protocol->writeSetBegin(TType::DOUBLE, 2);
$protocol->writeDouble(3.14);
$protocol->writeDouble(6.28);
$protocol->writeSetEnd();
}
);
$this->assertSkipBinaryConsumesBuffer($buffer, TType::SET);
}
public function testSkipBinaryThrowsForUnknownType(): void
{
$this->expectException(TProtocolException::class);
$this->expectExceptionCode(TProtocolException::INVALID_DATA);
TProtocol::skipBinary(new TMemoryBuffer(), 999);
}
private function buildBinaryBuffer(callable $writer): string
{
$transport = new TMemoryBuffer();
$protocol = new TBinaryProtocol($transport);
$writer($protocol);
return $transport->getBuffer();
}
private function assertSkipBinaryConsumesBuffer(string $buffer, int $type): void
{
$transport = new TMemoryBuffer($buffer);
$this->assertSame(strlen($buffer), TProtocol::skipBinary($transport, $type));
$this->assertSame(0, (int)$transport->available());
}
}