Skip to content

Commit 612b7c1

Browse files
authored
Merge pull request #51 from clue-labs/tests
Improve test suite and switch to normal stream handler
2 parents bf7b31e + e350a1c commit 612b7c1

File tree

4 files changed

+92
-44
lines changed

4 files changed

+92
-44
lines changed

src/Connection.php

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,6 @@
1414
*/
1515
class Connection extends Stream implements ConnectionInterface
1616
{
17-
public function handleData($stream)
18-
{
19-
// Socket is raw, not using fread as it's interceptable by filters
20-
// See issues #192, #209, and #240
21-
$data = stream_socket_recvfrom($stream, $this->bufferSize);
22-
if ('' !== $data && false !== $data) {
23-
$this->emit('data', array($data, $this));
24-
}
25-
26-
if ('' === $data || false === $data || !is_resource($stream) || feof($stream)) {
27-
$this->end();
28-
}
29-
}
30-
3117
public function handleClose()
3218
{
3319
if (is_resource($this->stream)) {

tests/ConnectionTest.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,9 @@ public function testGetRemoteAddress()
2929

3030
$servConn = new Connection($server->master, $loop);
3131

32-
$mock = $this->createCallableMock();
33-
$mock
34-
->expects($this->once())
35-
->method('__invoke')
36-
->with($method->invokeArgs($servConn, array(stream_socket_get_name($master->getValue($server), false))))
37-
;
32+
$mock = $this->expectCallableOnceWith(
33+
$method->invokeArgs($servConn, array(stream_socket_get_name($master->getValue($server), false)))
34+
);
3835

3936
$server->on('connection', function ($conn) use ($mock) {
4037
$mock($conn->getRemoteAddress());

tests/ServerTest.php

Lines changed: 78 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use React\Socket\Server;
66
use React\EventLoop\StreamSelectLoop;
7+
use React\Stream\Stream;
78

89
class ServerTest extends TestCase
910
{
@@ -64,7 +65,7 @@ public function testConnectionWithManyClients()
6465
* @covers React\EventLoop\StreamSelectLoop::tick
6566
* @covers React\Socket\Connection::handleData
6667
*/
67-
public function testDataWithNoData()
68+
public function testDataEventWillNotBeEmittedWhenClientSendsNoData()
6869
{
6970
$client = stream_socket_client('tcp://localhost:'.$this->port);
7071

@@ -81,17 +82,13 @@ public function testDataWithNoData()
8182
* @covers React\EventLoop\StreamSelectLoop::tick
8283
* @covers React\Socket\Connection::handleData
8384
*/
84-
public function testData()
85+
public function testDataWillBeEmittedWithDataClientSends()
8586
{
8687
$client = stream_socket_client('tcp://localhost:'.$this->port);
8788

8889
fwrite($client, "foo\n");
8990

90-
$mock = $this->createCallableMock();
91-
$mock
92-
->expects($this->once())
93-
->method('__invoke')
94-
->with("foo\n");
91+
$mock = $this->expectCallableOnceWith("foo\n");
9592

9693
$this->server->on('connection', function ($conn) use ($mock) {
9794
$conn->on('data', $mock);
@@ -101,23 +98,16 @@ public function testData()
10198
}
10299

103100
/**
104-
* Test data sent from python language
105-
*
106101
* @covers React\EventLoop\StreamSelectLoop::tick
107102
* @covers React\Socket\Connection::handleData
108103
*/
109-
public function testDataSentFromPy()
104+
public function testDataWillBeEmittedEvenWhenClientShutsDownAfterSending()
110105
{
111106
$client = stream_socket_client('tcp://localhost:' . $this->port);
112107
fwrite($client, "foo\n");
113108
stream_socket_shutdown($client, STREAM_SHUT_WR);
114109

115-
$mock = $this->createCallableMock();
116-
$mock
117-
->expects($this->once())
118-
->method('__invoke')
119-
->with("foo\n");
120-
110+
$mock = $this->expectCallableOnceWith("foo\n");
121111

122112
$this->server->on('connection', function ($conn) use ($mock) {
123113
$conn->on('data', $mock);
@@ -126,17 +116,13 @@ public function testDataSentFromPy()
126116
$this->loop->tick();
127117
}
128118

129-
public function testFragmentedMessage()
119+
public function testDataWillBeFragmentedToBufferSize()
130120
{
131121
$client = stream_socket_client('tcp://localhost:' . $this->port);
132122

133123
fwrite($client, "Hello World!\n");
134124

135-
$mock = $this->createCallableMock();
136-
$mock
137-
->expects($this->once())
138-
->method('__invoke')
139-
->with("He");
125+
$mock = $this->expectCallableOnceWith("He");
140126

141127
$this->server->on('connection', function ($conn) use ($mock) {
142128
$conn->bufferSize = 2;
@@ -146,10 +132,69 @@ public function testFragmentedMessage()
146132
$this->loop->tick();
147133
}
148134

135+
public function testLoopWillEndWhenServerIsShutDown()
136+
{
137+
// explicitly unset server because we already call shutdown()
138+
$this->server->shutdown();
139+
$this->server = null;
140+
141+
$this->loop->run();
142+
}
143+
144+
public function testLoopWillEndWhenServerIsShutDownAfterSingleConnection()
145+
{
146+
$client = stream_socket_client('tcp://localhost:' . $this->port);
147+
148+
// explicitly unset server because we only accept a single connection
149+
// and then already call shutdown()
150+
$server = $this->server;
151+
$this->server = null;
152+
153+
$server->on('connection', function ($conn) use ($server) {
154+
$conn->close();
155+
$server->shutdown();
156+
});
157+
158+
$this->loop->run();
159+
}
160+
161+
public function testDataWillBeEmittedInMultipleChunksWhenClientSendsExcessiveAmounts()
162+
{
163+
$client = stream_socket_client('tcp://localhost:' . $this->port);
164+
$stream = new Stream($client, $this->loop);
165+
166+
$bytes = 1024 * 1024;
167+
$stream->end(str_repeat('*', $bytes));
168+
169+
$mock = $this->expectCallableOnce();
170+
171+
// explicitly unset server because we only accept a single connection
172+
// and then already call shutdown()
173+
$server = $this->server;
174+
$this->server = null;
175+
176+
$received = 0;
177+
$server->on('connection', function ($conn) use ($mock, &$received, $server) {
178+
// count number of bytes received
179+
$conn->on('data', function ($data) use (&$received) {
180+
$received += strlen($data);
181+
});
182+
183+
$conn->on('end', $mock);
184+
185+
// do not await any further connections in order to let the loop terminate
186+
$server->shutdown();
187+
});
188+
189+
$this->loop->run();
190+
191+
$this->assertEquals($bytes, $received);
192+
}
193+
149194
/**
150195
* @covers React\EventLoop\StreamSelectLoop::tick
151196
*/
152-
public function testDisconnectWithoutDisconnect()
197+
public function testConnectionDoesNotEndWhenClientDoesNotClose()
153198
{
154199
$client = stream_socket_client('tcp://localhost:'.$this->port);
155200

@@ -166,7 +211,7 @@ public function testDisconnectWithoutDisconnect()
166211
* @covers React\EventLoop\StreamSelectLoop::tick
167212
* @covers React\Socket\Connection::end
168213
*/
169-
public function testDisconnect()
214+
public function testConnectionDoesEndWhenClientCloses()
170215
{
171216
$client = stream_socket_client('tcp://localhost:'.$this->port);
172217

@@ -181,6 +226,15 @@ public function testDisconnect()
181226
$this->loop->tick();
182227
}
183228

229+
/**
230+
* @expectedException React\Socket\ConnectionException
231+
*/
232+
public function testListenOnBusyPortThrows()
233+
{
234+
$another = new Server($this->loop);
235+
$another->listen($this->port);
236+
}
237+
184238
/**
185239
* @covers React\Socket\Server::shutdown
186240
*/

tests/TestCase.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ protected function expectCallableOnce()
2424
return $mock;
2525
}
2626

27+
protected function expectCallableOnceWith($value)
28+
{
29+
$mock = $this->createCallableMock();
30+
$mock
31+
->expects($this->once())
32+
->method('__invoke')
33+
->with($value);
34+
35+
return $mock;
36+
}
37+
2738
protected function expectCallableNever()
2839
{
2940
$mock = $this->createCallableMock();

0 commit comments

Comments
 (0)