[THRIFT-5757] Unit tests for php lib
diff --git a/composer.json b/composer.json
index 900fb28..684c1b3 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,8 @@
"php-mock/php-mock-phpunit": "^2.10",
"ext-json": "*",
"ext-xml": "*",
- "ext-curl": "*"
+ "ext-curl": "*",
+ "ext-pcntl": "*"
},
"autoload": {
"psr-4": {"Thrift\\": "lib/php/lib/"}
diff --git a/lib/php/lib/Factory/TFramedTransportFactory.php b/lib/php/lib/Factory/TFramedTransportFactory.php
index 485fca5..c0adfd0 100644
--- a/lib/php/lib/Factory/TFramedTransportFactory.php
+++ b/lib/php/lib/Factory/TFramedTransportFactory.php
@@ -1,5 +1,24 @@
<?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 Thrift\Factory;
use Thrift\Transport\TFramedTransport;
@@ -7,7 +26,7 @@
class TFramedTransportFactory implements TTransportFactoryInterface
{
- public static function getTransport(TTransport $transport)
+ public function getTransport(TTransport $transport)
{
return new TFramedTransport($transport);
}
diff --git a/lib/php/lib/Factory/TTransportFactory.php b/lib/php/lib/Factory/TTransportFactory.php
index 98ead95..4c0abd0 100644
--- a/lib/php/lib/Factory/TTransportFactory.php
+++ b/lib/php/lib/Factory/TTransportFactory.php
@@ -1,5 +1,24 @@
<?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 Thrift\Factory;
use Thrift\Transport\TTransport;
@@ -7,11 +26,10 @@
class TTransportFactory implements TTransportFactoryInterface
{
/**
- * @static
* @param TTransport $transport
* @return TTransport
*/
- public static function getTransport(TTransport $transport)
+ public function getTransport(TTransport $transport)
{
return $transport;
}
diff --git a/lib/php/lib/Factory/TTransportFactoryInterface.php b/lib/php/lib/Factory/TTransportFactoryInterface.php
index 614cea8..1c49067 100644
--- a/lib/php/lib/Factory/TTransportFactoryInterface.php
+++ b/lib/php/lib/Factory/TTransportFactoryInterface.php
@@ -1,5 +1,24 @@
<?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 Thrift\Factory;
use Thrift\Transport\TTransport;
@@ -7,9 +26,8 @@
interface TTransportFactoryInterface
{
/**
- * @static
* @param TTransport $transport
* @return TTransport
*/
- public static function getTransport(TTransport $transport);
+ public function getTransport(TTransport $transport);
}
diff --git a/lib/php/lib/Server/TSSLServerSocket.php b/lib/php/lib/Server/TSSLServerSocket.php
index ac589b7..e377897 100644
--- a/lib/php/lib/Server/TSSLServerSocket.php
+++ b/lib/php/lib/Server/TSSLServerSocket.php
@@ -49,6 +49,10 @@
{
$ssl_host = $this->getSSLHost($host);
parent::__construct($ssl_host, $port);
+ // Initialize a stream context if not provided
+ if ($context === null) {
+ $context = stream_context_create();
+ }
$this->context_ = $context;
}
diff --git a/lib/php/lib/Server/TServerTransport.php b/lib/php/lib/Server/TServerTransport.php
index 15a27af..82ee752 100644
--- a/lib/php/lib/Server/TServerTransport.php
+++ b/lib/php/lib/Server/TServerTransport.php
@@ -3,6 +3,7 @@
namespace Thrift\Server;
use Thrift\Exception\TTransportException;
+use Thrift\Transport\TTransport;
/**
* Generic class for Server agent.
diff --git a/lib/php/test/Unit/Lib/Factory/TFramedTransportFactoryTest.php b/lib/php/test/Unit/Lib/Factory/TFramedTransportFactoryTest.php
index 3b8b5cc..f8a860c 100644
--- a/lib/php/test/Unit/Lib/Factory/TFramedTransportFactoryTest.php
+++ b/lib/php/test/Unit/Lib/Factory/TFramedTransportFactoryTest.php
@@ -35,7 +35,7 @@
{
$transport = $this->createMock(TTransport::class);
$factory = new TFramedTransportFactory();
- $framedTransport = $factory::getTransport($transport);
+ $framedTransport = $factory->getTransport($transport);
$this->assertInstanceOf(TFramedTransport::class, $framedTransport);
diff --git a/lib/php/test/Unit/Lib/Factory/TTransportFactoryTest.php b/lib/php/test/Unit/Lib/Factory/TTransportFactoryTest.php
index a8a791a..9d3e640 100644
--- a/lib/php/test/Unit/Lib/Factory/TTransportFactoryTest.php
+++ b/lib/php/test/Unit/Lib/Factory/TTransportFactoryTest.php
@@ -34,7 +34,7 @@
{
$transport = $this->createMock(TTransport::class);
$factory = new TTransportFactory();
- $result = $factory::getTransport($transport);
+ $result = $factory->getTransport($transport);
$this->assertSame($transport, $result);
}
diff --git a/lib/php/test/Unit/Lib/Server/Fixture/TestProcessor.php b/lib/php/test/Unit/Lib/Server/Fixture/TestProcessor.php
new file mode 100644
index 0000000..8fc6891
--- /dev/null
+++ b/lib/php/test/Unit/Lib/Server/Fixture/TestProcessor.php
@@ -0,0 +1,30 @@
+<?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\Server\Fixture;
+
+class TestProcessor
+{
+ public function process($input, $output)
+ {
+ return true;
+ }
+}
diff --git a/lib/php/test/Unit/Lib/Server/TForkingServerTest.php b/lib/php/test/Unit/Lib/Server/TForkingServerTest.php
new file mode 100644
index 0000000..0a44032
--- /dev/null
+++ b/lib/php/test/Unit/Lib/Server/TForkingServerTest.php
@@ -0,0 +1,32 @@
+<?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\Server;
+
+use PHPUnit\Framework\TestCase;
+
+class TForkingServerTest extends TestCase
+{
+ public function testServe(): void
+ {
+ $this->markTestSkipped('Unit test could not be written for class which use pcntl_fork and exit functions');
+ }
+}
diff --git a/lib/php/test/Unit/Lib/Server/TSSLServerSocketTest.php b/lib/php/test/Unit/Lib/Server/TSSLServerSocketTest.php
new file mode 100644
index 0000000..02ae584
--- /dev/null
+++ b/lib/php/test/Unit/Lib/Server/TSSLServerSocketTest.php
@@ -0,0 +1,150 @@
+<?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\Server;
+
+use phpmock\phpunit\PHPMock;
+use PHPUnit\Framework\TestCase;
+use Thrift\Exception\TTransportException;
+use Thrift\Server\TSSLServerSocket;
+use Thrift\Transport\TSocket;
+
+class TSSLServerSocketTest extends TestCase
+{
+ use PHPMock;
+
+ public function testGetSSLHost()
+ {
+ $socket = new TSSLServerSocket();
+
+ $this->assertEquals('ssl://localhost', $socket->getSSLHost('localhost'));
+ $this->assertEquals('ssl://localhost', $socket->getSSLHost('ssl://localhost'));
+ $this->assertEquals('tcp://localhost', $socket->getSSLHost('tcp://localhost'));
+ }
+
+ public function testListenAndClose(): void
+ {
+ $options = [
+ 'ssl' => [
+ 'verify_peer' => true,
+ 'verify_peer_name' => true,
+ 'allow_self_signed' => true,
+ ],
+ ];
+ $context = stream_context_create($options);
+ $socket = new TSSLServerSocket('somehost', 999, $context);
+
+ $listener = tmpfile();
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_server')
+ ->expects($this->once())
+ ->with(
+ 'ssl://somehost:999', #$address
+ $this->anything(), #&$error_code
+ $this->anything(), #&$error_string
+ STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, #int $flags
+ $this->callback(function ($context) use ($options) {
+ $contextOptions = stream_context_get_options($context);
+
+ return is_resource($context) && $options === $contextOptions;
+ })#resource $context
+ )->willReturn($listener);
+
+ $socket->listen();
+
+ $reflection = new \ReflectionClass($socket);
+ $property = $reflection->getProperty('listener_');
+ $property->setAccessible(true);
+
+ $this->assertIsResource($property->getValue($socket));
+
+ $this->getFunctionMock('Thrift\Server', 'fclose')
+ ->expects($this->once())
+ ->with($this->equalTo($listener))
+ ->willReturn(true);
+
+ $socket->close();
+ $this->assertNull($property->getValue($socket));
+ }
+
+ public function testAccept()
+ {
+ $socket = new TSSLServerSocket('somehost', 999);
+ $socket->setAcceptTimeout(1000);
+
+ $listener = tmpfile();
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_server')
+ ->expects($this->once())
+ ->with(
+ 'ssl://somehost:999', #$address
+ $this->anything(), #&$error_code
+ $this->anything(), #&$error_string
+ STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, #int $flags
+ $this->callback(function ($context) {
+ $contextOptions = stream_context_get_options($context);
+
+ return is_resource($context) && $contextOptions === [];
+ }) #resource $context
+ )->willReturn($listener);
+
+ $transportHandle = tmpfile();
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_accept')
+ ->expects($this->once())
+ ->with(
+ $this->equalTo($listener),
+ 1
+ )->willReturn($transportHandle);
+
+ $socket->listen();
+ $result = $socket->accept();
+ $this->assertInstanceOf(TSocket::class, $result);
+
+ $reflection = new \ReflectionClass($result);
+ $property = $reflection->getProperty('handle_');
+ $property->setAccessible(true);
+ $this->assertEquals($transportHandle, $property->getValue($result));
+ }
+
+ public function testAcceptFailed()
+ {
+ $socket = new TSSLServerSocket('somehost', 999);
+ $socket->setAcceptTimeout(1000);
+
+ $listener = tmpfile();
+
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_server')
+ ->expects($this->once())
+ ->with('ssl://somehost:999')
+ ->willReturn($listener);
+
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_accept')
+ ->expects($this->once())
+ ->with(
+ $this->equalTo($listener),
+ 1
+ )->willReturn(null);
+
+ $this->expectException(TTransportException::class);
+ $this->expectExceptionMessage('accept() may not return NULL');
+
+ $socket->listen();
+ $socket->accept();
+ }
+}
diff --git a/lib/php/test/Unit/Lib/Server/TServerSocketTest.php b/lib/php/test/Unit/Lib/Server/TServerSocketTest.php
new file mode 100644
index 0000000..e9d3b96
--- /dev/null
+++ b/lib/php/test/Unit/Lib/Server/TServerSocketTest.php
@@ -0,0 +1,128 @@
+<?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\Server;
+
+use phpmock\phpunit\PHPMock;
+use PHPUnit\Framework\TestCase;
+use Thrift\Exception\TTransportException;
+use Thrift\Server\TServerSocket;
+use Thrift\Transport\TSocket;
+
+class TServerSocketTest extends TestCase
+{
+ use PHPMock;
+
+ public function testSetAcceptTimeout(): void
+ {
+ $socket = new TServerSocket();
+ $socket->setAcceptTimeout(1000);
+
+ $reflection = new \ReflectionClass($socket);
+ $property = $reflection->getProperty('acceptTimeout_');
+ $property->setAccessible(true);
+
+ $this->assertEquals(1000, $property->getValue($socket));
+ }
+
+ public function testListenAndClose(): void
+ {
+ $socket = new TServerSocket('somehost', 999);
+
+ $listener = tmpfile();
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_server')
+ ->expects($this->once())
+ ->with('tcp://somehost:999')
+ ->willReturn($listener);
+
+ $socket->listen();
+
+ $reflection = new \ReflectionClass($socket);
+ $property = $reflection->getProperty('listener_');
+ $property->setAccessible(true);
+
+ $this->assertIsResource($property->getValue($socket));
+
+ $this->getFunctionMock('Thrift\Server', 'fclose')
+ ->expects($this->once())
+ ->with($this->equalTo($listener))
+ ->willReturn(true);
+
+ $socket->close();
+ $this->assertNull($property->getValue($socket));
+ }
+
+ public function testAccept()
+ {
+ $socket = new TServerSocket('somehost', 999);
+ $socket->setAcceptTimeout(1000);
+
+ $listener = tmpfile();
+
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_server')
+ ->expects($this->once())
+ ->with('tcp://somehost:999')
+ ->willReturn($listener);
+
+ $transportHandle = tmpfile();
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_accept')
+ ->expects($this->once())
+ ->with(
+ $this->equalTo($listener),
+ 1
+ )->willReturn($transportHandle);
+
+ $socket->listen();
+ $result = $socket->accept();
+ $this->assertInstanceOf(TSocket::class, $result);
+
+ $reflection = new \ReflectionClass($result);
+ $property = $reflection->getProperty('handle_');
+ $property->setAccessible(true);
+ $this->assertEquals($transportHandle, $property->getValue($result));
+ }
+
+ public function testAcceptFailed()
+ {
+ $socket = new TServerSocket('somehost', 999);
+ $socket->setAcceptTimeout(1000);
+
+ $listener = tmpfile();
+
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_server')
+ ->expects($this->once())
+ ->with('tcp://somehost:999')
+ ->willReturn($listener);
+
+ $this->getFunctionMock('Thrift\Server', 'stream_socket_accept')
+ ->expects($this->once())
+ ->with(
+ $this->equalTo($listener),
+ 1
+ )->willReturn(null);
+
+ $this->expectException(TTransportException::class);
+ $this->expectExceptionMessage('accept() may not return NULL');
+
+ $socket->listen();
+ $socket->accept();
+ }
+}
diff --git a/lib/php/test/Unit/Lib/Server/TSimpleServerTest.php b/lib/php/test/Unit/Lib/Server/TSimpleServerTest.php
new file mode 100644
index 0000000..269b838
--- /dev/null
+++ b/lib/php/test/Unit/Lib/Server/TSimpleServerTest.php
@@ -0,0 +1,166 @@
+<?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\Server;
+
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+use Test\Thrift\Unit\Lib\Server\Fixture\TestProcessor;
+use Thrift\Factory\TProtocolFactory;
+use Thrift\Factory\TTransportFactoryInterface;
+use Thrift\Server\TServerTransport;
+use Thrift\Server\TSimpleServer;
+use Thrift\Transport\TTransport;
+
+class TSimpleServerTest extends TestCase
+{
+ /**
+ * @var object
+ */
+ private $processor;
+ /**
+ * @var MockObject|TServerTransport
+ */
+ private $transport;
+ /**
+ * @var MockObject|TTransportFactoryInterface
+ */
+ private $inputTransportFactory;
+ /**
+ * @var MockObject|TTransportFactoryInterface
+ */
+ private $outputTransportFactory;
+ /**
+ * @var MockObject|TProtocolFactory
+ */
+ private $inputProtocolFactory;
+ /**
+ * @var MockObject|TProtocolFactory
+ */
+ private $outputProtocolFactory;
+ /**
+ * @var TSimpleServer
+ */
+ private $server;
+
+ protected function setUp(): void
+ {
+ $this->processor = $this->createMock(TestProcessor::class);
+ $this->transport = $this->createMock(TServerTransport::class);
+ $this->inputTransportFactory = $this->createMock(TTransportFactoryInterface::class);
+ $this->outputTransportFactory = $this->createMock(TTransportFactoryInterface::class);
+ $this->inputProtocolFactory = $this->createMock(TProtocolFactory::class);
+ $this->outputProtocolFactory = $this->createMock(TProtocolFactory::class);
+
+ $this->server = new TSimpleServer(
+ $this->processor,
+ $this->transport,
+ $this->inputTransportFactory,
+ $this->outputTransportFactory,
+ $this->inputProtocolFactory,
+ $this->outputProtocolFactory
+ );
+ }
+
+ protected function tearDown(): void
+ {
+ unset(
+ $this->processor,
+ $this->transport,
+ $this->inputTransportFactory,
+ $this->outputTransportFactory,
+ $this->inputProtocolFactory,
+ $this->outputProtocolFactory,
+ $this->server
+ );
+ }
+
+ /**
+ * @dataProvider serveDataProvider
+ */
+ public function testServe(
+ $serveLoopCount,
+ array $processLoopResult
+ ): void {
+ $transport = $this->createMock(TTransport::class);
+
+ $this->transport->expects($this->once())
+ ->method('listen');
+ $this->transport->expects($this->exactly($serveLoopCount))
+ ->method('accept')
+ ->willReturn($transport);
+
+ $this->inputTransportFactory->expects($this->exactly($serveLoopCount))
+ ->method('getTransport')
+ ->willReturn($this->createMock(TServerTransport::class));
+ $this->outputTransportFactory->expects($this->exactly($serveLoopCount))
+ ->method('getTransport')
+ ->willReturn($this->createMock(TServerTransport::class));
+
+ $inputProtocol = $this->createMock(TServerTransport::class);
+ $this->inputProtocolFactory->expects($this->exactly($serveLoopCount))
+ ->method('getProtocol')
+ ->willReturn($inputProtocol);
+
+ $outputProtocol = $this->createMock(TServerTransport::class);
+ $this->outputProtocolFactory->expects($this->exactly($serveLoopCount))
+ ->method('getProtocol')
+ ->willReturn($outputProtocol);
+
+ /**
+ * ATTENTION!
+ * it is a hack to stop the server loop in unit test
+ * last call of process can return any value, but should stop server for removing infinite loop
+ **/
+ $processLoopResult[] = $this->returnCallback(function () {
+ $this->server->stop();
+
+ return false;
+ });
+
+ $this->processor->expects($this->exactly(count($processLoopResult)))
+ ->method('process')
+ ->with(
+ $this->equalTo($inputProtocol),
+ $this->equalTo($outputProtocol)
+ )
+ ->willReturnOnConsecutiveCalls(...$processLoopResult);
+
+ $this->server->serve();
+ }
+
+ public function serveDataProvider()
+ {
+ yield 'one serve loop' => [
+ 'serveLoopCount' => 1,
+ 'processLoopResult' => [
+ true,
+ ]
+ ];
+ yield 'two serve loop' => [
+ 'serveLoopCount' => 2,
+ 'processLoopResult' => [
+ true,
+ false,
+ ]
+ ];
+ }
+}