* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) * @link https://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network * @since CakePHP(tm) v 1.2.0.4206 * @license https://opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeSocket', 'Network'); /** * SocketTest class * * @package Cake.Test.Case.Network */ class CakeSocketTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() : void { parent::setUp(); $this->Socket = new CakeSocket(array('timeout' => 1)); } /** * tearDown method * * @return void */ public function tearDown() : void { parent::tearDown(); unset($this->Socket); } /** * testConstruct method * * @return void */ public function testConstruct() { $this->Socket = new CakeSocket(); $config = $this->Socket->config; $this->assertSame($config, array( 'persistent' => false, 'host' => 'localhost', 'protocol' => 'tcp', 'port' => 80, 'timeout' => 30, 'cryptoType' => 'tls', )); $this->Socket->reset(); $this->Socket->__construct(array('host' => 'foo-bar')); $config['host'] = 'foo-bar'; $this->assertSame($this->Socket->config, $config); $this->Socket = new CakeSocket(array('host' => 'www.cakephp.org', 'port' => 23, 'protocol' => 'udp')); $config = $this->Socket->config; $config['host'] = 'www.cakephp.org'; $config['port'] = 23; $config['protocol'] = 'udp'; $this->assertSame($this->Socket->config, $config); } /** * testSocketConnection method * * @return void */ public function testSocketConnection() { $this->assertFalse($this->Socket->connected); $this->Socket->disconnect(); $this->assertFalse($this->Socket->connected); try { $this->Socket->connect(); $this->assertTrue($this->Socket->connected); $this->Socket->connect(); $this->assertTrue($this->Socket->connected); $this->Socket->disconnect(); $config = array('persistent' => true); $this->Socket = new CakeSocket($config); $this->Socket->connect(); $this->assertTrue($this->Socket->connected); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * data provider function for testInvalidConnection * * @return array */ public static function invalidConnections() { return array( array(array('host' => 'invalid.host', 'port' => 9999, 'timeout' => 1)), array(array('host' => '127.0.0.1', 'port' => '70000', 'timeout' => 1)) ); } /** * testInvalidConnection method * * @dataProvider invalidConnections * @return void */ public function testInvalidConnection($data) { $this->expectException(SocketException::class); $this->Socket->config = array_merge($this->Socket->config, $data); $this->Socket->connect(); } /** * testSocketHost method * * @return void */ public function testSocketHost() { try { $this->Socket = new CakeSocket(); $this->Socket->connect(); $this->assertEquals('127.0.0.1', $this->Socket->address()); $this->assertEquals(gethostbyaddr('127.0.0.1'), $this->Socket->host()); $this->assertEquals(null, $this->Socket->lastError()); $this->assertTrue(in_array('127.0.0.1', $this->Socket->addresses())); $this->Socket = new CakeSocket(array('host' => '127.0.0.1')); $this->Socket->connect(); $this->assertEquals('127.0.0.1', $this->Socket->address()); $this->assertEquals(gethostbyaddr('127.0.0.1'), $this->Socket->host()); $this->assertEquals(null, $this->Socket->lastError()); $this->assertTrue(in_array('127.0.0.1', $this->Socket->addresses())); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testSocketWriting method * * @return void */ public function testSocketWriting() { try { $request = "GET / HTTP/1.1\r\nConnection: close\r\n\r\n"; $this->assertTrue((bool)$this->Socket->write($request)); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testSocketReading method * * @return void */ public function testSocketReading() { $this->Socket = new CakeSocket(array('timeout' => 5)); try { $this->Socket->connect(); $this->assertEquals(null, $this->Socket->read(26)); $config = array('host' => 'google.com', 'port' => 80, 'timeout' => 1); $this->Socket = new CakeSocket($config); $this->assertTrue($this->Socket->connect()); $this->assertEquals(null, $this->Socket->read(26)); $this->assertEquals('2: ' . __d('cake_dev', 'Connection timed out'), $this->Socket->lastError()); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testTimeOutConnection method * * @return void */ public function testTimeOutConnection() { $config = array('host' => '127.0.0.1', 'timeout' => 0.5); $this->Socket = new CakeSocket($config); try { $this->assertTrue($this->Socket->connect()); $config = array('host' => '127.0.0.1', 'timeout' => 0.00001); $this->Socket = new CakeSocket($config); $this->assertFalse($this->Socket->read(1024 * 1024)); $this->assertEquals('2: ' . __d('cake_dev', 'Connection timed out'), $this->Socket->lastError()); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testLastError method * * @return void */ public function testLastError() { $this->Socket = new CakeSocket(); $this->Socket->setLastError(4, 'some error here'); $this->assertEquals('4: some error here', $this->Socket->lastError()); } /** * testReset method * * @return void */ public function testReset() { $config = array( 'persistent' => true, 'host' => '127.0.0.1', 'protocol' => 'udp', 'port' => 80, 'timeout' => 20 ); $anotherSocket = new CakeSocket($config); $anotherSocket->reset(); $this->assertEquals(array(), $anotherSocket->config); } /** * testEncrypt * * @return void */ public function testEnableCryptoSocketExceptionNoSsl() { $this->expectException(SocketException::class); $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $configNoSslOrTls = array('host' => 'localhost', 'port' => 80, 'timeout' => 0.1); // testing exception on no ssl socket server for ssl and tls methods $this->Socket = new CakeSocket($configNoSslOrTls); $this->Socket->connect(); $this->Socket->enableCrypto('sslv3', 'client'); } /** * testEnableCryptoSocketExceptionNoTls * * @return void */ public function testEnableCryptoSocketExceptionNoTls() { $this->expectException(SocketException::class); $configNoSslOrTls = array('host' => 'localhost', 'port' => 80, 'timeout' => 0.1); // testing exception on no ssl socket server for ssl and tls methods $this->Socket = new CakeSocket($configNoSslOrTls); $this->Socket->connect(); $this->Socket->enableCrypto('tls', 'client'); } /** * Test that protocol in the host doesn't cause cert errors. * * @return void */ public function testConnectProtocolInHost() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $configSslTls = array('host' => 'ssl://smtp.gmail.com', 'port' => 465, 'timeout' => 5); $socket = new CakeSocket($configSslTls); try { $socket->connect(); $this->assertEquals('smtp.gmail.com', $socket->config['host']); $this->assertEquals('ssl', $socket->config['protocol']); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * _connectSocketToSslTls * * @return void */ protected function _connectSocketToSslTls() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $configSslTls = array('host' => 'smtp.gmail.com', 'port' => 465, 'timeout' => 5); $this->Socket = new CakeSocket($configSslTls); try { $this->Socket->connect(); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testEnableCryptoBadMode * * @return void */ public function testEnableCryptoBadMode() { $this->expectException(InvalidArgumentException::class); // testing wrong encryption mode $this->_connectSocketToSslTls(); $this->Socket->enableCrypto('doesntExistMode', 'server'); $this->Socket->disconnect(); } /** * testEnableCrypto * * @return void */ public function testEnableCrypto() { // testing on tls server $this->_connectSocketToSslTls(); $this->assertTrue($this->Socket->enableCrypto('tls', 'client')); $this->Socket->disconnect(); } /** * testEnableCrypto tlsv1_1 * * @return void */ public function testEnableCryptoTlsV12() { $this->skipIf(!defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT'), 'TLS1.2 is not supported on this system'); // testing on tls server $this->_connectSocketToSslTls(); $this->assertTrue($this->Socket->enableCrypto('tlsv1_2', 'client')); $this->Socket->disconnect(); } /** * testEnableCryptoExceptionEnableTwice * * @return void */ public function testEnableCryptoExceptionEnableTwice() { $this->expectException(SocketException::class); // testing on tls server $this->_connectSocketToSslTls(); $this->Socket->enableCrypto('tls', 'client'); $this->Socket->enableCrypto('tls', 'client'); } /** * testEnableCryptoExceptionDisableTwice * * @return void */ public function testEnableCryptoExceptionDisableTwice() { $this->expectException(SocketException::class); // testing on tls server $this->_connectSocketToSslTls(); $this->Socket->enableCrypto('tls', 'client', false); } /** * testEnableCryptoEnableStatus * * @return void */ public function testEnableCryptoEnableStatus() { // testing on tls server $this->_connectSocketToSslTls(); $this->assertFalse($this->Socket->encrypted); $this->Socket->enableCrypto('tls', 'client', true); $this->assertTrue($this->Socket->encrypted); } /** * test getting the context for a socket. * * @return void */ public function testGetContext() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $config = array( 'host' => 'smtp.gmail.com', 'port' => 465, 'timeout' => 5, 'context' => array( 'ssl' => array('capture_peer' => true) ) ); $this->Socket = new CakeSocket($config); $this->Socket->connect(); $result = $this->Socket->context(); $this->assertSame($config['context']['ssl']['capture_peer'], $result['ssl']['capture_peer']); } /** * test configuring the context from the flat keys. * * @return void */ public function testConfigContext() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $config = array( 'host' => 'smtp.gmail.com', 'port' => 465, 'timeout' => 5, 'ssl_verify_peer' => true, 'ssl_allow_self_signed' => false, 'ssl_verify_depth' => 5, 'ssl_verify_host' => true, ); $this->Socket = new CakeSocket($config); $this->Socket->connect(); $result = $this->Socket->context(); $this->assertTrue($result['ssl']['verify_peer']); $this->assertFalse($result['ssl']['allow_self_signed']); $this->assertEquals(5, $result['ssl']['verify_depth']); $this->assertEquals('smtp.gmail.com', $result['ssl']['CN_match']); $this->assertArrayNotHasKey('ssl_verify_peer', $this->Socket->config); $this->assertArrayNotHasKey('ssl_allow_self_signed', $this->Socket->config); $this->assertArrayNotHasKey('ssl_verify_host', $this->Socket->config); $this->assertArrayNotHasKey('ssl_verify_depth', $this->Socket->config); } }