blob: 8ee489a9d15d75145c3d7553ba07834883cd5415 [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\Transport;
use PHPUnit\Framework\TestCase;
use Thrift\Exception\TTransportException;
use Thrift\Transport\TBufferedTransport;
use Thrift\Transport\TFramedTransport;
use Thrift\Transport\TMemoryBuffer;
use Thrift\Transport\TTransport;
class TransportErrorScenariosTest extends TestCase
{
// =========================================================================
// TMemoryBuffer edge cases
// =========================================================================
public function testMemoryBufferReadFromEmptyBufferThrowsException()
{
$buffer = new TMemoryBuffer('');
$this->expectException(TTransportException::class);
$this->expectExceptionCode(TTransportException::UNKNOWN);
$buffer->read(10);
}
public function testMemoryBufferWriteEmptyStringAvailableReturnsZero()
{
$buffer = new TMemoryBuffer();
$buffer->write('');
$this->assertEquals(0, $buffer->available());
}
public function testMemoryBufferReadExactBufferSizeWorks()
{
$data = 'hello';
$buffer = new TMemoryBuffer($data);
$result = $buffer->read(5);
$this->assertEquals('hello', $result);
$this->assertEquals(0, $buffer->available());
}
public function testMemoryBufferReadAllWithInsufficientDataThrowsException()
{
$buffer = new TMemoryBuffer('abc');
$this->expectException(TTransportException::class);
// readAll needs 10 bytes but only 3 are available;
// after reading 3 bytes the buffer is empty and the next read() throws
$buffer->readAll(10);
}
public function testMemoryBufferGetBufferReturnsWhatWasWritten()
{
$buffer = new TMemoryBuffer();
$buffer->write('first');
$buffer->write('second');
$this->assertEquals('firstsecond', $buffer->getBuffer());
}
// =========================================================================
// TBufferedTransport error cases
// =========================================================================
public function testBufferedTransportReadAfterCloseThrowsException()
{
$transport = $this->createMock(TTransport::class);
$bufferedTransport = new TBufferedTransport($transport);
$transport
->expects($this->once())
->method('close');
$transport
->method('read')
->willThrowException(
new TTransportException('Transport not open', TTransportException::NOT_OPEN)
);
$bufferedTransport->close();
$this->expectException(TTransportException::class);
$this->expectExceptionCode(TTransportException::NOT_OPEN);
$bufferedTransport->read(10);
}
public function testBufferedTransportWriteOnUnderlyingTransportErrorThrowsException()
{
$transport = $this->createStub(TTransport::class);
// Use a small write buffer so that write triggers a flush to underlying transport
$bufferedTransport = new TBufferedTransport($transport, 512, 10);
$transport
->method('write')
->willThrowException(
new TTransportException('Write failed', TTransportException::UNKNOWN)
);
$this->expectException(TTransportException::class);
// Write more than wBufSize_ to trigger underlying write
$bufferedTransport->write('this string is longer than ten bytes');
}
public function testBufferedTransportFlushOnUnderlyingTransportErrorThrowsException()
{
$transport = $this->createStub(TTransport::class);
$bufferedTransport = new TBufferedTransport($transport);
$transport
->method('write')
->willThrowException(
new TTransportException('Flush write failed', TTransportException::UNKNOWN)
);
// Write some data to the buffer first
$bufferedTransport->write('data');
$this->expectException(TTransportException::class);
$bufferedTransport->flush();
}
// =========================================================================
// TFramedTransport error cases
// =========================================================================
public function testFramedTransportReadWithNoFrameAvailableThrowsException()
{
$transport = $this->createStub(TTransport::class);
$framedTransport = new TFramedTransport($transport);
// readFrame calls transport_->readAll(4) which will throw when no data available
$transport
->method('readAll')
->willThrowException(
new TTransportException(
'TMemoryBuffer: Could not read 4 bytes from buffer.',
TTransportException::UNKNOWN
)
);
$this->expectException(TTransportException::class);
$framedTransport->read(10);
}
public function testFramedTransportReadFrameOnClosedUnderlyingTransportThrowsException()
{
$transport = $this->createMock(TTransport::class);
$framedTransport = new TFramedTransport($transport);
$transport
->expects($this->once())
->method('close');
$transport
->method('readAll')
->willThrowException(
new TTransportException('Transport not open', TTransportException::NOT_OPEN)
);
$framedTransport->close();
$this->expectException(TTransportException::class);
$this->expectExceptionCode(TTransportException::NOT_OPEN);
$framedTransport->read(10);
}
}