Skip to content

Commit 65dfe45

Browse files
committed
Update test suite to find next free file descriptor in advance (Mac)
1 parent 6aaae22 commit 65dfe45

File tree

2 files changed

+34
-28
lines changed

2 files changed

+34
-28
lines changed

tests/FdServerTest.php

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ public function testCtorAddsResourceToLoop()
1515
$this->markTestSkipped('Not supported on your platform');
1616
}
1717

18+
$fd = self::getNextFreeFd();
1819
$socket = stream_socket_server('127.0.0.1:0');
19-
$fd = self::getFdFromResource($socket);
20+
assert($socket !== false);
2021

2122
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
2223
$loop->expects($this->once())->method('addReadStream');
@@ -48,9 +49,7 @@ public function testCtorThrowsForUnknownFd()
4849
$this->markTestSkipped('Not supported on your platform');
4950
}
5051

51-
$socket = stream_socket_server('127.0.0.1:0');
52-
$fd = self::getFdFromResource($socket);
53-
fclose($socket);
52+
$fd = self::getNextFreeFd();
5453

5554
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
5655
$loop->expects($this->never())->method('addReadStream');
@@ -69,8 +68,9 @@ public function testCtorThrowsIfFdIsAFileAndNotASocket()
6968
$this->markTestSkipped('Not supported on your platform');
7069
}
7170

71+
$fd = self::getNextFreeFd();
7272
$tmpfile = tmpfile();
73-
$fd = self::getFdFromResource($tmpfile);
73+
assert($tmpfile !== false);
7474

7575
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
7676
$loop->expects($this->never())->method('addReadStream');
@@ -90,9 +90,10 @@ public function testCtorThrowsIfFdIsAConnectedSocketInsteadOfServerSocket()
9090
}
9191

9292
$socket = stream_socket_server('tcp://127.0.0.1:0');
93-
$client = stream_socket_client('tcp://' . stream_socket_get_name($socket, false));
9493

95-
$fd = self::getFdFromResource($client);
94+
$fd = self::getNextFreeFd();
95+
$client = stream_socket_client('tcp://' . stream_socket_get_name($socket, false));
96+
assert($client !== false);
9697

9798
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
9899
$loop->expects($this->never())->method('addReadStream');
@@ -111,8 +112,8 @@ public function testGetAddressReturnsSameAddressAsOriginalSocketForIpv4Socket()
111112
$this->markTestSkipped('Not supported on your platform');
112113
}
113114

115+
$fd = self::getNextFreeFd();
114116
$socket = stream_socket_server('127.0.0.1:0');
115-
$fd = self::getFdFromResource($socket);
116117

117118
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
118119

@@ -127,8 +128,8 @@ public function testGetAddressReturnsSameAddressAsOriginalSocketForIpv4SocketGiv
127128
$this->markTestSkipped('Not supported on your platform');
128129
}
129130

131+
$fd = self::getNextFreeFd();
130132
$socket = stream_socket_server('127.0.0.1:0');
131-
$fd = self::getFdFromResource($socket);
132133

133134
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
134135

@@ -143,13 +144,12 @@ public function testGetAddressReturnsSameAddressAsOriginalSocketForIpv6Socket()
143144
$this->markTestSkipped('Not supported on your platform');
144145
}
145146

147+
$fd = self::getNextFreeFd();
146148
$socket = @stream_socket_server('[::1]:0');
147149
if ($socket === false) {
148150
$this->markTestSkipped('Listening on IPv6 not supported');
149151
}
150152

151-
$fd = self::getFdFromResource($socket);
152-
153153
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
154154

155155
$server = new FdServer($fd, $loop);
@@ -164,13 +164,12 @@ public function testGetAddressReturnsSameAddressAsOriginalSocketForUnixDomainSoc
164164
$this->markTestSkipped('Not supported on your platform');
165165
}
166166

167+
$fd = self::getNextFreeFd();
167168
$socket = @stream_socket_server($this->getRandomSocketUri());
168169
if ($socket === false) {
169170
$this->markTestSkipped('Listening on Unix domain socket (UDS) not supported');
170171
}
171172

172-
$fd = self::getFdFromResource($socket);
173-
174173
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
175174

176175
$server = new FdServer($fd, $loop);
@@ -184,8 +183,9 @@ public function testGetAddressReturnsNullAfterClose()
184183
$this->markTestSkipped('Not supported on your platform');
185184
}
186185

186+
$fd = self::getNextFreeFd();
187187
$socket = stream_socket_server('127.0.0.1:0');
188-
$fd = self::getFdFromResource($socket);
188+
assert($socket !== false);
189189

190190
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
191191

@@ -201,8 +201,9 @@ public function testCloseRemovesResourceFromLoop()
201201
$this->markTestSkipped('Not supported on your platform');
202202
}
203203

