From 0ff39c83d38ce538a9f5dba53eca0fa9cb16d9e6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 14:45:49 +0200 Subject: Adding upstream version 0.10.2+dfsg1. Signed-off-by: Daniel Baumann --- vendor/textalk/websocket/tests/ClientTest.php | 449 ++++++ vendor/textalk/websocket/tests/ExceptionTest.php | 52 + vendor/textalk/websocket/tests/MessageTest.php | 61 + vendor/textalk/websocket/tests/README.md | 29 + vendor/textalk/websocket/tests/ServerTest.php | 448 ++++++ vendor/textalk/websocket/tests/bootstrap.php | 6 + vendor/textalk/websocket/tests/mock/EchoLog.php | 34 + vendor/textalk/websocket/tests/mock/MockSocket.php | 79 + .../textalk/websocket/tests/mock/mock-socket.php | 78 + .../textalk/websocket/tests/mock/payload.128.txt | 5 + .../textalk/websocket/tests/mock/payload.65536.txt | 1682 ++++++++++++++++++++ .../websocket/tests/scripts/client.close.json | 76 + .../tests/scripts/client.connect-authed.json | 59 + .../tests/scripts/client.connect-bad-context.json | 7 + .../tests/scripts/client.connect-context.json | 59 + .../tests/scripts/client.connect-error.json | 23 + .../tests/scripts/client.connect-extended.json | 59 + .../tests/scripts/client.connect-failed.json | 19 + .../tests/scripts/client.connect-headers.json | 59 + .../tests/scripts/client.connect-invalid-key.json | 50 + .../scripts/client.connect-invalid-upgrade.json | 50 + .../tests/scripts/client.connect-persistent.json | 95 ++ .../tests/scripts/client.connect-timeout.json | 59 + .../websocket/tests/scripts/client.connect.json | 59 + .../websocket/tests/scripts/client.destruct.json | 23 + .../websocket/tests/scripts/client.reconnect.json | 100 ++ .../websocket/tests/scripts/close-remote.json | 55 + .../websocket/tests/scripts/config-timeout.json | 24 + .../textalk/websocket/tests/scripts/ping-pong.json | 150 ++ .../tests/scripts/receive-bad-opcode.json | 18 + .../tests/scripts/receive-broken-read.json | 58 + .../tests/scripts/receive-client-timeout.json | 50 + .../tests/scripts/receive-empty-read.json | 58 + .../tests/scripts/receive-fragmentation.json | 126 ++ .../websocket/tests/scripts/send-bad-opcode.json | 9 + .../websocket/tests/scripts/send-broken-write.json | 43 + .../websocket/tests/scripts/send-convenicance.json | 86 + .../websocket/tests/scripts/send-failed-write.json | 43 + .../websocket/tests/scripts/send-receive-128.json | 50 + .../tests/scripts/send-receive-65536.json | 113 ++ .../tests/scripts/send-receive-multi-fragment.json | 112 ++ .../websocket/tests/scripts/send-receive.json | 50 + .../tests/scripts/server.accept-destruct.json | 315 ++++ .../tests/scripts/server.accept-error-connect.json | 18 + .../scripts/server.accept-failed-connect.json | 14 + .../tests/scripts/server.accept-failed-http.json | 265 +++ .../tests/scripts/server.accept-failed-ws-key.json | 265 +++ .../tests/scripts/server.accept-timeout.json | 289 ++++ .../websocket/tests/scripts/server.accept.json | 287 ++++ .../websocket/tests/scripts/server.close.json | 70 + .../server.construct-error-socket-server.json | 28 + .../server.construct-failed-socket-server.json | 20 + .../websocket/tests/scripts/server.construct.json | 11 + 53 files changed, 6347 insertions(+) create mode 100644 vendor/textalk/websocket/tests/ClientTest.php create mode 100644 vendor/textalk/websocket/tests/ExceptionTest.php create mode 100644 vendor/textalk/websocket/tests/MessageTest.php create mode 100644 vendor/textalk/websocket/tests/README.md create mode 100644 vendor/textalk/websocket/tests/ServerTest.php create mode 100644 vendor/textalk/websocket/tests/bootstrap.php create mode 100644 vendor/textalk/websocket/tests/mock/EchoLog.php create mode 100644 vendor/textalk/websocket/tests/mock/MockSocket.php create mode 100644 vendor/textalk/websocket/tests/mock/mock-socket.php create mode 100644 vendor/textalk/websocket/tests/mock/payload.128.txt create mode 100644 vendor/textalk/websocket/tests/mock/payload.65536.txt create mode 100644 vendor/textalk/websocket/tests/scripts/client.close.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-authed.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-bad-context.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-context.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-error.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-extended.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-failed.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-headers.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-invalid-key.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-invalid-upgrade.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-persistent.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect-timeout.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.connect.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.destruct.json create mode 100644 vendor/textalk/websocket/tests/scripts/client.reconnect.json create mode 100644 vendor/textalk/websocket/tests/scripts/close-remote.json create mode 100644 vendor/textalk/websocket/tests/scripts/config-timeout.json create mode 100644 vendor/textalk/websocket/tests/scripts/ping-pong.json create mode 100644 vendor/textalk/websocket/tests/scripts/receive-bad-opcode.json create mode 100644 vendor/textalk/websocket/tests/scripts/receive-broken-read.json create mode 100644 vendor/textalk/websocket/tests/scripts/receive-client-timeout.json create mode 100644 vendor/textalk/websocket/tests/scripts/receive-empty-read.json create mode 100644 vendor/textalk/websocket/tests/scripts/receive-fragmentation.json create mode 100644 vendor/textalk/websocket/tests/scripts/send-bad-opcode.json create mode 100644 vendor/textalk/websocket/tests/scripts/send-broken-write.json create mode 100644 vendor/textalk/websocket/tests/scripts/send-convenicance.json create mode 100644 vendor/textalk/websocket/tests/scripts/send-failed-write.json create mode 100644 vendor/textalk/websocket/tests/scripts/send-receive-128.json create mode 100644 vendor/textalk/websocket/tests/scripts/send-receive-65536.json create mode 100644 vendor/textalk/websocket/tests/scripts/send-receive-multi-fragment.json create mode 100644 vendor/textalk/websocket/tests/scripts/send-receive.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.accept-destruct.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.accept-error-connect.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.accept-failed-connect.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.accept-failed-http.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.accept-failed-ws-key.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.accept-timeout.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.accept.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.close.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.construct-error-socket-server.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.construct-failed-socket-server.json create mode 100644 vendor/textalk/websocket/tests/scripts/server.construct.json (limited to 'vendor/textalk/websocket/tests') diff --git a/vendor/textalk/websocket/tests/ClientTest.php b/vendor/textalk/websocket/tests/ClientTest.php new file mode 100644 index 0000000..c7bdc16 --- /dev/null +++ b/vendor/textalk/websocket/tests/ClientTest.php @@ -0,0 +1,449 @@ +send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + $this->assertEquals(4096, $client->getFragmentSize()); + + MockSocket::initialize('send-receive', $this); + $client->send('Sending a message'); + $message = $client->receive(); + $this->assertTrue(MockSocket::isEmpty()); + $this->assertEquals('text', $client->getLastOpcode()); + + MockSocket::initialize('client.close', $this); + $this->assertTrue($client->isConnected()); + $this->assertNull($client->getCloseStatus()); + + $client->close(); + $this->assertFalse($client->isConnected()); + $this->assertEquals(1000, $client->getCloseStatus()); + + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testDestruct(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('client.destruct', $this); + } + + public function testClienExtendedUrl(): void + { + MockSocket::initialize('client.connect-extended', $this); + $client = new Client('ws://localhost:8000/my/mock/path?my_query=yes#my_fragment'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testClientWithTimeout(): void + { + MockSocket::initialize('client.connect-timeout', $this); + $client = new Client('ws://localhost:8000/my/mock/path', ['timeout' => 300]); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testClientWithContext(): void + { + MockSocket::initialize('client.connect-context', $this); + $client = new Client('ws://localhost:8000/my/mock/path', ['context' => '@mock-stream-context']); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testClientAuthed(): void + { + MockSocket::initialize('client.connect-authed', $this); + $client = new Client('wss://usename:password@localhost:8000/my/mock/path'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testWithHeaders(): void + { + MockSocket::initialize('client.connect-headers', $this); + $client = new Client('ws://localhost:8000/my/mock/path', [ + 'origin' => 'Origin header', + 'headers' => ['Generic header' => 'Generic content'], + ]); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testPayload128(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + + $payload = file_get_contents(__DIR__ . '/mock/payload.128.txt'); + + MockSocket::initialize('send-receive-128', $this); + $client->send($payload, 'text', false); + $message = $client->receive(); + $this->assertEquals($payload, $message); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testPayload65536(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + + $payload = file_get_contents(__DIR__ . '/mock/payload.65536.txt'); + $client->setFragmentSize(65540); + + MockSocket::initialize('send-receive-65536', $this); + $client->send($payload, 'text', false); + $message = $client->receive(); + $this->assertEquals($payload, $message); + $this->assertTrue(MockSocket::isEmpty()); + $this->assertEquals(65540, $client->getFragmentSize()); + } + + public function testMultiFragment(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('send-receive-multi-fragment', $this); + $client->setFragmentSize(8); + $client->send('Multi fragment test'); + $message = $client->receive(); + $this->assertEquals('Multi fragment test', $message); + $this->assertTrue(MockSocket::isEmpty()); + $this->assertEquals(8, $client->getFragmentSize()); + } + + public function testPingPong(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('ping-pong', $this); + $client->send('Server ping', 'ping'); + $client->send('', 'ping'); + $message = $client->receive(); + $this->assertEquals('Receiving a message', $message); + $this->assertEquals('text', $client->getLastOpcode()); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testRemoteClose(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('close-remote', $this); + + $message = $client->receive(); + $this->assertNull($message); + + $this->assertFalse($client->isConnected()); + $this->assertEquals(17260, $client->getCloseStatus()); + $this->assertNull($client->getLastOpcode()); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testSetTimeout(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('config-timeout', $this); + $client->setTimeout(300); + $this->assertTrue($client->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testReconnect(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('client.close', $this); + $this->assertTrue($client->isConnected()); + $this->assertNull($client->getCloseStatus()); + $client->close(); + $this->assertFalse($client->isConnected()); + $this->assertEquals(1000, $client->getCloseStatus()); + $this->assertNull($client->getLastOpcode()); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('client.reconnect', $this); + $message = $client->receive(); + $this->assertTrue($client->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testPersistentConnection(): void + { + MockSocket::initialize('client.connect-persistent', $this); + $client = new Client('ws://localhost:8000/my/mock/path', ['persistent' => true]); + $client->send('Connect'); + $client->disconnect(); + $this->assertFalse($client->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testBadScheme(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('bad://localhost:8000/my/mock/path'); + $this->expectException('WebSocket\BadUriException'); + $this->expectExceptionMessage('Url should have scheme ws or wss'); + $client->send('Connect'); + } + + public function testBadUrl(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('this is not an url'); + $this->expectException('WebSocket\BadUriException'); + $this->expectExceptionMessage('Invalid url \'this is not an url\' provided.'); + $client->send('Connect'); + } + + public function testBadStreamContext(): void + { + MockSocket::initialize('client.connect-bad-context', $this); + $client = new Client('ws://localhost:8000/my/mock/path', ['context' => 'BAD']); + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Stream context in $options[\'context\'] isn\'t a valid context'); + $client->send('Connect'); + } + + public function testFailedConnection(): void + { + MockSocket::initialize('client.connect-failed', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Could not open socket to "localhost:8000"'); + $client->send('Connect'); + } + + public function testFailedConnectionWithError(): void + { + MockSocket::initialize('client.connect-error', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Could not open socket to "localhost:8000"'); + $client->send('Connect'); + } + + public function testInvalidUpgrade(): void + { + MockSocket::initialize('client.connect-invalid-upgrade', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Connection to \'ws://localhost/my/mock/path\' failed'); + $client->send('Connect'); + } + + public function testInvalidKey(): void + { + MockSocket::initialize('client.connect-invalid-key', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Server sent bad upgrade response'); + $client->send('Connect'); + } + + public function testSendBadOpcode(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + + MockSocket::initialize('send-bad-opcode', $this); + $this->expectException('WebSocket\BadOpcodeException'); + $this->expectExceptionMessage('Bad opcode \'bad\'. Try \'text\' or \'binary\'.'); + $client->send('Bad Opcode', 'bad'); + } + + public function testRecieveBadOpcode(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + MockSocket::initialize('receive-bad-opcode', $this); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(1026); + $this->expectExceptionMessage('Bad opcode in websocket frame: 12'); + $message = $client->receive(); + } + + public function testBrokenWrite(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + MockSocket::initialize('send-broken-write', $this); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(1025); + $this->expectExceptionMessage('Could only write 18 out of 22 bytes.'); + $client->send('Failing to write'); + } + + public function testFailedWrite(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + MockSocket::initialize('send-failed-write', $this); + $this->expectException('WebSocket\TimeoutException'); + $this->expectExceptionCode(1024); + $this->expectExceptionMessage('Failed to write 22 bytes.'); + $client->send('Failing to write'); + } + + public function testBrokenRead(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + MockSocket::initialize('receive-broken-read', $this); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(1025); + $this->expectExceptionMessage('Broken frame, read 0 of stated 2 bytes.'); + $client->receive(); + } + + public function testReadTimeout(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + MockSocket::initialize('receive-client-timeout', $this); + $this->expectException('WebSocket\TimeoutException'); + $this->expectExceptionCode(1024); + $this->expectExceptionMessage('Client read timeout'); + $client->receive(); + } + + public function testEmptyRead(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $client->send('Connect'); + MockSocket::initialize('receive-empty-read', $this); + $this->expectException('WebSocket\TimeoutException'); + $this->expectExceptionCode(1024); + $this->expectExceptionMessage('Empty read; connection dead?'); + $client->receive(); + } + + public function testFrameFragmentation(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client( + 'ws://localhost:8000/my/mock/path', + ['filter' => ['text', 'binary', 'pong', 'close']] + ); + $client->send('Connect'); + MockSocket::initialize('receive-fragmentation', $this); + $message = $client->receive(); + $this->assertEquals('Server ping', $message); + $this->assertEquals('pong', $client->getLastOpcode()); + $message = $client->receive(); + $this->assertEquals('Multi fragment test', $message); + $this->assertEquals('text', $client->getLastOpcode()); + $this->assertTrue(MockSocket::isEmpty()); + MockSocket::initialize('close-remote', $this); + $message = $client->receive(); + $this->assertEquals('Closing', $message); + $this->assertTrue(MockSocket::isEmpty()); + $this->assertFalse($client->isConnected()); + $this->assertEquals(17260, $client->getCloseStatus()); + $this->assertEquals('close', $client->getLastOpcode()); + } + + public function testMessageFragmentation(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client( + 'ws://localhost:8000/my/mock/path', + ['filter' => ['text', 'binary', 'pong', 'close'], 'return_obj' => true] + ); + $client->send('Connect'); + MockSocket::initialize('receive-fragmentation', $this); + $message = $client->receive(); + $this->assertInstanceOf('WebSocket\Message\Message', $message); + $this->assertInstanceOf('WebSocket\Message\Pong', $message); + $this->assertEquals('Server ping', $message->getContent()); + $this->assertEquals('pong', $message->getOpcode()); + $message = $client->receive(); + $this->assertInstanceOf('WebSocket\Message\Message', $message); + $this->assertInstanceOf('WebSocket\Message\Text', $message); + $this->assertEquals('Multi fragment test', $message->getContent()); + $this->assertEquals('text', $message->getOpcode()); + $this->assertTrue(MockSocket::isEmpty()); + MockSocket::initialize('close-remote', $this); + $message = $client->receive(); + $this->assertInstanceOf('WebSocket\Message\Message', $message); + $this->assertInstanceOf('WebSocket\Message\Close', $message); + $this->assertEquals('Closing', $message->getContent()); + $this->assertEquals('close', $message->getOpcode()); + } + + public function testConvenicanceMethods(): void + { + MockSocket::initialize('client.connect', $this); + $client = new Client('ws://localhost:8000/my/mock/path'); + $this->assertNull($client->getName()); + $this->assertNull($client->getPier()); + $this->assertEquals('WebSocket\Client(closed)', "{$client}"); + $client->text('Connect'); + MockSocket::initialize('send-convenicance', $this); + $client->binary(base64_encode('Binary content')); + $client->ping(); + $client->pong(); + $this->assertEquals('127.0.0.1:12345', $client->getName()); + $this->assertEquals('127.0.0.1:8000', $client->getPier()); + $this->assertEquals('WebSocket\Client(127.0.0.1:12345)', "{$client}"); + } +} diff --git a/vendor/textalk/websocket/tests/ExceptionTest.php b/vendor/textalk/websocket/tests/ExceptionTest.php new file mode 100644 index 0000000..84b939c --- /dev/null +++ b/vendor/textalk/websocket/tests/ExceptionTest.php @@ -0,0 +1,52 @@ + 'with data'], + new TimeoutException( + 'Nested exception', + ConnectionException::TIMED_OUT + ) + ); + } catch (Throwable $e) { + } + + $this->assertInstanceOf('WebSocket\ConnectionException', $e); + $this->assertInstanceOf('WebSocket\Exception', $e); + $this->assertInstanceOf('Exception', $e); + $this->assertInstanceOf('Throwable', $e); + $this->assertEquals('An error message', $e->getMessage()); + $this->assertEquals(1025, $e->getCode()); + $this->assertEquals(['test' => 'with data'], $e->getData()); + + $p = $e->getPrevious(); + $this->assertInstanceOf('WebSocket\TimeoutException', $p); + $this->assertInstanceOf('WebSocket\ConnectionException', $p); + $this->assertEquals('Nested exception', $p->getMessage()); + $this->assertEquals(1024, $p->getCode()); + $this->assertEquals([], $p->getData()); + } +} diff --git a/vendor/textalk/websocket/tests/MessageTest.php b/vendor/textalk/websocket/tests/MessageTest.php new file mode 100644 index 0000000..2d06ab7 --- /dev/null +++ b/vendor/textalk/websocket/tests/MessageTest.php @@ -0,0 +1,61 @@ +create('text', 'Some content'); + $this->assertInstanceOf('WebSocket\Message\Text', $message); + $message = $factory->create('binary', 'Some content'); + $this->assertInstanceOf('WebSocket\Message\Binary', $message); + $message = $factory->create('ping', 'Some content'); + $this->assertInstanceOf('WebSocket\Message\Ping', $message); + $message = $factory->create('pong', 'Some content'); + $this->assertInstanceOf('WebSocket\Message\Pong', $message); + $message = $factory->create('close', 'Some content'); + $this->assertInstanceOf('WebSocket\Message\Close', $message); + } + + public function testMessage() + { + $message = new Text('Some content'); + $this->assertInstanceOf('WebSocket\Message\Message', $message); + $this->assertInstanceOf('WebSocket\Message\Text', $message); + $this->assertEquals('Some content', $message->getContent()); + $this->assertEquals('text', $message->getOpcode()); + $this->assertEquals(12, $message->getLength()); + $this->assertTrue($message->hasContent()); + $this->assertInstanceOf('DateTime', $message->getTimestamp()); + $message->setContent(''); + $this->assertEquals(0, $message->getLength()); + $this->assertFalse($message->hasContent()); + $this->assertEquals('WebSocket\Message\Text', "{$message}"); + } + + public function testBadOpcode() + { + $factory = new Factory(); + $this->expectException('WebSocket\BadOpcodeException'); + $this->expectExceptionMessage("Invalid opcode 'invalid' provided"); + $message = $factory->create('invalid', 'Some content'); + } +} diff --git a/vendor/textalk/websocket/tests/README.md b/vendor/textalk/websocket/tests/README.md new file mode 100644 index 0000000..b710a7e --- /dev/null +++ b/vendor/textalk/websocket/tests/README.md @@ -0,0 +1,29 @@ +# Testing + +Unit tests with [PHPUnit](https://phpunit.readthedocs.io/). + + +## How to run + +To run all test, run in console. + +``` +make test +``` + + +## Continuous integration + +GitHub Actions are run on PHP versions +`7.2`, `7.3`, `7.4` and `8.0`. + +Code coverage by [Coveralls](https://coveralls.io/github/Textalk/websocket-php). + + +## Test strategy + +Test set up overloads various stream and socket functions, +and use "scripts" to define and mock input/output of these functions. + +This set up negates the dependency on running servers, +and allow testing various errors that might occur. diff --git a/vendor/textalk/websocket/tests/ServerTest.php b/vendor/textalk/websocket/tests/ServerTest.php new file mode 100644 index 0000000..8294236 --- /dev/null +++ b/vendor/textalk/websocket/tests/ServerTest.php @@ -0,0 +1,448 @@ +assertTrue(MockSocket::isEmpty()); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + $this->assertEquals(8000, $server->getPort()); + $this->assertEquals('/my/mock/path', $server->getPath()); + $this->assertTrue($server->isConnected()); + $this->assertEquals(4096, $server->getFragmentSize()); + $this->assertNull($server->getCloseStatus()); + $this->assertEquals([ + 'GET /my/mock/path HTTP/1.1', + 'host: localhost:8000', + 'user-agent: websocket-client-php', + 'connection: Upgrade', + 'upgrade: websocket', + 'sec-websocket-key: cktLWXhUdDQ2OXF0ZCFqOQ==', + 'sec-websocket-version: 13', + '', + '', + ], $server->getRequest()); + $this->assertEquals('websocket-client-php', $server->getHeader('USER-AGENT')); + $this->assertNull($server->getHeader('no such header')); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('send-receive', $this); + $server->send('Sending a message'); + $message = $server->receive(); + $this->assertEquals('Receiving a message', $message); + $this->assertTrue(MockSocket::isEmpty()); + $this->assertNull($server->getCloseStatus()); + $this->assertEquals('text', $server->getLastOpcode()); + + MockSocket::initialize('server.close', $this); + $server->close(); + $this->assertFalse($server->isConnected()); + $this->assertEquals(1000, $server->getCloseStatus()); + $this->assertTrue(MockSocket::isEmpty()); + + $server->close(); // Already closed + } + + public function testDestruct(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + + MockSocket::initialize('server.accept-destruct', $this); + $server->accept(); + $message = $server->receive(); + } + + public function testServerWithTimeout(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(['timeout' => 300]); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('server.accept-timeout', $this); + $server->accept(); + $server->send('Connect'); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testPayload128(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + $this->assertTrue($server->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + + $payload = file_get_contents(__DIR__ . '/mock/payload.128.txt'); + + MockSocket::initialize('send-receive-128', $this); + $server->send($payload, 'text', false); + $message = $server->receive(); + $this->assertEquals($payload, $message); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testPayload65536(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + $this->assertTrue($server->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + + $payload = file_get_contents(__DIR__ . '/mock/payload.65536.txt'); + $server->setFragmentSize(65540); + + MockSocket::initialize('send-receive-65536', $this); + $server->send($payload, 'text', false); + $message = $server->receive(); + $this->assertEquals($payload, $message); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testMultiFragment(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + $this->assertTrue($server->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('send-receive-multi-fragment', $this); + $server->setFragmentSize(8); + $server->send('Multi fragment test'); + $message = $server->receive(); + $this->assertEquals('Multi fragment test', $message); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testPingPong(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + $this->assertTrue($server->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('ping-pong', $this); + $server->send('Server ping', 'ping'); + $server->send('', 'ping'); + $message = $server->receive(); + $this->assertEquals('Receiving a message', $message); + $this->assertEquals('text', $server->getLastOpcode()); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testRemoteClose(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + $this->assertTrue($server->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('close-remote', $this); + + $message = $server->receive(); + $this->assertEquals('', $message); + + $this->assertTrue(MockSocket::isEmpty()); + $this->assertFalse($server->isConnected()); + $this->assertEquals(17260, $server->getCloseStatus()); + $this->assertNull($server->getLastOpcode()); + } + + public function testSetTimeout(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + $this->assertTrue($server->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + + MockSocket::initialize('config-timeout', $this); + $server->setTimeout(300); + $this->assertTrue($server->isConnected()); + $this->assertTrue(MockSocket::isEmpty()); + } + + public function testFailedSocketServer(): void + { + MockSocket::initialize('server.construct-failed-socket-server', $this); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Could not open listening socket:'); + $server = new Server(['port' => 9999]); + } + + public function testFailedSocketServerWithError(): void + { + MockSocket::initialize('server.construct-error-socket-server', $this); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Could not open listening socket:'); + $server = new Server(['port' => 9999]); + } + + public function testFailedConnect(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + + MockSocket::initialize('server.accept-failed-connect', $this); + $server->accept(); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Server failed to connect'); + $server->send('Connect'); + } + + public function testFailedConnectWithError(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + + MockSocket::initialize('server.accept-error-connect', $this); + $server->accept(); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Server failed to connect'); + $server->send('Connect'); + } + + public function testFailedConnectTimeout(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(['timeout' => 300]); + + MockSocket::initialize('server.accept-failed-connect', $this); + $server->accept(); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Server failed to connect'); + $server->send('Connect'); + } + + public function testFailedHttp(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + MockSocket::initialize('server.accept-failed-http', $this); + $server->accept(); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('No GET in request'); + $server->send('Connect'); + } + + public function testFailedWsKey(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + MockSocket::initialize('server.accept-failed-ws-key', $this); + $server->accept(); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Client had no Key in upgrade request'); + $server->send('Connect'); + } + + public function testSendBadOpcode(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + $this->expectException('WebSocket\BadOpcodeException'); + $this->expectExceptionCode(0); + $this->expectExceptionMessage('Bad opcode \'bad\'. Try \'text\' or \'binary\'.'); + $server->send('Bad Opcode', 'bad'); + } + + public function testRecieveBadOpcode(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + MockSocket::initialize('receive-bad-opcode', $this); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(1026); + $this->expectExceptionMessage('Bad opcode in websocket frame: 12'); + $message = $server->receive(); + } + + public function testBrokenWrite(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + MockSocket::initialize('send-broken-write', $this); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(1025); + $this->expectExceptionMessage('Could only write 18 out of 22 bytes.'); + $server->send('Failing to write'); + } + + public function testFailedWrite(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + MockSocket::initialize('send-failed-write', $this); + $this->expectException('WebSocket\TimeoutException'); + $this->expectExceptionCode(1024); + $this->expectExceptionMessage('Failed to write 22 bytes.'); + $server->send('Failing to write'); + } + + public function testBrokenRead(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + MockSocket::initialize('receive-broken-read', $this); + $this->expectException('WebSocket\ConnectionException'); + $this->expectExceptionCode(1025); + $this->expectExceptionMessage('Broken frame, read 0 of stated 2 bytes.'); + $server->receive(); + } + + public function testEmptyRead(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + MockSocket::initialize('receive-empty-read', $this); + $this->expectException('WebSocket\TimeoutException'); + $this->expectExceptionCode(1024); + $this->expectExceptionMessage('Empty read; connection dead?'); + $server->receive(); + } + + public function testFrameFragmentation(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(['filter' => ['text', 'binary', 'pong', 'close']]); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + MockSocket::initialize('receive-fragmentation', $this); + $message = $server->receive(); + $this->assertEquals('Server ping', $message); + $this->assertEquals('pong', $server->getLastOpcode()); + $message = $server->receive(); + $this->assertEquals('Multi fragment test', $message); + $this->assertEquals('text', $server->getLastOpcode()); + $this->assertTrue(MockSocket::isEmpty()); + MockSocket::initialize('close-remote', $this); + $message = $server->receive(); + $this->assertEquals('Closing', $message); + $this->assertTrue(MockSocket::isEmpty()); + $this->assertFalse($server->isConnected()); + $this->assertEquals(17260, $server->getCloseStatus()); + $this->assertEquals('close', $server->getLastOpcode()); + } + + public function testMessageFragmentation(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(['filter' => ['text', 'binary', 'pong', 'close'], 'return_obj' => true]); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->send('Connect'); + MockSocket::initialize('receive-fragmentation', $this); + $message = $server->receive(); + $this->assertInstanceOf('WebSocket\Message\Message', $message); + $this->assertInstanceOf('WebSocket\Message\Pong', $message); + $this->assertEquals('Server ping', $message->getContent()); + $this->assertEquals('pong', $message->getOpcode()); + $message = $server->receive(); + $this->assertInstanceOf('WebSocket\Message\Message', $message); + $this->assertInstanceOf('WebSocket\Message\Text', $message); + $this->assertEquals('Multi fragment test', $message->getContent()); + $this->assertEquals('text', $message->getOpcode()); + $this->assertTrue(MockSocket::isEmpty()); + MockSocket::initialize('close-remote', $this); + $message = $server->receive(); + $this->assertInstanceOf('WebSocket\Message\Message', $message); + $this->assertInstanceOf('WebSocket\Message\Close', $message); + $this->assertEquals('Closing', $message->getContent()); + $this->assertEquals('close', $message->getOpcode()); + } + + public function testConvenicanceMethods(): void + { + MockSocket::initialize('server.construct', $this); + $server = new Server(); + $this->assertNull($server->getName()); + $this->assertNull($server->getPier()); + $this->assertEquals('WebSocket\Server(closed)', "{$server}"); + MockSocket::initialize('server.accept', $this); + $server->accept(); + $server->text('Connect'); + MockSocket::initialize('send-convenicance', $this); + $server->binary(base64_encode('Binary content')); + $server->ping(); + $server->pong(); + $this->assertEquals('127.0.0.1:12345', $server->getName()); + $this->assertEquals('127.0.0.1:8000', $server->getPier()); + $this->assertEquals('WebSocket\Server(127.0.0.1:12345)', "{$server}"); + $this->assertTrue(MockSocket::isEmpty()); + } +} diff --git a/vendor/textalk/websocket/tests/bootstrap.php b/vendor/textalk/websocket/tests/bootstrap.php new file mode 100644 index 0000000..5d6bdd0 --- /dev/null +++ b/vendor/textalk/websocket/tests/bootstrap.php @@ -0,0 +1,6 @@ +interpolate($message, $context); + $context_string = empty($context) ? '' : json_encode($context); + echo str_pad($level, 8) . " | {$message} {$context_string}\n"; + } + + public function interpolate($message, array $context = []) + { + // Build a replacement array with braces around the context keys + $replace = []; + foreach ($context as $key => $val) { + // Check that the value can be cast to string + if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { + $replace['{' . $key . '}'] = $val; + } + } + + // Interpolate replacement values into the message and return + return strtr($message, $replace); + } +} diff --git a/vendor/textalk/websocket/tests/mock/MockSocket.php b/vendor/textalk/websocket/tests/mock/MockSocket.php new file mode 100644 index 0000000..e12d6ed --- /dev/null +++ b/vendor/textalk/websocket/tests/mock/MockSocket.php @@ -0,0 +1,79 @@ +assertEquals($current['function'], $function); + foreach ($current['params'] as $index => $param) { + self::$asserter->assertEquals($param, $params[$index], json_encode([$current, $params])); + } + if (isset($current['error'])) { + $map = array_merge(['msg' => 'Error', 'type' => E_USER_NOTICE], (array)$current['error']); + trigger_error($map['msg'], $map['type']); + } + if (isset($current['return-op'])) { + return self::op($current['return-op'], $params, $current['return']); + } + if (isset($current['return'])) { + return $current['return']; + } + return call_user_func_array($function, $params); + } + + // Check if all expected calls are performed + public static function isEmpty(): bool + { + return empty(self::$queue); + } + + // Initialize call queue + public static function initialize($op_file, $asserter): void + { + $file = dirname(__DIR__) . "/scripts/{$op_file}.json"; + self::$queue = json_decode(file_get_contents($file), true); + self::$asserter = $asserter; + } + + // Special output handling + private static function op($op, $params, $data) + { + switch ($op) { + case 'chr-array': + // Convert int array to string + $out = ''; + foreach ($data as $val) { + $out .= chr($val); + } + return $out; + case 'file': + $content = file_get_contents(__DIR__ . "/{$data[0]}"); + return substr($content, $data[1], $data[2]); + case 'key-save': + preg_match('#Sec-WebSocket-Key:\s(.*)$#mUi', $params[1], $matches); + self::$stored['sec-websocket-key'] = trim($matches[1]); + return $data; + case 'key-respond': + $key = self::$stored['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; + $encoded = base64_encode(pack('H*', sha1($key))); + return str_replace('{key}', $encoded, $data); + } + return $data; + } +} diff --git a/vendor/textalk/websocket/tests/mock/mock-socket.php b/vendor/textalk/websocket/tests/mock/mock-socket.php new file mode 100644 index 0000000..1d6889a --- /dev/null +++ b/vendor/textalk/websocket/tests/mock/mock-socket.php @@ -0,0 +1,78 @@ +