| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334 |
- <?php
-
- /**
- * Hoa
- *
- *
- * @license
- *
- * New BSD License
- *
- * Copyright © 2007-2017, Hoa community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the Hoa nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
- namespace Hoa\Websocket\Test\Unit;
-
- use Hoa\Event;
- use Hoa\Socket;
- use Hoa\Test;
- use Hoa\Websocket;
- use Mock\Hoa\Websocket\Connection as SUT;
-
- /**
- * Class \Hoa\Websocket\Test\Unit\Connection.
- *
- * Test suite for the WebSocket connection class.
- *
- * @copyright Copyright © 2007-2017 Hoa community
- * @license New BSD License
- */
- class Connection extends Test\Unit\Suite
- {
- public function case_opcodes()
- {
- $this
- ->then
- ->integer(SUT::OPCODE_CONTINUATION_FRAME)
- ->isEqualTo(0x0)
- ->integer(SUT::OPCODE_TEXT_FRAME)
- ->isEqualTo(0x1)
- ->integer(SUT::OPCODE_BINARY_FRAME)
- ->isEqualTo(0x2)
- ->integer(SUT::OPCODE_CONNECTION_CLOSE)
- ->isEqualTo(0x8)
- ->integer(SUT::OPCODE_PING)
- ->isEqualTo(0x9)
- ->integer(SUT::OPCODE_PONG)
- ->isEqualTo(0xa);
- }
-
- public function case_close_codes()
- {
- $this
- ->then
- ->integer(SUT::CLOSE_NORMAL)
- ->isEqualTo(1000)
- ->integer(SUT::CLOSE_GOING_AWAY)
- ->isEqualTo(1001)
- ->integer(SUT::CLOSE_PROTOCOL_ERROR)
- ->isEqualTo(1002)
- ->integer(SUT::CLOSE_DATA_ERROR)
- ->isEqualTo(1003)
- ->integer(SUT::CLOSE_STATUS_ERROR)
- ->isEqualTo(1005)
- ->integer(SUT::CLOSE_ABNORMAL)
- ->isEqualTo(1006)
- ->integer(SUT::CLOSE_MESSAGE_ERROR)
- ->isEqualTo(1007)
- ->integer(SUT::CLOSE_POLICY_ERROR)
- ->isEqualTo(1008)
- ->integer(SUT::CLOSE_MESSAGE_TOO_BIG)
- ->isEqualTo(1009)
- ->integer(SUT::CLOSE_EXTENSION_MISSING)
- ->isEqualTo(1010)
- ->integer(SUT::CLOSE_SERVER_ERROR)
- ->isEqualTo(1011)
- ->integer(SUT::CLOSE_TLS)
- ->isEqualTo(1015);
- }
-
- public function case_constructor()
- {
- $this
- ->given($socket = new Socket\Client('tcp://*:1234'))
- ->when($result = new SUT($socket))
- ->then
- ->object($result->getConnection())
- ->isIdenticalTo($socket)
- ->string($socket->getNodeName())
- ->isEqualTo(Websocket\Node::class)
- ->let($listener = $this->invoke($result)->getListener())
- ->object($listener)
- ->isInstanceOf(Event\Listener::class)
- ->boolean($listener->listenerExists('open'))
- ->isTrue()
- ->boolean($listener->listenerExists('message'))
- ->isTrue()
- ->boolean($listener->listenerExists('binary-message'))
- ->isTrue()
- ->boolean($listener->listenerExists('ping'))
- ->isTrue()
- ->boolean($listener->listenerExists('close'))
- ->isTrue()
- ->boolean($listener->listenerExists('error'))
- ->isTrue();
- }
-
- public function case_run_do_handshake()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
-
- $connection->on(
- 'open',
- function (Event\Bucket $bucket) use (&$calledA, $self) {
- $calledA = true;
-
- $self
- ->variable($bucket->getData())
- ->isNull();
-
- return;
- }
- ),
-
- $this->calling($node)->getHandshake = FAILED,
- $this->calling($connection)->doHandshake = function () use (&$calledB) {
- $calledB = true;
-
- return;
- }
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->boolean($calledA)
- ->isTrue()
- ->boolean($calledB)
- ->isTrue();
- }
-
- public function case_run_cannot_read_the_frame()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation(new Websocket\Protocol\Rfc6455($socket)),
-
- $this->calling($socket)->read[1] =
- chr(
- (0x1 << 7)
- | (0x1 << 6)
- | (0x0 << 5)
- | (0x0 << 4)
- | Websocket\Connection::OPCODE_TEXT_FRAME
- ),
- $this->calling($socket)->read[2] =
- chr(
- (0x1 << 7)
- | 42
- ),
- $this->calling($socket)->getCurrentNode = $node,
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($connection)->close = function ($_code, $_reason) use (&$called, $self) {
- $called = true;
-
- $self
- ->integer($_code)
- ->isEqualTo(SUT::CLOSE_PROTOCOL_ERROR)
- ->string($_reason)
- ->isNotEmpty();
-
- return;
- }
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->boolean($called)
- ->isTrue();
- }
-
- public function case_run_client_messages_must_be_masked()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Server('tcp://*:1234'),
- $connection = new \Mock\Hoa\Websocket\Server($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_TEXT_FRAME,
- 'mask' => 0x0,
- 'length' => 6,
- 'message' => 'foobar'
- ],
- $this->calling($connection)->close = function ($_code, $_reason) use (&$called, $self) {
- $called = true;
-
- $self
- ->integer($_code)
- ->isEqualTo(SUT::CLOSE_MESSAGE_ERROR)
- ->string($_reason)
- ->isEqualTo('All messages from the client must be masked.');
-
- return;
- }
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->boolean($called)
- ->isTrue();
- }
-
- public function case_run_ping_opcode()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_PING,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => 'foobar'
- ],
- $this->calling($protocol)->writeFrame = function ($_message, $_opcode, $_mask) use (&$calledA, $self) {
- $calledA = true;
-
- $self
- ->string($_message)
- ->isEqualTo('foobar')
- ->integer($_opcode)
- ->isEqualTo(SUT::OPCODE_PONG)
- ->boolean($_mask)
- ->isTrue();
-
- return;
- },
-
- $connection->on(
- 'ping',
- function (Event\Bucket $bucket) use (&$calledB, $self) {
- $calledB = true;
-
- $self
- ->array($bucket->getData())
- ->isEqualTo([
- 'message' => 'foobar'
- ]);
-
- return;
- }
- )
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->boolean($calledA)
- ->isTrue()
- ->boolean($calledB)
- ->isTrue();
- }
-
- public function case_run_ping_opcode_not_fin()
- {
- return $this->_case_run_ping_opcode_with_invalid_frame([
- 'fin' => 0x0,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_PING,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => 'foobar'
- ]);
- }
-
- public function case_run_ping_opcode_with_length_too_big()
- {
- return $this->_case_run_ping_opcode_with_invalid_frame([
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_PING,
- 'mask' => 0x1,
- 'length' => 0x7e,
- 'message' => 'foobar…'
- ]);
- }
-
- protected function _case_run_ping_opcode_with_invalid_frame(array $frame)
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame = $frame,
- $this->calling($protocol)->writeFrame = function ($_message, $_opcode, $_mask) use (&$calledA) {
- $calledA = true;
-
- return;
- },
- $this->calling($connection)->close = function ($_code, $_reason) use (&$calledB, $self) {
- $calledB = true;
-
- $self
- ->integer($_code)
- ->isEqualTo(SUT::CLOSE_PROTOCOL_ERROR)
- ->variable($_reason)
- ->isNull();
-
- return;
- },
-
- $connection->on(
- 'ping',
- function (Event\Bucket $bucket) use (&$calledC) {
- $calledC = true;
-
- return;
- }
- )
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($calledA)
- ->isNull()
- ->boolean($calledB)
- ->isTrue()
- ->variable($calledC)
- ->isNull();
- }
-
- public function case_run_pong_opcode()
- {
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_PONG,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => 'foobar'
- ],
- $this->calling($protocol)->writeFrame = function ($_message, $_opcode, $_mask) use (&$called) {
- $called = true;
-
- return;
- }
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($called)
- ->isNull();
- }
-
- public function case_run_pong_opcode_not_fin()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x0,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_PONG,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => 'foobar'
- ],
- $this->calling($protocol)->writeFrame = function ($_message, $_opcode, $_mask) use (&$calledA) {
- $calledA = true;
-
- return;
- },
- $this->calling($connection)->close = function ($_code, $_reason) use (&$calledB, $self) {
- $calledB = true;
-
- $self
- ->integer($_code)
- ->isEqualTo(SUT::CLOSE_PROTOCOL_ERROR)
- ->variable($_reason)
- ->isNull();
-
- return;
- }
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($calledA)
- ->isNull()
- ->boolean($calledB)
- ->isTrue();
- }
-
- public function case_run_text_frame_opcode_with_fragments()
- {
- return $this->_case_run_x_frame_opcode_with_fragments(SUT::OPCODE_TEXT_FRAME);
- }
-
- public function case_run_binary_frame_opcode_with_fragments()
- {
- return $this->_case_run_x_frame_opcode_with_fragments(SUT::OPCODE_BINARY_FRAME);
- }
-
- protected function _case_run_x_frame_opcode_with_fragments($opcode)
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($node)->getNumberOfFragments = 42,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => $opcode,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => 'foobar'
- ],
- $this->calling($protocol)->writeFrame = function ($_message, $_opcode, $_mask) use (&$calledA) {
- $calledA = true;
-
- return;
- },
- $this->calling($connection)->close = function ($_code, $_reason) use (&$calledB, $self) {
- $calledB = true;
-
- $self
- ->integer($_code)
- ->isEqualTo(SUT::CLOSE_PROTOCOL_ERROR)
- ->variable($_reason)
- ->isNull();
-
- return;
- }
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($calledA)
- ->isNull()
- ->boolean($calledB)
- ->isTrue();
- }
-
- public function case_run_text_frame_opcode_with_invalid_message_encoding()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_TEXT_FRAME,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => iconv('UTF-8', 'UTF-16', '😄')
- ],
- $this->calling($protocol)->writeFrame = function ($_message, $_opcode, $_mask) use (&$calledA) {
- $calledA = true;
-
- return;
- },
- $this->calling($connection)->close = function ($_code, $_reason) use (&$calledB, $self) {
- $calledB = true;
-
- $self
- ->integer($_code)
- ->isEqualTo(SUT::CLOSE_MESSAGE_ERROR)
- ->variable($_reason)
- ->isNull();
-
- return;
- }
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($calledA)
- ->isNull()
- ->boolean($calledB)
- ->isTrue();
- }
-
- public function case_run_text_frame_opcode()
- {
- return $this->_case_run_x_frame_opcode(SUT::OPCODE_TEXT_FRAME);
- }
-
- public function case_run_binary_frame_opcode()
- {
- return $this->_case_run_x_frame_opcode(SUT::OPCODE_BINARY_FRAME);
- }
-
- protected function _case_run_x_frame_opcode($opcode)
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => $opcode,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => 'foobar'
- ],
- $this->calling($protocol)->writeFrame = function ($_message, $_opcode, $_mask) use (&$calledA) {
- $calledA = true;
-
- return;
- },
- $this->calling($connection)->close = function ($_code, $_reason) use (&$calledB) {
- $calledB = true;
-
- return;
- },
-
- $connection->on(
- SUT::OPCODE_TEXT_FRAME === $opcode ? 'message' : 'binary-message',
- function (Event\Bucket $bucket) use (&$calledC, $self) {
- $calledC = true;
-
- $self
- ->array($bucket->getData())
- ->isEqualTo([
- 'message' => 'foobar'
- ]);
-
- return;
- }
- )
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($calledA)
- ->isNull()
- ->variable($calledB)
- ->isNull()
- ->boolean($calledC)
- ->isTrue();
- }
-
- public function case_run_text_frame_opcode_with_an_exception_from_the_listener()
- {
- return $this->_case_run_x_frame_opcode_with_an_exception_from_the_listener(SUT::OPCODE_TEXT_FRAME);
- }
-
- public function case_run_binary_frame_opcode_with_an_exception_from_the_listener()
- {
- return $this->_case_run_x_frame_opcode_with_an_exception_from_the_listener(SUT::OPCODE_BINARY_FRAME);
- }
-
- protected function _case_run_x_frame_opcode_with_an_exception_from_the_listener($opcode)
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => $opcode,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => 'foobar'
- ],
- $this->calling($protocol)->writeFrame = function ($_message, $_opcode, $_mask) use (&$calledA) {
- $calledA = true;
-
- return;
- },
- $this->calling($connection)->close = function ($_code, $_reason) use (&$calledB) {
- $calledB = true;
-
- return;
- },
-
- $connection->on(
- SUT::OPCODE_TEXT_FRAME === $opcode ? 'message' : 'binary-message',
- function (Event\Bucket $bucket) use (&$calledC, $self) {
- $calledC = true;
-
- $self
- ->array($bucket->getData())
- ->isEqualTo([
- 'message' => 'foobar'
- ]);
-
- throw new \RuntimeException('bang');
- }
- ),
- $connection->on(
- 'error',
- function (Event\Bucket $bucket) use (&$calledD, $self) {
- $calledD = true;
-
- $self
- ->let($data = $bucket->getData())
- ->array($data)
- ->hasSize(1)
- ->hasKey('exception')
- ->exception($data['exception'])
- ->isInstanceOf(\RuntimeException::class)
- ->hasMessage('bang');
-
- return;
- }
- )
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($calledA)
- ->isNull()
- ->variable($calledB)
- ->isNull()
- ->boolean($calledC)
- ->isTrue()
- ->boolean($calledD)
- ->isTrue();
- }
-
- public function case_run_incomplete_text_frame_opcode()
- {
- return $this->_case_run_incomplete_x_frame_opcode(SUT::OPCODE_TEXT_FRAME);
- }
-
- public function case_run_incomplete_binary_frame_opcode()
- {
- return $this->_case_run_incomplete_x_frame_opcode(SUT::OPCODE_BINARY_FRAME);
- }
-
- protected function _case_run_incomplete_x_frame_opcode($opcode)
- {
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x0,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => $opcode,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => 'foobar'
- ],
- $this->calling($protocol)->writeFrame = function ($_message, $_opcode, $_mask) use (&$calledA) {
- $calledA = true;
-
- return;
- },
- $this->calling($connection)->close = function ($_code, $_reason) use (&$calledB) {
- $calledB = true;
-
- return;
- },
-
- $connection->on(
- 'message',
- function (Event\Bucket $bucket) use (&$calledC) {
- $calledC = true;
-
- return;
- }
- )
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($calledA)
- ->isNull()
- ->variable($calledB)
- ->isNull()
- ->variable($calledC)
- ->isNull()
- ->boolean($node->isMessageComplete())
- ->isFalse()
- ->integer($node->getNumberOfFragments())
- ->isEqualTo(1)
- ->string($node->getFragmentedMessage())
- ->isEqualTo('foobar')
- ->boolean($node->isBinary())
- ->isEqualTo(SUT::OPCODE_BINARY_FRAME === $opcode);
- }
-
- public function case_run_continuation_frame_opcode_with_fragments()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($node)->getNumberOfFragments = 42,
- $this->calling($protocol)->readFrame = [
- 'fin' => 0x0,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_CONTINUATION_FRAME,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => 'foobar'
- ],
- $this->calling($connection)->close = function ($_code, $_reason) use (&$called) {
- $called = true;
-
- $self
- ->integer($_code)
- ->isEqualTo(SUT::CLOSE_PROTOCOL_ERROR)
- ->variable($_reason)
- ->isNull();
-
- return;
- }
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($called)
- ->isNull();
- }
-
- public function case_run_text_frame_and_continuation_frame_opcodes()
- {
- return $this->_case_run_x_frame_and_continuation_frame_opcodes(SUT::OPCODE_TEXT_FRAME);
- }
-
- public function case_run_binary_frame_and_continuation_frame_opcodes()
- {
- return $this->_case_run_x_frame_and_continuation_frame_opcodes(SUT::OPCODE_BINARY_FRAME);
- }
-
- protected function _case_run_x_frame_and_continuation_frame_opcodes($opcode)
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame[1] = [
- 'fin' => 0x0,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => $opcode,
- 'mask' => 0x1,
- 'length' => 3,
- 'message' => 'foo'
- ],
- $this->calling($protocol)->readFrame[2] = [
- 'fin' => 0x0,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_CONTINUATION_FRAME,
- 'mask' => 0x1,
- 'length' => 3,
- 'message' => 'bar'
- ],
- $this->calling($protocol)->readFrame[3] = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_CONTINUATION_FRAME,
- 'mask' => 0x1,
- 'length' => 3,
- 'message' => 'baz'
- ],
- $this->calling($socket)->getCurrentNode = $node,
-
- $connection->on(
- SUT::OPCODE_TEXT_FRAME === $opcode ? 'message' : 'binary-message',
- function (Event\Bucket $bucket) use (&$called, $self) {
- $called = true;
-
- $self
- ->array($bucket->getData())
- ->isEqualTo([
- 'message' => 'foobarbaz'
- ]);
-
- return;
- }
- )
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->integer($node->getNumberOfFragments())
- ->isEqualTo(1)
- ->string($node->getFragmentedMessage())
- ->isEqualTo('foo')
- ->boolean($node->isMessageComplete())
- ->isFalse()
- ->variable($called)
- ->isNull()
-
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->integer($node->getNumberOfFragments())
- ->isEqualTo(2)
- ->string($node->getFragmentedMessage())
- ->isEqualTo('foobar')
- ->boolean($node->isMessageComplete())
- ->isFalse()
- ->variable($called)
- ->isNull()
-
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->integer($node->getNumberOfFragments())
- ->isEqualTo(0)
- ->variable($node->getFragmentedMessage())
- ->isNull()
- ->boolean($node->isMessageComplete())
- ->isTrue()
- ->boolean($called)
- ->isTrue();
- }
-
- public function case_run_text_frame_and_continuation_frame_opcodes_with_an_exception_from_the_listener()
- {
- return $this->_case_run_x_frame_and_continuation_frame_opcodes_with_an_exception_from_the_listener(SUT::OPCODE_TEXT_FRAME);
- }
-
- public function case_run_binary_frame_and_continuation_frame_opcodes_with_an_exception_from_the_listener()
- {
- return $this->_case_run_x_frame_and_continuation_frame_opcodes_with_an_exception_from_the_listener(SUT::OPCODE_BINARY_FRAME);
- }
-
- protected function _case_run_x_frame_and_continuation_frame_opcodes_with_an_exception_from_the_listener($opcode)
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame[1] = [
- 'fin' => 0x0,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => $opcode,
- 'mask' => 0x1,
- 'length' => 3,
- 'message' => 'foo'
- ],
- $this->calling($protocol)->readFrame[2] = [
- 'fin' => 0x0,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_CONTINUATION_FRAME,
- 'mask' => 0x1,
- 'length' => 3,
- 'message' => 'bar'
- ],
- $this->calling($protocol)->readFrame[3] = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_CONTINUATION_FRAME,
- 'mask' => 0x1,
- 'length' => 3,
- 'message' => 'baz'
- ],
- $this->calling($socket)->getCurrentNode = $node,
-
- $connection->on(
- SUT::OPCODE_TEXT_FRAME === $opcode ? 'message' : 'binary-message',
- function (Event\Bucket $bucket) use (&$calledA, $self) {
- $calledA = true;
-
- $self
- ->array($bucket->getData())
- ->isEqualTo([
- 'message' => 'foobarbaz'
- ]);
-
- throw new \RuntimeException('bang');
- }
- ),
- $connection->on(
- 'error',
- function (Event\Bucket $bucket) use (&$calledB, $self) {
- $calledB = true;
-
- $self
- ->let($data = $bucket->getData())
- ->array($data)
- ->hasSize(1)
- ->hasKey('exception')
- ->exception($data['exception'])
- ->isInstanceOf(\RuntimeException::class)
- ->hasMessage('bang');
-
- return;
- }
- )
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->integer($node->getNumberOfFragments())
- ->isEqualTo(1)
- ->string($node->getFragmentedMessage())
- ->isEqualTo('foo')
- ->boolean($node->isMessageComplete())
- ->isFalse()
- ->variable($calledA)
- ->isNull()
- ->variable($calledB)
- ->isNull()
-
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->integer($node->getNumberOfFragments())
- ->isEqualTo(2)
- ->string($node->getFragmentedMessage())
- ->isEqualTo('foobar')
- ->boolean($node->isMessageComplete())
- ->isFalse()
- ->variable($calledA)
- ->isNull()
- ->variable($calledB)
- ->isNull()
-
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->integer($node->getNumberOfFragments())
- ->isEqualTo(0)
- ->variable($node->getFragmentedMessage())
- ->isNull()
- ->boolean($node->isMessageComplete())
- ->isTrue()
- ->boolean($calledA)
- ->isTrue()
- ->boolean($calledB)
- ->isTrue();
- }
-
- public function case_run_text_frame_and_continuation_frame_opcodes_with_invalid_message_encoding()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $this->calling($node)->getHandshake = SUCCEED,
- $this->calling($protocol)->readFrame[1] = [
- 'fin' => 0x0,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_TEXT_FRAME,
- 'mask' => 0x1,
- 'length' => 3,
- 'message' => 'foo'
- ],
- $this->calling($protocol)->readFrame[2] = [
- 'fin' => 0x1,
- 'rsv1' => 0x0,
- 'rsv2' => 0x0,
- 'rsv3' => 0x0,
- 'opcode' => SUT::OPCODE_CONTINUATION_FRAME,
- 'mask' => 0x1,
- 'length' => 6,
- 'message' => iconv('UTF-8', 'UTF-16', '😄')
- ],
- $this->calling($socket)->getCurrentNode = $node,
-
- $this->calling($connection)->close = function ($_code, $_reason) use (&$called, $self) {
- $called = true;
-
- $self
- ->integer($_code)
- ->isEqualTo(SUT::CLOSE_MESSAGE_ERROR)
- ->variable($_reason)
- ->isNull();
-
- return;
- }
- )
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->integer($node->getNumberOfFragments())
- ->isEqualTo(1)
- ->string($node->getFragmentedMessage())
- ->isEqualTo('foo')
- ->boolean($node->isMessageComplete())
- ->isFalse()
- ->variable($called)
- ->isNull()
-
- ->when($result = $this->invoke($connection)->_run($node))
- ->then
- ->integer($node->getNumberOfFragments())
- ->isEqualTo(0)
- ->variable($node->getFragmentedMessage())
- ->isNull()
- ->boolean($node->isMessageComplete())
- ->isTrue()
- ->boolean($called)
- ->isTrue();
- }
-
- public function case__send()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $message = 'foobar',
- $opcode = SUT::OPCODE_TEXT_FRAME,
- $end = true,
-
- $this->calling($node)->getHandshake = true,
- $this->calling($protocol)->send = function ($_message, $_opcode, $_end, $_mask) use (&$called, $self, $message, $opcode, $end) {
- $called = true;
-
- $self
- ->string($_message)
- ->isEqualTo($message)
- ->integer($_opcode)
- ->isEqualTo($opcode)
- ->boolean($_end)
- ->isEqualTo($end)
- ->boolean($_mask)
- ->isFalse();
-
- return 42;
- },
-
- $closure = $this->invoke($connection)->_send($message, $node)
- )
- ->when($result = new \ReflectionFunction($closure))
- ->then
- ->integer($result->getNumberOfRequiredParameters())
- ->isEqualTo(2)
-
- ->when($result = $closure($opcode, $end))
- ->then
- ->integer($result)
- ->isEqualTo(42)
- ->boolean($called)
- ->isTrue();
- }
-
- public function case__send_with_no_handshake()
- {
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $message = 'foobar',
- $opcode = SUT::OPCODE_TEXT_FRAME,
- $end = true,
-
- $this->calling($protocol)->send = function ($_message, $_opcode, $_end, $_mask) use (&$called) {
- $called = true;
-
- return 42;
- },
-
- $closure = $this->invoke($connection)->_send($message, $node)
- )
- ->when($result = new \ReflectionFunction($closure))
- ->then
- ->integer($result->getNumberOfRequiredParameters())
- ->isEqualTo(2)
-
- ->when($result = $closure($opcode, $end))
- ->then
- ->variable($result)
- ->isNull()
- ->variable($called)
- ->isNull();
- }
-
- public function case_close_with_no_protocol()
- {
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
-
- $this->calling($socket)->getCurrentNode = $node
- )
- ->when($result = $connection->close(SUT::CLOSE_DATA_ERROR, 'foo'))
- ->then
- ->variable($result)
- ->isNull()
- ->boolean($socket->isDisconnected())
- ->isTrue();
- }
-
- public function case_close()
- {
- $self = $this;
-
- $this
- ->given(
- $socket = new \Mock\Hoa\Socket\Client('tcp://*:1234'),
- $connection = new SUT($socket),
- $protocol = new \Mock\Hoa\Websocket\Protocol\Rfc6455($socket),
- $this->mockGenerator->orphanize('__construct'),
- $node = new \Mock\Hoa\Websocket\Node(),
- $node->setProtocolImplementation($protocol),
-
- $code = SUT::CLOSE_DATA_ERROR,
- $reason = 'foo',
-
- $this->calling($protocol)->close = function ($_code, $_reason) use (&$called, $self, $code, $reason) {
- $called = true;
-
- $self
- ->integer($_code)
- ->isEqualTo($code)
- ->string($_reason)
- ->isEqualTo($reason);
-
- return;
- },
- $this->calling($socket)->getCurrentNode = $node
- )
- ->when($result = $connection->close($code, $reason))
- ->then
- ->variable($result)
- ->isNull()
- ->boolean($socket->isDisconnected())
- ->isTrue()
- ->boolean($called)
- ->isTrue();
- }
- }
|