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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy