Skip to content

Commit be35aef

Browse files
committed
Add tests
1 parent 43d9416 commit be35aef

File tree

1 file changed

+277
-0
lines changed

1 file changed

+277
-0
lines changed

tests/UnixServerTest.php

Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
<?php
2+
3+
namespace React\Tests\Socket;
4+
5+
use React\EventLoop\StreamSelectLoop;
6+
use React\Socket\UnixServer;
7+
use React\Stream\DuplexResourceStream;
8+
9+
class UnixServerTest extends TestCase
10+
{
11+
private $loop;
12+
private $server;
13+
private $uds;
14+
15+
private function createLoop()
16+
{
17+
return new StreamSelectLoop();
18+
}
19+
20+
/**
21+
* @covers React\Socket\UnixServer::__construct
22+
* @covers React\Socket\UnixServer::getAddress
23+
*/
24+
public function setUp()
25+
{
26+
$this->loop = $this->createLoop();
27+
$this->uds = $this->getRandomSocketUri();
28+
$this->server = new UnixServer($this->uds, $this->loop);
29+
}
30+
31+
/**
32+
* @covers React\Socket\UnixServer::handleConnection
33+
*/
34+
public function testConnection()
35+
{
36+
$client = stream_socket_client($this->uds);
37+
38+
$this->server->on('connection', $this->expectCallableOnce());
39+
$this->loop->tick();
40+
}
41+
42+
/**
43+
* @covers React\Socket\UnixServer::handleConnection
44+
*/
45+
public function testConnectionWithManyClients()
46+
{
47+
$client1 = stream_socket_client($this->uds);
48+
$client2 = stream_socket_client($this->uds);
49+
$client3 = stream_socket_client($this->uds);
50+
51+
$this->server->on('connection', $this->expectCallableExactly(3));
52+
$this->loop->tick();
53+
$this->loop->tick();
54+
$this->loop->tick();
55+
}
56+
57+
public function testDataEventWillNotBeEmittedWhenClientSendsNoData()
58+
{
59+
$client = stream_socket_client($this->uds);
60+
61+
$mock = $this->expectCallableNever();
62+
63+
$this->server->on('connection', function ($conn) use ($mock) {
64+
$conn->on('data', $mock);
65+
});
66+
$this->loop->tick();
67+
$this->loop->tick();
68+
}
69+
70+
public function testDataWillBeEmittedWithDataClientSends()
71+
{
72+
$client = stream_socket_client($this->uds);
73+
74+
fwrite($client, "foo\n");
75+
76+
$mock = $this->expectCallableOnceWith("foo\n");
77+
78+
$this->server->on('connection', function ($conn) use ($mock) {
79+
$conn->on('data', $mock);
80+
});
81+
$this->loop->tick();
82+
$this->loop->tick();
83+
}
84+
85+
public function testDataWillBeEmittedEvenWhenClientShutsDownAfterSending()
86+
{
87+
$client = stream_socket_client($this->uds);
88+
fwrite($client, "foo\n");
89+
stream_socket_shutdown($client, STREAM_SHUT_WR);
90+
91+
$mock = $this->expectCallableOnceWith("foo\n");
92+
93+
$this->server->on('connection', function ($conn) use ($mock) {
94+
$conn->on('data', $mock);
95+
});
96+
$this->loop->tick();
97+
$this->loop->tick();
98+
}
99+
100+
public function testLoopWillEndWhenServerIsClosed()
101+
{
102+
// explicitly unset server because we already call close()
103+
$this->server->close();
104+
$this->server = null;
105+
106+
$this->loop->run();
107+
}
108+
109+
public function testCloseTwiceIsNoOp()
110+
{
111+
$this->server->close();
112+
$this->server->close();
113+
}
114+
115+
public function testGetAddressAfterCloseReturnsNull()
116+
{
117+
$this->server->close();
118+
$this->assertNull($this->server->getAddress());
119+
}
120+
121+
public function testLoopWillEndWhenServerIsClosedAfterSingleConnection()
122+
{
123+
$client = stream_socket_client($this->uds);
124+
125+
// explicitly unset server because we only accept a single connection
126+
// and then already call close()
127+
$server = $this->server;
128+
$this->server = null;
129+
130+
$server->on('connection', function ($conn) use ($server) {
131+
$conn->close();
132+
$server->close();
133+
});
134+
135+
$this->loop->run();
136+
}
137+
138+
public function testDataWillBeEmittedInMultipleChunksWhenClientSendsExcessiveAmounts()
139+
{
140+
$client = stream_socket_client($this->uds);
141+
$stream = new DuplexResourceStream($client, $this->loop);
142+
143+
$bytes = 1024 * 1024;
144+
$stream->end(str_repeat('*', $bytes));
145+
146+
$mock = $this->expectCallableOnce();
147+
148+
// explicitly unset server because we only accept a single connection
149+
// and then already call close()
150+
$server = $this->server;
151+
$this->server = null;
152+
153+
$received = 0;
154+
$server->on('connection', function ($conn) use ($mock, &$received, $server) {
155+
// count number of bytes received
156+
$conn->on('data', function ($data) use (&$received) {
157+
$received += strlen($data);
158+
});
159+
160+
$conn->on('end', $mock);
161+
162+
// do not await any further connections in order to let the loop terminate
163+
$server->close();
164+
});
165+
166+
$this->loop->run();
167+
168+
$this->assertEquals($bytes, $received);
169+
}
170+
171+
/**
172+
* @covers React\EventLoop\StreamSelectLoop::tick
173+
*/
174+
public function testConnectionDoesNotEndWhenClientDoesNotClose()
175+
{
176+
$client = stream_socket_client($this->uds);
177+
178+
$mock = $this->expectCallableNever();
179+
180+
$this->server->on('connection', function ($conn) use ($mock) {
181+
$conn->on('end', $mock);
182+
});
183+
$this->loop->tick();
184+
$this->loop->tick();
185+
}
186+
187+
/**
188+
* @covers React\EventLoop\StreamSelectLoop::tick
189+
* @covers React\Socket\Connection::end
190+
*/
191+
public function testConnectionDoesEndWhenClientCloses()
192+
{
193+
$client = stream_socket_client($this->uds);
194+
195+
fclose($client);
196+
197+
$mock = $this->expectCallableOnce();
198+
199+
$this->server->on('connection', function ($conn) use ($mock) {
200+
$conn->on('end', $mock);
201+
});
202+
$this->loop->tick();
203+
$this->loop->tick();
204+
}
205+
206+
public function testCtorAddsResourceToLoop()
207+
{
208+
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
209+
$loop->expects($this->once())->method('addReadStream');
210+
211+
$server = new UnixServer($this->getRandomSocketUri(), $loop);
212+
}
213+
214+
public function testResumeWithoutPauseIsNoOp()
215+
{
216+
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
217+
$loop->expects($this->once())->method('addReadStream');
218+
219+
$server = new UnixServer($this->getRandomSocketUri(), $loop);
220+
$server->resume();
221+
}
222+
223+
public function testPauseRemovesResourceFromLoop()
224+
{
225+
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
226+
$loop->expects($this->once())->method('removeReadStream');
227+
228+
$server = new UnixServer($this->getRandomSocketUri(), $loop);
229+
$server->pause();
230+
}
231+
232+
public function testPauseAfterPauseIsNoOp()
233+
{
234+
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
235+
$loop->expects($this->once())->method('removeReadStream');
236+
237+
$server = new UnixServer($this->getRandomSocketUri(), $loop);
238+
$server->pause();
239+
$server->pause();
240+
}
241+
242+
public function testCloseRemovesResourceFromLoop()
243+
{
244+
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
245+
$loop->expects($this->once())->method('removeReadStream');
246+
247+
$server = new UnixServer($this->getRandomSocketUri(), $loop);
248+
$server->close();
249+
}
250+
251+
/**
252+
* @expectedException RuntimeException
253+
*/
254+
public function testListenOnBusyPortThrows()
255+
{
256+
if (DIRECTORY_SEPARATOR === '\\') {
257+
$this->markTestSkipped('Windows supports listening on same port multiple times');
258+
}
259+
260+
$another = new UnixServer($this->uds, $this->loop);
261+
}
262+
263+
/**
264+
* @covers React\Socket\UnixServer::close
265+
*/
266+
public function tearDown()
267+
{
268+
if ($this->server) {
269+
$this->server->close();
270+
}
271+
}
272+
273+
private function getRandomSocketUri()
274+
{
275+
return "unix://" . uniqid(rand(), true) . '.sock';
276+
}
277+
}

0 commit comments

Comments
 (0)