Skip to content

Commit 6fb97a0

Browse files
committed
100% code coverage, doc fixes, and minor clean ups.
1 parent 36b4aea commit 6fb97a0

File tree

9 files changed

+173
-32
lines changed

9 files changed

+173
-32
lines changed

RELEASE-1.0.0b3

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Bug fixes on edge cases, and some API changes
22

3+
* Persistent connections are now properly supported. Added a new Registry class to facilitate this.
34
* The second and third argument of Request::__construct() have been swapped.
45
* At Request::__construct(), a backslash can now be escaped in an argument value.
56
* Client::getStreamResponses() and Client::setStreamResponses() are now Client::isStreamingResponses() and Client::setStreamingResponses(), respectively.

src/PEAR2/Net/RouterOS/Client.php

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -622,18 +622,20 @@ public function close()
622622
{
623623
$result = false;
624624
try {
625-
if (0 !== $this->pendingRequestsCount) {
626-
if (null !== $this->registry) {
627-
$this->registry->setTaglessMode(true);
628-
}
629-
$response = $this->sendSync(new Request('/quit'));
630-
if (null !== $this->registry) {
631-
$this->registry->setTaglessMode(false);
632-
}
633-
$result = $response->getType() === Response::TYPE_FATAL;
625+
if (null !== $this->registry) {
626+
$this->registry->setTaglessMode(true);
634627
}
628+
$response = $this->sendSync(new Request('/quit'));
629+
if (null !== $this->registry) {
630+
$this->registry->setTaglessMode(false);
631+
}
632+
$result = $response->getType() === Response::TYPE_FATAL;
633+
$result = $result && $this->com->close();
635634
} catch (SocketException $e) {
636-
$result = $e->getCode() === 205;
635+
$result = $e->getCode() === 40900;
636+
if (null !== $this->registry) {
637+
$this->registry->setTaglessMode(false);
638+
}
637639
}
638640
$this->callbacks = array();
639641
$this->pendingRequestsCount = 0;

src/PEAR2/Net/RouterOS/Registry.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,10 @@ public static function parseTag($tag)
9999
}
100100

101101
/**
102-
* Checks if any instance is in tagless mode right now.
102+
* Checks if this instance is the tagless mode owner.
103103
*
104-
* @return bool TRUE if an instance is in tagless mode, FALSE otherwise.
104+
* @return bool TRUE if this instance is the tagless mode owner, FALSE
105+
* otherwise.
105106
*/
106107
public function isTaglessModeOwner()
107108
{
@@ -247,11 +248,6 @@ public function close()
247248
self::$requestId = -1;
248249
self::$instanceIdSeed = -1;
249250
$this->shm->clear();
250-
251-
//foreach ($this->shm->getIterator('/^(responseBuffer\_)/', true)
252-
// as $targetBufferName) {
253-
// $this->_close($targetBufferName);
254-
//}
255251
}
256252

257253
/**

tests/ClientFeaturesTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,5 +988,48 @@ public function testDefaultCharsets()
988988
Communicator::getDefaultCharset(Communicator::CHARSET_LOCAL)
989989
);
990990
}
991+
992+
public function testSendSyncReturningResponseLargeDataException()
993+
{
994+
//Required for this test
995+
$memoryLimit = ini_set('memory_limit', -1);
996+
try {
997+
998+
$comment = fopen('php://temp', 'r+b');
999+
$fillerString = str_repeat('t', 0xFFFFFF);
1000+
//fwrite($comment, $fillerString);
1001+
for ($i = 0; $i < 16; $i++) {
1002+
fwrite($comment, $fillerString);
1003+
}
1004+
unset($fillerString);
1005+
fwrite(
1006+
$comment,
1007+
str_repeat('t', 0xF/* - strlen('=comment=') */)
1008+
);
1009+
rewind($comment);
9911010

