A text, audio and video chat application built with webRTC and Ratchet (PHP WebSocket)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

498 lines
12 KiB

<?php
namespace React\Tests\EventLoop;
abstract class AbstractLoopTest extends TestCase
{
/**
* @var \React\EventLoop\LoopInterface
*/
protected $loop;
public function setUp()
{
$this->loop = $this->createLoop();
}
abstract public function createLoop();
public function createStream()
{
return fopen('php://temp', 'r+');
}
public function writeToStream($stream, $content)
{
fwrite($stream, $content);
rewind($stream);
}
public function testAddReadStream()
{
$input = $this->createStream();
$this->loop->addReadStream($input, $this->expectCallableExactly(2));
$this->writeToStream($input, "foo\n");
$this->loop->tick();
$this->writeToStream($input, "bar\n");
$this->loop->tick();
}
public function testAddWriteStream()
{
$input = $this->createStream();
$this->loop->addWriteStream($input, $this->expectCallableExactly(2));
$this->loop->tick();
$this->loop->tick();
}
public function testRemoveReadStreamInstantly()
{
$input = $this->createStream();
$this->loop->addReadStream($input, $this->expectCallableNever());
$this->loop->removeReadStream($input);
$this->writeToStream($input, "bar\n");
$this->loop->tick();
}
public function testRemoveReadStreamAfterReading()
{
$input = $this->createStream();
$this->loop->addReadStream($input, $this->expectCallableOnce());
$this->writeToStream($input, "foo\n");
$this->loop->tick();
$this->loop->removeReadStream($input);
$this->writeToStream($input, "bar\n");
$this->loop->tick();
}
public function testRemoveWriteStreamInstantly()
{
$input = $this->createStream();
$this->loop->addWriteStream($input, $this->expectCallableNever());
$this->loop->removeWriteStream($input);
$this->loop->tick();
}
public function testRemoveWriteStreamAfterWriting()
{
$input = $this->createStream();
$this->loop->addWriteStream($input, $this->expectCallableOnce());
$this->loop->tick();
$this->loop->removeWriteStream($input);
$this->loop->tick();
}
public function testRemoveStreamInstantly()
{
$input = $this->createStream();
$this->loop->addReadStream($input, $this->expectCallableNever());
$this->loop->addWriteStream($input, $this->expectCallableNever());
$this->loop->removeStream($input);
$this->writeToStream($input, "bar\n");
$this->loop->tick();
}
public function testRemoveStreamForReadOnly()
{
$input = $this->createStream();
$this->loop->addReadStream($input, $this->expectCallableNever());
$this->loop->addWriteStream($input, $this->expectCallableOnce());
$this->loop->removeReadStream($input);
$this->writeToStream($input, "foo\n");
$this->loop->tick();
}
public function testRemoveStreamForWriteOnly()
{
$input = $this->createStream();
$this->writeToStream($input, "foo\n");
$this->loop->addReadStream($input, $this->expectCallableOnce());
$this->loop->addWriteStream($input, $this->expectCallableNever());
$this->loop->removeWriteStream($input);
$this->loop->tick();
}
public function testRemoveStream()
{
$input = $this->createStream();
$this->loop->addReadStream($input, $this->expectCallableOnce());
$this->loop->addWriteStream($input, $this->expectCallableOnce());
$this->writeToStream($input, "bar\n");
$this->loop->tick();
$this->loop->removeStream($input);
$this->writeToStream($input, "bar\n");
$this->loop->tick();
}
public function testRemoveInvalid()
{
$stream = $this->createStream();
// remove a valid stream from the event loop that was never added in the first place
$this->loop->removeReadStream($stream);
$this->loop->removeWriteStream($stream);
$this->loop->removeStream($stream);
}
/** @test */
public function emptyRunShouldSimplyReturn()
{
$this->assertRunFasterThan(0.005);
}
/** @test */
public function runShouldReturnWhenNoMoreFds()
{
$input = $this->createStream();
$loop = $this->loop;
$this->loop->addReadStream($input, function ($stream) use ($loop) {
$loop->removeStream($stream);
});
$this->writeToStream($input, "foo\n");
$this->assertRunFasterThan(0.015);
}
/** @test */
public function stopShouldStopRunningLoop()
{
$input = $this->createStream();
$loop = $this->loop;
$this->loop->addReadStream($input, function ($stream) use ($loop) {
$loop->stop();
});
$this->writeToStream($input, "foo\n");
$this->assertRunFasterThan(0.005);
}
public function testStopShouldPreventRunFromBlocking($timeLimit = 0.005)
{
$this->loop->addTimer(
1,
function () {
$this->fail('Timer was executed.');
}
);
$this->loop->nextTick(
function () {
$this->loop->stop();
}
);
$this->assertRunFasterThan($timeLimit);
}
public function testIgnoreRemovedCallback()
{
// two independent streams, both should be readable right away
$stream1 = $this->createStream();
$stream2 = $this->createStream();
$loop = $this->loop;
$loop->addReadStream($stream1, function ($stream) use ($loop, $stream2) {
// stream1 is readable, remove stream2 as well => this will invalidate its callback
$loop->removeReadStream($stream);
$loop->removeReadStream($stream2);
});
// this callback would have to be called as well, but the first stream already removed us
$loop->addReadStream($stream2, $this->expectCallableNever());
$this->writeToStream($stream1, "foo\n");
$this->writeToStream($stream2, "foo\n");
$loop->run();
}
public function testNextTick()
{
$called = false;
$callback = function ($loop) use (&$called) {
$this->assertSame($this->loop, $loop);
$called = true;
};
$this->loop->nextTick($callback);
$this->assertFalse($called);
$this->loop->tick();
$this->assertTrue($called);
}
public function testNextTickFiresBeforeIO()
{
$stream = $this->createStream();
$this->loop->addWriteStream(
$stream,
function () {
echo 'stream' . PHP_EOL;
}
);
$this->loop->nextTick(
function () {
echo 'next-tick' . PHP_EOL;
}
);
$this->expectOutputString('next-tick' . PHP_EOL . 'stream' . PHP_EOL);
$this->loop->tick();
}
public function testRecursiveNextTick()
{
$stream = $this->createStream();
$this->loop->addWriteStream(
$stream,
function () {
echo 'stream' . PHP_EOL;
}
);
$this->loop->nextTick(
function () {
$this->loop->nextTick(
function () {
echo 'next-tick' . PHP_EOL;
}
);
}
);
$this->expectOutputString('next-tick' . PHP_EOL . 'stream' . PHP_EOL);
$this->loop->tick();
}
public function testRunWaitsForNextTickEvents()
{
$stream = $this->createStream();
$this->loop->addWriteStream(
$stream,
function () use ($stream) {
$this->loop->removeStream($stream);
$this->loop->nextTick(
function () {
echo 'next-tick' . PHP_EOL;
}
);
}
);
$this->expectOutputString('next-tick' . PHP_EOL);
$this->loop->run();
}
public function testNextTickEventGeneratedByFutureTick()
{
$stream = $this->createStream();
$this->loop->futureTick(
function () {
$this->loop->nextTick(
function () {
echo 'next-tick' . PHP_EOL;
}
);
}
);
$this->expectOutputString('next-tick' . PHP_EOL);
$this->loop->run();
}
public function testNextTickEventGeneratedByTimer()
{
$this->loop->addTimer(
0.001,
function () {
$this->loop->nextTick(
function () {
echo 'next-tick' . PHP_EOL;
}
);
}
);
$this->expectOutputString('next-tick' . PHP_EOL);
$this->loop->run();
}
public function testFutureTick()
{
$called = false;
$callback = function ($loop) use (&$called) {
$this->assertSame($this->loop, $loop);
$called = true;
};
$this->loop->futureTick($callback);
$this->assertFalse($called);
$this->loop->tick();
$this->assertTrue($called);
}
public function testFutureTickFiresBeforeIO()
{
$stream = $this->createStream();
$this->loop->addWriteStream(
$stream,
function () {
echo 'stream' . PHP_EOL;
}
);
$this->loop->futureTick(
function () {
echo 'future-tick' . PHP_EOL;
}
);
$this->expectOutputString('future-tick' . PHP_EOL . 'stream' . PHP_EOL);
$this->loop->tick();
}
public function testRecursiveFutureTick()
{
$stream = $this->createStream();
$this->loop->addWriteStream(
$stream,
function () use ($stream) {
echo 'stream' . PHP_EOL;
$this->loop->removeWriteStream($stream);
}
);
$this->loop->futureTick(
function () {
echo 'future-tick-1' . PHP_EOL;
$this->loop->futureTick(
function () {
echo 'future-tick-2' . PHP_EOL;
}
);
}
);
$this->expectOutputString('future-tick-1' . PHP_EOL . 'stream' . PHP_EOL . 'future-tick-2' . PHP_EOL);
$this->loop->run();
}
public function testRunWaitsForFutureTickEvents()
{
$stream = $this->createStream();
$this->loop->addWriteStream(
$stream,
function () use ($stream) {
$this->loop->removeStream($stream);
$this->loop->futureTick(
function () {
echo 'future-tick' . PHP_EOL;
}
);
}
);
$this->expectOutputString('future-tick' . PHP_EOL);
$this->loop->run();
}
public function testFutureTickEventGeneratedByNextTick()
{
$stream = $this->createStream();
$this->loop->nextTick(
function () {
$this->loop->futureTick(
function () {
echo 'future-tick' . PHP_EOL;
}
);
}
);
$this->expectOutputString('future-tick' . PHP_EOL);
$this->loop->run();
}
public function testFutureTickEventGeneratedByTimer()
{
$this->loop->addTimer(
0.001,
function () {
$this->loop->futureTick(
function () {
echo 'future-tick' . PHP_EOL;
}
);
}
);
$this->expectOutputString('future-tick' . PHP_EOL);
$this->loop->run();
}
private function assertRunFasterThan($maxInterval)
{
$start = microtime(true);
$this->loop->run();
$end = microtime(true);
$interval = $end - $start;
$this->assertLessThan($maxInterval, $interval);
}
}