blob: ce6813c1bd1cd99cfc20fd3ea83889eda6de9b25 [file] [log] [blame]
<?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.
*/
namespace Test\Thrift\Unit\Lib\Transport;
use phpmock\phpunit\PHPMock;
use PHPUnit\Framework\TestCase;
use Thrift\Exception\TTransportException;
use Thrift\Transport\THttpClient;
class THttpClientTest extends TestCase
{
use PHPMock;
public function testSetTimeoutSecs()
{
$host = 'localhost';
$transport = new THttpClient($host);
$transport->setTimeoutSecs(1000);
$ref = new \ReflectionClass($transport);
$prop = $ref->getProperty('timeout_');
$prop->setAccessible(true);
$this->assertEquals(1000, $prop->getValue($transport));
}
public function testIsOpen()
{
$host = 'localhost';
$transport = new THttpClient($host);
$this->assertTrue($transport->isOpen());
}
public function testOpen()
{
$host = 'localhost';
$transport = new THttpClient($host);
$this->assertNull($transport->open());
}
public function testClose()
{
$handle = fopen('php://temp', 'r+');
$this->getFunctionMock('Thrift\\Transport', 'fclose')
->expects($this->once())
->with($handle)
->willReturn(true);
$host = 'localhost';
$transport = new THttpClient($host);
$ref = new \ReflectionClass($transport);
$propRequest = $ref->getProperty('handle_');
$propRequest->setAccessible(true);
$propRequest->setValue($transport, $handle);
$this->assertNull($transport->close());
$this->assertNull($propRequest->getValue($transport));
}
/**
* @dataProvider readDataProvider
*/
public function testRead(
$readLen,
$freadResult,
$streamGetMetaDataResult,
$expectedResult,
$expectedException,
$expectedExceptionMessage,
$expectedExceptionCode
) {
$handle = fopen('php://temp', 'r+');
$this->getFunctionMock('Thrift\\Transport', 'fread')
->expects($this->once())
->with($handle, $readLen)
->willReturn($freadResult);
$this->getFunctionMock('Thrift\\Transport', 'stream_get_meta_data')
->expects(!empty($streamGetMetaDataResult) ? $this->once() : $this->never())
->with($handle)
->willReturn($streamGetMetaDataResult);
if ($expectedException) {
$this->expectException($expectedException);
$this->expectExceptionMessage($expectedExceptionMessage);
$this->expectExceptionCode($expectedExceptionCode);
}
$host = 'localhost';
$transport = new THttpClient($host);
$ref = new \ReflectionClass($transport);
$propRequest = $ref->getProperty('handle_');
$propRequest->setAccessible(true);
$propRequest->setValue($transport, $handle);
$this->assertEquals($expectedResult, $transport->read($readLen));
}
public function readDataProvider()
{
yield 'read success' => [
'readLen' => 10,
'freadResult' => '1234567890',
'streamGetMetaDataResult' => [],
'expectedResult' => '1234567890',
'expectedException' => null,
'expectedExceptionMessage' => null,
'expectedExceptionCode' => null,
];
yield 'read failed' => [
'readLen' => 10,
'freadResult' => false,
'streamGetMetaDataResult' => [
'timed_out' => false,
],
'expectedResult' => '',
'expectedException' => TTransportException::class,
'expectedExceptionMessage' => 'THttpClient: Could not read 10 bytes from localhost:80',
'expectedExceptionCode' => TTransportException::UNKNOWN,
];
yield 'read timeout' => [
'readLen' => 10,
'freadResult' => '',
'streamGetMetaDataResult' => [
'timed_out' => true,
],
'expectedResult' => '',
'expectedException' => TTransportException::class,
'expectedExceptionMessage' => 'THttpClient: timed out reading 10 bytes from localhost:80',
'expectedExceptionCode' => TTransportException::TIMED_OUT,
];
}
public function testWrite()
{
$host = 'localhost';
$transport = new THttpClient($host);
$ref = new \ReflectionClass($transport);
$prop = $ref->getProperty('buf_');
$prop->setAccessible(true);
$transport->write('1234567890');
$this->assertEquals('1234567890', $prop->getValue($transport));
}
/**
* @dataProvider flushDataProvider
*/
public function testFlush(
$host,
$port,
$uri,
$scheme,
$context,
$headers,
$timeout,
$streamContextOptions,
$streamContext,
$fopenResult,
$expectedHost,
$expectedUri,
$expectedException,
$expectedExceptionMessage,
$expectedExceptionCode
) {
$this->getFunctionMock('Thrift\\Transport', 'stream_context_create')
->expects($this->once())
->with($streamContextOptions)
->willReturn($streamContext);
$this->getFunctionMock('Thrift\\Transport', 'fopen')
->expects($this->once())
->with(
$scheme . '://' . $expectedHost . $expectedUri,
'r',
false,
$streamContext
)->willReturn($fopenResult);
if ($expectedException) {
$this->expectException($expectedException);
$this->expectExceptionMessage($expectedExceptionMessage);
$this->expectExceptionCode($expectedExceptionCode);
}
$transport = new THttpClient($host, $port, $uri, $scheme, $context);
if (!empty($headers)) {
$transport->addHeaders($headers);
}
if (!empty($timeout)) {
$transport->setTimeoutSecs($timeout);
}
$this->assertNull($transport->flush());
}
public function flushDataProvider()
{
$default = [
'host' => 'localhost',
'port' => '80',
'uri' => '',
'scheme' => 'http',
'context' => [],
'headers' => [],
'timeout' => null,
'streamContextOptions' => [
'http' => [
'method' => 'POST',
'header' => "Host: localhost\r\n" .
"Accept: application/x-thrift\r\n" .
"User-Agent: PHP/THttpClient\r\n" .
"Content-Type: application/x-thrift\r\n" .
"Content-Length: 0",
'content' => '',
'max_redirects' => 1,
],
],
'streamContext' => fopen('php://temp', 'r+'),
'fopenResult' => fopen('php://memory', 'r+'),
'expectedHost' => 'localhost',
'expectedUri' => '',
'expectedException' => '',
'expectedExceptionMessage' => '',
'expectedExceptionCode' => '',
];
yield 'success' => $default;
yield 'additionalHeaders' => array_merge(
$default,
[
'headers' => [
'X-Test-Header' => 'test',
],
'streamContextOptions' => [
'http' => [
'method' => 'POST',
'header' => "Host: localhost\r\n" .
"Accept: application/x-thrift\r\n" .
"User-Agent: PHP/THttpClient\r\n" .
"Content-Type: application/x-thrift\r\n" .
"Content-Length: 0\r\n" .
"X-Test-Header: test",
'content' => '',
'max_redirects' => 1,
],
],
]
);
yield 'timeout' => array_merge(
$default,
[
'timeout' => 1000,
'streamContextOptions' => [
'http' => [
'method' => 'POST',
'header' => "Host: localhost\r\n" .
"Accept: application/x-thrift\r\n" .
"User-Agent: PHP/THttpClient\r\n" .
"Content-Type: application/x-thrift\r\n" .
"Content-Length: 0",
'content' => '',
'max_redirects' => 1,
'timeout' => 1000,
],
],
]
);
yield 'fopenFailed' => array_merge(
$default,
[
'host' => 'localhost',
'port' => 8080,
'uri' => 'test',
'expectedHost' => 'localhost:8080',
'expectedUri' => '/test',
'streamContextOptions' => [
'http' => [
'method' => 'POST',
'header' => "Host: localhost:8080\r\n" .
"Accept: application/x-thrift\r\n" .
"User-Agent: PHP/THttpClient\r\n" .
"Content-Type: application/x-thrift\r\n" .
"Content-Length: 0",
'content' => '',
'max_redirects' => 1,
],
],
'fopenResult' => false,
'expectedException' => TTransportException::class,
'expectedExceptionMessage' => 'THttpClient: Could not connect to localhost:8080/test',
'expectedExceptionCode' => TTransportException::NOT_OPEN,
]
);
}
public function testAddHeaders()
{
$host = 'localhost';
$transport = new THttpClient($host);
$ref = new \ReflectionClass($transport);
$propRequest = $ref->getProperty('headers_');
$propRequest->setAccessible(true);
$propRequest->setValue($transport, ['test' => '1234567890']);
$transport->addHeaders(['test2' => '12345']);
$this->assertEquals(['test' => '1234567890', 'test2' => '12345'], $propRequest->getValue($transport));
}
}