1011+
$commentString = stream_get_contents($comment);
1012+
$maxArgL = 0xFFFFFFF - strlen('=comment=');
1013+
$this->assertGreaterThan(
1014+
$maxArgL, strlen($commentString), '$comment is not long enough.'
1015+
);
1016+
unset($commentString);
1017+
rewind($comment);
1018+
$printRequest = new Request('/ip/arp/print');
1019+
$printRequest->setQuery(Query::where('comment', $comment));
1020+
$this->object->sendSync($printRequest);
1021+
fclose($comment);
1022+
//Clearing out for other tests.
1023+
ini_set('memory_limit', $memoryLimit);
1024+
$this->fail('Lengths above 0xFFFFFFF should not be supported.');
1025+
} catch (LengthException $e) {
1026+
fclose($comment);
1027+
$this->assertEquals(
1028+
1200, $e->getCode(), 'Improper exception thrown.'
1029+
);
1030+
}
1031+
1032+
//Clearing out for other tests.
1033+
ini_set('memory_limit', $memoryLimit);
1034+
}
9921035
}

tests/ClientPersistentFeaturesTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,26 @@ protected function tearDown()
1616
$this->object->close();
1717
unset($this->object);
1818
}
19+
20+
public function testCancellingSeparation()
21+
{
22+
$client = new Client(\HOSTNAME, USERNAME, PASSWORD, PORT, true);
23+
$pingRequest = new Request('/ping', null, 'ping');
24+
$pingRequest->setArgument('address', HOSTNAME);
25+
$this->object->sendAsync($pingRequest);
26+
$client->sendAsync($pingRequest);
27+
$client->loop(2);
28+
$this->object->loop(2);
29+
$this->assertGreaterThan(
30+
0, count($client->extractNewResponses('ping'))
31+
);
32+
$this->assertGreaterThan(
33+
0, count($this->object->extractNewResponses('ping'))
34+
);
35+
unset($client);
36+
$this->object->loop(2);
37+
$this->assertGreaterThan(
38+
0, count($this->object->extractNewResponses('ping'))
39+
);
40+
}
1941
}

tests/RequestHandlingTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,59 @@ public function testInvokability()
775775
$com('/quit');
776776
$com('');
777777
}
778+
779+
public function testTaglessModePassing()
780+
{
781+
$com1 = new Communicator(\HOSTNAME, PORT, true);
782+
Client::login($com1, USERNAME, PASSWORD);
783+
$reg1 = new Registry('dummy');
784+
785+
$com2 = new Communicator(\HOSTNAME, PORT, true);
786+
$reg2 = new Registry('dummy');
787+
788+
$this->assertNotEquals(
789+
$reg1->getOwnershipTag(), $reg2->getOwnershipTag()
790+
);
791+
792+
$pingRequest1 = new Request(
793+
'/ping address=' . HOSTNAME, null, 'ping'
794+
);
795+
$pingRequest1->send($com1, $reg1);
796+
797+
$response1_1 = new Response($com1, false, $reg1);
798+
799+
$cancelRequest = new Request('/cancel');
800+
$reg1->setTaglessMode(true);
801+
$cancelRequest->setArgument('tag', $reg1->getOwnershipTag() . 'ping');
802+
$cancelRequest->send($com1, $reg1);
803+
804+
$pingRequest2 = new Request(
805+
'/ping count=2 address=' . HOSTNAME, null, 'ping'
806+
);
807+
$pingRequest2->send($com2, $reg2);
808+
809+
$response2_1 = new Response($com2, false, $reg2);
810+
$response2_2 = new Response($com2, false, $reg2);
811+
$response2_3 = new Response($com2, false, $reg2);
812+
$reg1->setTaglessMode(false);
813+
814+
$com1->close();
815+
$com2->close();
816+
817+
$this->assertEquals(Response::TYPE_DATA, $response2_1->getType());
818+
$this->assertEquals(Response::TYPE_DATA, $response2_2->getType());
819+
$this->assertEquals(Response::TYPE_FINAL, $response2_3->getType());
820+
821+
$response1_2 = new Response($com1, false, $reg1);
822+
$response1_3 = new Response($com1, false, $reg1);
823+
824+
$this->assertEquals(Response::TYPE_DATA, $response1_1->getType());
825+
$this->assertEquals(Response::TYPE_ERROR, $response1_2->getType());
826+
$this->assertEquals(Response::TYPE_FINAL, $response1_3->getType());
827+
828+
$reg1->close();
829+
$this->assertStringStartsWith('-1_', $reg2->getOwnershipTag());
830+
}
778831

