Skip to content

Commit 9514d9b

Browse files
Extended tests. Added socket connect and disconnect methods.
1 parent 858d56e commit 9514d9b

File tree

6 files changed

+230
-72
lines changed

6 files changed

+230
-72
lines changed

Bolt.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ private function packProtocolVersions(): string
218218
*/
219219
public function init(string $name, string $user, string $password, array $routing = null): bool
220220
{
221+
if (!$this->socket->connect())
222+
return false;
223+
221224
if (!$this->handshake())
222225
return false;
223226

@@ -397,6 +400,8 @@ public function __destruct()
397400
echo 'GOODBYE';
398401
$this->protocol->goodbye();
399402
}
403+
404+
$this->socket->disconnect();
400405
}
401406

402407
}

Socket.php

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,22 @@
1111
*/
1212
final class Socket
1313
{
14+
15+
/**
16+
* @var string
17+
*/
18+
private $ip;
19+
20+
/**
21+
* @var int
22+
*/
23+
private $port;
24+
25+
/**
26+
* @var int
27+
*/
28+
private $timeout;
29+
1430
/**
1531
* @var resource
1632
*/
@@ -26,30 +42,44 @@ public function __construct(string $ip, int $port, int $timeout)
2642
{
2743
if (!extension_loaded('sockets')) {
2844
Bolt::error('PHP Extension sockets not enabled');
29-
return;
3045
}
3146

47+
$this->ip = $ip;
48+
$this->port = $port;
49+
$this->timeout = $timeout;
50+
}
51+
52+
/**
53+
* Create socket connection
54+
* @return bool
55+
* @throws \Exception
56+
*/
57+
public function connect(): bool
58+
{
3259
$this->socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
3360
if (!is_resource($this->socket)) {
3461
Bolt::error('Cannot create socket');
35-
return;
62+
return false;
3663
}
3764

3865
if (socket_set_block($this->socket) === false) {
3966
Bolt::error('Cannot set socket into blocking mode');
40-
return;
67+
return false;
4168
}
4269

4370
socket_set_option($this->socket, SOL_TCP, TCP_NODELAY, 1);
4471
socket_set_option($this->socket, SOL_SOCKET, SO_KEEPALIVE, 1);
45-
socket_set_option($this->socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => $timeout, 'usec' => 0]);
46-
socket_set_option($this->socket, SOL_SOCKET, SO_SNDTIMEO, ['sec' => $timeout, 'usec' => 0]);
72+
socket_set_option($this->socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => $this->timeout, 'usec' => 0]);
73+
socket_set_option($this->socket, SOL_SOCKET, SO_SNDTIMEO, ['sec' => $this->timeout, 'usec' => 0]);
4774

48-
$conn = socket_connect($this->socket, $ip, $port);
75+
$conn = @socket_connect($this->socket, $this->ip, $this->port);
4976
if (!$conn) {
5077
$code = socket_last_error($this->socket);
5178
Bolt::error(socket_strerror($code), $code);
79+
return false;
5280
}
81+
82+
return true;
5383
}
5484

5585
/**
@@ -132,10 +162,12 @@ private function printHex(string $str, bool $write = true)
132162
}
133163

134164
/**
135-
* Close socket
165+
* Close socket connection
136166
*/
137-
public function __destruct()
167+
public function disconnect()
138168
{
169+
socket_shutdown($this->socket);
139170
@socket_close($this->socket);
140171
}
172+
141173
}

phpunit.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
</php>
1111
<filter>
1212
<whitelist>
13+
<directory suffix=".php">protocol</directory>
14+
<directory suffix=".php">PackStream</directory>
1315
<file>Bolt.php</file>
1416
<file>Socket.php</file>
1517
</whitelist>

tests/BoltTest.php

Lines changed: 45 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@
77

88
/**
99
* Class BoltTest
10+
*
1011
* @author Michal Stefanak
1112
* @link https://github.com/stefanak-michal/Bolt
13+
*
1214
* @covers \Bolt\Bolt
15+
* @covers \Bolt\Socket
16+
*
1317
* @package Bolt\tests
1418
* @requires PHP >= 7.1
1519
* @requires extension sockets
@@ -18,109 +22,68 @@
1822
class BoltTest extends TestCase
1923
{
2024

21-
public static function setUpBeforeClass(): void
22-
{
23-
Bolt::$errorHandler = function ($msg, $code) {
24-
echo $msg . ' (' . $code . ')' . PHP_EOL;
25-
};
26-
27-
//Todo pridat ked bude debugHandler aby sa dal naformatovat output
28-
//Bolt::$debug = true;
29-
}
30-
3125
/**
32-
* @return Bolt
33-
* @throws \Exception
26+
* @return Bolt|null
3427
*/
35-
public function test__construct()
28+
public function testHello(): Bolt
3629
{
37-
$bolt = new Bolt($GLOBALS['NEO_HOST'] ?? '127.0.0.1', $GLOBALS['NEO_PORT'] ?? 7687);
38-
$this->assertInstanceOf(Bolt::class, $bolt);
39-
return $bolt;
40-
}
30+
try {
31+
$bolt = new Bolt($GLOBALS['NEO_HOST'] ?? '127.0.0.1', $GLOBALS['NEO_PORT'] ?? 7687);
32+
$this->assertInstanceOf(Bolt::class, $bolt);
33+
$this->assertTrue($bolt->hello('Test/1.0', $GLOBALS['NEO_USER'], $GLOBALS['NEO_PASS']));
34+
return $bolt;
35+
} catch (\Exception $e) {
36+
$this->markTestSkipped($e->getMessage());
37+
}
4138

