Skip to content

Commit 065fbdd

Browse files
committed
temp commit
1 parent 5dffed9 commit 065fbdd

File tree

5 files changed

+263
-0
lines changed

5 files changed

+263
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Neo4j PHP Client and Driver package.
7+
*
8+
* (c) Nagels <https://nagels.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Exception;
15+
16+
use RuntimeException;
17+
18+
final class SSLConnectionException extends RuntimeException
19+
{
20+
}

src/Exception/TimeoutException.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Neo4j PHP Client and Driver package.
7+
*
8+
* (c) Nagels <https://nagels.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Exception;
15+
16+
use RuntimeException;
17+
18+
class TimeoutException extends RuntimeException
19+
{
20+
}

testkit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 9057529dbc3f71c05dd557caa0e2245267100413

tests/Unit/BoltFactoryTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Neo4j PHP Client and Driver package.
7+
*
8+
* (c) Nagels <https://nagels.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Tests\Unit;
15+
16+
use Bolt\connection\IConnection;
17+
use Bolt\enum\ServerState;
18+
use Bolt\protocol\V5;
19+
use Laudis\Neo4j\Bolt\BoltConnection;
20+
use Laudis\Neo4j\Bolt\Connection;
21+
use Laudis\Neo4j\Bolt\ProtocolFactory;
22+
use Laudis\Neo4j\Bolt\SslConfigurationFactory;
23+
use Laudis\Neo4j\BoltFactory;
24+
use Laudis\Neo4j\Common\Uri;
25+
use Laudis\Neo4j\Contracts\AuthenticateInterface;
26+
use Laudis\Neo4j\Contracts\BasicConnectionFactoryInterface;
27+
use Laudis\Neo4j\Databags\ConnectionRequestData;
28+
use Laudis\Neo4j\Databags\SessionConfiguration;
29+
use Laudis\Neo4j\Databags\SslConfiguration;
30+
use PHPUnit\Framework\TestCase;
31+
32+
final class BoltFactoryTest extends TestCase
33+
{
34+
private BoltFactory $factory;
35+
36+
protected function setUp(): void
37+
{
38+
parent::setUp();
39+
$basicConnectionFactory = $this->createMock(BasicConnectionFactoryInterface::class);
40+
$basicConnectionFactory->method('create')
41+
->willReturn(new Connection($this->createMock(IConnection::class), ''));
42+
43+
$protocolFactory = $this->createMock(ProtocolFactory::class);
44+
$protocolFactory->method('createProtocol')
45+
->willReturnCallback(static function (IConnection $connection) {
46+
$protocol = new V5(1, $connection);
47+
$protocol->serverState = ServerState::READY;
48+
49+
return $protocol;
50+
});
51+
52+
$this->factory = new BoltFactory(
53+
$basicConnectionFactory,
54+
$protocolFactory,
55+
new SslConfigurationFactory()
56+
);
57+
}
58+
59+
public function testCreateBasic(): void
60+
{
61+
$auth = $this->createMock(AuthenticateInterface::class);
62+
$auth->method('authenticateBolt')
63+
->willReturn(['server' => 'abc', 'connection_id' => 'i', 'hints' => []]);
64+
65+
$connection = $this->factory->createConnection(
66+
new ConnectionRequestData('', Uri::create(''), $auth, '', SslConfiguration::default()),
67+
SessionConfiguration::default()
68+
);
69+
70+
self::assertInstanceOf(BoltConnection::class, $connection);
71+
self::assertEquals('', $connection->getEncryptionLevel());
72+
self::assertInstanceOf(V5::class, $connection->getImplementation()[0]);
73+
self::assertInstanceOf(Connection::class,
74+
$connection->getImplementation()[1]);
75+
}
76+
}

