summaryrefslogtreecommitdiffstats
path: root/vendor/textalk/websocket/tests
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/textalk/websocket/tests')
-rw-r--r--vendor/textalk/websocket/tests/ClientTest.php449
-rw-r--r--vendor/textalk/websocket/tests/ExceptionTest.php52
-rw-r--r--vendor/textalk/websocket/tests/MessageTest.php61
-rw-r--r--vendor/textalk/websocket/tests/README.md29
-rw-r--r--vendor/textalk/websocket/tests/ServerTest.php448
-rw-r--r--vendor/textalk/websocket/tests/bootstrap.php6
-rw-r--r--vendor/textalk/websocket/tests/mock/EchoLog.php34
-rw-r--r--vendor/textalk/websocket/tests/mock/MockSocket.php79
-rw-r--r--vendor/textalk/websocket/tests/mock/mock-socket.php78
-rw-r--r--vendor/textalk/websocket/tests/mock/payload.128.txt5
-rw-r--r--vendor/textalk/websocket/tests/mock/payload.65536.txt1682
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.close.json76
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-authed.json59
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-bad-context.json7
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-context.json59
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-error.json23
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-extended.json59
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-failed.json19
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-headers.json59
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-invalid-key.json50
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-invalid-upgrade.json50
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-persistent.json95
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect-timeout.json59
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.connect.json59
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.destruct.json23
-rw-r--r--vendor/textalk/websocket/tests/scripts/client.reconnect.json100
-rw-r--r--vendor/textalk/websocket/tests/scripts/close-remote.json55
-rw-r--r--vendor/textalk/websocket/tests/scripts/config-timeout.json24
-rw-r--r--vendor/textalk/websocket/tests/scripts/ping-pong.json150
-rw-r--r--vendor/textalk/websocket/tests/scripts/receive-bad-opcode.json18
-rw-r--r--vendor/textalk/websocket/tests/scripts/receive-broken-read.json58
-rw-r--r--vendor/textalk/websocket/tests/scripts/receive-client-timeout.json50
-rw-r--r--vendor/textalk/websocket/tests/scripts/receive-empty-read.json58
-rw-r--r--vendor/textalk/websocket/tests/scripts/receive-fragmentation.json126
-rw-r--r--vendor/textalk/websocket/tests/scripts/send-bad-opcode.json9
-rw-r--r--vendor/textalk/websocket/tests/scripts/send-broken-write.json43
-rw-r--r--vendor/textalk/websocket/tests/scripts/send-convenicance.json86
-rw-r--r--vendor/textalk/websocket/tests/scripts/send-failed-write.json43
-rw-r--r--vendor/textalk/websocket/tests/scripts/send-receive-128.json50
-rw-r--r--vendor/textalk/websocket/tests/scripts/send-receive-65536.json113
-rw-r--r--vendor/textalk/websocket/tests/scripts/send-receive-multi-fragment.json112
-rw-r--r--vendor/textalk/websocket/tests/scripts/send-receive.json50
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.accept-destruct.json315
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.accept-error-connect.json18
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.accept-failed-connect.json14
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.accept-failed-http.json265
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.accept-failed-ws-key.json265
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.accept-timeout.json289
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.accept.json287
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.close.json70
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.construct-error-socket-server.json28
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.construct-failed-socket-server.json20
-rw-r--r--vendor/textalk/websocket/tests/scripts/server.construct.json11
53 files changed, 6347 insertions, 0 deletions
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 @@
+<?php
+
+/**
+ * Test case for Client.
+ * Note that this test is performed by mocking socket/stream calls.
+ */
+
+declare(strict_types=1);
+
+namespace WebSocket;
+
+use PHPUnit\Framework\TestCase;
+
+class ClientTest extends TestCase
+{
+
+ public function setUp(): void
+ {
+ error_reporting(-1);
+ }
+
+ public function testClientMasked(): void
+ {
+ MockSocket::initialize('client.connect', $this);
+ $client = new Client('ws://localhost:8000/my/mock/path');
+ $client->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 @@
+<?php
+
+/**
+ * Test case for Exceptions.
+ */
+
+declare(strict_types=1);
+
+namespace WebSocket;
+
+use PHPUnit\Framework\TestCase;
+use Throwable;
+
+class ExceptionTest extends TestCase
+{
+
+ public function setUp(): void
+ {
+ error_reporting(-1);
+ }
+
+ public function testConnectionException(): void
+ {
+ try {
+ throw new ConnectionException(
+ 'An error message',
+ ConnectionException::EOF,
+ ['test' => '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 @@
+<?php
+
+/**
+ * Test case for Message subsection.
+ */
+
+declare(strict_types=1);
+
+namespace WebSocket;
+
+use PHPUnit\Framework\TestCase;
+use WebSocket\Message\Factory;
+use WebSocket\Message\Text;
+
+class MessageTest extends TestCase
+{
+
+ public function setUp(): void
+ {
+ error_reporting(-1);
+ }
+
+ public function testFactory(): void
+ {
+ $factory = new Factory();
+ $message = $factory->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 @@
+<?php
+
+/**
+ * Test case for Server.
+ * Note that this test is performed by mocking socket/stream calls.
+ */
+
+declare(strict_types=1);
+
+namespace WebSocket;
+
+use PHPUnit\Framework\TestCase;
+
+class ServerTest extends TestCase
+{
+
+ public function setUp(): void
+ {
+ error_reporting(-1);
+ }
+
+ public function testServerMasked(): void
+ {
+ MockSocket::initialize('server.construct', $this);
+ $server = new Server();
+ $this->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 @@
+<?php
+
+namespace WebSocket;
+
+require dirname(__DIR__) . '/vendor/autoload.php';
+require __DIR__ . '/mock/mock-socket.php';
diff --git a/vendor/textalk/websocket/tests/mock/EchoLog.php b/vendor/textalk/websocket/tests/mock/EchoLog.php
new file mode 100644
index 0000000..369131a
--- /dev/null
+++ b/vendor/textalk/websocket/tests/mock/EchoLog.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * Simple echo logger (only available when running in dev environment)
+ */
+
+namespace WebSocket;
+
+class EchoLog implements \Psr\Log\LoggerInterface
+{
+ use \Psr\Log\LoggerTrait;
+
+ public function log($level, $message, array $context = [])
+ {
+ $message = $this->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 @@
+<?php
+
+/**
+ * This class is used by tests to mock and track various socket/stream calls.
+ */
+
+namespace WebSocket;
+
+class MockSocket
+{
+
+ private static $queue = [];
+ private static $stored = [];
+ private static $asserter;
+
+ // Handler called by function overloads in mock-socket.php
+ public static function handle($function, $params = [])
+ {
+ $current = array_shift(self::$queue);
+ if ($function == 'get_resource_type' && is_null($current)) {
+ return null; // Catch destructors
+ }
+ self::$asserter->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 @@
+<?php
+
+/**
+ * This file is used by tests to overload and mock various socket/stream calls.
+ */
+
+namespace WebSocket;
+
+function stream_socket_server($local_socket, &$errno, &$errstr)
+{
+ $args = [$local_socket, $errno, $errstr];
+ return MockSocket::handle('stream_socket_server', $args);
+}
+function stream_socket_accept()
+{
+ $args = func_get_args();
+ return MockSocket::handle('stream_socket_accept', $args);
+}
+function stream_set_timeout()
+{
+ $args = func_get_args();
+ return MockSocket::handle('stream_set_timeout', $args);
+}
+function stream_get_line()
+{
+ $args = func_get_args();
+ return MockSocket::handle('stream_get_line', $args);
+}
+function stream_get_meta_data()
+{
+ $args = func_get_args();
+ return MockSocket::handle('stream_get_meta_data', $args);
+}
+function feof()
+{
+ $args = func_get_args();
+ return MockSocket::handle('feof', $args);
+}
+function ftell()
+{
+ $args = func_get_args();
+ return MockSocket::handle('ftell', $args);
+}
+function fclose()
+{
+ $args = func_get_args();
+ return MockSocket::handle('fclose', $args);
+}
+function fwrite()
+{
+ $args = func_get_args();
+ return MockSocket::handle('fwrite', $args);
+}
+function fread()
+{
+ $args = func_get_args();
+ return MockSocket::handle('fread', $args);
+}
+function stream_context_create()
+{
+ $args = func_get_args();
+ return MockSocket::handle('stream_context_create', $args);
+}
+function stream_socket_client($remote_socket, &$errno, &$errstr, $timeout, $flags, $context)
+{
+ $args = [$remote_socket, $errno, $errstr, $timeout, $flags, $context];
+ return MockSocket::handle('stream_socket_client', $args);
+}
+function get_resource_type()
+{
+ $args = func_get_args();
+ return MockSocket::handle('get_resource_type', $args);
+}
+function stream_socket_get_name()
+{
+ $args = func_get_args();
+ return MockSocket::handle('stream_socket_get_name', $args);
+}
diff --git a/vendor/textalk/websocket/tests/mock/payload.128.txt b/vendor/textalk/websocket/tests/mock/payload.128.txt
new file mode 100644
index 0000000..4c078a8
--- /dev/null
+++ b/vendor/textalk/websocket/tests/mock/payload.128.txt
@@ -0,0 +1,5 @@
+128-chars
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+a \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/mock/payload.65536.txt b/vendor/textalk/websocket/tests/mock/payload.65536.txt
new file mode 100644
index 0000000..284eadd
--- /dev/null
+++ b/vendor/textalk/websocket/tests/mock/payload.65536.txt
@@ -0,0 +1,1682 @@
+65536-chars
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abscdefgheijklmnopqrstuvwxyz0123456789
+abcd \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.close.json b/vendor/textalk/websocket/tests/scripts/client.close.json
new file mode 100644
index 0000000..d449c17
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.close.json
@@ -0,0 +1,76 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [],
+ "return": 12
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return":[136, 154]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return":[98, 250, 210, 113]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 26
+ ],
+ "return-op": "chr-array",
+ "return": [97, 18, 145, 29, 13, 137, 183, 81, 3, 153, 185, 31, 13, 141, 190, 20, 6, 157, 183, 21, 88, 218, 227, 65, 82, 202]
+ },
+ {
+ "function": "fclose",
+ "params": [
+ "@mock-stream"
+ ],
+ "return":true
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "Unknown"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-authed.json b/vendor/textalk/websocket/tests/scripts/client.connect-authed.json
new file mode 100644
index 0000000..6f75b6b
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-authed.json
@@ -0,0 +1,59 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "ssl:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 5
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return-op": "key-save",
+ "return": 248
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return-op": "key-respond",
+ "return": "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {key}"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 13
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-bad-context.json b/vendor/textalk/websocket/tests/scripts/client.connect-bad-context.json
new file mode 100644
index 0000000..e084a84
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-bad-context.json
@@ -0,0 +1,7 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [],
+ "return": "@mock-bad-context"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-context.json b/vendor/textalk/websocket/tests/scripts/client.connect-context.json
new file mode 100644
index 0000000..0fcc279
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-context.json
@@ -0,0 +1,59 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [],
+ "return": "stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 5
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return-op": "key-save",
+ "return": 199
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return-op": "key-respond",
+ "return": "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {key}"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 13
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-error.json b/vendor/textalk/websocket/tests/scripts/client.connect-error.json
new file mode 100644
index 0000000..e6c523d
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-error.json
@@ -0,0 +1,23 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "error": {
+ "msg": "A PHP error",
+ "type": 512
+ },
+ "return": false
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-extended.json b/vendor/textalk/websocket/tests/scripts/client.connect-extended.json
new file mode 100644
index 0000000..4659e3e
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-extended.json
@@ -0,0 +1,59 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 5
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return-op": "key-save",
+ "return": 224
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return-op": "key-respond",
+ "return": "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {key}"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 13
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-failed.json b/vendor/textalk/websocket/tests/scripts/client.connect-failed.json
new file mode 100644
index 0000000..47725c2
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-failed.json
@@ -0,0 +1,19 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": false
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-headers.json b/vendor/textalk/websocket/tests/scripts/client.connect-headers.json
new file mode 100644
index 0000000..69808ce
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-headers.json
@@ -0,0 +1,59 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 5
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return-op": "key-save",
+ "return": 255
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return-op": "key-respond",
+ "return": "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {key}"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 13
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-invalid-key.json b/vendor/textalk/websocket/tests/scripts/client.connect-invalid-key.json
new file mode 100644
index 0000000..6472317
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-invalid-key.json
@@ -0,0 +1,50 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 5
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 199
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return": "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: BAD"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-invalid-upgrade.json b/vendor/textalk/websocket/tests/scripts/client.connect-invalid-upgrade.json
new file mode 100644
index 0000000..28cbc7e
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-invalid-upgrade.json
@@ -0,0 +1,50 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 5
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 199
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return": "Invalid upgrade response"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-persistent.json b/vendor/textalk/websocket/tests/scripts/client.connect-persistent.json
new file mode 100644
index 0000000..d95af01
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-persistent.json
@@ -0,0 +1,95 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 5,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "persistent stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "persistent stream"
+ },
+ {
+ "function": "ftell",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 0
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 5
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return-op": "key-save",
+ "return": 248
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return-op": "key-respond",
+ "return": "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {key}"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 13
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "persistent stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "persistent stream"
+ },
+ {
+ "function": "fclose",
+ "params": [
+ "@mock-stream"
+ ],
+ "return":true
+ }
+]
+
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect-timeout.json b/vendor/textalk/websocket/tests/scripts/client.connect-timeout.json
new file mode 100644
index 0000000..c1ae6b5
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect-timeout.json
@@ -0,0 +1,59 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 300,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 300
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return-op": "key-save",
+ "return": 199
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return-op": "key-respond",
+ "return": "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {key}"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 13
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.connect.json b/vendor/textalk/websocket/tests/scripts/client.connect.json
new file mode 100644
index 0000000..eb7ecd2
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.connect.json
@@ -0,0 +1,59 @@
+[
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 5
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return-op": "key-save",
+ "return": 199
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return-op": "key-respond",
+ "return": "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {key}"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 13
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.destruct.json b/vendor/textalk/websocket/tests/scripts/client.destruct.json
new file mode 100644
index 0000000..c04755b
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.destruct.json
@@ -0,0 +1,23 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fclose",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": true
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/client.reconnect.json b/vendor/textalk/websocket/tests/scripts/client.reconnect.json
new file mode 100644
index 0000000..9d505fe
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/client.reconnect.json
@@ -0,0 +1,100 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "Unknown"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_context_create",
+ "params": [],
+ "return": "@mock-stream-context"
+ },
+ {
+ "function": "stream_socket_client",
+ "params": [
+ "tcp:\/\/localhost:8000",
+ null,
+ null,
+ 5,
+ 4,
+ "@mock-stream-context"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 5
+ ],
+ "return": true
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return-op": "key-save",
+ "return": 199
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n\r\n"
+ ],
+ "return-op": "key-respond",
+ "return": "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {key}"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [129, 147]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [33, 111, 149, 174]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 19
+ ],
+ "return-op": "chr-array",
+ "return": [115, 10, 246, 203, 72, 25, 252, 192, 70, 79, 244, 142, 76, 10, 230, 221, 64, 8, 240]
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/close-remote.json b/vendor/textalk/websocket/tests/scripts/close-remote.json
new file mode 100644
index 0000000..d2eea02
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/close-remote.json
@@ -0,0 +1,55 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [136, 137]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [54, 79, 233, 244]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 9
+ ],
+ "return-op": "chr-array",
+ "return": [117, 35, 170, 152, 89, 60, 128, 154, 81]
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [],
+ "return": 33
+ },
+ {
+ "function": "fclose",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": true
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/config-timeout.json b/vendor/textalk/websocket/tests/scripts/config-timeout.json
new file mode 100644
index 0000000..243ae22
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/config-timeout.json
@@ -0,0 +1,24 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 300
+ ],
+ "return": true
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/ping-pong.json b/vendor/textalk/websocket/tests/scripts/ping-pong.json
new file mode 100644
index 0000000..b647e91
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/ping-pong.json
@@ -0,0 +1,150 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 17
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 6
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [138, 139]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [1, 1, 1, 1]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 11
+ ],
+ "return-op": "chr-array",
+ "return": [82, 100, 115, 119, 100, 115, 33, 113, 104, 111, 102]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [138, 128]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [1, 1, 1, 1]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [137, 139]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [180, 77, 192, 201]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 11
+ ],
+ "return-op": "chr-array",
+ "return": [247, 33, 169, 172, 218, 57, 224, 185, 221, 35, 167]
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 17
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [129, 147]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [33, 111, 149, 174]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 19
+ ],
+ "return-op": "chr-array",
+ "return": [115, 10, 246, 203, 72, 25, 252, 192, 70, 79, 244, 142, 76, 10, 230, 221, 64, 8, 240]
+ }
+]
diff --git a/vendor/textalk/websocket/tests/scripts/receive-bad-opcode.json b/vendor/textalk/websocket/tests/scripts/receive-bad-opcode.json
new file mode 100644
index 0000000..27dd2ba
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/receive-bad-opcode.json
@@ -0,0 +1,18 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [140, 115]
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/receive-broken-read.json b/vendor/textalk/websocket/tests/scripts/receive-broken-read.json
new file mode 100644
index 0000000..15e3fa9
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/receive-broken-read.json
@@ -0,0 +1,58 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [],
+ "return": false
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": true,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": true,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "fclose",
+ "params": [
+ "@mock-stream"
+ ],
+ "return":true
+ }
+]
diff --git a/vendor/textalk/websocket/tests/scripts/receive-client-timeout.json b/vendor/textalk/websocket/tests/scripts/receive-client-timeout.json
new file mode 100644
index 0000000..5a258b0
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/receive-client-timeout.json
@@ -0,0 +1,50 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [],
+ "return": false
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": true,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 0,
+ "seekable": false
+ }
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fclose",
+ "params": [
+ "@mock-stream"
+ ],
+ "return":true
+ }
+]
diff --git a/vendor/textalk/websocket/tests/scripts/receive-empty-read.json b/vendor/textalk/websocket/tests/scripts/receive-empty-read.json
new file mode 100644
index 0000000..f752017
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/receive-empty-read.json
@@ -0,0 +1,58 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [],
+ "return": ""
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 0,
+ "seekable": false
+ }
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": true,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "fclose",
+ "params": [
+ "@mock-stream"
+ ],
+ "return":true
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/receive-fragmentation.json b/vendor/textalk/websocket/tests/scripts/receive-fragmentation.json
new file mode 100644
index 0000000..5ae9572
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/receive-fragmentation.json
@@ -0,0 +1,126 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [1, 136]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [105, 29, 187, 18]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 8
+ ],
+ "return-op": "chr-array",
+ "return": [36, 104, 215, 102, 0, 61, 221, 96]
+ },
+
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [138, 139]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [1, 1, 1, 1]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 11
+ ],
+ "return-op": "chr-array",
+ "return": [82, 100, 115, 119, 100, 115, 33, 113, 104, 111, 102]
+ },
+
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [0, 136]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [221, 240, 46, 69]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 8
+ ],
+ "return-op": "chr-array",
+ "return": [188, 151, 67, 32, 179, 132, 14, 49]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [128, 131]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [9, 60, 117, 193]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 3
+ ],
+ "return-op": "chr-array",
+ "return": [108, 79, 1]
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/send-bad-opcode.json b/vendor/textalk/websocket/tests/scripts/send-bad-opcode.json
new file mode 100644
index 0000000..c0859d1
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/send-bad-opcode.json
@@ -0,0 +1,9 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/send-broken-write.json b/vendor/textalk/websocket/tests/scripts/send-broken-write.json
new file mode 100644
index 0000000..838c826
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/send-broken-write.json
@@ -0,0 +1,43 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 18
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": true,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "fclose",
+ "params": [],
+ "return": true
+ }
+]
diff --git a/vendor/textalk/websocket/tests/scripts/send-convenicance.json b/vendor/textalk/websocket/tests/scripts/send-convenicance.json
new file mode 100644
index 0000000..194cb5a
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/send-convenicance.json
@@ -0,0 +1,86 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 26
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 6
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 6
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_socket_get_name",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "127.0.0.1:12345"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_socket_get_name",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "127.0.0.1:8000"
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_socket_get_name",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "127.0.0.1:12345"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/send-failed-write.json b/vendor/textalk/websocket/tests/scripts/send-failed-write.json
new file mode 100644
index 0000000..ea3d46b
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/send-failed-write.json
@@ -0,0 +1,43 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": true,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "fclose",
+ "params": [],
+ "return": true
+ }
+]
diff --git a/vendor/textalk/websocket/tests/scripts/send-receive-128.json b/vendor/textalk/websocket/tests/scripts/send-receive-128.json
new file mode 100644
index 0000000..66abea7
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/send-receive-128.json
@@ -0,0 +1,50 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 132
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [129, 126]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [0, 128]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 128
+ ],
+ "return-op": "file",
+ "return": ["payload.128.txt", 0, 132]
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/send-receive-65536.json b/vendor/textalk/websocket/tests/scripts/send-receive-65536.json
new file mode 100644
index 0000000..67604b5
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/send-receive-65536.json
@@ -0,0 +1,113 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 65546
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [129, 127]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 8
+ ],
+ "return-op": "chr-array",
+ "return": [0, 0, 0, 0, 0, 1, 0, 0]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 65536
+ ],
+ "return-op": "file",
+ "return": ["payload.65536.txt", 0, 16374]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 49162
+ ],
+ "return-op": "file",
+ "return": ["payload.65536.txt", 16374, 8192]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 40970
+ ],
+ "return-op": "file",
+ "return": ["payload.65536.txt", 24566, 8192]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 32778
+ ],
+ "return-op": "file",
+ "return": ["payload.65536.txt", 32758, 8192]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 24586
+ ],
+ "return-op": "file",
+ "return": ["payload.65536.txt", 40950, 8192]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 16394
+ ],
+ "return-op": "file",
+ "return": ["payload.65536.txt", 49142, 8192]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 8202
+ ],
+ "return-op": "file",
+ "return": ["payload.65536.txt", 57334, 8192]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 10
+ ],
+ "return-op": "file",
+ "return": ["payload.65536.txt", 65526, 10]
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/send-receive-multi-fragment.json b/vendor/textalk/websocket/tests/scripts/send-receive-multi-fragment.json
new file mode 100644
index 0000000..426434e
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/send-receive-multi-fragment.json
@@ -0,0 +1,112 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [],
+ "return": 14
+ },
+ {
+ "function": "fwrite",
+ "params": [],
+ "return": 14
+ },
+ {
+ "function": "fwrite",
+ "params": [],
+ "return": 9
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [1, 136]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [105, 29, 187, 18]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 8
+ ],
+ "return-op": "chr-array",
+ "return": [36, 104, 215, 102, 0, 61, 221, 96]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [0, 136]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [221, 240, 46, 69]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 8
+ ],
+ "return-op": "chr-array",
+ "return": [188, 151, 67, 32, 179, 132, 14, 49]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [128, 131]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [9, 60, 117, 193]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 3
+ ],
+ "return-op": "chr-array",
+ "return": [108, 79, 1]
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/send-receive.json b/vendor/textalk/websocket/tests/scripts/send-receive.json
new file mode 100644
index 0000000..7ad0350
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/send-receive.json
@@ -0,0 +1,50 @@
+[
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 23
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [129, 147]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [33, 111, 149, 174]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 19
+ ],
+ "return-op": "chr-array",
+ "return": [115, 10, 246, 203, 72, 25, 252, 192, 70, 79, 244, 142, 76, 10, 230, 221, 64, 8, 240]
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.accept-destruct.json b/vendor/textalk/websocket/tests/scripts/server.accept-destruct.json
new file mode 100644
index 0000000..970286b
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.accept-destruct.json
@@ -0,0 +1,315 @@
+[
+ {
+ "function": "stream_socket_accept",
+ "params": [
+ "@mock-socket"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "stream_socket_get_name",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "127.0.0.1:12345"
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "GET \/my\/mock\/path HTTP\/1.1"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 171,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "host: localhost:8000"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 149,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "user-agent: websocket-client-php"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 115,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "connection: Upgrade"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 94,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "upgrade: websocket"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 74,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "sec-websocket-key: cktLWXhUdDQ2OXF0ZCFqOQ=="
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 29,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "sec-websocket-version: 13"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ }
+ ,
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": ""
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 0,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream",
+ "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: YmysboNHNoWzWVeQpduY7xELjgU=\r\n\r\n"
+ ],
+ "return": 129
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [129, 147]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [33, 111, 149, 174]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 19
+ ],
+ "return-op": "chr-array",
+ "return": [115, 10, 246, 203, 72, 25, 252, 192, 70, 79, 244, 142, 76, 10, 230, 221, 64, 8, 240]
+ },
+
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fclose",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": true
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.accept-error-connect.json b/vendor/textalk/websocket/tests/scripts/server.accept-error-connect.json
new file mode 100644
index 0000000..f0fef27
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.accept-error-connect.json
@@ -0,0 +1,18 @@
+[
+ {
+ "function": "stream_socket_accept",
+ "params": [],
+ "error": {
+ "msg": "A PHP error",
+ "type": 512
+ },
+ "return": false
+ },
+ {
+ "function": "fclose",
+ "params": [
+ false
+ ],
+ "return": true
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.accept-failed-connect.json b/vendor/textalk/websocket/tests/scripts/server.accept-failed-connect.json
new file mode 100644
index 0000000..24692db
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.accept-failed-connect.json
@@ -0,0 +1,14 @@
+[
+ {
+ "function": "stream_socket_accept",
+ "params": [],
+ "return": false
+ },
+ {
+ "function": "fclose",
+ "params": [
+ false
+ ],
+ "return": true
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.accept-failed-http.json b/vendor/textalk/websocket/tests/scripts/server.accept-failed-http.json
new file mode 100644
index 0000000..ab66db4
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.accept-failed-http.json
@@ -0,0 +1,265 @@
+[
+ {
+ "function": "stream_socket_accept",
+ "params": [
+ "@mock-socket"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "stream_socket_get_name",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "127.0.0.1:12345"
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "missing http header"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 171,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "host: localhost:8000"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 149,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "user-agent: websocket-client-php"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 115,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "connection: Upgrade"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 94,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "upgrade: websocket"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 74,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "no key in upgrade request"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 29,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "sec-websocket-version: 13"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ }
+ ,
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": ""
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 0,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.accept-failed-ws-key.json b/vendor/textalk/websocket/tests/scripts/server.accept-failed-ws-key.json
new file mode 100644
index 0000000..06bf4e6
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.accept-failed-ws-key.json
@@ -0,0 +1,265 @@
+[
+ {
+ "function": "stream_socket_accept",
+ "params": [
+ "@mock-socket"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "stream_socket_get_name",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "127.0.0.1:12345"
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "GET \/my\/mock\/path HTTP\/1.1"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 171,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "host: localhost:8000"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 149,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "user-agent: websocket-client-php"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 115,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "connection: Upgrade"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 94,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "upgrade: websocket"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 74,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "no key in upgrade request"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 29,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "sec-websocket-version: 13"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ }
+ ,
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": ""
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 0,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.accept-timeout.json b/vendor/textalk/websocket/tests/scripts/server.accept-timeout.json
new file mode 100644
index 0000000..17a5660
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.accept-timeout.json
@@ -0,0 +1,289 @@
+[
+ {
+ "function": "stream_socket_accept",
+ "params": [
+ "@mock-socket",
+ 300
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "stream_set_timeout",
+ "params": [
+ "@mock-stream",
+ 300
+ ],
+ "return": true
+ },
+ {
+ "function": "stream_socket_get_name",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "127.0.0.1:12345"
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "GET \/my\/mock\/path HTTP\/1.1"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 171,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "host: localhost:8000"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 149,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "user-agent: websocket-client-php"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 115,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "connection: Upgrade"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 94,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "upgrade: websocket"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 74,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "sec-websocket-key: cktLWXhUdDQ2OXF0ZCFqOQ=="
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 29,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "sec-websocket-version: 13"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ }
+ ,
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": ""
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 0,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream",
+ "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: YmysboNHNoWzWVeQpduY7xELjgU=\r\n\r\n"
+ ],
+ "return": 129
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 13
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.accept.json b/vendor/textalk/websocket/tests/scripts/server.accept.json
new file mode 100644
index 0000000..a1463dc
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.accept.json
@@ -0,0 +1,287 @@
+[
+ {
+ "function": "stream_socket_accept",
+ "params": [
+ "@mock-socket"
+ ],
+ "return": "@mock-stream"
+ },
+ {
+ "function": "stream_socket_get_name",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "127.0.0.1:12345"
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "GET \/my\/mock\/path HTTP\/1.1"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 171,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "host: localhost:8000"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 149,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "user-agent: websocket-client-php"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 115,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "connection: Upgrade"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 94,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "upgrade: websocket"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 74,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "sec-websocket-key: cktLWXhUdDQ2OXF0ZCFqOQ=="
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 29,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": "sec-websocket-version: 13"
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 2,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ }
+ ,
+ {
+ "function": "stream_get_line",
+ "params": [
+ "@mock-stream",
+ 1024,
+ "\r\n"
+ ],
+ "return": ""
+ },
+ {
+ "function": "stream_get_meta_data",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": {
+ "timed_out": false,
+ "blocked": true,
+ "eof": false,
+ "stream_type": "tcp_socket\/ssl",
+ "mode": "r+",
+ "unread_bytes": 0,
+ "seekable": false
+ }
+ },
+ {
+ "function": "feof",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": false
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream",
+ "HTTP\/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: YmysboNHNoWzWVeQpduY7xELjgU=\r\n\r\n"
+ ],
+ "return": 129
+ },
+ {
+ "function": "fwrite",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": 13
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.close.json b/vendor/textalk/websocket/tests/scripts/server.close.json
new file mode 100644
index 0000000..b6e045c
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.close.json
@@ -0,0 +1,70 @@
+[
+
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": true
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fwrite",
+ "params": [],
+ "return":12
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "stream"
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 2
+ ],
+ "return-op": "chr-array",
+ "return": [136,154]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 4
+ ],
+ "return-op": "chr-array",
+ "return": [245,55,62,8]
+ },
+ {
+ "function": "fread",
+ "params": [
+ "@mock-stream",
+ 26
+ ],
+ "return-op": "chr-array",
+ "return": [246,223,125,100,154,68,91,40,148,84,85,102,154,64,82,109,145,80,91,108,207,23,15,56,197,7]
+ },
+ {
+ "function": "fclose",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": true
+ },
+ {
+ "function": "get_resource_type",
+ "params": [
+ "@mock-stream"
+ ],
+ "return": "Unknown"
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.construct-error-socket-server.json b/vendor/textalk/websocket/tests/scripts/server.construct-error-socket-server.json
new file mode 100644
index 0000000..3f4909f
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.construct-error-socket-server.json
@@ -0,0 +1,28 @@
+[
+ {
+ "function": "stream_socket_server",
+ "params": [
+ "tcp://0.0.0.0:9999",
+ null,
+ null
+ ],
+ "error": {
+ "msg": "A PHP error",
+ "type": 512
+ },
+ "return": false
+ },
+ {
+ "function": "stream_socket_server",
+ "params": [
+ "tcp://0.0.0.0:10000",
+ null,
+ null
+ ],
+ "error": {
+ "msg": "A PHP error",
+ "type": 512
+ },
+ "return": false
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.construct-failed-socket-server.json b/vendor/textalk/websocket/tests/scripts/server.construct-failed-socket-server.json
new file mode 100644
index 0000000..30d1ea6
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.construct-failed-socket-server.json
@@ -0,0 +1,20 @@
+[
+ {
+ "function": "stream_socket_server",
+ "params": [
+ "tcp://0.0.0.0:9999",
+ null,
+ null
+ ],
+ "return": false
+ },
+ {
+ "function": "stream_socket_server",
+ "params": [
+ "tcp://0.0.0.0:10000",
+ null,
+ null
+ ],
+ "return": false
+ }
+] \ No newline at end of file
diff --git a/vendor/textalk/websocket/tests/scripts/server.construct.json b/vendor/textalk/websocket/tests/scripts/server.construct.json
new file mode 100644
index 0000000..c3181f3
--- /dev/null
+++ b/vendor/textalk/websocket/tests/scripts/server.construct.json
@@ -0,0 +1,11 @@
+[
+ {
+ "function": "stream_socket_server",
+ "params": [
+ "tcp://0.0.0.0:8000",
+ null,
+ null
+ ],
+ "return": "@mock-socket"
+ }
+] \ No newline at end of file