Browse Source

code style finetyne

pull/8/head
Paul Rock 7 years ago
parent
commit
efd9e83179
  1. 21
      src/APIConnector.php
  2. 114
      src/APILengthCoDec.php
  3. 38
      src/Client.php
  4. 31
      src/Helpers/BinaryStringHelper.php
  5. 19
      src/Interfaces/StreamInterface.php
  6. 21
      src/SocketTrait.php
  7. 64
      src/Streams/ResourceStream.php
  8. 42
      src/Streams/StringStream.php
  9. 74
      tests/APIConnectorTest.php
  10. 2
      tests/APILengthCoDecTest.php
  11. 139
      tests/Streams/ResourceStreamTest.php
  12. 72
      tests/Streams/StringStreamTest.php

21
src/APIConnector.php

@ -1,17 +1,17 @@
<?php
namespace RouterOS;
use RouterOS\Interfaces\StreamInterface;
/**
* class APIConnector
* Class APIConnector
*
* Implement middle level dialog with router by masking word dialog implementation to client class
*
* @package RouterOS
* @since 0.9
*/
class APIConnector
{
/**
@ -38,19 +38,22 @@ class APIConnector
*
* @return string The word content, en empty string for end of SENTENCE
*/
public function readWord() : string
public function readWord(): string
{
// Get length of next word
$length = APILengthCoDec::decodeLength($this->stream);
if ($length>0) {
return $this->stream->read($length);
}
return '';
return ($length > 0) ? $this->stream->read($length) : '';
}
public function writeWord(string $word)
/**
* Write word to stream
*
* @param string $word
* @return int return number of written bytes
*/
public function writeWord(string $word): int
{
$encodedLength = APILengthCoDec::encodeLength(strlen($word));
return $this->stream->write($encodedLength.$word);
return $this->stream->write($encodedLength . $word);
}
}

114
src/APILengthCoDec.php