779832
public function testReceivingLargeWords()
780833
{

tests/StateAlteringFeaturesTest.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,18 +224,21 @@ public function testSendSyncReturningResponseLarge4bytesLength()
224224

225225
public function testSendSyncReturningResponseLargeDataException()
226226
{
227+
$this->markTestIncomplete(
228+
'TODO: A known issue; Requests with excessively long words "leak".'
229+
);
227230
//Required for this test
228231
$memoryLimit = ini_set('memory_limit', -1);
229232
try {
230233

231234
$comment = fopen('php://temp', 'r+b');
232-
fwrite($comment, str_pad('t', 0xFFFFFF, 't'));
235+
fwrite($comment, str_repeat('t', 0xFFFFFF));
233236
for ($i = 0; $i < 14; $i++) {
234-
fwrite($comment, str_pad('t', 0xFFFFFF, 't'));
237+
fwrite($comment, str_repeat('t', 0xFFFFFF));
235238
}
236239
fwrite(
237240
$comment,
238-
str_pad('t', 0xFFFFFF + 0xF/* - strlen('=comment=') */, 't')
241+
str_repeat('t', 0xFFFFFF + 0xF/* - strlen('=comment=') */)
239242
);
240243
rewind($comment);
241244

@@ -244,9 +247,11 @@ public function testSendSyncReturningResponseLargeDataException()
244247
$this->assertGreaterThan(
245248
$maxArgL, strlen($commentString), '$comment is not long enough.'
246249
);
250+
unset($commentString);
251+
rewind($comment);
247252
$addRequest = new Request('/queue/simple/add');
248253
$addRequest->setArgument('name', TEST_QUEUE_NAME);
249-
$addRequest->setArgument('comment', $commentString);
254+
$addRequest->setArgument('comment', $comment);
250255
$responses = $this->object->sendSync($addRequest);
251256
if (count($responses) === 1
252257
&& $responses->getLast()->getType() === Response::TYPE_FINAL
@@ -255,7 +260,9 @@ public function testSendSyncReturningResponseLargeDataException()
255260
$removeRequest->setArgument('numbers', TEST_QUEUE_NAME);
256261
$response = $this->object->sendSync($removeRequest);
257262
}
258-
263+
264+
//Clearing out for other tests.
265+
ini_set('memory_limit', $memoryLimit);
259266
$this->fail('Lengths above 0xFFFFFFF should not be supported.');
260267
} catch (LengthException $e) {
261268
$this->assertEquals(

tests/bootstrap.php

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,35 @@
88
\PEAR2\Autoload::initialize('../../PEAR2_Net_Transmitter.git/src');
99
\PEAR2\Autoload::initialize('../../PEAR2_Cache_SHM.git/src');
1010

11-
//Resolving HOSTNAME_* constants
12-
$constants = array('HOSTNAME', 'HOSTNAME_INVALID', 'HOSTNAME_SILENT');
13-
foreach ($constants as $constant) {
14-
$hostnames = dns_get_record(constant($constant));
15-
foreach ($hostnames as $hostname) {
16-
switch($hostname['type']) {
11+
/**
12+
* Resolves a hostname to an IP address.
13+
*
14+
* Resolves a hostname to an IP address. Used instead of gethostbyname() in
15+
* order to enable resolutions to IPv6 hosts.
16+
*
17+
* @param $hostname Hostname to resolve.
18+
*
19+
* @return string An IP (v4 or v6) for this hostname.
20+
*/
21+
function resolve($hostname) {
22+
$info = dns_get_record($hostname);
23+
foreach ($info as $entry) {
24+
switch($entry['type']) {
1725
case 'A':
26+
return $entry['ip'];
1827
case 'AAAA':
1928
case 'A6':
20-
$newConstant = __NAMESPACE__ . '\\' . $constant;
21-
define($newConstant, $hostname['ip']);
22-
continue 3;
29+
return $entry['ipv6'];
30+
case 'CNAME':
31+
if ($entry['host'] === $hostname) {
32+
return resolve($entry['target']);
33+
}
2334
}
2435
}
36+
}
37+
38+
//Resolving HOSTNAME_* constants
39+
$constants = array('HOSTNAME', 'HOSTNAME_INVALID', 'HOSTNAME_SILENT');
40+
foreach ($constants as $constant) {
41+
define(__NAMESPACE__ . '\\' . $constant, resolve(constant($constant)));
2542
}

tests/phpunit.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<phpunit
33
bootstrap="bootstrap.php"
44
colors="false"
5-
stopOnFailure="false"
5+
stopOnFailure="true"
66
verbose="true"
77
strict="true"
88

0 commit comments

Comments
 (0)