tests/Unit/ConnectionPoolTest.php

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Neo4j PHP Client and Driver package.
7+
*
8+
* (c) Nagels <https://nagels.tech>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Laudis\Neo4j\Tests\Unit;
15+
16+
use Bolt\error\ConnectionTimeoutException;
17+
use Laudis\Neo4j\Bolt\BoltConnection;
18+
use Laudis\Neo4j\Bolt\ConnectionPool;
19+
use Laudis\Neo4j\BoltFactory;
20+
use Laudis\Neo4j\Common\Neo4jLogger;
21+
use Laudis\Neo4j\Contracts\AuthenticateInterface;
22+
use Laudis\Neo4j\Contracts\SemaphoreInterface;
23+
use Laudis\Neo4j\Databags\ConnectionRequestData;
24+
use Laudis\Neo4j\Databags\SessionConfiguration;
25+
use Laudis\Neo4j\Databags\SslConfiguration;
26+
use Laudis\Neo4j\Enum\SslMode;
27+
use Laudis\Neo4j\Exception\TimeoutException;
28+
use PHPUnit\Framework\MockObject\MockObject;
29+
use PHPUnit\Framework\TestCase;
30+
use Psr\Http\Message\UriInterface;
31+
use ReflectionClass;
32+
33+
class ConnectionPoolTest extends TestCase
34+
{
35+
private MockObject&SemaphoreInterface $semaphore;
36+
private MockObject&BoltFactory $factory;
37+
private ConnectionRequestData $requestData;
38+
private MockObject&Neo4jLogger $logger;
39+
private SessionConfiguration $sessionConfig;
40+
private MockObject&UriInterface $uri;
41+
private MockObject&AuthenticateInterface $auth;
42+
43+
protected function setUp(): void
44+
{
45+
$this->semaphore = $this->createMock(SemaphoreInterface::class);
46+
$this->factory = $this->createMock(BoltFactory::class);
47+
$this->sessionConfig = SessionConfiguration::default();
48+
$this->logger = $this->createMock(Neo4jLogger::class);
49+
$this->uri = $this->createMock(UriInterface::class);
50+
$this->auth = $this->createMock(AuthenticateInterface::class);
51+
52+
$this->uri->method('getHost')->willReturn('localhost');
53+
54+
$this->requestData = new ConnectionRequestData(
55+
'localhost',
56+
$this->uri,
57+
$this->auth,
58+
'test-user-agent',
59+
new SslConfiguration(SslMode::DISABLE(), false)
60+
);
61+
}
62+
63+
public function testTimeoutExceptionIsThrown(): void
64+
{
65+
$this->expectException(TimeoutException::class);
66+
$this->expectExceptionMessage('Connection timed out');
67+
68+
$this->semaphore->method('wait')->willReturn((function () {
69+
yield 0.1;
70+
})());
71+
72+
$this->factory->method('createConnection')
73+
->willThrowException(new ConnectionTimeoutException('Connection timed out'));
74+
75+
$pool = new ConnectionPool(
76+
$this->semaphore,
77+
$this->factory,
78+
$this->requestData,
79+
$this->logger,
80+
0.5
81+
);
82+
83+
$generator = $pool->acquire($this->sessionConfig);
84+
85+
try {
86+
while ($generator->valid()) {
87+
$generator->send(true);
88+
}
89+
$generator->getReturn();
90+
} catch (ConnectionTimeoutException $e) {
91+
// Wrap Bolt exception into driver-specific TimeoutException
92+
throw new TimeoutException($e->getMessage(), 0, $e);
93+
}
94+
}
95+
96+
public function testReuseConnectionIfPossibleReturnsReusableConnection(): void
97+
{
98+
$connection = $this->createMock(BoltConnection::class);
99+
$connection->method('getServerState')->willReturn('READY');
100+
$this->factory->method('canReuseConnection')->willReturn(true);
101+
$this->factory->method('reuseConnection')->willReturn($connection);
102+
103+
// Use real ConnectionPool instance without mocking isConnectionExpired
104+
$pool = new ConnectionPool(
105+
$this->semaphore,
106+
$this->factory,
107+
$this->requestData,
108+
$this->logger,
109+
1.0
110+
);
111+
112+
$reflection = new ReflectionClass(ConnectionPool::class);
113+
$property = $reflection->getProperty('activeConnections');
114+
$property->setValue($pool, [$connection]);
115+
116+
$method = $reflection->getMethod('reuseConnectionIfPossible');
117+
$result = $method->invoke($pool, $this->sessionConfig);
118+
119+
$this->assertSame($connection, $result);
120+
}
121+
122+
public function testReuseConnectionIfPossibleReturnsNullWhenNoReusableConnectionFound(): void
123+
{
124+
$connection = $this->createMock(BoltConnection::class);
125+
$connection->method('getServerState')->willReturn('READY');
126+
$this->factory->method('canReuseConnection')->willReturn(false);
127+
128+
// Use real ConnectionPool instance without mocking isConnectionExpired
129+
$pool = new ConnectionPool(
130+
$this->semaphore,
131+
$this->factory,
132+
$this->requestData,
133+
$this->logger,
134+
1.0
135+
);
136+
137+
$reflection = new ReflectionClass(ConnectionPool::class);
138+
$property = $reflection->getProperty('activeConnections');
139+
$property->setValue($pool, [$connection]);
140+
141+
$method = $reflection->getMethod('reuseConnectionIfPossible');
142+
$result = $method->invoke($pool, $this->sessionConfig);
143+
144+
$this->assertNull($result);
145+
}
146+
}

0 commit comments

Comments
 (0)