diff options
author | Jordi Boggiano <j.boggiano@seld.be> | 2016-09-19 22:01:19 +0200 |
---|---|---|
committer | Jordi Boggiano <j.boggiano@seld.be> | 2016-09-19 23:14:24 +0200 |
commit | 3dc7a79a3e88ee543f2f032d39b2354548898034 (patch) | |
tree | 9b614bbf93b0ddb8df727c56b5eb476de1741bce /tests | |
parent | a0f59df992f83c4b8c19cfcb891ae247fd7a3872 (diff) | |
download | monolog-3dc7a79a3e88ee543f2f032d39b2354548898034.zip monolog-3dc7a79a3e88ee543f2f032d39b2354548898034.tar.gz monolog-3dc7a79a3e88ee543f2f032d39b2354548898034.tar.bz2 |
Fixing the socket mess, maybe.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Monolog/Handler/FlowdockHandlerTest.php | 38 | ||||
-rw-r--r-- | tests/Monolog/Handler/HipChatHandlerTest.php | 88 | ||||
-rw-r--r-- | tests/Monolog/Handler/LogEntriesHandlerTest.php | 39 | ||||
-rw-r--r-- | tests/Monolog/Handler/LogmaticHandlerTest.php | 39 | ||||
-rw-r--r-- | tests/Monolog/Handler/PushoverHandlerTest.php | 52 | ||||
-rw-r--r-- | tests/Monolog/Handler/SlackHandlerTest.php | 50 | ||||
-rw-r--r-- | tests/Monolog/Handler/SocketHandlerTest.php | 72 | ||||
-rw-r--r-- | tests/Monolog/Handler/UdpSocketTest.php | 44 | ||||
-rw-r--r-- | tests/Monolog/Util/LocalSocket.php | 234 |
9 files changed, 307 insertions, 349 deletions
diff --git a/tests/Monolog/Handler/FlowdockHandlerTest.php b/tests/Monolog/Handler/FlowdockHandlerTest.php index f7f02e1..742d808 100644 --- a/tests/Monolog/Handler/FlowdockHandlerTest.php +++ b/tests/Monolog/Handler/FlowdockHandlerTest.php @@ -14,6 +14,7 @@ namespace Monolog\Handler; use Monolog\Formatter\FlowdockFormatter; use Monolog\Test\TestCase; use Monolog\Logger; +use Monolog\Util\LocalSocket; /** * @author Dominik Liebler <liebler.dominik@gmail.com> @@ -42,7 +43,7 @@ class FlowdockHandlerTest extends TestCase { $this->initHandlerAndSocket(); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/POST \/v1\/messages\/team_inbox\/.* HTTP\/1.1\\r\\nHost: api.flowdock.com\\r\\nContent-Type: application\/json\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); @@ -61,28 +62,7 @@ class FlowdockHandlerTest extends TestCase private function initHandlerAndSocket($token = 'myToken') { - $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php'; - file_put_contents($tmpFile, <<<'SCRIPT' -<?php - -$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); -socket_bind($sock, '127.0.0.1', 51984); -socket_listen($sock); - -while (true) { - $res = socket_accept($sock); - socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500)); - while ($read = socket_read($res, 1024)) { - echo $read; - } - socket_close($res); -} -SCRIPT -); - - $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile)); - $this->socket->start(); - + $this->socket = LocalSocket::initSocket(); $this->handler = new FlowdockHandler($token); $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); @@ -92,18 +72,8 @@ SCRIPT $this->handler->setFormatter(new FlowdockFormatter('test_source', 'source@test.com')); } - private function closeSocket() - { - $this->socket->stop(); - - return $this->socket->getOutput(); - } - public function tearDown() { - if (isset($this->socket)) { - $this->closeSocket(); - unset($this->socket); - } + unset($this->socket, $this->handler); } } diff --git a/tests/Monolog/Handler/HipChatHandlerTest.php b/tests/Monolog/Handler/HipChatHandlerTest.php index c5445d9..4e24af3 100644 --- a/tests/Monolog/Handler/HipChatHandlerTest.php +++ b/tests/Monolog/Handler/HipChatHandlerTest.php @@ -13,6 +13,7 @@ namespace Monolog\Handler; use Monolog\Test\TestCase; use Monolog\Logger; +use Monolog\Util\LocalSocket; /** * @author Rafael Dohms <rafael@doh.ms> @@ -28,65 +29,49 @@ class HipChatHandlerTest extends TestCase { $this->initHandlerAndSocket('myToken', 'room1', 'Monolog', false, 'hipchat.foo.bar', 'v2'); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->socket->getOutput(); - $this->assertRegexp('/POST \/v2\/room\/room1\/notification\?auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + + $this->assertRegexp('{POST /v2/room/room1/notification\?auth_token=.* HTTP/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n}', $content); return $content; } - public function testWriteV2Notify() + /** + * @depends testWriteV2 + */ + public function testWriteContentV2($content) { - $this->initHandlerAndSocket('myToken', 'room1', 'Monolog', true, 'hipchat.foo.bar', 'v2'); - $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->socket->getOutput(); - - $this->assertRegexp('/POST \/v2\/room\/room1\/notification\?auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); - - return $content; + $this->assertRegexp('/notify=false&message=test1&message_format=text&color=red&from=Monolog$/', $content); } - public function testRoomSpaces() + public function testWriteV2Notify() { - $this->initHandlerAndSocket('myToken', 'room name', 'Monolog', false, 'hipchat.foo.bar', 'v2'); + $this->initHandlerAndSocket('myToken', 'room2', 'Monolog', true, 'hipchat.foo.bar', 'v2'); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); $content = $this->socket->getOutput(); - $this->assertRegexp('/POST \/v2\/room\/room%20name\/notification\?auth_token=.* HTTP\/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); + $this->assertRegexp('{POST /v2/room/room2/notification\?auth_token=.* HTTP/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n}', $content); return $content; } /** - * @depends testWriteHeader + * @depends testWriteV2Notify */ - public function testWriteContent($content) + public function testWriteContentV2Notify($content) { - $this->assertRegexp('/notify=0&message=test1&message_format=text&color=red&room_id=room1&from=Monolog$/', $content); + $this->assertRegexp('/notify=true&message=test1&message_format=text&color=red&from=Monolog$/', $content); } - /** - * @depends testWriteCustomHostHeader - */ - public function testWriteContentNotify($content) + public function testRoomSpaces() { - $this->assertRegexp('/notify=1&message=test1&message_format=text&color=red&room_id=room1&from=Monolog$/', $content); - } + $this->initHandlerAndSocket('myToken', 'room name', 'Monolog', false, 'hipchat.foo.bar', 'v2'); + $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); + $content = $this->socket->getOutput(); - /** - * @depends testWriteV2 - */ - public function testWriteContentV2($content) - { - $this->assertRegexp('/notify=false&message=test1&message_format=text&color=red&from=Monolog$/', $content); - } + $this->assertRegexp('{POST /v2/room/room%20name/notification\?auth_token=.* HTTP/1.1\\r\\nHost: hipchat.foo.bar\\r\\nContent-Type: application/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n}', $content); - /** - * @depends testWriteV2Notify - */ - public function testWriteContentV2Notify($content) - { - $this->assertRegexp('/notify=true&message=test1&message_format=text&color=red&from=Monolog$/', $content); + return $content; } public function testWriteContentV2WithoutName() @@ -198,28 +183,7 @@ class HipChatHandlerTest extends TestCase private function initHandlerAndSocket($token = 'myToken', $room = 'room1', $name = 'Monolog', $notify = false, $host = 'api.hipchat.com', $version = 'v1') { - $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php'; - file_put_contents($tmpFile, <<<'SCRIPT' -<?php - -$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); -socket_bind($sock, '127.0.0.1', 51984); -socket_listen($sock); - -while (true) { - $res = socket_accept($sock); - socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500)); - while ($read = socket_read($res, 1024)) { - echo $read; - } - socket_close($res); -} -SCRIPT -); - - $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile)); - $this->socket->start(); - + $this->socket = LocalSocket::initSocket(); $this->handler = new HipChatHandler($token, $room, $name, $notify, Logger::DEBUG, true, true, 'text', $host, $version); $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); @@ -229,16 +193,8 @@ SCRIPT $this->handler->setFormatter($this->getIdentityFormatter()); } - private function closeSocket() - { - $this->socket->stop(); - } - public function tearDown() { - if (isset($this->socket)) { - $this->closeSocket(); - unset($this->socket); - } + unset($this->socket, $this->handler); } } diff --git a/tests/Monolog/Handler/LogEntriesHandlerTest.php b/tests/Monolog/Handler/LogEntriesHandlerTest.php index 56c25dc..ce0df94 100644 --- a/tests/Monolog/Handler/LogEntriesHandlerTest.php +++ b/tests/Monolog/Handler/LogEntriesHandlerTest.php @@ -13,6 +13,7 @@ namespace Monolog\Handler; use Monolog\Test\TestCase; use Monolog\Logger; +use Monolog\Util\LocalSocket; /** * @author Robert Kaufmann III <rok3@rok3.me> @@ -34,7 +35,7 @@ class LogEntriesHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/testToken \[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+00:00\] test.CRITICAL: Critical write test/', $content); } @@ -48,33 +49,13 @@ class LogEntriesHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->handleBatch($records); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/(testToken \[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}\+00:00\] .* \[\] \[\]\n){3}/', $content); } private function initHandlerAndSocket() { - $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php'; - file_put_contents($tmpFile, <<<'SCRIPT' -<?php - -$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); -socket_bind($sock, '127.0.0.1', 51984); -socket_listen($sock); - -while (true) { - $res = socket_accept($sock); - socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500)); - while ($read = socket_read($res, 1024)) { - echo $read; - } - socket_close($res); -} -SCRIPT -); - - $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile)); - $this->socket->start(); + $this->socket = LocalSocket::initSocket(); $useSSL = extension_loaded('openssl'); $this->handler = new LogEntriesHandler('testToken', $useSSL, Logger::DEBUG, true); @@ -84,18 +65,8 @@ SCRIPT $reflectionProperty->setValue($this->handler, '127.0.0.1:51984'); } - private function closeSocket() - { - $this->socket->stop(); - - return $this->socket->getOutput(); - } - public function tearDown() { - if (isset($this->socket)) { - $this->closeSocket(); - unset($this->socket); - } + unset($this->socket, $this->handler); } } diff --git a/tests/Monolog/Handler/LogmaticHandlerTest.php b/tests/Monolog/Handler/LogmaticHandlerTest.php index 6156c3e..b667a21 100644 --- a/tests/Monolog/Handler/LogmaticHandlerTest.php +++ b/tests/Monolog/Handler/LogmaticHandlerTest.php @@ -13,6 +13,7 @@ namespace Monolog\Handler; use Monolog\Test\TestCase; use Monolog\Logger; +use Monolog\Util\LocalSocket; /** * @author Julien Breux <julien.breux@gmail.com> @@ -34,7 +35,7 @@ class LogmaticHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Critical write test')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/testToken {"message":"Critical write test","context":\[\],"level":500,"level_name":"CRITICAL","channel":"test","datetime":"(.*)","extra":\[\],"hostname":"testHostname","appname":"testAppname"}/', $content); } @@ -49,34 +50,14 @@ class LogmaticHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->handleBatch($records); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/testToken {"message":"test","context":\[\],"level":300,"level_name":"WARNING","channel":"test","datetime":"(.*)","extra":\[\],"hostname":"testHostname","appname":"testAppname"}/', $content); } private function initHandlerAndSocket() { - $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php'; - file_put_contents($tmpFile, <<<'SCRIPT' -<?php - -$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); -socket_bind($sock, '127.0.0.1', 51984); -socket_listen($sock); - -while (true) { - $res = socket_accept($sock); - socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500)); - while ($read = socket_read($res, 1024)) { - echo $read; - } - socket_close($res); -} -SCRIPT -); - - $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile)); - $this->socket->start(); + $this->socket = LocalSocket::initSocket(); $useSSL = extension_loaded('openssl'); $this->handler = new LogmaticHandler('testToken', 'testHostname', 'testAppname', $useSSL, Logger::DEBUG, true); @@ -86,18 +67,8 @@ SCRIPT $reflectionProperty->setValue($this->handler, '127.0.0.1:51984'); } - private function closeSocket() - { - $this->socket->stop(); - - return $this->socket->getOutput(); - } - public function tearDown() { - if (isset($this->socket)) { - $this->closeSocket(); - unset($this->socket); - } + unset($this->socket, $this->handler); } } diff --git a/tests/Monolog/Handler/PushoverHandlerTest.php b/tests/Monolog/Handler/PushoverHandlerTest.php index 0e7f7cf..7ac995d 100644 --- a/tests/Monolog/Handler/PushoverHandlerTest.php +++ b/tests/Monolog/Handler/PushoverHandlerTest.php @@ -13,6 +13,7 @@ namespace Monolog\Handler; use Monolog\Test\TestCase; use Monolog\Logger; +use Monolog\Util\LocalSocket; /** * Almost all examples (expected header, titles, messages) taken from @@ -30,7 +31,7 @@ class PushoverHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/POST \/1\/messages.json HTTP\/1.1\\r\\nHost: api.pushover.net\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); @@ -49,7 +50,7 @@ class PushoverHandlerTest extends TestCase { $this->initHandlerAndSocket('myToken', 'myUser', 'Backup finished - SQL1'); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/title=Backup\+finished\+-\+SQL1/', $content); } @@ -59,7 +60,7 @@ class PushoverHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications $this->handler->handle($this->getRecord(Logger::CRITICAL, 'Backup of database "example" finished in 16 minutes.')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/message=Backup\+of\+database\+%22example%22\+finished\+in\+16\+minutes\./', $content); } @@ -70,7 +71,7 @@ class PushoverHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->setHighPriorityLevel(Logger::EMERGENCY); // skip priority notifications $this->handler->handle($this->getRecord(Logger::CRITICAL, $message)); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $expectedMessage = substr($message, 0, 505); @@ -81,7 +82,7 @@ class PushoverHandlerTest extends TestCase { $this->initHandlerAndSocket(); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}&priority=1$/', $content); } @@ -90,16 +91,18 @@ class PushoverHandlerTest extends TestCase { $this->initHandlerAndSocket(); $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/token=myToken&user=myUser&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); } public function testWriteToMultipleUsers() { + $this->markTestIncomplete('LocalSocket buffer does not support multiple-connections'); + $this->initHandlerAndSocket('myToken', ['userA', 'userB']); $this->handler->handle($this->getRecord(Logger::EMERGENCY, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/token=myToken&user=userA&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200POST/', $content); $this->assertRegexp('/token=myToken&user=userB&message=test1&title=Monolog×tamp=\d{10}&priority=2&retry=30&expire=25200$/', $content); @@ -107,28 +110,7 @@ class PushoverHandlerTest extends TestCase private function initHandlerAndSocket($token = 'myToken', $user = 'myUser', $title = 'Monolog') { - $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php'; - file_put_contents($tmpFile, <<<'SCRIPT' -<?php - -$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); -socket_bind($sock, '127.0.0.1', 51984); -socket_listen($sock); - -while (true) { - $res = socket_accept($sock); - socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500)); - while ($read = socket_read($res, 1024)) { - echo $read; - } - socket_close($res); -} -SCRIPT -); - - $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile)); - $this->socket->start(); - + $this->socket = LocalSocket::initSocket(); $this->handler = new PushoverHandler($token, $user, $title); $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); @@ -138,18 +120,8 @@ SCRIPT $this->handler->setFormatter($this->getIdentityFormatter()); } - private function closeSocket() - { - $this->socket->stop(); - - return $this->socket->getOutput(); - } - public function tearDown() { - if (isset($this->socket)) { - $this->closeSocket(); - unset($this->socket); - } + unset($this->socket, $this->handler); } } diff --git a/tests/Monolog/Handler/SlackHandlerTest.php b/tests/Monolog/Handler/SlackHandlerTest.php index bfacd65..ee8d8dc 100644 --- a/tests/Monolog/Handler/SlackHandlerTest.php +++ b/tests/Monolog/Handler/SlackHandlerTest.php @@ -14,6 +14,7 @@ namespace Monolog\Handler; use Monolog\Test\TestCase; use Monolog\Logger; use Monolog\Formatter\LineFormatter; +use Monolog\Util\LocalSocket; /** * @author Greg Kedzierski <greg@gregkedzierski.com> @@ -43,7 +44,7 @@ class SlackHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/POST \/api\/chat.postMessage HTTP\/1.1\\r\\nHost: slack.com\\r\\nContent-Type: application\/x-www-form-urlencoded\\r\\nContent-Length: \d{2,4}\\r\\n\\r\\n/', $content); } @@ -52,7 +53,7 @@ class SlackHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=&attachments=.*$/', $content); } @@ -60,12 +61,12 @@ class SlackHandlerTest extends TestCase { $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', false); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', false); $this->handler->setFormatter(new LineFormatter('foo--%message%')); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test2')); - $content2 = $this->closeSocket(); + $content2 = $this->socket->getOutput(); $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=test1.*$/', $content); $this->assertRegexp('/token=myToken&channel=channel1&username=Monolog&text=foo--test2.*$/', $content2); @@ -76,7 +77,7 @@ class SlackHandlerTest extends TestCase $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', true, 'alien'); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/icon_emoji=%3Aalien%3A$/', $content); } @@ -88,7 +89,7 @@ class SlackHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->handler->handle($this->getRecord($level, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/color%22%3A%22'.$expectedColor.'/', $content); } @@ -97,7 +98,7 @@ class SlackHandlerTest extends TestCase $this->initHandlerAndSocket('myToken', 'channel1', 'Monolog', false); $this->handler->handle($this->getRecord(Logger::CRITICAL, 'test1')); - $content = $this->closeSocket(); + $content = $this->socket->getOutput(); $this->assertRegexp('/text=test1/', $content); } @@ -117,28 +118,7 @@ class SlackHandlerTest extends TestCase private function initHandlerAndSocket($token = 'myToken', $channel = 'channel1', $username = 'Monolog', $useAttachment = true, $iconEmoji = null, $useShortAttachment = false, $includeExtra = false) { - $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php'; - file_put_contents($tmpFile, <<<'SCRIPT' -<?php - -$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); -socket_bind($sock, '127.0.0.1', 51984); -socket_listen($sock); - -while (true) { - $res = socket_accept($sock); - socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500)); - while ($read = socket_read($res, 1024)) { - echo $read; - } - socket_close($res); -} -SCRIPT -); - - $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile)); - $this->socket->start(); - + $this->socket = LocalSocket::initSocket(); $this->handler = new SlackHandler($token, $channel, $username, $useAttachment, $iconEmoji, Logger::DEBUG, true, $useShortAttachment, $includeExtra); $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'connectionString'); @@ -148,18 +128,8 @@ SCRIPT $this->handler->setFormatter($this->getIdentityFormatter()); } - private function closeSocket() - { - $this->socket->stop(); - - return $this->socket->getOutput(); - } - public function tearDown() { - if (isset($this->socket)) { - $this->closeSocket(); - unset($this->socket); - } + unset($this->socket, $this->handler); } } diff --git a/tests/Monolog/Handler/SocketHandlerTest.php b/tests/Monolog/Handler/SocketHandlerTest.php index 50bbd25..e37ce18 100644 --- a/tests/Monolog/Handler/SocketHandlerTest.php +++ b/tests/Monolog/Handler/SocketHandlerTest.php @@ -13,6 +13,7 @@ namespace Monolog\Handler; use Monolog\Test\TestCase; use Monolog\Logger; +use Monolog\Util\LocalSocket; /** * @author Pablo de Leon Belloc <pablolb@gmail.com> @@ -112,39 +113,19 @@ class SocketHandlerTest extends TestCase $this->initHandlerAndSocket(); $this->writeRecord('Hello world'); - $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'resource'); - $reflectionProperty->setAccessible(true); - fclose($reflectionProperty->getValue($this->handler)); + LocalSocket::shutdownSocket(); - $this->writeRecord('Hello world'); + $this->writeRecord('Hello world2'); } - /** - * @expectedException RuntimeException - */ - public function testWriteFailsOnIncompleteWrite() + public function testWriteRealSocket() { $this->initHandlerAndSocket(); + $this->writeRecord("foo bar baz content test1\n"); + $this->writeRecord("foo bar baz content test2\n"); + $this->writeRecord("foo bar baz content test3\n"); - $this->handler->setWritingTimeout(1); - - // the socket will close itself after processing 10000 bytes so while processing b, and then c write fails - $this->writeRecord(str_repeat("aaaaaaaaaa\n", 700)); - $this->assertTrue(true); // asserting to make sure we reach this point - $this->writeRecord(str_repeat("bbbbbbbbbb\n", 700)); - $this->assertTrue(true); // asserting to make sure we reach this point - $this->writeRecord(str_repeat("cccccccccc\n", 700)); - $this->fail('The test should not reach here'); - } - - public function testWriteWithMemoryFile() - { - $this->initHandlerAndSocket(); - $this->writeRecord('test1'); - $this->writeRecord('test2'); - $this->writeRecord('test3'); - $this->closeSocket(); - $this->assertEquals('test1test2test3', $this->socket->getOutput()); + $this->assertEquals("foo bar baz content test1\nfoo bar baz content test2\nfoo bar baz content test3\n", $this->socket->getOutput()); } public function testClose() @@ -187,47 +168,14 @@ class SocketHandlerTest extends TestCase private function initHandlerAndSocket() { - $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php'; - file_put_contents($tmpFile, <<<'SCRIPT' -<?php - -$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); -socket_bind($sock, '127.0.0.1', 51984); -socket_listen($sock); -$res = socket_accept($sock); -socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500)); -$bytesRead = 0; -while ($read = socket_read($res, 1024)) { - echo $read; - $bytesRead += strlen($read); - if ($bytesRead > 10000) { - socket_close($res); - socket_close($sock); - die('CLOSED'); - } -} -echo 'EXIT'; -socket_close($res); -SCRIPT -); - - $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile)); - $this->socket->start(); + $this->socket = LocalSocket::initSocket(); $this->handler = new SocketHandler('tcp://127.0.0.1:51984'); $this->handler->setFormatter($this->getIdentityFormatter()); } - private function closeSocket() - { - $this->socket->stop(); - } - public function tearDown() { - if (isset($this->socket)) { - $this->closeSocket(); - unset($this->socket); - } + unset($this->socket, $this->handler); } } diff --git a/tests/Monolog/Handler/UdpSocketTest.php b/tests/Monolog/Handler/UdpSocketTest.php index d8343fa..4c7d5b2 100644 --- a/tests/Monolog/Handler/UdpSocketTest.php +++ b/tests/Monolog/Handler/UdpSocketTest.php @@ -13,6 +13,7 @@ namespace Monolog\Handler; use Monolog\Test\TestCase; use Monolog\Handler\SyslogUdp\UdpSocket; +use Monolog\Util\LocalSocket; /** * @requires extension sockets @@ -23,10 +24,9 @@ class UdpSocketTest extends TestCase { $this->initSocket(); - $socket = new UdpSocket('127.0.0.1', 51984); + $socket = new UdpSocket('127.0.0.1', 51983); $socket->write("The quick brown fox jumps over the lazy dog", "HEADER: "); - $this->closeSocket(); $this->assertEquals('HEADER: The quick brown fox jumps over the lazy dog', $this->socket->getOutput()); } @@ -34,14 +34,12 @@ class UdpSocketTest extends TestCase { $this->initSocket(); - $socket = new UdpSocket('127.0.0.1', 51984); + $socket = new UdpSocket('127.0.0.1', 51983); $longString = str_repeat("derp", 20000); $socket->write($longString, "HEADER"); $truncatedString = str_repeat("derp", 16254).'d'; - - $this->closeSocket(); $this->assertEquals('HEADER'.$truncatedString, $this->socket->getOutput()); } @@ -64,43 +62,11 @@ class UdpSocketTest extends TestCase private function initSocket() { - $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php'; - file_put_contents($tmpFile, <<<'SCRIPT' -<?php - -$sock = socket_create(AF_INET, SOCK_DGRAM, getprotobyname('udp')); -socket_bind($sock, '127.0.0.1', 51984); -echo 'INIT'; -while (true) { - socket_recvfrom($sock, $read, 100*1024, 0, $ip, $port); - echo $read; -} -SCRIPT -); - - $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile)); - $this->socket->start(); - while (true) { - if ($this->socket->getOutput() === 'INIT') { - $this->socket->clearOutput(); - break; - } - usleep(100); - } - } - - private function closeSocket() - { - usleep(100); - $this->socket->stop(); + $this->socket = LocalSocket::initSocket(51983, LocalSocket::UDP); } public function tearDown() { - if (isset($this->socket)) { - $this->closeSocket(); - unset($this->socket); - } + unset($this->socket, $this->handler); } - } diff --git a/tests/Monolog/Util/LocalSocket.php b/tests/Monolog/Util/LocalSocket.php new file mode 100644 index 0000000..59ab1d5 --- /dev/null +++ b/tests/Monolog/Util/LocalSocket.php @@ -0,0 +1,234 @@ +<?php declare(strict_types=1); + +/* + * This file is part of the Monolog package. + * + * (c) Jordi Boggiano <j.boggiano@seld.be> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Monolog\Util; + +use Symfony\Component\Process\Process; + +class LocalSocket +{ + const TCP = 'tcp'; + const UDP = 'udp'; + + private static $sockets = []; + private static $shutdownHandler = false; + + public static function initSocket(int $port = 51984, string $proto = LocalSocket::TCP) + { + if (!isset(self::$sockets[$proto][$port])) { + $file = self::initFile($port, $proto); + + $process = new Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($file)); + $process->start(function ($type, $out) use ($proto, $port) { + if ($type === 'err') { + if (substr($out, 0, 4) === 'INIT') { + if ($proto === LocalSocket::UDP) { + self::$sockets[$proto][$port]['comms'] = null; + } else { + $sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname($proto)); + socket_connect($sock, '127.0.0.1', $port); + socket_write($sock, "MONITOR\n"); + self::$sockets[$proto][$port]['comms'] = $sock; + } + } + } + }); + + self::$sockets[$proto][$port] = [ + 'file' => $file, + 'process' => $process, + 'busy' => false, + ]; + + // make sure the socket is listening + while (true) { + if ($process->getErrorOutput() === 'INIT') { + break; + } + usleep(100); + } + + if (!self::$shutdownHandler) { + register_shutdown_function(function () { + LocalSocket::shutdownSockets(); + }); + self::$shutdownHandler = true; + } + } + + $sock = self::$sockets[$proto][$port]; + if (!$sock['process']->isRunning()) { + throw new \RuntimeException( + 'LocalSocket '.$proto.'://127.0.0.1:'.$port.' appears to have died unexpectedly: ' . "\n\n" . + $sock['process']->getOutput() + ); + } + + self::clearSocket($port, $proto); + + return new class($sock['process'], $sock['comms']) { + public function __construct(Process $proc, $comms) + { + $this->process = $proc; + $this->comms = $comms; + } + + public function getOutput() + { + // read out until getting a !DONE! ack and then tell the socket to terminate the connection + if ($this->comms) { + $out = ''; + socket_write($this->comms, "DONE?\n"); + while ($data = socket_read($this->comms, 2048)) { + $out .= $data; + if (substr($out, -6) === '!DONE!') { + $out = substr($out, 0, -6); + break; + } + } + $out = preg_replace('{.*!BEGIN!}', '', $out); + + socket_write($this->comms, "TERMINATE\n"); + + return $out; + } + + // wait 3 seconds max for output for UDP + $retries = 3000; + while (!$this->process->getOutput() && $retries-- && $this->process->getStatus()) { + usleep(100); + } + + return $this->process->getOutput(); + } + }; + } + + private static function clearSocket(int $port = 51984, string $proto = LocalSocket::TCP) + { + if (isset(self::$sockets[$proto][$port])) { + self::$sockets[$proto][$port]['process']->clearOutput(); + } + } + + public static function shutdownSocket(int $port = 51984, string $proto = LocalSocket::TCP) + { + if (!isset(self::$sockets[$proto][$port])) { + return; + } + + if (is_resource(self::$sockets[$proto][$port]['comms'])) { + socket_write(self::$sockets[$proto][$port]['comms'], "EXIT\n"); + socket_close(self::$sockets[$proto][$port]['comms']); + } + $sock = self::$sockets[$proto][$port]; + $sock['process']->stop(); + @unlink($sock['file']); + unset(self::$sockets[$proto][$port]); + } + + public static function shutdownSockets() + { + foreach (self::$sockets as $proto => $ports) { + foreach ($ports as $port => $sock) { + self::shutdownSocket($port, $proto); + } + } + } + + private static function initFile(int $port, string $proto): string + { + $tmpFile = sys_get_temp_dir().'/monolog-test-'.$proto.'-socket-'.$port.'.php'; + + if ($proto === self::UDP) { + file_put_contents($tmpFile, <<<SCRIPT +<?php + +\$sock = socket_create(AF_INET, SOCK_DGRAM, getprotobyname('udp')); +if (!socket_bind(\$sock, '127.0.0.1', $port)) { + fwrite(STDERR, 'COULD NOT BIND $port'); +} +fwrite(STDERR, 'INIT'); +while (true) { + socket_recvfrom(\$sock, \$read, 100*1024, 0, \$ip, \$port); + fwrite(STDOUT, \$read); +} +SCRIPT + ); + } else { + file_put_contents($tmpFile, <<<SCRIPT +<?php + +\$sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); +if (!socket_bind(\$sock, '127.0.0.1', $port)) { + fwrite(STDERR, 'COULD NOT BIND $port'); +} +if (!socket_listen(\$sock)) { + fwrite(STDERR, 'COULD NOT LISTEN $port'); +} +fwrite(STDERR, 'INIT'); + +\$monitor = socket_accept(\$sock); +\$read = socket_read(\$monitor, 1024, PHP_NORMAL_READ); +if (substr(\$read, 0, 7) !== 'MONITOR') { + fwrite(STDERR, "Unexpected input: \$read"); +} else { + fwrite(STDERR, "MONITORED"); +} + +while (true) { + \$res = socket_accept(\$sock); + socket_set_option(\$res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 0)); + socket_write(\$monitor, '!BEGIN!'); + + while (true) { + \$read = [\$res, \$monitor, \$sock]; + \$write = []; + \$except = []; + \$timeout = 0; + + if (socket_select(\$read, \$write, \$except, \$timeout) < 1) { + continue; + } + + foreach (\$read as \$readsock) { + if (\$readsock === \$res) { + \$bytes = socket_read(\$res, 1024); + //if (\$bytes === '' && in_array(\$sock, \$read)) { + // // client closed + // socket_write(\$monitor, 'CLIENTCLOSED'); + // break 2; + //} + socket_write(\$monitor, \$bytes); + } else { + \$bytes = socket_read(\$monitor, 1024, PHP_NORMAL_READ); + if (substr(trim(\$bytes), 0, 9) === 'TERMINATE') { + break 2; + } elseif (substr(trim(\$bytes), 0, 5) === 'DONE?') { + socket_write(\$monitor, '!DONE!'); + } elseif (substr(trim(\$bytes), 0, 5) === 'EXIT') { + socket_close(\$res); + socket_close(\$monitor); + die; + } + } + } + } + + socket_close(\$res); +} +SCRIPT + ); + } + + return $tmpFile; + } +} |