From 07d1ef580b78ccb851dc5fd6e4ec4838263d7651 Mon Sep 17 00:00:00 2001 From: denpamusic Date: Thu, 21 Feb 2019 05:47:47 +0300 Subject: [PATCH] Improved test coverage --- README.md | 156 ++++++++++++++++++--- src/Bucket.php | 78 ++++++----- src/BucketInterface.php | 12 -- src/CommandFactory.php | 4 +- src/Connection.php | 2 +- src/ConnectionInterface.php | 2 +- src/Exceptions/EntryTooLargeException.php | 9 ++ src/Exceptions/UnexpectedTypeException.php | 9 ++ src/Exceptions/UnknownCommandException.php | 9 ++ src/Exceptions/UnpackException.php | 9 ++ src/Section/Reader.php | 8 +- src/Section/Section.php | 4 +- src/Types/Bytearray.php | 14 +- src/Types/Type.php | 4 +- src/Types/Varint.php | 4 +- src/functions.php | 22 ++- tests/BucketTest.php | 142 ++++++++++--------- tests/CommandFactoryTest.php | 4 +- tests/ConnectionTest.php | 84 +++++------ tests/FunctionsTest.php | 71 +++++++++- tests/Section/ReaderTest.php | 104 ++++++++++++++ tests/Section/SectionTest.php | 4 +- tests/TestCase.php | 69 +++++++++ tests/Types/BytearrayTest.php | 10 +- tests/Types/TypeTest.php | 4 +- tests/Types/VarintTest.php | 4 +- 26 files changed, 619 insertions(+), 223 deletions(-) create mode 100644 src/Exceptions/EntryTooLargeException.php create mode 100644 src/Exceptions/UnexpectedTypeException.php create mode 100644 src/Exceptions/UnknownCommandException.php create mode 100644 src/Exceptions/UnpackException.php diff --git a/README.md b/README.md index 4463050..9fffe04 100644 --- a/README.md +++ b/README.md @@ -6,38 +6,152 @@ [![Code Coverage](https://codeclimate.com/github/denpamusic/php-levin/badges/coverage.svg)](https://codeclimate.com/github/denpamusic/php-levin/coverage) -## Example +## Examples +### Using helpers ```php +require 'vendor/autoload.php'; + use Denpa\Levin; $vars = [ 'network_id' => 'somenetwork', ]; -Levin\connection($ip, $port, $vars)->listen(function ($bucket, $connection) { - if ($bucket->isRequest('supportflags', 'timedsync', 'ping')) { - // respond to supportflags, timedsync and ping requests - // to keep the connection open - $connection->write($bucket->response()); +Levin\connection($ip, $port, $vars)->connect( + function ($bucket, $connection) { + if ($bucket->isRequest('supportflags', 'timedsync', 'ping')) { + // respond to supportflags, timedsync and ping requests + // to keep the connection open + $connection->write($bucket->response()); + } + + if ($bucket->isResponse('handshake')) { + // send ping request to the server after + // receiving handshake response + $connection->write(Levin\request('ping')); + } + + if ($bucket->isResponse('ping')) { + // dump server response to the console + var_dump($bucket->getPayload()); + + // returning false closes connection + return false; + } } +); +``` + +### Using objects +```php +require 'vendor/autoload.php'; + +use Denpa\Levin\Bucket; +use Denpa\Levin\Connection; +use Denpa\Levin\Requests\Handshake; + +$handshake = new Handshake(['network_id' => 'somenetwork']); +$request = (new Bucket())->request($handshake); + +$connection = new Connection($ip, $port); +$connection->write($request); + +while ($bucket = $connection->read()) { + // ... +} +``` + +### Fetching peers +```php +require 'vendor/autoload.php'; + +use Denpa\Levin; + +function peerlist(array $entries) : array +{ + $peers = []; + + foreach ($entries as $entry) { + $addr = $entry['adr']['addr'] ?? null; + + if (is_null($addr)) continue; + + // convert ip to big-endian int + $ip = Levin\uint32($addr['m_ip']->toBinary()); + + $peer = []; + $peer['ip'] = inet_ntop($ip->toBinary()); + $peer['port'] = $addr['m_port']->toInt(); + $peer['last_seen'] = isset($entry['last_seen']) ? + date('Y-m-d H:i:s', $entry['last_seen']->toInt()) : null; + + $peers[] = $peer; + } - if ($bucket->isResponse('ping')) { - // dump server response to the console - var_dump($bucket->payload()); - - // returning false closes connection - return false; + return $peers; +} + +$vars = [ + 'network_id' => 'somenetwork', +]; + +$section = []; + +Levin\connection($ip, $port, $vars)->connect( + function ($bucket, $connection) use ($section) { + if ($bucket->isResponse('handshake')) { + $section = $bucket->getPayload(); + + return false; + } } - - if ($bucket->isResponse('handshake')) { - // send ping request to the server after - // receiving handshake response - $connection->write(Levin\request('ping')); +); + +$peers = peerlist($section['local_peerlist_new'] ?? []); + +var_dump($peers); +/** + * Array( + * Array( + * 'ip' => '88.99.122.111', + * 'port' => 1000, + * 'last_seen' => '2019-02-21 12:00:00' + * ), + * ... + * ) + */ +``` +### Monitoring blocks +```php +require 'vendor/autoload.php'; + +use Denpa\Levin; + +$vars = [ + 'network_id' => 'somenetwork', +]; + +Levin\connection($ip, $port, $vars)->connect( + function ($bucket, $connection) { + if ($bucket->isRequest('supportflags', 'timedsync', 'ping')) { + // respond to supportflags, timedsync and ping requests + // to keep the connection open + $connection->write($bucket->response()); + } + + if ($bucket->isRequest('newblock')) { + $section = $bucket->getPayload(); + + printf("New block: %d\n", $section['current_blockchain_height']); + var_dump($section['b']); + + // no need to respond to notification + } } -}); +); ``` -## Command Support +## Request Support | command | link | request | response | |--------------|---------------------------------------------------------------------------------------|---------|----------| | Handshake | [p2p_protocol_defs.h#L177](https://github.com/monero-project/monero/blob/master/src/p2p/p2p_protocol_defs.h#L177) | ✅ | ✅ | @@ -61,7 +175,11 @@ Levin\connection($ip, $port, $vars)->listen(function ($bucket, $connection) { ## Exceptions * `Denpa\Levin\Exceptions\ConnectionException` - thrown on connection errors. +* `Denpa\Levin\Exceptions\EntryTooLargeException` - thrown when type or packet size is too large. * `Denpa\Levin\Exceptions\SignatureMismatchException` - thrown on section or bucket signature mismatches. +* `Denpa\Levin\Exceptions\UnexpectedTypeException` - thrown on unexpected or invalid type. +* `Denpa\Levin\Exceptions\UnknownCommandException` - thrown on unknown command. +* `Denpa\Levin\Exceptions\UnpackException` - thrown when unable to unpack binary data. ## License This product is distributed under the [MIT license](https://github.com/denpamusic/php-levin/blob/master/LICENSE). diff --git a/src/Bucket.php b/src/Bucket.php index 8c5dabd..e4ed4ff 100644 --- a/src/Bucket.php +++ b/src/Bucket.php @@ -2,6 +2,8 @@ namespace Denpa\Levin; +use BadMethodCallException; +use Denpa\Levin\Exceptions\EntryTooLargeException; use Denpa\Levin\Exceptions\SignatureMismatchException; use Denpa\Levin\Section\Reader; use Denpa\Levin\Section\Section; @@ -9,9 +11,18 @@ use Denpa\Levin\Types\Int32; use Denpa\Levin\Types\Uint32; use Denpa\Levin\Types\Uint64; -use LengthException; use UnexpectedValueException; +/** + * @method \Denpa\Levin\Types\Uint64 getSignature() + * @method \Denpa\Levin\Types\Uint64 getCb() + * @method \Denpa\Levin\Types\Uint32 getReturnData() + * @method \Denpa\Levin\Command getCommand() + * @method \Denpa\Levin\Types\Int32 getReturnCode() + * @method \Denpa\Levin\Types\Uint32 getFlags() + * @method \Denpa\Levin\Types\Uint32 getProtocolVersion() + * @method \Denpa\Levin\Section getPayload() + */ class Bucket implements BucketInterface { /** @@ -52,7 +63,7 @@ class Bucket implements BucketInterface /** * @var \Denpa\Levin\Section|null */ - protected $payloadSection = null; + protected $payload = null; /** * @return void @@ -72,7 +83,7 @@ public function __construct(array $params = []) $params = $params + $defaults; foreach ($params as $key => $value) { - $mutator = 'set'.camel_case($key); + $mutator = 'set'.ucfirst(camel_case($key)); if (method_exists($this, $mutator)) { $this->$mutator($value); } @@ -155,20 +166,12 @@ public function setCb($cb) : self if ($this->cb->toInt() > self::LEVIN_DEFAULT_MAX_PACKET_SIZE) { $maxsize = self::LEVIN_DEFAULT_MAX_PACKET_SIZE; - throw new LengthException("Packet is too large [> $maxsize]"); + throw new EntryTooLargeException("Bucket is too large [> $maxsize]"); } return $this; } - /** - * @return \Denpa\Levin\Types\Uint64 - */ - public function getCb() : Uint64 - { - return $this->cb; - } - /** * @param mixed $returnData * @@ -197,14 +200,6 @@ public function setCommand($command) : self return $this; } - /** - * @return \Denpa\Levin\CommandInterface|null - */ - public function getCommand() : ?CommandInterface - { - return $this->command; - } - /** * @param \Denpa\Levin\CommandInterface $command * @@ -215,7 +210,7 @@ public function fill(CommandInterface $command) : self $method = $this->isRequest() ? 'request' : 'response'; $this->command = $command; - $this->setPayloadSection($command->$method()); + $this->setPayload($command->$method()); return $this; } @@ -263,10 +258,10 @@ public function setProtocolVersion($protocolVersion) : self * * @return self */ - public function setPayloadSection(Section $section) : self + public function setPayload(Section $section) : self { $this->setCb($section->getByteSize()); - $this->payloadSection = $section; + $this->payload = $section; return $this; } @@ -274,7 +269,7 @@ public function setPayloadSection(Section $section) : self /** * @return string */ - public function head() : string + public function getHead() : string { $head = [ 'signature' => $this->signature, @@ -301,14 +296,6 @@ public function head() : string return implode('', $head); } - /** - * @return \Denpa\Levin\Section|null - */ - public function payload() : ?Section - { - return $this->payloadSection; - } - /** * @param \Denpa\Levin\Connection $connection * @@ -316,10 +303,10 @@ public function payload() : ?Section */ public function write(Connection $connection) : void { - $connection->write($this->head()); + $connection->write($this->getHead()); - if (!is_null($this->payloadSection)) { - $connection->write($this->payload()->toBinary()); + if (!is_null($this->payload)) { + $connection->write($this->getPayload()->toBinary()); } } @@ -344,9 +331,9 @@ public function read(Connection $connection) : ?self 'protocol_version' => $connection->read(uint32le()), ]); - if ($bucket->getCb()->toInt() > 0) { + if ($bucket->cb->toInt() > 0) { $section = (new Reader($connection))->read(); - $bucket->setPayloadSection($section); + $bucket->setPayload($section); } return $bucket; @@ -387,4 +374,21 @@ public function response(?CommandInterface $command = null) : self return $this; } + + /** + * @param string $method + * @param array $args + * + * @return mixed + */ + public function __call(string $method, array $args = []) + { + if (substr($method, 0, 3) == 'get') { + $variable = camel_case(substr($method, 3)); + + return $this->$variable ?? null; + } + + throw new BadMethodCallException("Method [$method] does not exist"); + } } diff --git a/src/BucketInterface.php b/src/BucketInterface.php index 97f6cb7..d65a5c1 100644 --- a/src/BucketInterface.php +++ b/src/BucketInterface.php @@ -2,8 +2,6 @@ namespace Denpa\Levin; -use Denpa\Levin\Section\Section; - interface BucketInterface { /** @@ -31,16 +29,6 @@ interface BucketInterface */ const LEVIN_DEFAULT_MAX_PACKET_SIZE = 100000000; // 100MB - /** - * @return string - */ - public function head() : string; - - /** - * @return \Denpa\Levin\Section|null - */ - public function payload() : ?Section; - /** * @param \Denpa\Levin\Connection $connection * diff --git a/src/CommandFactory.php b/src/CommandFactory.php index 8fcd927..4ea58bb 100644 --- a/src/CommandFactory.php +++ b/src/CommandFactory.php @@ -2,7 +2,7 @@ namespace Denpa\Levin; -use UnexpectedValueException; +use Denpa\Levin\Exceptions\UnknownCommandException; class CommandFactory { @@ -48,7 +48,7 @@ public function __construct() public function getCommand(int $command) : CommandInterface { if (!isset($this->commands[$command])) { - throw new UnexpectedValueException("Unknown command [$command]"); + throw new UnknownCommandException("Unknown command [$command]"); } return new $this->commands[$command](); diff --git a/src/Connection.php b/src/Connection.php index 1e72e59..3fd501c 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -47,7 +47,7 @@ public function __destruct() * * @return void */ - public function listen(callable $callback) : void + public function connect(callable $callback) : void { if (!$this->isOpen()) { return; diff --git a/src/ConnectionInterface.php b/src/ConnectionInterface.php index c647233..a3d083e 100644 --- a/src/ConnectionInterface.php +++ b/src/ConnectionInterface.php @@ -9,7 +9,7 @@ interface ConnectionInterface * * @return void */ - public function listen(callable $callback) : void; + public function connect(callable $callback) : void; /** * @param mixed $object diff --git a/src/Exceptions/EntryTooLargeException.php b/src/Exceptions/EntryTooLargeException.php new file mode 100644 index 0000000..3d022b2 --- /dev/null +++ b/src/Exceptions/EntryTooLargeException.php @@ -0,0 +1,9 @@ +connection->read(new Uint8())->toInt(); if (($type & Section::SERIALIZE_FLAG_ARRAY) != 0) { - throw new UnexpectedValueException('Incorrect array sequence'); + throw new UnexpectedTypeException('Incorrect type sequence'); } return $this->readArrayEntry($type); @@ -147,7 +147,7 @@ protected function readArrayEntry(int $type) : Bytearray $count--; } - return Levin\bytearray($result); + return Levin\bytearray($result, new $this->types[$type]()); } /** @@ -158,7 +158,7 @@ protected function readArrayEntry(int $type) : Bytearray protected function readValue(int $type) : BoostSerializable { if (!array_key_exists($type, $this->types)) { - throw new UnexpectedValueException( + throw new UnexpectedTypeException( "Cannot unserialize unknown type [$type]" ); } diff --git a/src/Section/Section.php b/src/Section/Section.php index 974261f..12fb78a 100644 --- a/src/Section/Section.php +++ b/src/Section/Section.php @@ -6,12 +6,12 @@ use Countable; use Denpa\Levin; use Denpa\Levin\BufferInterface; +use Denpa\Levin\Exceptions\UnexpectedTypeException; use Denpa\Levin\Traits\Arrayable; use Denpa\Levin\Types\BoostSerializable; use Denpa\Levin\Types\Bytestring; use Denpa\Levin\Types\Uint8; use IteratorAggregate; -use UnexpectedValueException; class Section implements SectionInterface, @@ -131,7 +131,7 @@ public function serialize() : string foreach ($this->entries as $key => $entry) { if (!$entry instanceof BoostSerializable) { - throw new UnexpectedValueException( + throw new UnexpectedTypeException( "Cannot serialize unserializable item [$key]" ); } diff --git a/src/Types/Bytearray.php b/src/Types/Bytearray.php index e071636..4323958 100644 --- a/src/Types/Bytearray.php +++ b/src/Types/Bytearray.php @@ -4,9 +4,9 @@ use ArrayAccess; use Countable; +use Denpa\Levin\Exceptions\UnexpectedTypeException; use Denpa\Levin\Section\Section; use Denpa\Levin\Traits\Arrayable; -use InvalidArgumentException; use IteratorAggregate; class Bytearray implements @@ -110,6 +110,14 @@ public function __toString() : string return $this->toBinary(); } + /** + * @return \Denpa\Levin\Types\Uint8 + */ + public function getType() : Uint8 + { + return $this->type; + } + /** * @return \Denpa\Levin\Types\Uint8 */ @@ -130,13 +138,13 @@ public function getSerializeType() : Uint8 protected function validate($value) : void { if (!$value instanceof BoostSerializable) { - throw new InvalidArgumentException( + throw new UnexpectedTypeException( 'Array entries must be serializable' ); } if ($this->type && ($this->type != $value->getSerializeType())) { - throw new InvalidArgumentException( + throw new UnexpectedTypeException( 'Array entries must be of the same type' ); } diff --git a/src/Types/Type.php b/src/Types/Type.php index 1283591..36bbbc9 100644 --- a/src/Types/Type.php +++ b/src/Types/Type.php @@ -3,7 +3,7 @@ namespace Denpa\Levin\Types; use Countable; -use UnexpectedValueException; +use Denpa\Levin\Exceptions\UnpackException; abstract class Type implements TypeInterface, Countable { @@ -32,7 +32,7 @@ public function __construct($value = null, int $endianness = self::BE) $unpacked = @unpack($this->getTypeCode(), $this->value); if ($unpacked === false || !isset($unpacked[1])) { - throw new UnexpectedValueException( + throw new UnpackException( "Failed to unpack binary data [{$this->value}]" ); } diff --git a/src/Types/Varint.php b/src/Types/Varint.php index 8bc35d0..d11d202 100644 --- a/src/Types/Varint.php +++ b/src/Types/Varint.php @@ -3,7 +3,7 @@ namespace Denpa\Levin\Types; use Denpa\Levin\Connection; -use UnexpectedValueException; +use Denpa\Levin\Exceptions\EntryTooLargeException; class Varint extends Type { @@ -48,7 +48,7 @@ public function toBinary() : string $value = new Uint32(($this->value << 2) | self::PORTABLE_RAW_SIZE_MARK_DWORD, Type::LE); break; case $this->value >= 4611686018427387903: - throw new UnexpectedValueException('VarInt is too large [> 4611686018427387903]'); + throw new EntryTooLargeException('VarInt is too large [> 4611686018427387903]'); default: $value = new Uint64(($this->value << 2) | self::PORTABLE_RAW_SIZE_MARK_INT64, Type::LE); } diff --git a/src/functions.php b/src/functions.php index c40a947..a509cd3 100644 --- a/src/functions.php +++ b/src/functions.php @@ -308,9 +308,27 @@ function connection(string $host, $port, array $vars = []) : ConnectionInterface */ function camel_case(string $string) : string { - $string = str_replace('_', ' ', $string); + $string = str_replace('_', ' ', ltrim(snake_case($string), '_')); - return str_replace(' ', '', ucwords(strtolower($string))); + return str_replace(' ', '', lcfirst(ucwords(strtolower($string)))); + } +} + +if (!function_exists('snake_case')) { + /** + * @param string $string + * + * @return string + * + * @copyright 2016 Syone + * + * @link https://stackoverflow.com/a/35719689/10405250 Answer on StackOverflow. + */ + function snake_case(string $string) : string + { + $string = preg_replace(['/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'], '$1_$2', $string); + + return strtolower($string); } } diff --git a/tests/BucketTest.php b/tests/BucketTest.php index 0d857ab..7af85a2 100644 --- a/tests/BucketTest.php +++ b/tests/BucketTest.php @@ -2,10 +2,12 @@ namespace Denpa\Levin\Tests; +use BadMethodCallException; use Denpa\Levin; use Denpa\Levin\Bucket; use Denpa\Levin\CommandInterface; use Denpa\Levin\Connection; +use Denpa\Levin\Exceptions\EntryTooLargeException; use Denpa\Levin\Exceptions\SignatureMismatchException; use Denpa\Levin\Requests\Handshake; use Denpa\Levin\Requests\RequestInterface; @@ -27,16 +29,16 @@ public function setUp() : void { parent::setUp(); - $this->bucket = new FakeBucket(); + $this->bucket = new Bucket(); $this->headBytemap = [ 'signature' => count(new Uint64()), 'cb' => count(new Uint64()), - 'returnData' => count(new Boolean()), + 'return_data' => count(new Boolean()), 'command' => count(new Uint32()), - 'returnCode' => count(new Int32()), + 'return_code' => count(new Int32()), 'flags' => count(new Uint32()), - 'protocolVersion' => count(new Uint32()), + 'protocol_version' => count(new Uint32()), ]; } @@ -46,12 +48,12 @@ public function setUp() : void public function testIsRequest() : void { $handshake = new Handshake(); - $request = (new FakeBucket())->request($handshake); + $request = (new Bucket())->request($handshake); $this->assertTrue($request->isRequest('handshake')); $this->assertTrue($request->isRequest()); $this->assertFalse($request->isRequest('ping')); - $response = (new FakeBucket())->response($handshake); + $response = (new Bucket())->response($handshake); $this->assertFalse($response->isRequest('handshake')); $this->assertFalse($response->isRequest()); } @@ -62,12 +64,12 @@ public function testIsRequest() : void public function testIsResponse() : void { $handshake = new Handshake(); - $response = (new FakeBucket())->response($handshake); + $response = (new Bucket())->response($handshake); $this->assertTrue($response->isResponse('handshake')); $this->assertTrue($response->isResponse()); $this->assertFalse($response->isResponse('ping')); - $request = (new FakeBucket())->request($handshake); + $request = (new Bucket())->request($handshake); $this->assertFalse($request->isResponse('handshake')); $this->assertFalse($request->isResponse()); } @@ -78,7 +80,7 @@ public function testIsResponse() : void public function testIs() : void { $handshake = new Handshake(); - $bucket = (new FakeBucket())->fill($handshake); + $bucket = (new Bucket())->fill($handshake); $this->assertTrue($bucket->is('handshake')); $this->assertFalse($bucket->is('ping')); } @@ -89,7 +91,7 @@ public function testIs() : void public function testIsWithMultipleArgs() : void { $handshake = new Handshake(); - $bucket = (new FakeBucket())->fill($handshake); + $bucket = (new Bucket())->fill($handshake); $this->assertTrue($bucket->is('handshake', 'ping')); $this->assertTrue($bucket->is('supportflags', 'handshake')); $this->assertFalse($bucket->is('ping', 'supportflags')); @@ -101,8 +103,8 @@ public function testIsWithMultipleArgs() : void public function testSetSignature() : void { $this->bucket->setSignature(Bucket::LEVIN_SIGNATURE); - $this->assertInstanceOf(Uint64::class, $this->bucket->signature); - $this->assertSame(Bucket::LEVIN_SIGNATURE, $this->bucket->signature->toInt()); + $this->assertInstanceOf(Uint64::class, $this->bucket->getSignature()); + $this->assertSame(Bucket::LEVIN_SIGNATURE, $this->bucket->getSignature()->toInt()); } /** @@ -112,8 +114,8 @@ public function testSetSignatureWithUint() : void { $uint64 = new Uint64(Bucket::LEVIN_SIGNATURE, Uint64::LE); $this->bucket->setSignature($uint64); - $this->assertInstanceOf(Uint64::class, $this->bucket->signature); - $this->assertSame(Bucket::LEVIN_SIGNATURE, $this->bucket->signature->toInt()); + $this->assertInstanceOf(Uint64::class, $this->bucket->getSignature()); + $this->assertSame(Bucket::LEVIN_SIGNATURE, $this->bucket->getSignature()->toInt()); } /** @@ -132,8 +134,8 @@ public function testSetSignatureWithMismatch() : void public function testSetCb() : void { $this->bucket->setCb(100); - $this->assertInstanceOf(Uint64::class, $this->bucket->cb); - $this->assertSame(100, $this->bucket->cb->toInt()); + $this->assertInstanceOf(Uint64::class, $this->bucket->getCb()); + $this->assertSame(100, $this->bucket->getCb()->toInt()); } /** @@ -143,8 +145,8 @@ public function testSetCbWithUint() : void { $uint64 = new Uint64(100, Uint64::LE); $this->bucket->setCb($uint64); - $this->assertInstanceOf(Uint64::class, $this->bucket->cb); - $this->assertSame(100, $this->bucket->cb->toInt()); + $this->assertInstanceOf(Uint64::class, $this->bucket->getCb()); + $this->assertSame(100, $this->bucket->getCb()->toInt()); } /** @@ -153,8 +155,8 @@ public function testSetCbWithUint() : void public function testSetCbMaxSize() : void { $maxsize = Bucket::LEVIN_DEFAULT_MAX_PACKET_SIZE; - $this->expectException(\Exception::class); - $this->expectExceptionMessage("Packet is too large [> $maxsize]"); + $this->expectException(EntryTooLargeException::class); + $this->expectExceptionMessage("Bucket is too large [> $maxsize]"); $this->bucket->setCb($maxsize + 1); } @@ -164,8 +166,8 @@ public function testSetCbMaxSize() : void public function testSetReturnData() : void { $this->bucket->setReturnData(false); - $this->assertInstanceOf(Boolean::class, $this->bucket->returnData); - $this->assertSame(false, $this->bucket->returnData->getValue()); + $this->assertInstanceOf(Boolean::class, $this->bucket->getReturnData()); + $this->assertSame(false, $this->bucket->getReturnData()->getValue()); } /** @@ -175,8 +177,8 @@ public function testSetReturnDataWithUint() : void { $boolean = new Boolean(false); $this->bucket->setReturnData($boolean); - $this->assertInstanceOf(Boolean::class, $this->bucket->returnData); - $this->assertSame(false, $this->bucket->returnData->getValue()); + $this->assertInstanceOf(Boolean::class, $this->bucket->getReturnData()); + $this->assertSame(false, $this->bucket->getReturnData()->getValue()); } /** @@ -185,8 +187,8 @@ public function testSetReturnDataWithUint() : void public function testSetCommand() : void { $this->bucket->setCommand(RequestInterface::P2P_COMMANDS_POOL_BASE + 1); - $this->assertInstanceOf(RequestInterface::class, $this->bucket->command); - $this->assertSame(RequestInterface::P2P_COMMANDS_POOL_BASE + 1, $this->bucket->command->getCommandCode()); + $this->assertInstanceOf(RequestInterface::class, $this->bucket->getCommand()); + $this->assertSame(RequestInterface::P2P_COMMANDS_POOL_BASE + 1, $this->bucket->getCommand()->getCommandCode()); } /** @@ -196,8 +198,8 @@ public function testSetCommandWithUint() { $uint32 = new Uint32(RequestInterface::P2P_COMMANDS_POOL_BASE + 1, Uint32::LE); $this->bucket->setCommand($uint32); - $this->assertInstanceOf(RequestInterface::class, $this->bucket->command); - $this->assertSame(RequestInterface::P2P_COMMANDS_POOL_BASE + 1, $this->bucket->command->getCommandCode()); + $this->assertInstanceOf(RequestInterface::class, $this->bucket->getCommand()); + $this->assertSame(RequestInterface::P2P_COMMANDS_POOL_BASE + 1, $this->bucket->getCommand()->getCommandCode()); } /** @@ -217,8 +219,8 @@ public function testFill() : void { $handshake = new Handshake(); $this->bucket->fill($handshake); - $this->assertSame($handshake->getCommandCode(), $this->bucket->command->getCommandCode()); - $this->assertSame($handshake->request()['network_id'], $this->bucket->command->request()['network_id']); + $this->assertSame($handshake->getCommandCode(), $this->bucket->getCommand()->getCommandCode()); + $this->assertSame($handshake->request()['network_id'], $this->bucket->getCommand()->request()['network_id']); } /** @@ -227,8 +229,8 @@ public function testFill() : void public function testSetReturnCode() : void { $this->bucket->setReturnCode(0); - $this->assertInstanceOf(Int32::class, $this->bucket->returnCode); - $this->assertSame(0, $this->bucket->returnCode->toInt()); + $this->assertInstanceOf(Int32::class, $this->bucket->getReturnCode()); + $this->assertSame(0, $this->bucket->getReturnCode()->toInt()); } /** @@ -238,8 +240,8 @@ public function testSetReturnCodeWithInt() : void { $int32 = new Int32(0, Int32::LE); $this->bucket->setReturnCode($int32); - $this->assertInstanceOf(Int32::class, $this->bucket->returnCode); - $this->assertSame(0, $this->bucket->returnCode->toInt()); + $this->assertInstanceOf(Int32::class, $this->bucket->getReturnCode()); + $this->assertSame(0, $this->bucket->getReturnCode()->toInt()); } /** @@ -248,8 +250,8 @@ public function testSetReturnCodeWithInt() : void public function testSetFlags() : void { $this->bucket->setFlags(Bucket::LEVIN_PACKET_REQUEST); - $this->assertInstanceOf(Uint32::class, $this->bucket->flags); - $this->assertSame(Bucket::LEVIN_PACKET_REQUEST, $this->bucket->flags->toInt()); + $this->assertInstanceOf(Uint32::class, $this->bucket->getFlags()); + $this->assertSame(Bucket::LEVIN_PACKET_REQUEST, $this->bucket->getFlags()->toInt()); } /** @@ -259,8 +261,8 @@ public function testSetFlagsWithUint() : void { $uint32 = new Uint32(Bucket::LEVIN_PACKET_REQUEST, Uint32::LE); $this->bucket->setFlags($uint32); - $this->assertInstanceOf(Uint32::class, $this->bucket->flags); - $this->assertSame(Bucket::LEVIN_PACKET_REQUEST, $this->bucket->flags->toInt()); + $this->assertInstanceOf(Uint32::class, $this->bucket->getFlags()); + $this->assertSame(Bucket::LEVIN_PACKET_REQUEST, $this->bucket->getFlags()->toInt()); } /** @@ -269,8 +271,8 @@ public function testSetFlagsWithUint() : void public function testSetProtocolVersion() : void { $this->bucket->setProtocolVersion(Bucket::LEVIN_PROTOCOL_VER_1); - $this->assertInstanceOf(Uint32::class, $this->bucket->protocolVersion); - $this->assertSame(Bucket::LEVIN_PROTOCOL_VER_1, $this->bucket->protocolVersion->toInt()); + $this->assertInstanceOf(Uint32::class, $this->bucket->getProtocolVersion()); + $this->assertSame(Bucket::LEVIN_PROTOCOL_VER_1, $this->bucket->getProtocolVersion()->toInt()); } /** @@ -280,33 +282,34 @@ public function testSetProtocolVersionWithUint() : void { $uint32 = new Uint32(Bucket::LEVIN_PROTOCOL_VER_1, Uint32::LE); $this->bucket->setProtocolVersion($uint32); - $this->assertInstanceOf(Uint32::class, $this->bucket->protocolVersion); - $this->assertSame(Bucket::LEVIN_PROTOCOL_VER_1, $this->bucket->protocolVersion->toInt()); + $this->assertInstanceOf(Uint32::class, $this->bucket->getProtocolVersion()); + $this->assertSame(Bucket::LEVIN_PROTOCOL_VER_1, $this->bucket->getProtocolVersion()->toInt()); } /** * @return void */ - public function testSetPayloadSection() : void + public function testSetPayload() : void { $section = new Section(['foo' => new Uint32(0, Uint32::LE)]); - $this->bucket->setPayloadSection($section); - $this->assertSame($section['foo'], $this->bucket->payload()['foo']); + $this->bucket->setPayload($section); + $this->assertSame($section['foo'], $this->bucket->getPayload()['foo']); } /** * @return void */ - public function testHead() : void + public function testGetHead() : void { $handshake = new Handshake(); $this->bucket->fill($handshake); $offset = 0; - $head = $this->bucket->head(); + $head = $this->bucket->getHead(); foreach ($this->headBytemap as $key => $size) { - $item = ($this->bucket->$key instanceof CommandInterface) ? - $this->bucket->$key->getCommand() : $this->bucket->$key; + $getter = 'get'.ucfirst(Levin\camel_case($key)); + $item = ($this->bucket->$getter() instanceof CommandInterface) ? + $this->bucket->$getter()->getCommand() : $this->bucket->$getter(); $this->assertEquals($item->toBinary(), substr($head, $offset, $size)); $offset += $size; @@ -320,7 +323,7 @@ public function testHeadWithNotAllValuesSet() : void { $this->expectException(UnexpectedValueException::class); $this->expectExceptionMessage('Value for [command] must be set'); - $this->bucket->head(); + $this->bucket->getHead(); } /** @@ -330,7 +333,7 @@ public function testPayload() : void { $handshake = new Handshake(); $this->bucket->fill($handshake); - $this->assertSame($handshake->request()['network_id'], $this->bucket->payload()['network_id']); + $this->assertSame($handshake->request()['network_id'], $this->bucket->getPayload()['network_id']); } /** @@ -339,9 +342,9 @@ public function testPayload() : void public function testRequest() : void { $handshake = new Handshake(); - $request = (new FakeBucket())->request($handshake); - $this->assertInstanceOf(FakeBucket::class, $request); - $this->assertEquals(Bucket::LEVIN_PACKET_REQUEST, $request->flags->toInt()); + $request = (new Bucket())->request($handshake); + $this->assertInstanceOf(Bucket::class, $request); + $this->assertEquals(Bucket::LEVIN_PACKET_REQUEST, $request->getFlags()->toInt()); $this->assertEquals($handshake, $request->getCommand()); } @@ -351,9 +354,9 @@ public function testRequest() : void public function testResponse() : void { $handshake = new Handshake(); - $response = (new FakeBucket())->response($handshake); - $this->assertInstanceOf(FakeBucket::class, $response); - $this->assertEquals(Bucket::LEVIN_PACKET_RESPONSE, $response->flags->toInt()); + $response = (new Bucket())->response($handshake); + $this->assertInstanceOf(Bucket::class, $response); + $this->assertEquals(Bucket::LEVIN_PACKET_RESPONSE, $response->getFlags()->toInt()); $this->assertEquals($handshake, $response->getCommand()); } @@ -370,8 +373,8 @@ public function testWrite() : void $connection->expects($this->exactly(2)) ->method('write') ->withConsecutive( - [$this->bucket->head()], - [$this->bucket->payload()->toBinary()] + [$this->bucket->getHead()], + [$this->bucket->getPayload()->toBinary()] ); $this->bucket->write($connection); @@ -449,16 +452,15 @@ public function testReadEof() : void $this->isNull($bucket); } -} -class FakeBucket extends Bucket -{ - public $signature; - public $cb; - public $returnData; - public $command; - public $returnCode; - public $flags; - public $protocolVersion; - public $payloadSection = null; + /** + * @return void + */ + public function testMagicWithUnknownMethod() : void + { + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage('Method [nonExistent] does not exist'); + + $this->bucket->nonExistent(); + } } diff --git a/tests/CommandFactoryTest.php b/tests/CommandFactoryTest.php index 362afa0..b8201c8 100644 --- a/tests/CommandFactoryTest.php +++ b/tests/CommandFactoryTest.php @@ -4,6 +4,7 @@ use Denpa\Levin\Bucket; use Denpa\Levin\CommandFactory; +use Denpa\Levin\Exceptions\UnknownCommandException; use Denpa\Levin\Notifications\NewBlock; use Denpa\Levin\Notifications\NewFluffyBlock; use Denpa\Levin\Notifications\NewTransactions; @@ -20,7 +21,6 @@ use Denpa\Levin\Requests\StatInfo; use Denpa\Levin\Requests\SupportFlags; use Denpa\Levin\Requests\TimedSync; -use UnexpectedValueException; class CommandFactoryTest extends TestCase { @@ -52,7 +52,7 @@ public function testGetCommand(int $command, string $handler) : void */ public function testGetCommandWithUnknown() : void { - $this->expectException(UnexpectedValueException::class); + $this->expectException(UnknownCommandException::class); $this->expectExceptionMessage('Unknown command [9999]'); $this->commandFactory->getCommand(9999); } diff --git a/tests/ConnectionTest.php b/tests/ConnectionTest.php index 4dfbdcc..340fdd3 100644 --- a/tests/ConnectionTest.php +++ b/tests/ConnectionTest.php @@ -7,12 +7,6 @@ use Denpa\Levin\Exceptions\ConnectionException; use Denpa\Levin\Requests\Handshake; use Denpa\Levin\Types\Uint64; -use VirtualFileSystem\FileSystem; - -/** - * @var \VirtualFileSystem\FileSystem - */ -$fs = null; class ConnectionTest extends TestCase { @@ -21,27 +15,18 @@ class ConnectionTest extends TestCase */ public function setUp() : void { - global $fs; parent::setUp(); - $this->fs = new FileSystem(); - - if (is_null($fs)) { - $fs = $this->fs; - } + $this->socket = $this->createSocketMock('handshake'); } /** * @return void */ - public function testListen() : void + public function testConnect() : void { - $handshake = (new Bucket())->response(new Handshake()); - $response = $handshake->head().$handshake->payload()->toBinary(); - file_put_contents($this->fs->path('127.0.0.1:1000'), $response); - - $connection = new Connection('127.0.0.1', 1000); - $connection->listen(function ($bucket, $connection) { + $connection = new Connection(...$this->socket); + $connection->connect(function ($bucket, $connection) { $this->assertInstanceOf(Bucket::class, $bucket); $this->assertInstanceOf(Connection::class, $connection); $this->assertTrue($bucket->is('handshake')); @@ -53,15 +38,34 @@ public function testListen() : void /** * @return void */ - public function testRead() : void + public function testListenOnClosedConnection() : void { - $handshake = (new Bucket())->response(new Handshake()); - $response = $handshake->head().$handshake->payload()->toBinary(); - file_put_contents($this->fs->path('127.0.0.1:1000'), $response); + $connection = new Connection(...$this->socket); + $connection->close(); + + $run = false; + $connection->connect(function ($bucket) use ($run) { + $run = true; + }); + + $this->assertFalse($run, 'Listen function run on closed connection.'); + } - $uint64 = (new Connection('127.0.0.1', 1000))->read(new Uint64()); + /** + * @return void + */ + public function testRead() : void + { + $connection = new Connection(...$this->socket); + $uint64 = $connection->read(new Uint64()); $this->assertInstanceOf(Uint64::class, $uint64); $this->assertEquals(Bucket::LEVIN_SIGNATURE, $uint64->toInt()); + + $size = (new Uint64())->getByteSize(); + $this->assertEquals( + "\x08\x01\x00\x00\x00\x00\x00\x00", + $connection->read($size) + ); } /** @@ -80,40 +84,18 @@ public function testReadWithConnectionException() : void */ public function testWrite() : void { + $socket = $this->createSocketMock(null, '127.0.0.2'); + $handshake = (new Bucket())->response(new Handshake()); - $connection = new Connection('127.0.0.1', 1000); + + $connection = new Connection(...$socket); $connection->write($handshake); $connection->close(); // pointer resets after connection will be reopened due to "r+" mode // so we should be able to read the bucket, that we just wrote - $bucket = (new Connection('127.0.0.1', 1000))->read(new Bucket()); + $bucket = (new Connection(...$socket))->read(new Bucket()); $this->assertInstanceOf(Bucket::class, $bucket); $this->assertTrue($bucket->is('handshake')); } } - -namespace Denpa\Levin; - -/** - * @param string $host - * @param int $port - * @param mixed &$errno - * @param mixed &$errstr - * @param int $timeout - * - * @return resource - */ -function fsockopen( - string $host, - int $port, - &$errno, - &$errstr, - int $timeout -) { - $errno = 101; - $errstr = 'Test error message'; - global $fs; - - return fopen($fs->path("$host:$port"), 'r+'); -} diff --git a/tests/FunctionsTest.php b/tests/FunctionsTest.php index 197a6c0..8701b7f 100644 --- a/tests/FunctionsTest.php +++ b/tests/FunctionsTest.php @@ -4,6 +4,8 @@ use Denpa\Levin; use Denpa\Levin\Bucket; +use Denpa\Levin\Connection; +use Denpa\Levin\Requests\Handshake; use Denpa\Levin\Section\Section; use Denpa\Levin\Types\Boolean; use Denpa\Levin\Types\Bytearray; @@ -230,9 +232,74 @@ public function testResponse() : void /** * @return void */ - public function testCamelCase() : void + public function testConnection() : void { - $this->assertEquals('TestCamelcase', Levin\camel_case('teSt_cAMElcase')); + $socket = $this->createSocketMock(null); + + $connection = Levin\connection(...$socket); + $this->assertInstanceOf(Connection::class, $connection); + $connection->close(); + + // pointer resets after connection will be reopened due to "r+" mode + // so we should be able to read the bucket, that we just wrote + $connection = new Connection(...$socket); + + $bucket = $connection->read(); + $this->assertInstanceOf(Handshake::class, $bucket->getCommand()); + $this->assertEquals( + Bucket::LEVIN_PACKET_REQUEST, + $bucket->getFlags()->toInt() + ); + } + + /** + * @return void + * + * @dataProvider camelCaseProvider + */ + public function testCamelCase(string $string, string $expected) : void + { + $this->assertEquals($expected, Levin\camel_case($string)); + } + + /** + * @return void + * + * @dataProvider snakeCaseProvider + */ + public function testSnakeCase(string $string, string $expected) : void + { + $this->assertEquals($expected, Levin\snake_case($string)); + } + + /** + * @return array + */ + public function camelCaseProvider() : array + { + return [ + ['test_camel_case', 'testCamelCase'], + ['test__camel_case', 'testCamelCase'], + ['testCamelCase', 'testCamelCase'], + ['TESTCamelCase123', 'testCamelCase123'], + ['_test_camel_case', 'testCamelCase'], + ['123testCAMELCase', '123testCamelCase'], + ]; + } + + /** + * @return array + */ + public function snakeCaseProvider() : array + { + return [ + ['testSnakeCase', 'test_snake_case'], + ['TestSnakeCase', 'test_snake_case'], + ['test_snake_case', 'test_snake_case'], + ['TESTSnakeCASE', 'test_snake_case'], + ['__TestSnakeCase123', '__test_snake_case123'], + ['123testCAMELCase', '123test_camel_case'], + ]; } /** diff --git a/tests/Section/ReaderTest.php b/tests/Section/ReaderTest.php index 3265417..cfaeb2e 100644 --- a/tests/Section/ReaderTest.php +++ b/tests/Section/ReaderTest.php @@ -5,9 +5,12 @@ use Denpa\Levin; use Denpa\Levin\Connection; use Denpa\Levin\Exceptions\SignatureMismatchException; +use Denpa\Levin\Exceptions\UnexpectedTypeException; use Denpa\Levin\Section\Reader; use Denpa\Levin\Section\Section; use Denpa\Levin\Tests\TestCase; +use Denpa\Levin\Types\BoostSerializable; +use Denpa\Levin\Types\Bytearray; use Denpa\Levin\Types\Uint32; use Denpa\Levin\Types\Uint8; use Denpa\Levin\Types\Varint; @@ -95,6 +98,92 @@ public function testGetName() : void $name = $this->reader->readName(); $this->assertEquals('test', $name); } + + /** + * @return void + */ + public function testLoadEntries() : void + { + $this->connection + ->expects($this->exactly(3)) + ->method('read') + ->withConsecutive( + [$this->isInstanceOf(Uint8::class)], + [$this->isInstanceOf(Uint8::class)], + [$this->isInstanceOf(Varint::class)] + ) + ->willReturnOnConsecutiveCalls( + new Uint8(Section::SERIALIZE_TYPE_ARRAY), + new Uint8(Section::SERIALIZE_TYPE_UINT32), + new Varint(0) + ); + + $entries = $this->reader->loadEntries(); + + $this->assertInstanceOf(Bytearray::class, $entries); + $this->assertSame(Section::SERIALIZE_TYPE_UINT32, $entries->getType()->toInt()); + } + + /** + * @return void + */ + public function testLoadEntriesWithIncorrectArrayTypeSequence() : void + { + $this->expectException(UnexpectedTypeException::class); + $this->expectExceptionMessage('Incorrect type sequence'); + + $this->connection + ->expects($this->exactly(2)) + ->method('read') + ->withConsecutive( + [$this->isInstanceOf(Uint8::class)], + [$this->isInstanceOf(Uint8::class)] + ) + ->willReturnOnConsecutiveCalls( + new Uint8(Section::SERIALIZE_TYPE_ARRAY), + new Uint8(Section::SERIALIZE_TYPE_UINT32 | Section::SERIALIZE_FLAG_ARRAY) + ); + + $this->reader->loadEntries(); + } + + /** + * @return void + */ + public function testReadArrayEntry() : void + { + $this->connection + ->expects($this->exactly(3)) + ->method('read') + ->withConsecutive( + [$this->isInstanceOf(Varint::class)], + [$this->isInstanceOf(Uint32::class)], + [$this->isInstanceOf(Uint32::class)] + ) + ->willReturnOnConsecutiveCalls( + new Varint(2), + new Uint32(39), + new Uint32(40) + ); + + $type = Section::SERIALIZE_TYPE_UINT32 | Section::SERIALIZE_FLAG_ARRAY; + + $entries = $this->reader->readArrayEntry($type); + $this->assertInstanceOf(Bytearray::class, $entries); + $this->assertSame(39, $entries[0]->toInt()); + $this->assertSame(40, $entries[1]->toInt()); + } + + /** + * @return void + */ + public function testReadValueWithUnknownType() : void + { + $this->expectException(UnexpectedTypeException::class); + $this->expectExceptionMessage('Cannot unserialize unknown type [999]'); + + $this->reader->readValue(999); + } } class FakeReader extends Reader @@ -108,4 +197,19 @@ public function readName() : string { return parent::readName(); } + + public function loadEntries() : BoostSerializable + { + return parent::loadEntries(); + } + + public function readArrayEntry(int $type) : Bytearray + { + return parent::readArrayEntry($type); + } + + public function readValue(int $type) : BoostSerializable + { + return parent::readValue($type); + } } diff --git a/tests/Section/SectionTest.php b/tests/Section/SectionTest.php index 74e40e0..1d07ae0 100644 --- a/tests/Section/SectionTest.php +++ b/tests/Section/SectionTest.php @@ -2,13 +2,13 @@ namespace Denpa\Levin\Tests\Section; +use Denpa\Levin\Exceptions\UnexpectedTypeException; use Denpa\Levin\Section\Section; use Denpa\Levin\Tests\TestCase; use Denpa\Levin\Types\Bytestring; use Denpa\Levin\Types\Uint32; use Denpa\Levin\Types\Uint8; use Denpa\Levin\Types\Varint; -use UnexpectedValueException; class SectionTest extends TestCase { @@ -100,7 +100,7 @@ public function testToBinary() : void */ public function testToBinaryWithInvalidData() : void { - $this->expectException(UnexpectedValueException::class); + $this->expectException(UnexpectedTypeException::class); $this->expectExceptionMessage('Cannot serialize unserializable item [test]'); $this->section['test'] = new Varint(3); $this->section->toBinary(); diff --git a/tests/TestCase.php b/tests/TestCase.php index 6372512..198c85f 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,6 +2,75 @@ namespace Denpa\Levin\Tests; +use Denpa\Levin\Bucket; +use Denpa\Levin\CommandFactory; +use VirtualFileSystem\FileSystem; + +/** + * @var \VirtualFileSystem\FileSystem + */ +$fs = null; + class TestCase extends \PHPUnit\Framework\TestCase { + /** + * @return void + */ + public function setUp() : void + { + global $fs; + parent::setUp(); + + $fs = $this->fs = new FileSystem(); + } + + /** + * @param string $command + * @param string $host + * @param int $port + * + * @return array + */ + protected function createSocketMock( + ?string $command, + string $host = '127.0.0.1', + int $port = 1000 + ) : array { + $response = ''; + + if (!is_null($command)) { + $command = (new CommandFactory())->$command(); + $handshake = (new Bucket())->response($command); + $response = $handshake->getHead().$handshake->getPayload()->toBinary(); + } + + file_put_contents($this->fs->path("$host:$port"), $response); + + return [$host, $port]; + } +} + +namespace Denpa\Levin; + +/** + * @param string $host + * @param int $port + * @param mixed &$errno + * @param mixed &$errstr + * @param int $timeout + * + * @return resource + */ +function fsockopen( + string $host, + int $port, + &$errno, + &$errstr, + int $timeout +) { + $errno = 101; + $errstr = 'Test error message'; + global $fs; + + return fopen($fs->path("$host:$port"), 'r+'); } diff --git a/tests/Types/BytearrayTest.php b/tests/Types/BytearrayTest.php index 7fd32d2..8d7b0a8 100644 --- a/tests/Types/BytearrayTest.php +++ b/tests/Types/BytearrayTest.php @@ -2,12 +2,12 @@ namespace Denpa\Levin\Tests\Types; +use Denpa\Levin\Exceptions\UnexpectedTypeException; use Denpa\Levin\Tests\TestCase; use Denpa\Levin\Types\BoostSerializable; use Denpa\Levin\Types\Bytearray; use Denpa\Levin\Types\Bytestring; use Denpa\Levin\Types\Uint8; -use InvalidArgumentException; class BytearrayTest extends TestCase { @@ -27,7 +27,7 @@ public function setUp() : void */ public function testCreateWithIllegalType() : void { - $this->expectException(InvalidArgumentException::class); + $this->expectException(UnexpectedTypeException::class); $this->expectExceptionMessage('Array entries must be serializable'); $bytearray = new Bytearray(['fail']); } @@ -37,7 +37,7 @@ public function testCreateWithIllegalType() : void */ public function testCreateWithMultipleTypes() : void { - $this->expectException(InvalidArgumentException::class); + $this->expectException(UnexpectedTypeException::class); $this->expectExceptionMessage('Array entries must be of the same type'); $bytearray = new Bytearray([ @@ -60,7 +60,7 @@ public function offsetSet() : void */ public function testOffsetSetWithIllegalType() : void { - $this->expectException(InvalidArgumentException::class); + $this->expectException(UnexpectedTypeException::class); $this->expectExceptionMessage('Array entries must be serializable'); $this->bytearray->offsetSet(null, 'fail'); } @@ -70,7 +70,7 @@ public function testOffsetSetWithIllegalType() : void */ public function testOffsetSetWithMultipleTypes() : void { - $this->expectException(InvalidArgumentException::class); + $this->expectException(UnexpectedTypeException::class); $this->expectExceptionMessage('Array entries must be of the same type'); $this->bytearray->offsetSet(null, new Uint8(1)); diff --git a/tests/Types/TypeTest.php b/tests/Types/TypeTest.php index d8c63b0..2849a75 100644 --- a/tests/Types/TypeTest.php +++ b/tests/Types/TypeTest.php @@ -2,9 +2,9 @@ namespace Denpa\Levin\Tests\Types; +use Denpa\Levin\Exceptions\UnpackException; use Denpa\Levin\Tests\TestCase; use Denpa\Levin\Types\Type; -use UnexpectedValueException; class TypeTest extends TestCase { @@ -46,7 +46,7 @@ public function testToBinary() */ public function testToBinaryWithInvalidData() { - $this->expectException(UnexpectedValueException::class); + $this->expectException(UnpackException::class); $this->expectExceptionMessage('Failed to unpack binary data [&]'); $type = $this->getMockForAbstractClass(Type::class, ['&']); diff --git a/tests/Types/VarintTest.php b/tests/Types/VarintTest.php index 596400f..32b24ac 100644 --- a/tests/Types/VarintTest.php +++ b/tests/Types/VarintTest.php @@ -3,10 +3,10 @@ namespace Denpa\Levin\Tests\Types; use Denpa\Levin\Connection; +use Denpa\Levin\Exceptions\EntryTooLargeException; use Denpa\Levin\Tests\TestCase; use Denpa\Levin\Types\Uint8; use Denpa\Levin\Types\Varint; -use UnexpectedValueException; class VarintTest extends TestCase { @@ -28,7 +28,7 @@ public function testToBinary(int $int, string $expected) : void */ public function testToBinaryTooLarge() : void { - $this->expectException(UnexpectedValueException::class); + $this->expectException(EntryTooLargeException::class); $this->expectExceptionMessage('VarInt is too large [> 4611686018427387903]'); (new Varint(4611686018427387904))->toBinary(); }