Skip to content

Commit a915115

Browse files
authored
Merge pull request #185 from clue-labs/tests-race
Improve test suite to avoid some possible race conditions
2 parents 1218d5a + 54fba44 commit a915115

1 file changed

Lines changed: 84 additions & 10 deletions

File tree

tests/FunctionalSecureServerTest.php

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,67 @@ public function setUp()
2424
}
2525
}
2626

27-
public function testEmitsConnectionForNewConnection()
27+
public function testClientCanConnectToServer()
2828
{
2929
$loop = Factory::create();
3030

3131
$server = new TcpServer(0, $loop);
3232
$server = new SecureServer($server, $loop, array(
3333
'local_cert' => __DIR__ . '/../examples/localhost.pem'
3434
));
35-
$server->on('connection', $this->expectCallableOnce());
3635

3736
$connector = new SecureConnector(new TcpConnector($loop), $loop, array(
3837
'verify_peer' => false
3938
));
4039
$promise = $connector->connect($server->getAddress());
4140

42-
Block\await($promise, $loop, self::TIMEOUT);
41+
/* @var ConnectionInterface $client */
42+
$client = Block\await($promise, $loop, self::TIMEOUT);
43+
44+
$this->assertInstanceOf('React\Socket\ConnectionInterface', $client);
45+
$this->assertEquals($server->getAddress(), $client->getRemoteAddress());
46+
47+
$client->close();
48+
$server->close();
49+
}
50+
51+
public function testServerEmitsConnectionForClientConnection()
52+
{
53+
$loop = Factory::create();
54+
55+
$server = new TcpServer(0, $loop);
56+
$server = new SecureServer($server, $loop, array(
57+
'local_cert' => __DIR__ . '/../examples/localhost.pem'
58+
));
59+
60+
$peer = new Promise(function ($resolve, $reject) use ($server) {
61+
$server->on('connection', $resolve);
62+
$server->on('error', $reject);
63+
});
64+
65+
$connector = new SecureConnector(new TcpConnector($loop), $loop, array(
66+
'verify_peer' => false
67+
));
68+
$client = $connector->connect($server->getAddress());
69+
70+
// await both client and server side end of connection
71+
/* @var ConnectionInterface[] $both */
72+
$both = Block\awaitAll(array($peer, $client), $loop, self::TIMEOUT);
73+
74+
// both ends of the connection are represented by different instances of ConnectionInterface
75+
$this->assertCount(2, $both);
76+
$this->assertInstanceOf('React\Socket\ConnectionInterface', $both[0]);
77+
$this->assertInstanceOf('React\Socket\ConnectionInterface', $both[1]);
78+
$this->assertNotSame($both[0], $both[1]);
79+
80+
// server side end has local server address and client end has remote server address
81+
$this->assertEquals($server->getAddress(), $both[0]->getLocalAddress());
82+
$this->assertEquals($server->getAddress(), $both[1]->getRemoteAddress());
83+
84+
// clean up all connections and server again
85+
$both[0]->close();
86+
$both[1]->close();
87+
$server->close();
4388
}
4489

4590
public function testWritesDataToConnection()
@@ -275,7 +320,7 @@ public function testEmitsErrorForClientWithTlsVersionMismatch()
275320
Block\await($promise, $loop, self::TIMEOUT);
276321
}
277322

278-
public function testEmitsConnectionForNewConnectionWithEncryptedCertificate()
323+
public function testServerEmitsConnectionForNewConnectionWithEncryptedCertificate()
279324
{
280325
$loop = Factory::create();
281326

@@ -284,26 +329,30 @@ public function testEmitsConnectionForNewConnectionWithEncryptedCertificate()
284329
'local_cert' => __DIR__ . '/../examples/localhost_swordfish.pem',
285330
'passphrase' => 'swordfish'
286331
));
287-
$server->on('connection', $this->expectCallableOnce());
332+
333+
$peer = new Promise(function ($resolve, $reject) use ($server) {
334+
$server->on('connection', $resolve);
335+
$server->on('error', $reject);
336+
});
288337

289338
$connector = new SecureConnector(new TcpConnector($loop), $loop, array(
290339
'verify_peer' => false
291340
));
292-
$promise = $connector->connect($server->getAddress());
341+
$connector->connect($server->getAddress());
293342

294-
Block\await($promise, $loop, self::TIMEOUT);
343+
$connection = Block\await($peer, $loop, self::TIMEOUT);
344+
345+
$this->assertInstanceOf('React\Socket\ConnectionInterface', $connection);
295346
}
296347

297-
public function testEmitsErrorForServerWithInvalidCertificate()
348+
public function testClientRejectsWithErrorForServerWithInvalidCertificate()
298349
{
299350
$loop = Factory::create();
300351

301352
$server = new TcpServer(0, $loop);
302353
$server = new SecureServer($server, $loop, array(
303354
'local_cert' => 'invalid.pem'
304355
));
305-
$server->on('connection', $this->expectCallableNever());
306-
$server->on('error', $this->expectCallableOnce());
307356

308357
$connector = new SecureConnector(new TcpConnector($loop), $loop, array(
309358
'verify_peer' => false
@@ -314,6 +363,31 @@ public function testEmitsErrorForServerWithInvalidCertificate()
314363
Block\await($promise, $loop, self::TIMEOUT);
315364
}
316365

366+
public function testServerEmitsErrorForClientWithInvalidCertificate()
367+
{
368+
$loop = Factory::create();
369+
370+
$server = new TcpServer(0, $loop);
371+
$server = new SecureServer($server, $loop, array(
372+
'local_cert' => 'invalid.pem'
373+
));
374+
375+
$peer = new Promise(function ($resolve, $reject) use ($server) {
376+
$server->on('connection', function () use ($reject) {
377+
$reject(new \RuntimeException('Did not expect connection to succeed'));
378+
});
379+
$server->on('error', $reject);
380+
});
381+
382+
$connector = new SecureConnector(new TcpConnector($loop), $loop, array(
383+
'verify_peer' => false
384+
));
385+
$connector->connect($server->getAddress());
386+
387+
$this->setExpectedException('RuntimeException', 'handshake');
388+
Block\await($peer, $loop, self::TIMEOUT);
389+
}
390+
317391
public function testEmitsErrorForServerWithEncryptedCertificateMissingPassphrase()
318392
{
319393
$loop = Factory::create();

0 commit comments

Comments
 (0)