204+
$fd = self::getNextFreeFd();
204205
$socket = stream_socket_server('127.0.0.1:0');
205-
$fd = self::getFdFromResource($socket);
206+
assert($socket !== false);
206207

207208
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
208209
$loop->expects($this->once())->method('removeReadStream');
@@ -217,8 +218,9 @@ public function testCloseTwiceRemovesResourceFromLoopOnce()
217218
$this->markTestSkipped('Not supported on your platform');
218219
}
219220

221+
$fd = self::getNextFreeFd();
220222
$socket = stream_socket_server('127.0.0.1:0');
221-
$fd = self::getFdFromResource($socket);
223+
assert($socket !== false);
222224

223225
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
224226
$loop->expects($this->once())->method('removeReadStream');
@@ -234,8 +236,9 @@ public function testResumeWithoutPauseIsNoOp()
234236
$this->markTestSkipped('Not supported on your platform');
235237
}
236238

239+
$fd = self::getNextFreeFd();
237240
$socket = stream_socket_server('127.0.0.1:0');
238-
$fd = self::getFdFromResource($socket);
241+
assert($socket !== false);
239242

240243
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
241244
$loop->expects($this->once())->method('addReadStream');
@@ -250,8 +253,9 @@ public function testPauseRemovesResourceFromLoop()
250253
$this->markTestSkipped('Not supported on your platform');
251254
}
252255

256+
$fd = self::getNextFreeFd();
253257
$socket = stream_socket_server('127.0.0.1:0');
254-
$fd = self::getFdFromResource($socket);
258+
assert($socket !== false);
255259

256260
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
257261
$loop->expects($this->once())->method('removeReadStream');
@@ -266,8 +270,9 @@ public function testPauseAfterPauseIsNoOp()
266270
$this->markTestSkipped('Not supported on your platform');
267271
}
268272

273+
$fd = self::getNextFreeFd();
269274
$socket = stream_socket_server('127.0.0.1:0');
270-
$fd = self::getFdFromResource($socket);
275+
assert($socket !== false);
271276

272277
$loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock();
273278
$loop->expects($this->once())->method('removeReadStream');
@@ -283,8 +288,9 @@ public function testServerEmitsConnectionEventForNewConnection()
283288
$this->markTestSkipped('Not supported on your platform');
284289
}
285290

291+
$fd = self::getNextFreeFd();
286292
$socket = stream_socket_server('127.0.0.1:0');
287-
$fd = self::getFdFromResource($socket);
293+
assert($socket !== false);
288294

289295
$client = stream_socket_client('tcp://' . stream_socket_get_name($socket, false));
290296

@@ -313,8 +319,9 @@ public function testEmitsErrorWhenAcceptListenerFails()
313319
return true;
314320
}));
315321

322+
$fd = self::getNextFreeFd();
316323
$socket = stream_socket_server('127.0.0.1:0');
317-
$fd = self::getFdFromResource($socket);
324+
assert($socket !== false);
318325

319326
$server = new FdServer($fd, $loop);
320327

@@ -351,26 +358,25 @@ public function testEmitsTimeoutErrorWhenAcceptListenerFails(\RuntimeException $
351358
}
352359

353360
/**
354-
* @param resource $resource
355361
* @return int
356362
* @throws \UnexpectedValueException
357363
* @throws \BadMethodCallException
358364
* @throws \UnderflowException
359365
* @copyright Copyright (c) 2018 Christian Lück, taken from https://github.com/clue/fd with permission
360366
*/
361-
public static function getFdFromResource($resource)
367+
public static function getNextFreeFd()
362368
{
363-
$stat = @fstat($resource);
364-
if (!isset($stat['ino']) || $stat['ino'] === 0) {
365-
throw new \UnexpectedValueException('Could not access inode of given resource (unsupported type or platform)');
366-
}
369+
// open tmpfile to occupy next free FD temporarily
370+
$tmp = tmpfile();
367371

368372
$dir = @scandir('/dev/fd');
369373
if ($dir === false) {
370374
throw new \BadMethodCallException('Not supported on your platform because /dev/fd is not readable');
371375
}
372376

377+
$stat = fstat($tmp);
373378
$ino = (int) $stat['ino'];
379+
374380
foreach ($dir as $file) {
375381
$stat = @stat('/dev/fd/' . $file);
376382
if (isset($stat['ino']) && $stat['ino'] === $ino) {

tests/SocketServerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ public function testConstructWithExistingFileDescriptorReturnsSameAddressAsOrigi
124124
$this->markTestSkipped('Not supported on your platform');
125125
}
126126

127+
$fd = FdServerTest::getNextFreeFd();
127128
$socket = stream_socket_server('127.0.0.1:0');
128-
$fd = FdServerTest::getFdFromResource($socket);
129129

130130
$server = new SocketServer('php://fd/' . $fd);
131131
$server->pause();

0 commit comments

Comments
 (0)