42-
/**
43-
* @depends test__construct
44-
* @param Bolt $bolt
45-
* @return Bolt
46-
* @throws \Exception
47-
*/
48-
public function testInit(Bolt $bolt)
49-
{
50-
$this->assertTrue($bolt->init('Test/1.0', $GLOBALS['NEO_USER'], $GLOBALS['NEO_PASS']));
51-
return $bolt;
39+
return null;
5240
}
5341

5442
/**
55-
* @depends testInit
43+
* @depends testHello
5644
* @param Bolt $bolt
57-
* @return Bolt
5845
*/
59-
public function testRun(Bolt $bolt)
46+
public function testPull(Bolt $bolt)
6047
{
6148
$res = $bolt->run('RETURN 1 AS num, 2 AS cnt');
6249
$this->assertIsArray($res);
6350
$this->assertArrayHasKey('fields', $res);
64-
return $bolt;
65-
}
6651

67-
/**
68-
* @depends testRun
69-
* @param Bolt $bolt
70-
* @return Bolt
71-
*/
72-
public function testPull(Bolt $bolt)
73-
{
7452
$res = $bolt->pull();
7553
$this->assertEquals(1, $res[0][0] ?? 0);
7654
$this->assertEquals(2, $res[0][1] ?? 0);
77-
return $bolt;
7855
}
7956

8057
/**
81-
* @depends testInit
58+
* @depends testHello
8259
* @param Bolt $bolt
8360
*/
8461
public function testDiscard(Bolt $bolt)
8562
{
86-
//test discard
8763
$this->assertNotFalse($bolt->run('MATCH (a:Test) RETURN *'));
8864
$this->assertTrue($bolt->discard());
8965
}
9066

9167
/**
92-
* @depends testInit
93-
* @depends testPull
68+
* @depends testHello
9469
* @param Bolt $bolt
95-
* @return int
9670
*/
97-
public function testNodeCreate(Bolt $bolt)
71+
public function testNode(Bolt $bolt)
9872
{
9973
$this->assertNotFalse($bolt->run('CREATE (a:Test) RETURN a, ID(a)'));
10074

10175
$created = $bolt->pull();
10276
$this->assertIsArray($created);
10377
$this->assertInstanceOf(\Bolt\structures\Node::class, $created[0][0]);
104-
return $created[0][1];
105-
}
10678

107-
/**
108-
* @depends testInit
109-
* @depends testNodeCreate
110-
* @param Bolt $bolt
111-
* @param int $id
112-
*/
113-
public function testNodeDelete(Bolt $bolt, int $id)
114-
{
115-
//test delete created node
116-
$this->assertNotFalse($bolt->run('MATCH (a:Test) WHERE ID(a) = ' . ($this->getParameterType($bolt) ? '{a}' : '$a') . ' DELETE a', [
117-
'a' => $id
79+
$this->assertNotFalse($bolt->run('MATCH (a:Test) WHERE ID(a) = ' . $this->formatParameter($bolt, 'a') . ' DELETE a', [
80+
'a' => $created[0][1]
11881
]));
11982
$this->assertEquals(1, $bolt->pull()[0]['stats']['nodes-deleted'] ?? 0);
12083
}
12184

12285
/**
123-
* @depends testInit
86+
* @depends testHello
12487
* @param Bolt $bolt
12588
*/
12689
public function testTransaction(Bolt $bolt)
@@ -136,14 +99,31 @@ public function testTransaction(Bolt $bolt)
13699
$this->assertIsArray($created);
137100
$this->assertTrue($bolt->rollback());
138101

139-
$this->assertNotFalse($bolt->run('MATCH (a:Test) WHERE ID(a) = ' . ($this->getParameterType($bolt) ? '{a}' : '$a') . ' RETURN COUNT(a)', [
102+
$this->assertNotFalse($bolt->run('MATCH (a:Test) WHERE ID(a) = ' . $this->formatParameter($bolt, 'a') . ' RETURN COUNT(a)', [
140103
'a' => $created[0][1]
141104
]));
142105
$res = $bolt->pull();
143106
$this->assertIsArray($res);
144107
$this->assertEquals(0, $res[0][0]);
145108
}
146109

110+
public function testError()
111+
{
112+
$this->expectException(\Exception::class);
113+
Bolt::error('test');
114+
}
115+
116+
public function testErrorHandler()
117+
{
118+
$tmp = '';
119+
Bolt::$errorHandler = function ($msg, $code) use (&$tmp) {
120+
$tmp = $msg;
121+
};
122+
Bolt::error('test');
123+
$this->assertEquals('test', $tmp);
124+
Bolt::$errorHandler = null;
125+
}
126+
147127
/**
148128
* @var bool
149129
*/
@@ -152,9 +132,10 @@ public function testTransaction(Bolt $bolt)
152132
/**
153133
* Because from Neo4j >= 4.0 is different placeholder for parameters
154134
* @param Bolt $bolt
155-
* @return bool
135+
* @param string $name
136+
* @return string
156137
*/
157-
private function getParameterType(Bolt $bolt): bool
138+
private function formatParameter(Bolt $bolt, string $name): string
158139
{
159140
if (self::$parameterType == null) {
160141
$this->assertNotFalse($bolt->run('call dbms.components() yield versions unwind versions as version return version'));
@@ -163,7 +144,7 @@ private function getParameterType(Bolt $bolt): bool
163144
self::$parameterType = version_compare($neo4jVersion, '4') == -1;
164145
}
165146

166-
return self::$parameterType;
147+
return self::$parameterType ? ('{' . $name . '}') : ('$' . $name);
167148
}
168149

169150
}

0 commit comments

Comments
 (0)