SocketHandlerTest.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php declare(strict_types=1);
  2. /*
  3. * This file is part of the Monolog package.
  4. *
  5. * (c) Jordi Boggiano <j.boggiano@seld.be>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Monolog\Handler;
  11. use Monolog\Test\TestCase;
  12. use Monolog\Logger;
  13. /**
  14. * @author Pablo de Leon Belloc <pablolb@gmail.com>
  15. */
  16. class SocketHandlerTest extends TestCase
  17. {
  18. /**
  19. * @var Monolog\Handler\SocketHandler
  20. */
  21. private $handler;
  22. /**
  23. * @var resource
  24. */
  25. private $res;
  26. /**
  27. * @expectedException UnexpectedValueException
  28. */
  29. public function testInvalidHostname()
  30. {
  31. $this->createHandler('garbage://here');
  32. $this->writeRecord('data');
  33. }
  34. /**
  35. * @expectedException \InvalidArgumentException
  36. */
  37. public function testBadConnectionTimeout()
  38. {
  39. $this->createHandler('localhost:1234');
  40. $this->handler->setConnectionTimeout(-1);
  41. }
  42. public function testSetConnectionTimeout()
  43. {
  44. $this->createHandler('localhost:1234');
  45. $this->handler->setConnectionTimeout(10.1);
  46. $this->assertEquals(10.1, $this->handler->getConnectionTimeout());
  47. }
  48. /**
  49. * @expectedException \InvalidArgumentException
  50. */
  51. public function testBadTimeout()
  52. {
  53. $this->createHandler('localhost:1234');
  54. $this->handler->setTimeout(-1);
  55. }
  56. public function testSetTimeout()
  57. {
  58. $this->createHandler('localhost:1234');
  59. $this->handler->setTimeout(10.25);
  60. $this->assertEquals(10.25, $this->handler->getTimeout());
  61. }
  62. public function testSetWritingTimeout()
  63. {
  64. $this->createHandler('localhost:1234');
  65. $this->handler->setWritingTimeout(10.25);
  66. $this->assertEquals(10.25, $this->handler->getWritingTimeout());
  67. }
  68. public function testSetConnectionString()
  69. {
  70. $this->createHandler('tcp://localhost:9090');
  71. $this->assertEquals('tcp://localhost:9090', $this->handler->getConnectionString());
  72. }
  73. /**
  74. * @expectedException UnexpectedValueException
  75. */
  76. public function testExceptionIsThrownOnFsockopenError()
  77. {
  78. $this->createHandler('tcp://127.0.0.1:51985');
  79. $this->writeRecord('Hello world');
  80. }
  81. /**
  82. * @expectedException UnexpectedValueException
  83. */
  84. public function testExceptionIsThrownOnPfsockopenError()
  85. {
  86. $this->createHandler('tcp://127.0.0.1:51985');
  87. $this->handler->setPersistent(true);
  88. $this->writeRecord('Hello world');
  89. }
  90. /**
  91. * @expectedException RuntimeException
  92. */
  93. public function testWriteFailsOnIfFwriteReturnsFalse()
  94. {
  95. $this->initHandlerAndSocket();
  96. $this->writeRecord('Hello world');
  97. $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'resource');
  98. $reflectionProperty->setAccessible(true);
  99. fclose($reflectionProperty->getValue($this->handler));
  100. $this->writeRecord('Hello world');
  101. }
  102. /**
  103. * @expectedException RuntimeException
  104. */
  105. public function testWriteFailsOnIncompleteWrite()
  106. {
  107. $this->initHandlerAndSocket();
  108. $this->handler->setWritingTimeout(1);
  109. // the socket will close itself after processing 10000 bytes so while processing b, and then c write fails
  110. $this->writeRecord(str_repeat("aaaaaaaaaa\n", 700));
  111. $this->assertTrue(true); // asserting to make sure we reach this point
  112. $this->writeRecord(str_repeat("bbbbbbbbbb\n", 700));
  113. $this->assertTrue(true); // asserting to make sure we reach this point
  114. $this->writeRecord(str_repeat("cccccccccc\n", 700));
  115. $this->fail('The test should not reach here');
  116. }
  117. public function testWriteWithMemoryFile()
  118. {
  119. $this->initHandlerAndSocket();
  120. $this->writeRecord('test1');
  121. $this->writeRecord('test2');
  122. $this->writeRecord('test3');
  123. $this->closeSocket();
  124. $this->assertEquals('test1test2test3', $this->socket->getOutput());
  125. }
  126. public function testClose()
  127. {
  128. $this->initHandlerAndSocket();
  129. $this->writeRecord('Hello world');
  130. $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'resource');
  131. $reflectionProperty->setAccessible(true);
  132. $this->assertInternalType('resource', $reflectionProperty->getValue($this->handler));
  133. $this->handler->close();
  134. $this->assertFalse(is_resource($reflectionProperty->getValue($this->handler)), "Expected resource to be closed after closing handler");
  135. }
  136. public function testCloseDoesNotClosePersistentSocket()
  137. {
  138. $this->initHandlerAndSocket();
  139. $this->handler->setPersistent(true);
  140. $this->writeRecord('Hello world');
  141. $reflectionProperty = new \ReflectionProperty('\Monolog\Handler\SocketHandler', 'resource');
  142. $reflectionProperty->setAccessible(true);
  143. $this->assertTrue(is_resource($reflectionProperty->getValue($this->handler)));
  144. $this->handler->close();
  145. $this->assertTrue(is_resource($reflectionProperty->getValue($this->handler)));
  146. }
  147. private function createHandler($connectionString)
  148. {
  149. $this->handler = new SocketHandler($connectionString);
  150. $this->handler->setFormatter($this->getIdentityFormatter());
  151. }
  152. private function writeRecord($string)
  153. {
  154. $this->handler->handle($this->getRecord(Logger::WARNING, $string));
  155. }
  156. private function initHandlerAndSocket()
  157. {
  158. $tmpFile = sys_get_temp_dir().'/monolog-test-socket.php';
  159. file_put_contents($tmpFile, <<<'SCRIPT'
  160. <?php
  161. $sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
  162. socket_bind($sock, '127.0.0.1', 51984);
  163. socket_listen($sock);
  164. $res = socket_accept($sock);
  165. socket_set_option($res, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 0, "usec" => 500));
  166. $bytesRead = 0;
  167. while ($read = socket_read($res, 1024)) {
  168. echo $read;
  169. $bytesRead += strlen($read);
  170. if ($bytesRead > 10000) {
  171. socket_close($res);
  172. socket_close($sock);
  173. die('CLOSED');
  174. }
  175. }
  176. echo 'EXIT';
  177. socket_close($res);
  178. SCRIPT
  179. );
  180. $this->socket = new \Symfony\Component\Process\Process(escapeshellarg(PHP_BINARY).' '.escapeshellarg($tmpFile));
  181. $this->socket->start();
  182. $this->handler = new SocketHandler('tcp://127.0.0.1:51984');
  183. $this->handler->setFormatter($this->getIdentityFormatter());
  184. }
  185. private function closeSocket()
  186. {
  187. $this->socket->stop();
  188. }
  189. public function tearDown()
  190. {
  191. if (isset($this->socket)) {
  192. $this->closeSocket();
  193. unset($this->socket);
  194. }
  195. }
  196. }