SecureServerTest.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. namespace React\Tests\Socket;
  3. use React\Socket\SecureServer;
  4. use React\Socket\TcpServer;
  5. use React\Promise\Promise;
  6. class SecureServerTest extends TestCase
  7. {
  8. /**
  9. * @before
  10. */
  11. public function setUpSkipTest()
  12. {
  13. if (defined('HHVM_VERSION')) {
  14. $this->markTestSkipped('Not supported on legacy HHVM');
  15. }
  16. }
  17. public function testCtorThrowsForInvalidLoop()
  18. {
  19. $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
  20. $this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
  21. new SecureServer($tcp, 'loop');
  22. }
  23. public function testConstructWithoutLoopAssignsLoopAutomatically()
  24. {
  25. $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
  26. $server = new SecureServer($tcp);
  27. $ref = new \ReflectionProperty($server, 'encryption');
  28. $ref->setAccessible(true);
  29. $encryption = $ref->getValue($server);
  30. $ref = new \ReflectionProperty($encryption, 'loop');
  31. $ref->setAccessible(true);
  32. $loop = $ref->getValue($encryption);
  33. $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop);
  34. }
  35. public function testGetAddressWillBePassedThroughToTcpServer()
  36. {
  37. $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
  38. $tcp->expects($this->once())->method('getAddress')->willReturn('tcp://127.0.0.1:1234');
  39. $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  40. $server = new SecureServer($tcp, $loop, array());
  41. $this->assertEquals('tls://127.0.0.1:1234', $server->getAddress());
  42. }
  43. public function testGetAddressWillReturnNullIfTcpServerReturnsNull()
  44. {
  45. $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
  46. $tcp->expects($this->once())->method('getAddress')->willReturn(null);
  47. $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  48. $server = new SecureServer($tcp, $loop, array());
  49. $this->assertNull($server->getAddress());
  50. }
  51. public function testPauseWillBePassedThroughToTcpServer()
  52. {
  53. $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
  54. $tcp->expects($this->once())->method('pause');
  55. $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  56. $server = new SecureServer($tcp, $loop, array());
  57. $server->pause();
  58. }
  59. public function testResumeWillBePassedThroughToTcpServer()
  60. {
  61. $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
  62. $tcp->expects($this->once())->method('resume');
  63. $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  64. $server = new SecureServer($tcp, $loop, array());
  65. $server->resume();
  66. }
  67. public function testCloseWillBePassedThroughToTcpServer()
  68. {
  69. $tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
  70. $tcp->expects($this->once())->method('close');
  71. $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  72. $server = new SecureServer($tcp, $loop, array());
  73. $server->close();
  74. }
  75. public function testConnectionWillBeClosedWithErrorIfItIsNotAStream()
  76. {
  77. $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  78. $tcp = new TcpServer(0, $loop);
  79. $connection = $this->getMockBuilder('React\Socket\ConnectionInterface')->getMock();
  80. $connection->expects($this->once())->method('close');
  81. $server = new SecureServer($tcp, $loop, array());
  82. $server->on('error', $this->expectCallableOnce());
  83. $tcp->emit('connection', array($connection));
  84. }
  85. public function testConnectionWillTryToEnableEncryptionAndWaitForHandshake()
  86. {
  87. $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  88. $tcp = new TcpServer(0, $loop);
  89. $connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->getMock();
  90. $connection->expects($this->once())->method('getRemoteAddress')->willReturn('tcp://127.0.0.1:1234');
  91. $connection->expects($this->never())->method('close');
  92. $server = new SecureServer($tcp, $loop, array());
  93. $pending = new Promise(function () { });
  94. $encryption = $this->getMockBuilder('React\Socket\StreamEncryption')->disableOriginalConstructor()->getMock();
  95. $encryption->expects($this->once())->method('enable')->willReturn($pending);
  96. $ref = new \ReflectionProperty($server, 'encryption');
  97. $ref->setAccessible(true);
  98. $ref->setValue($server, $encryption);
  99. $ref = new \ReflectionProperty($server, 'context');
  100. $ref->setAccessible(true);
  101. $ref->setValue($server, array());
  102. $server->on('error', $this->expectCallableNever());
  103. $server->on('connection', $this->expectCallableNever());
  104. $tcp->emit('connection', array($connection));
  105. }
  106. public function testConnectionWillBeClosedWithErrorIfEnablingEncryptionFails()
  107. {
  108. $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  109. $tcp = new TcpServer(0, $loop);
  110. $connection = $this->getMockBuilder('React\Socket\Connection')->disableOriginalConstructor()->getMock();
  111. $connection->expects($this->once())->method('getRemoteAddress')->willReturn('tcp://127.0.0.1:1234');
  112. $connection->expects($this->once())->method('close');
  113. $server = new SecureServer($tcp, $loop, array());
  114. $error = new \RuntimeException('Original');
  115. $encryption = $this->getMockBuilder('React\Socket\StreamEncryption')->disableOriginalConstructor()->getMock();
  116. $encryption->expects($this->once())->method('enable')->willReturn(\React\Promise\reject($error));
  117. $ref = new \ReflectionProperty($server, 'encryption');
  118. $ref->setAccessible(true);
  119. $ref->setValue($server, $encryption);
  120. $ref = new \ReflectionProperty($server, 'context');
  121. $ref->setAccessible(true);
  122. $ref->setValue($server, array());
  123. $error = null;
  124. $server->on('error', $this->expectCallableOnce());
  125. $server->on('error', function ($e) use (&$error) {
  126. $error = $e;
  127. });
  128. $tcp->emit('connection', array($connection));
  129. $this->assertInstanceOf('RuntimeException', $error);
  130. $this->assertEquals('Connection from tcp://127.0.0.1:1234 failed during TLS handshake: Original', $error->getMessage());
  131. }
  132. public function testSocketErrorWillBeForwarded()
  133. {
  134. $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
  135. $tcp = new TcpServer(0, $loop);
  136. $server = new SecureServer($tcp, $loop, array());
  137. $server->on('error', $this->expectCallableOnce());
  138. $tcp->emit('error', array(new \RuntimeException('test')));
  139. }
  140. }