@ -13,10 +13,9 @@ use RouterOS\Helpers\BinaryStringHelper;
* @package RouterOS
* @since 0.9
*/
class APILengthCoDec
{
public static function encodeLength(int $length)
public static function encodeLength(int $length): string
{
// Encode the length :
// - if length <= 0x7F (binary : 01111111 => 7 bits set to 1)
@ -26,63 +25,63 @@ class APILengthCoDec
// - length <= 0x3FFF (binary : 00111111 11111111 => 14 bits set to 1)
// - encode length with two bytes
// - set length value to 0x8000 (=> 10000000 00000000)
// - add length : as length maximumal value is 14 bits to 1, this does not modify the 2 most significants bits (10)
// - add length : as length maximumal value is 14 bits to 1, this does not modify the 2 most significance bits (10)
// - end
// => minimal encoded value is 10000000 10000000
// - length <= 0x1FFFFF (binary : 00011111 11111111 11111111 => 21 bits set to 1)
// - encode length with three bytes
// - set length value to 0xC00000 (binary : 11000000 00000000 00000000)
// - add length : as length maximal vlaue is 21 bits to 1, this does not modify the 3 most significants bits (110)
// - add length : as length maximal vlaue is 21 bits to 1, this does not modify the 3 most significance bits (110)
// - end
// => minimal encoded value is 11000000 01000000 00000000
// - length <= 0x0FFFFFFF (binary : 00001111 11111111 11111111 11111111 => 28 bits set to 1)
// - encode length with four bytes
// - set length value to 0xE0000000 (binary : 11100000 00000000 00000000 00000000)
// - add length : as length maximal vlaue is 28 bits to 1, this does not modify the 4 most significants bits (1110)
// - add length : as length maximal vlaue is 28 bits to 1, this does not modify the 4 most significance bits (1110)
// - end
// => minimal encoded value is 11100000 00100000 00000000 00000000
// - length <= 0x7FFFFFFFFF (binary : 00000111 11111111 11111111 11111111 11111111 => 35 bits set to 1)
// - encode length with five bytes
// - set length value to 0xF000000000 (binary : 11110000 00000000 00000000 00000000 00000000)
// - add length : as length maximal vlaue is 35 bits to 1, this does not modify the 5 most significants bits (11110)
// - add length : as length maximal vlaue is 35 bits to 1, this does not modify the 5 most significance bits (11110)
// - end
// - length > 0x7FFFFFFFFF : not supported
if ($length<0)
{
throw new \DomainException(sprintf("Length of word can not be negative (%d)", $length));
if ($length < 0) {
throw new \DomainException("Length of word can not be negative ($length)");
}
if ($length<=0x7F) {
if ($length <= 0x7F) {
return BinaryStringHelper::IntegerToNBOBinaryString($length);
}
else if ($length<=0x3FFF) {
return BinaryStringHelper::IntegerToNBOBinaryString(0x8000+$length);
if ($length <= 0x3FFF) {
return BinaryStringHelper::IntegerToNBOBinaryString(0x8000 + $length);
}
else if ($length<=0x1FFFFF) {
return BinaryStringHelper::IntegerToNBOBinaryString(0xC00000+$length);
if ($length <= 0x1FFFFF) {
return BinaryStringHelper::IntegerToNBOBinaryString(0xC00000 + $length);
}
else if ($length<=0x0FFFFFFF){
return BinaryStringHelper::IntegerToNBOBinaryString(0xE0000000+$length);
if ($length <= 0x0FFFFFFF) {
return BinaryStringHelper::IntegerToNBOBinaryString(0xE0000000 + $length);
} // cannot compare with 0x7FFFFFFFFF on 32 bits systems
if (PHP_INT_SIZE < 8) {
// Cannot be done on 32 bits systems
// PHP5 windows versions of php, even on 64 bits systems was impacted
// see : https://stackoverflow.com/questions/27865340/php-int-size-returns-4-but-my-operating-system-is-64-bit
// @codeCoverageIgnoreStart
throw new \OverflowException("Your system is using 32 bits integers, cannot encode length of $length bytes on this system");
// @codeCoverageIgnoreEnd
}
// cannot compare with 0x7FFFFFFFFF on 32 bits systems
else {
if (PHP_INT_SIZE<8) {
// Cannot be done on 32 bits systems
// PHP5 windows versions of php, even on 64 bits systems was impacted
// see : https://stackoverflow.com/questions/27865340/php-int-size-returns-4-but-my-operating-system-is-64-bit
// @codeCoverageIgnoreStart
throw new \OverflowException(sprintf("Your system is using 32 bits integers, cannot encode length of %d bytes on this system", $length));
// @codeCoverageIgnoreEnd
}
if ($length<=0x7FFFFFFFFF)
{
return BinaryStringHelper::IntegerToNBOBinaryString(0xF000000000+$length);
}
if ($length <= 0x7FFFFFFFFF) {
return BinaryStringHelper::IntegerToNBOBinaryString(0xF000000000 + $length);
}
throw new \DomainException(sprintf('Length of word too huge (%x)', $length));
throw new \DomainException("Length of word too huge ($length)");
}
// Decode length of data when reading :
@ -107,7 +106,7 @@ class APILengthCoDec
// After receiving unknown control byte API client cannot proceed, because it cannot know how to interpret following bytes
// Currently control bytes are not used
public static function decodeLength(StreamInterface $stream)
public static function decodeLength(StreamInterface $stream): int
{
// if (false === is_resource($stream)) {
// throw new \InvalidArgumentException(
@ -122,29 +121,31 @@ class APILengthCoDec
$firstByte = ord($stream->read(1));
// If first byte is not set, length is the value of the byte
if (0==($firstByte&0x80)) {
if (0 === ($firstByte & 0x80)) {
return $firstByte;
}
// if 10xxxxxx, length is 2 bytes encoded
if (0x80==($firstByte&0xC0))
{
// Set 2 most significants bits to 0
if (0x80 === ($firstByte & 0xC0)) {
// Set 2 most significands bits to 0
$result = $firstByte & 0x3F;
// shift left 8 bits to have 2 bytes
$result = $result << 8;
$result <<= 8;
// read next byte and use it as least significant
$result |= ord($stream->read(1));
return $result;
}
// if 110xxxxx, length is 3 bytes encoded
if (0xC0 == ($firstByte & 0xE0))
{
// Set 3 most significants bits to 0
if (0xC0 === ($firstByte & 0xE0)) {
// Set 3 most significands bits to 0
$result = $firstByte & 0x1F;
// shift left 16 bits to have 3 bytes
$result = $result << 16;
$result <<= 16;
// read next 2 bytes as value and use it as least significant position
$result |= (ord($stream->read(1)) << 8);
$result |= ord($stream->read(1));
@ -152,12 +153,13 @@ class APILengthCoDec
}
// if 1110xxxx, length is 4 bytes encoded
if (0xE0 == ($firstByte & 0xF0))
{
// Set 4 most significants bits to 0
if (0xE0 === ($firstByte & 0xF0)) {
// Set 4 most significance bits to 0
$result = $firstByte & 0x0F;
// shift left 24 bits to have 4 bytes
$result = $result << 24;
$result <<= 24;
// read next 3 bytes as value and use it as least significant position
$result |= (ord($stream->read(1)) << 16);
$result |= (ord($stream->read(1)) << 8);
@ -166,22 +168,24 @@ class APILengthCoDec
}
// if 11110xxx, length is 5 bytes encoded
if (0xF0 == ($firstByte & 0xF8))
{
// Not possibe on 32 bits systems
if (PHP_INT_SIZE<8) {
if (0xF0 === ($firstByte & 0xF8)) {
// Not possible on 32 bits systems
if (PHP_INT_SIZE < 8) {
// Cannot be done on 32 bits systems
// PHP5 windows versions of php, even on 64 bits systems was impacted
// see : https://stackoverflow.com/questions/27865340/php-int-size-returns-4-but-my-operating-system-is-64-bit
// How can we test it ?
// @codeCoverageIgnoreStart
throw new \OverflowException(sprintf("Your system is using 32 bits integers, cannot decode this value (%x) on this system", $firstByte));
throw new \OverflowException("Your system is using 32 bits integers, cannot decode this value ($firstByte) on this system");
// @codeCoverageIgnoreEnd
}
// Set 5 most significants bits to 0
// Set 5 most significance bits to 0
$result = $firstByte & 0x07;
// shift left 232 bits to have 5 bytes
$result = $result << 32;
$result <<= 32;
// read next 4 bytes as value and use it as least significant position
$result |= (ord($stream->read(1)) << 24);
$result |= (ord($stream->read(1)) << 16);
@ -190,8 +194,8 @@ class APILengthCoDec
return $result;
}
// Now the only solution is 5 most significants bits are set to 1 (11111xxx)
// Now the only solution is 5 most significance bits are set to 1 (11111xxx)
// This is a control word, not implemented by Mikrotik for the moment
throw new \UnexpectedValueException("Control Word found\n");
throw new \UnexpectedValueException('Control Word found');
}
}

38
src/Client.php

@ -18,27 +18,6 @@ class Client implements Interfaces\ClientInterface
use SocketTrait;
/**
* Socket resource
*
* @var resource|null
*/
private $_socket;
/**
* Code of error
*
* @var int
*/
private $_socket_err_num;
/**
* Description of socket error
*
* @var string
*/
private $_socket_err_str;
/**
* Configuration of connection
*
* @var \RouterOS\Config
@ -48,10 +27,10 @@ class Client implements Interfaces\ClientInterface
/**
* API communication object
*
* @var APIConnector
* @var \RouterOS\APIConnector
*/
private $connector;
private $_connector;
/**
* Client constructor.
@ -121,7 +100,6 @@ class Client implements Interfaces\ClientInterface
*
* @param string|array|\RouterOS\Query $query
* @return \RouterOS\Client
* @throws \RouterOS\Exceptions\ClientException
* @throws \RouterOS\Exceptions\QueryException
*/
public function write($query): Client
@ -139,11 +117,11 @@ class Client implements Interfaces\ClientInterface
// Send commands via loop to router
foreach ($query->getQuery() as $command) {
$this->connector->writeWord(trim($command));
$this->_connector->writeWord(trim($command));
}
// Write zero-terminator (empty string)
$this->connector->writeWord('');
$this->_connector->writeWord('');
return $this;
}
@ -169,9 +147,9 @@ class Client implements Interfaces\ClientInterface
// Read answer from socket in loop
while (true) {
$word = $this->connector->readWord();
$word = $this->_connector->readWord();
if (''===$word) {
if ('' === $word) {
if ($lastReply) {
// We received a !done or !fatal message in a precedent loop
// response is complete
@ -202,7 +180,6 @@ class Client implements Interfaces\ClientInterface
*
* @param string|array|\RouterOS\Query $query
* @return \RouterOS\Client
* @throws \RouterOS\Exceptions\ClientException
* @throws \RouterOS\Exceptions\QueryException
*/
public function w($query): Client
@ -373,7 +350,7 @@ class Client implements Interfaces\ClientInterface
// If socket is active
if (null !== $this->getSocket()) {
$this->connector = new APIConnector(new Streams\ResourceStream($this->getSocket()));
$this->_connector = new APIConnector(new Streams\ResourceStream($this->getSocket()));
// If we logged in then exit from loop
if (true === $this->login()) {
$connected = true;
@ -382,7 +359,6 @@ class Client implements Interfaces\ClientInterface
// Else close socket and start from begin
$this->closeSocket();
$this->stream = null;
}
// Sleep some time between tries

31
src/Helpers/BinaryStringHelper.php

@ -1,21 +1,21 @@
<?php
namespace RouterOS\Helpers;
/**
* class BinaryStringHelper
*
* Strings and binary datas manipulations
* Strings and binary data manipulations
*
* @package RouterOS\Helpers
* @since 0.9
*/
class BinaryStringHelper
{
/**
* Convert an integer value in a "Network Byte Ordered" binary string (most significant value first)
*
* Reads the integer, starting from the most signficant byte, one byte a time.
* Reads the integer, starting from the most significant byte, one byte a time.
* Once reach a non 0 byte, construct a binary string representing this values
* ex :
* 0xFF7 => chr(0x0F).chr(0xF7)
@ -23,38 +23,43 @@ class BinaryStringHelper
* Compatible with 8, 16, 32, 64 etc.. bits systems
*
* @see https://en.wikipedia.org/wiki/Endianness
* @param int $value the integer value to be converted
* @return string the binary string
* @param int $value the integer value to be converted
* @return string the binary string
*/
public static function IntegerToNBOBinaryString(int $value)
public static function IntegerToNBOBinaryString(int $value): string
{
// Initialize an empty string
$buffer = '';
// Lets start from the most significant byte
for ($i=(PHP_INT_SIZE-1); $i>=0; $i--) {
for ($i = (PHP_INT_SIZE - 1); $i >= 0; $i--) {
// Prepare a mask to keep only the most significant byte of $value
$mask = 0xFF << ($i*8);
$mask = 0xFF << ($i * 8);
// If the most significant byte is not 0, the final string must contain it
// If we have already started to construct the string (i.e. there are more signficant digits)
// we must set the byte, even if it is a 0.
// 0xFF00FF, for example, require to set the second byte byte with a 0 value
if (($value & $mask) || strlen($buffer)!=0) {
// Get the curent byte by shifting it to least significant position and add it to the string
if (($value & $mask) || $buffer !== '') {
// Get the current byte by shifting it to least significant position and add it to the string
// 0xFF12345678 => 0xFF
$byte = $value>>(8*$i);
$byte = $value >> (8 * $i);
$buffer .= chr($byte);
// Set the most significant byte to 0 so we can restart the process being shure
// that the value is left padded with 0
// 0xFF12345678 => 0x12345678
// -1 = 0xFFFFF.... (number of F depend of PHP_INT_SIZE )
$mask = -1 >> ((PHP_INT_SIZE-$i)*8);
$mask = -1 >> ((PHP_INT_SIZE - $i) * 8);
$value &= $mask;
}
}
// Special case, 0 will not fill the buffer, have to construct it manualy
if (0==$value) {
if (0 === $value) {
$buffer = chr(0);
}
return $buffer;
}
}

19
src/Interfaces/StreamInterface.php

@ -1,4 +1,5 @@
<?php
namespace RouterOS\Interfaces;
/**
@ -17,10 +18,10 @@ interface StreamInterface
* Reads $length bytes from the stream, returns the bytes into a string
* Must be binary safe (as fread).
*
* @param int $length the numer of bytes to read
* @return string a binary string containing the readed byes
* @param int $length the numer of bytes to read
* @return string a binary string containing the readed byes
*/
public function read(int $length) : string;
public function read(int $length): string;
/**
* Writes a string to a stream
@ -30,10 +31,16 @@ interface StreamInterface
* if $length is greater than string length, write all string and return number of writen bytes
* if $length os smaller than string length, remaining bytes are losts.
*
* @param int $length the numer of bytes to read
* @return int the numer of writen bytes
* @param string $string
* @param int $length the number of bytes to read
* @return int return number of written bytes
*/
public function write(string $string, $length=-1) : int;
public function write(string $string, int $length = -1): int;
/**
* Close stream connection
*
* @return void
*/
public function close();
}

21
src/SocketTrait.php

@ -7,6 +7,27 @@ use RouterOS\Exceptions\ClientException;
trait SocketTrait
{
/**
* Socket resource
*
* @var resource|null
*/
private $_socket;
/**
* Code of error
*
* @var int
*/
private $_socket_err_num;
/**
* Description of socket error
*
* @var string
*/
private $_socket_err_str;
/**
* Initiate socket session
*
* @return void

64
src/Streams/ResourceStream.php

@ -1,4 +1,5 @@
<?php
namespace RouterOS\Streams;
use RouterOS\Interfaces\StreamInterface;
@ -12,14 +13,18 @@ use RouterOS\Exceptions\StreamException;
* @package RouterOS
* @since 0.9
*/
class ResourceStream implements StreamInterface
{
protected $stream;
/**
* ResourceStream constructor.
*
* @param $stream
*/
public function __construct($stream)
{
if (false === is_resource($stream)) {
if (!is_resource($stream)) {
throw new \InvalidArgumentException(
sprintf(
'Argument must be a valid resource type. %s given.',
@ -27,54 +32,79 @@ class ResourceStream implements StreamInterface
)
);
}
// // TODO : Should we verify the resource type ?
// TODO: Should we verify the resource type?
$this->stream = $stream;
}
/**
* {@inheritDoc}
* @throws \InvalidArgumentException
* @param int $length
* @return string
* @throws \RouterOS\Exceptions\StreamException
* @throws \InvalidArgumentException
*/
public function read(int $length) : string
public function read(int $length): string
{
if ($length<=0) {
throw new \InvalidArgumentException("Cannot read zero ot negative count of bytes from a stream");
if ($length <= 0) {
throw new \InvalidArgumentException('Cannot read zero ot negative count of bytes from a stream');
}
// TODO: Ignore errors here, but why?
$result = @fread($this->stream, $length);
if (false === $result) {
throw new StreamException(sprintf("Error reading %d bytes", $length));
throw new StreamException("Error reading $length bytes");
}
return $result;
}
/**
* {@inheritDoc}
* Writes a string to a stream
*
* Write $length bytes of string, if not mentioned, write all the string
* Must be binary safe (as fread).
* if $length is greater than string length, write all string and return number of writen bytes
* if $length os smaller than string length, remaining bytes are losts.
*
* @param string $string
* @param int|null $length the numer of bytes to read
* @return int the number of written bytes
* @throws \RouterOS\Exceptions\StreamException
*/
public function write(string $string, $length=null) : int
public function write(string $string, int $length = null): int
{
if (is_null($length)) {
if (null === $length) {
$length = strlen($string);
}
// TODO: Ignore errors here, but why?
$result = @fwrite($this->stream, $string, $length);
if (false === $result) {
throw new StreamException(sprintf("Error writing %d bytes", $length));
throw new StreamException("Error writing $length bytes");
}
return $result;
}
/**
* Close stream connection
*
* @return void
* @throws \RouterOS\Exceptions\StreamException
*/
public function close()
{
$hasBeenClosed = false;
if (!is_null($this->stream)) {
if (null !== $this->stream) {
$hasBeenClosed = @fclose($this->stream);
$this->stream=null;
$this->stream = null;
}
if (false===$hasBeenClosed) {
throw new StreamException("Error closing stream");
if (false === $hasBeenClosed) {
throw new StreamException('Error closing stream');
}
}
}

42
src/Streams/StringStream.php

@ -1,4 +1,5 @@
<?php
namespace RouterOS\Streams;
use RouterOS\Interfaces\StreamInterface;
@ -13,7 +14,6 @@ use RouterOS\Exceptions\StreamException;
* @package RouterOS\Streams
* @since 0.9
*/
class StringStream implements StreamInterface
{
/**
@ -22,7 +22,7 @@ class StringStream implements StreamInterface
protected $buffer;
/**
* Constuctor
* StringStream constructor.
*
* @param string $string
*/
@ -37,25 +37,24 @@ class StringStream implements StreamInterface
* @throws \InvalidArgumentException when length parameter is invalid
* @throws StreamException when the stream have been tatly red and read methd is called again
*/
public function read(int $length) : string
public function read(int $length): string
{
$remaining = strlen($this->buffer);
if ($length<0) {
throw new \InvalidArgumentException("Cannot read a negative count of bytes from a stream");
if ($length < 0) {
throw new \InvalidArgumentException('Cannot read a negative count of bytes from a stream');
}
if (0 == $remaining) {
throw new StreamException("End of stream");
if (0 === $remaining) {
throw new StreamException('End of stream');
}
if ($length>=$remaining) {
if ($length >= $remaining) {
// returns all
$result = $this->buffer;
// No more in the buffer
$this->buffer='';
}
else {
$this->buffer = '';
} else {
// acquire $length characters from the buffer
$result = substr($this->buffer, 0, $length);
// remove $length characters from the buffer
@ -68,24 +67,29 @@ class StringStream implements StreamInterface
/**
* Fake write method, do nothing except return the "writen" length
*
* @param string $string The string to write
* @param int|null $length the number of characters to write
* @throws \InvalidArgumentException on invalid length
* @return number of "writen" bytes
* @param string $string The string to write
* @param int|null $length the number of characters to write
* @return int number of "writen" bytes
* @throws \InvalidArgumentException on invalid length
*/
public function write(string $string, $length=null) : int
public function write(string $string, int $length = null): int
{
if(null === $length) {
if (null === $length) {
$length = strlen($string);
}
if ($length<0) {
throw new \InvalidArgumentException("Cannot write a negative count of bytes");
if ($length < 0) {
throw new \InvalidArgumentException('Cannot write a negative count of bytes');
}
return min($length, strlen($string));
}
/**
* Close stream connection
*
* @return void
*/
public function close()
{
$this->buffer = '';

74
tests/APIConnectorTest.php

@ -3,30 +3,29 @@
namespace RouterOS\Tests;
use PHPUnit\Framework\TestCase;
use RouterOS\APIConnector;
use RouterOS\Streams\StringStream;
use RouterOS\Streams\ResourceStream;
use RouterOS\APILengthCoDec;
use RouterOS\Interfaces\StreamInterface;
/**
* Limit code coverage to the class RouterOS\APIStream
* @coversDefaultClass RouterOS\APIConnector
*
* @coversDefaultClass \RouterOS\APIConnector
*/
class APIConnectorTest extends TestCase
{
/**
* Test that constructor is OK with different kinds of resources
*
* @covers ::__construct
* @dataProvider constructProvider
* @param Resource $resource Cannot typehint, PHP refuse it
* @param bool $closeResource shall we close the resource ?
*
* @param StreamInterface $stream Cannot typehint, PHP refuse it
* @param bool $closeResource shall we close the resource ?
*/
public function test_construct(StreamInterface $stream, bool $closeResource=false)
public function test_construct(StreamInterface $stream, bool $closeResource = false)
{
$apiStream = new APIConnector($stream);
$this->assertInstanceOf(APIConnector::class, $apiStream);
@ -35,14 +34,14 @@ class APIConnectorTest extends TestCase
}
}
public function constructProvider()
public function constructProvider(): array
{
return [
[ new ResourceStream(fopen(__FILE__, 'r')), ], // Myself, sure I exists
[ new ResourceStream(fsockopen('tcp://127.0.0.1', 18728)), ], // Socket
[ new ResourceStream(STDIN), false ], // Try it, but do not close STDIN please !!!
[ new StringStream('Hello World !!!') ], // Try it, but do not close STDIN please !!!
[ new StringStream('') ], // Try it, but do not close STDIN please !!!
[new ResourceStream(fopen(__FILE__, 'rb')),], // Myself, sure I exists
[new ResourceStream(fsockopen('tcp://127.0.0.1', 18728)),], // Socket
[new ResourceStream(STDIN), false], // Try it, but do not close STDIN please !!!
[new StringStream('Hello World !!!')], // Try it, but do not close STDIN please !!!
[new StringStream('')], // Try it, but do not close STDIN please !!!
// What else ?
];
}
@ -50,43 +49,50 @@ class APIConnectorTest extends TestCase
/**
* @covers ::readWord
* @dataProvider readWordProvider
*
* @param APIConnector $connector
* @param string $expected
*/
public function test__readWord(APIConnector $connector, $expected)
public function test__readWord(APIConnector $connector, string $expected)
{
$this->assertSame($expected, $connector->readWord());
}
public function readWordProvider()
public function readWordProvider(): array
{
$longString = '=comment='.str_repeat('a',10000);
$length = strlen($longString);
return [
[ new APIConnector(new StringStream(chr(0))), ''],
[ new APIConnector(new StringStream(chr(3).'!re')), '!re'],
[ new APIConnector(new StringStream(chr(5).'!done')), '!done'],
[ new APIConnector(new StringStream(APILengthCoDec::encodeLength($length).$longString)), $longString],
$longString = '=comment=' . str_repeat('a', 10000);
$length = strlen($longString);
return [
[new APIConnector(new StringStream(chr(0))), ''],
[new APIConnector(new StringStream(chr(3) . '!re')), '!re'],
[new APIConnector(new StringStream(chr(5) . '!done')), '!done'],
[new APIConnector(new StringStream(APILengthCoDec::encodeLength($length) . $longString)), $longString],
];
}
/**
* @covers ::writeWord
* @dataProvider writeWordProvider
*/
/**
* @covers ::writeWord
* @dataProvider writeWordProvider
*
* @param APIConnector $connector
* @param string $toWrite
* @param int $expected
*/
public function test_writeWord(APIConnector $connector, string $toWrite, int $expected)
{
$this->assertEquals($expected, $connector->writeWord($toWrite));
}
public function writeWordProvider()
public function writeWordProvider(): array
{
return [
[ new APIConnector(new StringStream('Have FUN !!!')), '', 1 ], // length is 0, but have to write it on 1 byte, minimum
[ new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 54), 55 ], // arbitrary value
[ new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 127), 128 ], // maximum value for 1 byte encoding lentgth
[ new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 128), 130 ], // minimum value for 2 bytes encoding lentgth
[ new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 254), 256 ], // special value isn't it ?
[ new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 255), 257 ], // special value isn't it ?
[new APIConnector(new StringStream('Have FUN !!!')), '', 1], // length is 0, but have to write it on 1 byte, minimum
[new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 54), 55], // arbitrary value
[new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 127), 128], // maximum value for 1 byte encoding lentgth
[new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 128), 130], // minimum value for 2 bytes encoding lentgth
[new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 254), 256], // special value isn't it ?
[new APIConnector(new StringStream('Have FUN !!!')), str_repeat(' ', 255), 257], // special value isn't it ?
];
}
}

2
tests/APILengthCoDecTest.php

@ -11,7 +11,7 @@ use RouterOS\Helpers\BinaryStringHelper;
/**
* Limit code coverage to the class
* @coversDefaultClass RouterOS\APILengthCoDec
* @coversDefaultClass \RouterOS\APILengthCoDec
*/
class APILengthCoDecTest extends TestCase
{

139
tests/Streams/ResourceStreamTest.php

@ -4,13 +4,12 @@ namespace RouterOS\Tests\Streams;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Constraint\IsType;
use RouterOS\Streams\ResourceStream;
use RouterOS\Exceptions\StreamException;
/**
* Limit code coverage to the class RouterOS\APIStream
* @coversDefaultClass RouterOS\Streams\ResourceStream
*
* @coversDefaultClass \RouterOS\Streams\ResourceStream
*/
class ResourceStreamTest extends TestCase
{
@ -20,6 +19,8 @@ class ResourceStreamTest extends TestCase
* @covers ::__construct
* @expectedException \InvalidArgumentException
* @dataProvider constructNotResourceProvider
*
* @param $notResource
*/
public function test__constructNotResource($notResource)
@ -32,16 +33,16 @@ class ResourceStreamTest extends TestCase
*
* returns data not of type resource
*/
public function constructNotResourceProvider()
public function constructNotResourceProvider(): array
{
return [
[0], // integer
[3.14], // float
['a string'], // string
[
[ 0 , 3.14 ] // Array
[0, 3.14] // Array
],
[ new \stdClass() ], // Object
[new \stdClass()], // Object
// What else ?
];
}
@ -51,18 +52,18 @@ class ResourceStreamTest extends TestCase
*
* @covers ::__construct
* @dataProvider constructProvider
* @param resource $resource Cannot typehint, PHP refuse it
* @param bool $closeResource shall we close the resource ?
*
* @param resource $resource Cannot typehint, PHP refuse it
* @param bool $closeResource shall we close the resource ?
*/
public function test_construct($resource, bool $closeResource=true)
public function test_construct($resource, bool $closeResource = true)
{
$resourceStream = new ResourceStream($resource);
$stream = $this->getObjectAttribute($resourceStream, 'stream');
$this->assertInternalType(IsType::TYPE_RESOURCE, $stream);
if ($closeResource)
{
if ($closeResource) {
fclose($resource);
}
}
@ -70,14 +71,14 @@ class ResourceStreamTest extends TestCase
/**
* Data provider for test__construct
*
* returns data of type resource
* @return array data of type resource
*/
public function constructProvider()
public function constructProvider(): array
{
return [
[ fopen(__FILE__, 'r'), ], // Myself, sure I exists
[ fsockopen('tcp://127.0.0.1', 18728), ], // Socket
[ STDIN, false ], // Try it, but do not close STDIN please !!!
[fopen(__FILE__, 'rb'),], // Myself, sure I exists
[fsockopen('tcp://127.0.0.1', 18728),], // Socket
[STDIN, false], // Try it, but do not close STDIN please !!!
// What else ?
];
}
@ -87,23 +88,26 @@ class ResourceStreamTest extends TestCase
*
* @covers ::read
* @dataProvider readProvider
* @param resource $resource Cannot typehint, PHP refuse it
* @param string $expected the rsult we should have
*
* @param ResourceStream $stream Cannot typehint, PHP refuse it
* @param string $expected the result we should have
* @throws \RouterOS\Exceptions\StreamException
* @throws \InvalidArgumentException
*/
public function test__read(ResourceStream $stream, string $expected)
{
$this->assertSame($expected, $stream->read(strlen($expected)));
}
public function readProvider()
public function readProvider(): array
{
$resource = fopen(__FILE__, 'r');
$me = new ResourceStream($resource);
$resource = fopen(__FILE__, 'rb');
$me = new ResourceStream($resource);
return [
[ $me, '<'], // Read for byte
[ $me, '?php'], // Read following bytes. File statrts with "<php"
[$me, '<'], // Read for byte
[$me, '?php'], // Read following bytes. File statrts with "<php"
];
fclose($resource);
}
/**
@ -112,43 +116,50 @@ class ResourceStreamTest extends TestCase
* @covers ::read
* @dataProvider readBadLengthProvider
* @expectedException \InvalidArgumentException
* @param resource $resource Cannot typehint, PHP refuse it
*
* @param ResourceStream $stream Cannot typehint, PHP refuse it
* @param int $length
* @throws \RouterOS\Exceptions\StreamException
* @throws \InvalidArgumentException
*/
public function test__readBadLength(ResourceStream $stream, int $length)
{
$stream->read($length);
}
public function readBadLengthProvider()
public function readBadLengthProvider(): array
{
$resource = fopen(__FILE__, 'r');
$me = new ResourceStream($resource);
$resource = fopen(__FILE__, 'rb');
$me = new ResourceStream($resource);
return [
[ $me, 0 ],
[ $me, -1 ],
[$me, 0],
[$me, -1],
];
fclose($resource);
}
/**
* Test read to invalid resource
*
* @covers ::read
* @dataProvider readBadResourceProvider
* @expectedException RouterOS\Exceptions\StreamException
* @param resource $resource Cannot typehint, PHP refuse it
* @expectedException \RouterOS\Exceptions\StreamException
*
* @param ResourceStream $stream Cannot typehint, PHP refuse it
* @param int $length
*/
public function test__readBadResource(ResourceStream $stream, int $length)
{
$stream->read($length);
}
public function readBadResourceProvider()
public function readBadResourceProvider(): array
{
$resource = fopen(__FILE__, 'r');
$me = new ResourceStream($resource);
$resource = fopen(__FILE__, 'rb');
$me = new ResourceStream($resource);
fclose($resource);
return [
[ $me, 1 ],
[$me, 1],
];
}
@ -157,22 +168,24 @@ class ResourceStreamTest extends TestCase
*
* @covers ::write
* @dataProvider writeProvider
* @param ResourceStram $resource to test
* @param string $toWrite the writed string
*
* @param ResourceStream $stream to test
* @param string $toWrite the writed string
* @throws \RouterOS\Exceptions\StreamException
*/
public function test__write(ResourceStream $stream, string $toWrite)
{
$this->assertEquals(strlen($toWrite) , $stream->write($toWrite));
$this->assertEquals(strlen($toWrite), $stream->write($toWrite));
}
public function writeProvider()
public function writeProvider(): array
{
$resource = fopen("/dev/null", 'w');
$null = new ResourceStream($resource);
$resource = fopen('/dev/null', 'wb');
$null = new ResourceStream($resource);
return [
[ $null, 'yyaagagagag'], // Take that
[$null, 'yyaagagagag'], // Take that
];
fclose($resource);
}
/**
@ -180,22 +193,24 @@ class ResourceStreamTest extends TestCase
*
* @covers ::write
* @dataProvider writeBadResourceProvider
* @expectedException RouterOS\Exceptions\StreamException
* @param resource $resource to test
* @param string $toWrite the writed string
* @expectedException \RouterOS\Exceptions\StreamException
*
* @param ResourceStream $stream to test
* @param string $toWrite the written string
*/
public function test__writeBadResource(ResourceStream $stream, string $toWrite)
{
$stream->write($toWrite);
}
public function writeBadResourceProvider()
public function writeBadResourceProvider(): array
{
$resource = fopen('/dev/null', 'w');
$me = new ResourceStream($resource);
$resource = fopen('/dev/null', 'wb');
$me = new ResourceStream($resource);
fclose($resource);
return [
[ $me, 'sasasaas' ], // Take that
[$me, 'sasasaas'], // Take that
];
}
@ -204,8 +219,9 @@ class ResourceStreamTest extends TestCase
*
* @covers ::close
* @dataProvider doubleCloseProvider
* @expectedException RouterOS\Exceptions\StreamException
* @param resource $resource to test
* @expectedException \RouterOS\Exceptions\StreamException
*
* @param ResourceStream $stream to test
*/
public function test_doubleClose(ResourceStream $stream)
{
@ -213,10 +229,10 @@ class ResourceStreamTest extends TestCase
$stream->close();
}
public function doubleCloseProvider()
public function doubleCloseProvider(): array
{
return [
[ new ResourceStream(fopen('/dev/null', 'w')), 'sasasaas' ], // Take that
[new ResourceStream(fopen('/dev/null', 'wb')), 'sasasaas'], // Take that
];
}
@ -226,9 +242,10 @@ class ResourceStreamTest extends TestCase
* @covers ::close
* @covers ::write
* @dataProvider writeClosedResourceProvider
* @expectedException RouterOS\Exceptions\StreamException
* @param resource $resource to test
* @param string $toWrite the writed string
* @expectedException \RouterOS\Exceptions\StreamException
*
* @param ResourceStream $stream to test
* @param string $toWrite the written string
*/
public function test_close(ResourceStream $stream, string $toWrite)
{
@ -236,10 +253,10 @@ class ResourceStreamTest extends TestCase
$stream->write($toWrite);
}
public function writeClosedResourceProvider()
public function writeClosedResourceProvider(): array
{
return [
[ new ResourceStream(fopen('/dev/null', 'w')), 'sasasaas' ], // Take that
[new ResourceStream(fopen('/dev/null', 'wb')), 'sasasaas'], // Take that
];
}

72
tests/Streams/StringStreamTest.php

@ -10,66 +10,70 @@ use RouterOS\Exceptions\StreamException;
/**
* Limit code coverage to the class RouterOS\APIStream
* @coversDefaultClass RouterOS\Streams\StringStream
*
* @coversDefaultClass \RouterOS\Streams\StringStream
*/
class StringStreamTest extends TestCase
{
/**
* @covers ::__construct
* @dataProvider constructProvider
*
* @param string $string
*/
public function test__construct(string $string)
{
$this->assertInstanceOf(StringStream::class, new StringStream($string));
}
public function constructProvider()
public function constructProvider(): array
{
return [
[ chr(0) ],
[ '' ],
[ '1' ],
[ 'lkjl'.chr(0).'kjkljllkjkljljklkjkljlkjljlkjkljkljlkjjll'],
[chr(0)],
[''],
['1'],
['lkjl' . chr(0) . 'kjkljllkjkljljklkjkljlkjljlkjkljkljlkjjll'],
];
}
/**
* test that write function returns the effective writen bytes
* Test that write function returns the effective written bytes
*
* @covers ::write
* @dataProvider writeProvider
* @param string $toWrite the string to write
* @param int|null $length the count if bytes to write
* @param int $expected the number of bytes that must be writen
*
* @param string $string the string to write
* @param int|null $length the count if bytes to write
* @param int $expected the number of bytes that must be writen
*/
public function test__write(string $string, $length, int $expected)
{
$stream = new StringStream('Does not matters');
if (is_null($length)) {
if (null === $length) {
$this->assertEquals($expected, $stream->write($string));
}
else {
} else {
$this->assertEquals($expected, $stream->write($string, $length));
}
}
public function writeProvider()
public function writeProvider(): array
{
return [
[ '', 0, 0 ],
[ '', 10, 0 ],
[ '', null, 0 ],
[ 'Yabala', 0, 0],
[ 'Yabala', 1, 1],
[ 'Yabala', 6, 6],
[ 'Yabala', 100, 6],
[ 'Yabala', null, 6],
[ chr(0), 0, 0],
[ chr(0), 1, 1],
[ chr(0), 100, 1],
[ chr(0), null, 1],
['', 0, 0],
['', 10, 0],
['', null, 0],
['Yabala', 0, 0],
['Yabala', 1, 1],
['Yabala', 6, 6],
['Yabala', 100, 6],
['Yabala', null, 6],
[chr(0), 0, 0],
[chr(0), 1, 1],
[chr(0), 100, 1],
[chr(0), null, 1],
];
}
@ -80,11 +84,13 @@ class StringStreamTest extends TestCase
public function test__writeWithNegativeLength()
{
$stream = new StringStream('Does not matters');
$stream->write("PLOP", -1);
$stream->write('PLOP', -1);
}
/**
* Test read function
*
* @throws \RouterOS\Exceptions\StreamException
*/
public function test__read()
{
@ -99,7 +105,9 @@ class StringStreamTest extends TestCase
}
/**
* @expectedException InvalidArgumentException
* @expectedException \InvalidArgumentException
*
* @throws \RouterOS\Exceptions\StreamException
*/
public function test__readBadLength()
{
@ -111,12 +119,20 @@ class StringStreamTest extends TestCase
* @covers ::read
* @dataProvider readWhileEmptyProvider
* @expectedException \RouterOS\Exceptions\StreamException
*
* @param StringStream $stream
* @param int $length
* @throws \RouterOS\Exceptions\StreamException
*/
public function test__readWhileEmpty(StringStream $stream, int $length)
{
$stream->read($length);
}
/**
* @return \Generator
* @throws StreamException
*/
public function readWhileEmptyProvider()
{
$stream = new StringStream('123456789');

Loading…
Cancel
Save