Skip to content

Commit

Permalink
Added letter time notation support to Util::parseValue();
Browse files Browse the repository at this point in the history
Added a preliminary changelog;
Altered the Packer template to support newer RouterOS versions;
Moved some Communicator tests into a new test folder.
  • Loading branch information
boenrobot committed Nov 28, 2015
1 parent 56fa48c commit 193d995
Show file tree
Hide file tree
Showing 22 changed files with 636 additions and 160 deletions.
4 changes: 2 additions & 2 deletions README.md
@@ -1,8 +1,8 @@
Project: [![Total Downloads](https://poser.pugx.org/pear2/net_routeros/downloads)](https://packagist.org/packages/pear2/net_routeros) [![License](https://poser.pugx.org/pear2/net_routeros/license)](https://packagist.org/packages/pear2/net_routeros)

Stable: [![Dependency Status](https://www.versioneye.com/php/pear2:net_routeros/dev-master/badge.svg)](https://www.versioneye.com/php/pear2:net_routeros/dev-master)
Stable (master): [![Dependency Status](https://www.versioneye.com/php/pear2:net_routeros/dev-master/badge.svg)](https://www.versioneye.com/php/pear2:net_routeros/dev-master)

Unstable: [![Dependency Status](https://www.versioneye.com/php/pear2:net_routeros/dev-develop/badge.svg)](https://www.versioneye.com/php/pear2:net_routeros/dev-develop)
Unstable (develop): [![Dependency Status](https://www.versioneye.com/php/pear2:net_routeros/dev-develop/badge.svg)](https://www.versioneye.com/php/pear2:net_routeros/dev-develop)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/pear2/Net_RouterOS/badges/quality-score.png?b=develop)](https://scrutinizer-ci.com/g/pear2/Net_RouterOS/?branch=develop)

See [the project wiki](https://github.com/pear2/Net_RouterOS/wiki) for installation instructions and other documentation.
Expand Down
7 changes: 7 additions & 0 deletions RELEASE-1.0.0b6
@@ -0,0 +1,7 @@
Bug fixes, mostly.

* New Util methods:
- newRequest()
- comment()
* Util::parseValue() now supports letter notation for time (1h2m3s), not just double colon notation (01:02:03), modeled after RouterOS. Related to that is also that leading zeroes, and zero minutes and seconds are now optional (e.g. "1:" is a valid way of saying 1 hour). Sub-second information is rounded up to the nearest second on current PHP versions (future versions are expected to support sub-second information in DateInterval by allowing seconds to be a double; The code currently attempts to give DateInterval a double, falling back to rounding to a second).
* Client::login() consumes the !done or !fatal response even when called on an already logged in connection.
76 changes: 66 additions & 10 deletions src/PEAR2/Net/RouterOS/Util.php
Expand Up @@ -36,10 +36,15 @@
use Countable;

/**
* Used to reliably write to streams at {@link static::prepareScript()}.
* Used to reliably write to streams at {@link Util::prepareScript()}.
*/
use PEAR2\Net\Transmitter\Stream;

/**
* Used to catch a DateInterval exception at {@link Util::parseValue()}.
*/
use Exception as E;

/**
* Utility class.
*
Expand Down Expand Up @@ -108,11 +113,19 @@ public static function parseValue($value)
return $num;
} elseif (preg_match(
'/^
(?:(\d+)w)?
(?:(\d+)d)?
(?:(\d\d)\:)?
(\d\d)\:
(\d\d(:\.\d{1,6})?)
(?:(\d+)w)?
(?:(\d+)d)?
(?:(\d+)(?:\:|h))?
(?|
(\d+)\:
(\d*(?:\.\d{1,9})?)
|
(?:(\d+)m)?
(?:(\d+|\d*\.\d{1,9})s)?
(?:((?5))ms)?
(?:((?5))us)?
(?:((?5))ns)?
)
$/x',
$value,
$time
Expand All @@ -121,12 +134,55 @@ public static function parseValue($value)
if (isset($time[1])) {
$days += 7 * (int)$time[1];
}
if ('' === $time[3]) {
if (empty($time[3])) {
$time[3] = 0;
}
return new DateInterval(
"P{$days}DT{$time[3]}H{$time[4]}M{$time[5]}S"
);
if (empty($time[4])) {
$time[4] = 0;
}
if (empty($time[5])) {
$time[5] = 0;
}

$subsecondTime = 0.0;
//@codeCoverageIgnoreStart
// No PHP version currently supports sub-second DateIntervals,
// meaning this section is untestable, since no version constraints
// can be specified for test inputs.
// All inputs currently use integer seconds only, making this
// section unreachable during tests.
// Nevertheless, this section exists right now, in order to provide
// such support as soon as PHP has it.
if (!empty($time[6])) {
$subsecondTime += ((double)$time[6]) / 1000;
}
if (!empty($time[7])) {
$subsecondTime += ((double)$time[7]) / 1000000;
}
if (!empty($time[8])) {
$subsecondTime += ((double)$time[8]) / 1000000000;
}
//@codeCoverageIgnoreEnd

$secondsSpec = $time[5] + $subsecondTime;
try {
return new DateInterval(
"P{$days}DT{$time[3]}H{$time[4]}M{$secondsSpec}S"
);
//@codeCoverageIgnoreStart
// See previous ignored section's note.
//
// This section is added for backwards compatibility with current
// PHP versions, when in the future sub-second support is added.
// In that event, the test inputs for older versions will be
// expected to get a rounded up result of the sub-second data.
} catch (E $e) {
$secondsSpec = (int)round($secondsSpec);
return new DateInterval(
"P{$days}DT{$time[3]}H{$time[4]}M{$secondsSpec}S"
);
}
//@codeCoverageIgnoreEnd
} elseif (('"' === $value[0]) && substr(strrev($value), 0, 1) === '"') {
return str_replace(
array('\"', '\\\\', "\\\n", "\\\r\n", "\\\r"),
Expand Down
88 changes: 88 additions & 0 deletions tests/Communicator/Safe.php
@@ -0,0 +1,88 @@
<?php

namespace PEAR2\Net\RouterOS\Test\Communicator;

use PEAR2\Net\RouterOS\Communicator;
use PEAR2\Net\RouterOS\Request;
use PEAR2\Net\RouterOS\Response;
use PEAR2\Net\RouterOS\Query;
use PEAR2\Net\RouterOS\InvalidArgumentException;
use PEAR2\Net\RouterOS\SocketException;
use PHPUnit_Framework_TestCase;

abstract class Safe extends PHPUnit_Framework_TestCase
{

/**
* @var Communicator
*/
protected $object;

public function testNonSeekableCommunicatorWord()
{
$value = fopen('php://output', 'a');
try {
$this->object->sendWordFromStream('', $value);
$this->fail('Call had to fail.');
} catch (InvalidArgumentException $e) {
$this->assertEquals(
InvalidArgumentException::CODE_SEEKABLE_REQUIRED,
$e->getCode(),
'Improper exception code.'
);
}
}

public function testInvokability()
{
$com = $this->object;
$request = new Request('/ping');
$request('address', HOSTNAME)->setTag('p');
$this->assertEquals(HOSTNAME, $request('address'));
$this->assertEquals('p', $request->getTag());
$this->assertEquals('p', $request());
$request($com);
$response = new Response(
$com,
false,
ini_get('default_socket_timeout')
);
$this->assertInternalType('string', $response());
$this->assertEquals(HOSTNAME, $response('host'));

$request = new Request('/queue/simple/print');
$query = Query::where('target', HOSTNAME_INVALID . '/32');
$request($query);
$this->assertSame($query, $request->getQuery());
$com('/log/print');
$com('');
}

public function testInvalidSocketOnReceive()
{
try {
new Response($this->object);
$this->fail('Receiving had to fail.');
} catch (SocketException $e) {
$this->assertEquals(
SocketException::CODE_NO_DATA,
$e->getCode(),
'Improper exception code.'
);
}
}

public function testInvalidSocketOnStreamReceive()
{
try {
$response = new Response($this->object, true);
$this->fail('Receiving had to fail.');
} catch (SocketException $e) {
$this->assertEquals(
SocketException::CODE_NO_DATA,
$e->getCode(),
'Improper exception code.'
);
}
}
}
15 changes: 15 additions & 0 deletions tests/Communicator/Safe/NonPersistent.php
@@ -0,0 +1,15 @@
<?php

namespace PEAR2\Net\RouterOS\Test\Communicator\Safe;

use PEAR2\Net\RouterOS\Test\Communicator\Safe;

require_once __DIR__ . '/../Safe.php';

abstract class NonPersistent extends Safe
{
protected function tearDown()
{
unset($this->object);
}
}
41 changes: 41 additions & 0 deletions tests/Communicator/Safe/NonPersistent/EncryptedTest.php
@@ -0,0 +1,41 @@
<?php

namespace PEAR2\Net\RouterOS\Test\Communicator\Safe\NonPersistent;

use PEAR2\Net\RouterOS\Client;
use PEAR2\Net\RouterOS\Communicator;
use PEAR2\Net\RouterOS\Test\Communicator\Safe\NonPersistent;
use PEAR2\Net\Transmitter\NetworkStream;

require_once __DIR__ . '/../NonPersistent.php';

/**
* ~
*
* @group Communicator
* @group Safe
* @group NonPersistent
* @group Encrypted
*
* @requires extension openssl
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
class EncryptedTest extends NonPersistent
{
protected function setUp()
{
$this->object = new Communicator(
\HOSTNAME,
ENC_PORT,
false,
null,
NetworkStream::CRYPTO_TLS
);
Client::login($this->object, USERNAME, PASSWORD);
}
}
32 changes: 32 additions & 0 deletions tests/Communicator/Safe/NonPersistent/UnencryptedTest.php
@@ -0,0 +1,32 @@
<?php

namespace PEAR2\Net\RouterOS\Test\Communicator\Safe\NonPersistent;

use PEAR2\Net\RouterOS\Client;
use PEAR2\Net\RouterOS\Communicator;
use PEAR2\Net\RouterOS\Test\Communicator\Safe\NonPersistent;

require_once __DIR__ . '/../NonPersistent.php';

/**
* ~
*
* @group Communicator
* @group Safe
* @group NonPersistent
* @group Unencrypted
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
class UnencryptedTest extends NonPersistent
{
protected function setUp()
{
$this->object = new Communicator(\HOSTNAME, PORT);
Client::login($this->object, USERNAME, PASSWORD);
}
}
17 changes: 17 additions & 0 deletions tests/Communicator/Safe/Persistent.php
@@ -0,0 +1,17 @@
<?php

namespace PEAR2\Net\RouterOS\Test\Communicator\Safe;

use PEAR2\Net\RouterOS\Test\Communicator\Safe;

require_once __DIR__ . '/../Safe.php';

abstract class Persistent extends Safe
{

protected function tearDown()
{
$this->object->close();
unset($this->object);
}
}
42 changes: 42 additions & 0 deletions tests/Communicator/Safe/Persistent/EncryptedTest.php
@@ -0,0 +1,42 @@
<?php

namespace PEAR2\Net\RouterOS\Test\Communicator\Safe\Persistent;

use PEAR2\Net\RouterOS\Client;
use PEAR2\Net\RouterOS\Communicator;
use PEAR2\Net\RouterOS\Test\Communicator\Safe\Persistent;
use PEAR2\Net\Transmitter\NetworkStream;

require_once __DIR__ . '/../Persistent.php';

/**
* ~
*
* @group Communicator
* @group Safe
* @group Persistent
* @group Encrypted
*
* @requires extension openssl
* @requires PHP 5.3.9
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
class EncryptedTest extends Persistent
{
protected function setUp()
{
$this->object = new Communicator(
\HOSTNAME,
ENC_PORT,
true,
null,
NetworkStream::CRYPTO_TLS
);
Client::login($this->object, USERNAME, PASSWORD);
}
}
34 changes: 34 additions & 0 deletions tests/Communicator/Safe/Persistent/UnencryptedTest.php
@@ -0,0 +1,34 @@
<?php

namespace PEAR2\Net\RouterOS\Test\Communicator\Safe\Persistent;

use PEAR2\Net\RouterOS\Client;
use PEAR2\Net\RouterOS\Communicator;
use PEAR2\Net\RouterOS\Test\Communicator\Safe\Persistent;

require_once __DIR__ . '/../Persistent.php';

/**
* ~
*
* @group Communicator
* @group Safe
* @group Persistent
* @group Unencrypted
*
* @requires PHP 5.3.9
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
class UnencryptedTest extends Persistent
{
protected function setUp()
{
$this->object = new Communicator(\HOSTNAME, PORT, true);
Client::login($this->object, USERNAME, PASSWORD);
}
}

0 comments on commit 193d995

Please sign in to comment.