Skip to content

Commit ea6e165

Browse files
Socket moved to connections, added interface. Finished tests for all protocol versions.
1 parent 9203329 commit ea6e165

File tree

13 files changed

+504
-137
lines changed

13 files changed

+504
-137
lines changed

Bolt.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Exception;
66
use Bolt\PackStream\{IPacker, IUnpacker};
77
use Bolt\protocol\AProtocol;
8+
use Bolt\connection\IConnection;
89

910
/**
1011
* Main class Bolt
@@ -32,9 +33,9 @@ final class Bolt
3233
private $protocol;
3334

3435
/**
35-
* @var Socket
36+
* @var IConnection
3637
*/
37-
private $socket;
38+
private $connection;
3839

3940
/**
4041
* @var array
@@ -77,7 +78,7 @@ final class Bolt
7778
*/
7879
public function __construct(string $ip = '127.0.0.1', int $port = 7687, int $timeout = 15)
7980
{
80-
$this->socket = new Socket($ip, $port, $timeout);
81+
$this->connection = new \Bolt\connection\Socket($ip, $port, $timeout);
8182

8283
$packerClass = "\\Bolt\\PackStream\\v" . $this->packStreamVersion . "\\Packer";
8384
if (!class_exists($packerClass)) {
@@ -142,8 +143,8 @@ private function handshake(): bool
142143
if (self::$debug)
143144
echo 'HANDSHAKE';
144145

145-
$this->socket->write(chr(0x60) . chr(0x60) . chr(0xb0) . chr(0x17));
146-
$this->socket->write($this->packProtocolVersions());
146+
$this->connection->write(chr(0x60) . chr(0x60) . chr(0xb0) . chr(0x17));
147+
$this->connection->write($this->packProtocolVersions());
147148

148149
$this->unpackProtocolVersion();
149150
if (empty($this->version)) {
@@ -155,7 +156,7 @@ private function handshake(): bool
155156
if (!class_exists($protocolClass)) {
156157
Bolt::error('Requested Protocol version (' . $this->version . ') not yet implemented');
157158
} else {
158-
$this->protocol = new $protocolClass($this->packer, $this->unpacker, $this->socket);
159+
$this->protocol = new $protocolClass($this->packer, $this->unpacker, $this->connection);
159160
}
160161

161162
return $this->protocol instanceof AProtocol;
@@ -168,7 +169,7 @@ private function unpackProtocolVersion()
168169
{
169170
$result = [];
170171

171-
foreach (str_split($this->socket->read(4)) as $ch)
172+
foreach (str_split($this->connection->read(4)) as $ch)
172173
$result[] = unpack('C', $ch)[1] ?? 0;
173174

174175
$result = array_filter($result);
@@ -218,7 +219,7 @@ private function packProtocolVersions(): string
218219
*/
219220
public function init(string $name, string $user, string $password, array $routing = null): bool
220221
{
221-
if (!$this->socket->connect())
222+
if (!$this->connection->connect())
222223
return false;
223224

224225
if (!$this->handshake())
@@ -401,7 +402,7 @@ public function __destruct()
401402
$this->protocol->goodbye();
402403
}
403404

404-
$this->socket->disconnect();
405+
$this->connection->disconnect();
405406
}
406407

407408
}

connection/IConnection.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Bolt\connection;
4+
5+
/**
6+
* Interface IConnection
7+
*
8+
* @author Michal Stefanak
9+
* @link https://github.com/stefanak-michal/Bolt
10+
* @package Bolt\connection
11+
*/
12+
interface IConnection
13+
{
14+
public function connect(): bool;
15+
16+
public function write(string $buffer);
17+
18+
public function read(int $length = 2048): string;
19+
20+
public function disconnect();
21+
}

Socket.php renamed to connection/Socket.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
<?php
22

3-
namespace Bolt;
3+
namespace Bolt\connection;
4+
5+
use Bolt\Bolt;
46

57
/**
68
* Socket class
79
*
810
* @author Michal Stefanak
911
* @link https://github.com/stefanak-michal/Bolt
10-
* @package Bolt
12+
* @package Bolt\connection
1113
*/
12-
final class Socket
14+
class Socket implements IConnection
1315
{
1416

1517
/**

phpunit.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
</php>
1111
<filter>
1212
<whitelist>
13-
<directory suffix=".php">protocol</directory>
13+
<directory suffix=".php">connection</directory>
1414
<directory suffix=".php">PackStream</directory>
15+
<directory suffix=".php">protocol</directory>
1516
<file>Bolt.php</file>
16-
<file>Socket.php</file>
1717
</whitelist>
1818
</filter>
1919
</phpunit>

protocol/AProtocol.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use Bolt\Bolt;
66
use Bolt\PackStream\{IPacker, IUnpacker};
7-
use Bolt\Socket;
7+
use Bolt\connection\IConnection;
88
use Exception;
99

1010
/**
@@ -33,21 +33,21 @@ abstract class AProtocol implements IProtocol
3333
protected $unpacker;
3434

3535
/**
36-
* @var Socket
36+
* @var IConnection
3737
*/
38-
private $socket;
38+
private $connection;
3939

4040
/**
4141
* AProtocol constructor.
4242
* @param IPacker $packer
4343
* @param IUnpacker $unpacker
44-
* @param Socket $socket
44+
* @param IConnection $connection
4545
*/
46-
public function __construct(IPacker $packer, IUnpacker $unpacker, Socket $socket)
46+
public function __construct(IPacker $packer, IUnpacker $unpacker, IConnection $connection)
4747
{
4848
$this->packer = $packer;
4949
$this->unpacker = $unpacker;
50-
$this->socket = $socket;
50+
$this->connection = $connection;
5151
}
5252

5353
public function begin(...$args): bool
@@ -71,17 +71,17 @@ public function goodbye(...$args)
7171
}
7272

7373
/**
74-
* Write to socket
74+
* Write to connection
7575
* @param string $buffer
7676
* @throws Exception
7777
*/
7878
protected function write(string $buffer)
7979
{
80-
$this->socket->write($buffer);
80+
$this->connection->write($buffer);
8181
}
8282

8383
/**
84-
* Read from socket
84+
* Read from connection
8585
* @param int|null $signature
8686
* @return mixed|null
8787
* @throws Exception
@@ -90,11 +90,11 @@ protected function read(?int &$signature)
9090
{
9191
$msg = '';
9292
while (true) {
93-
$header = $this->socket->read(2);
93+
$header = $this->connection->read(2);
9494
if (ord($header[0]) == 0x00 && ord($header[1]) == 0x00)
9595
break;
9696
$length = unpack('n', $header)[1] ?? 0;
97-
$msg .= $this->socket->read($length);
97+
$msg .= $this->connection->read($length);
9898
}
9999

100100
$output = null;

protocol/V3.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public function goodbye(...$args)
160160
$msg = $this->packer->pack(0x02);
161161
} catch (Exception $ex) {
162162
Bolt::error($ex->getMessage());
163-
return false;
163+
return;
164164
}
165165

166166
$this->write($msg);

tests/ATest.php

Lines changed: 85 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
namespace Bolt\tests;
44

5-
use \PHPUnit\Framework\TestCase;
5+
use PHPUnit\Framework\TestCase;
6+
use Bolt\connection\IConnection;
67

78
/**
89
* Class TestBase
@@ -14,30 +15,96 @@ abstract class ATest extends TestCase
1415
{
1516

1617
/**
17-
* @var bool
18+
* @var int Internal pointer for "readArray"
1819
*/
19-
private static $bypass = false;
20+
static $readIndex = 0;
21+
/**
22+
* @var array Order of consecutive returns from "read" method calls
23+
*/
24+
static $readArray = [];
25+
/**
26+
* @var int Internal pointer for "writeBuffer"
27+
*/
28+
static $writeIndex = 0;
29+
/**
30+
* @var array Expected write buffers or keep empty to skip verification
31+
*/
32+
static $writeBuffer = [];
33+
34+
/**
35+
* Mock Socket class with "write" and "read" methods
36+
* @return IConnection
37+
*/
38+
protected function mockConnection()
39+
{
40+
$mockBuilder = $this
41+
->getMockBuilder(IConnection::class)
42+
->disableOriginalConstructor();
43+
call_user_func([$mockBuilder, method_exists($mockBuilder, 'onlyMethods') ? 'onlyMethods' : 'setMethods'], ['write', 'read', 'connect', 'disconnect']);
44+
/** @var IConnection $connection */
45+
$connection = $mockBuilder->getMock();
46+
47+
$connection
48+
->method('write')
49+
->with(
50+
$this->callback(function ($buffer) {
51+
$i = self::$writeIndex;
52+
self::$writeIndex++;
53+
54+
//skip write buffer check
55+
if (empty(self::$writeBuffer))
56+
return true;
57+
58+
//verify expected buffer
59+
return (self::$writeBuffer[$i] ?? '') == $buffer;
60+
})
61+
);
62+
63+
$connection
64+
->method('read')
65+
->will($this->returnCallback([$this, 'readCallback']));
66+
67+
return $connection;
68+
}
2069

2170
/**
22-
* Bypass Socket final keyword before autoload
71+
* Mocked Socket read method
72+
* @return string
2373
*/
24-
public static function setUpBeforeClass(): void
74+
public function readCallback(): string
2575
{
26-
if (!self::$bypass) {
27-
$path = __DIR__;
28-
while (!file_exists($path . DS . 'Socket.php')) {
29-
$path = dirname($path);
30-
}
31-
32-
$content = file_get_contents($path . DS . 'Socket.php');
33-
if (strpos($content, "final class Socket") !== false) {
34-
file_put_contents($path . DS . 'Socket.php', str_replace('final class Socket', 'class Socket', $content));
35-
$socket = new \Bolt\Socket('localhost', 0, 0);
36-
file_put_contents($path . DS . 'Socket.php', $content);
37-
}
76+
switch (self::$readArray[self::$readIndex]) {
77+
case 1:
78+
$output = hex2bin('0003'); // header of length 3
79+
break;
80+
case 2:
81+
$output = hex2bin('B170A0'); // success {}
82+
break;
83+
case 3:
84+
$output = hex2bin('B171A0'); // record {}
85+
break;
86+
case 4:
87+
$output = hex2bin('004b'); // failure header
88+
break;
89+
case 5:
90+
$output = hex2bin('b17fa284636f6465d0254e656f2e436c69656e744572726f722e53746174656d656e742e53796e7461784572726f72876d657373616765d012736f6d65206572726f72206d657373616765'); // failure message
91+
break;
92+
default:
93+
$output = hex2bin('0000'); // end
3894
}
3995

40-
self::$bypass = true;
96+
self::$readIndex++;
97+
return (string)$output;
4198
}
4299

100+
/**
101+
* Reset mockup IConnetion variables
102+
*/
103+
protected function setUp()
104+
{
105+
self::$readIndex = 0;
106+
self::$readArray = [];
107+
self::$writeIndex = 0;
108+
self::$writeBuffer = [];
109+
}
43110
}

tests/BoltTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* @link https://github.com/stefanak-michal/Bolt
1212
*
1313
* @covers \Bolt\Bolt
14-
* @covers \Bolt\Socket
14+
* @covers \Bolt\connection\Socket
1515
*
1616
* @package Bolt\tests
1717
* @requires PHP >= 7.1

0 commit comments

Comments
 (0)