98 lines
3.1 KiB
PHP
98 lines
3.1 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace Blax\WebRtc\Tests;
|
||
|
|
|
||
|
|
use Blax\WebRtc\Media\Rust\ControlClient;
|
||
|
|
use Blax\WebRtc\Media\Rust\SidecarException;
|
||
|
|
use PHPUnit\Framework\TestCase;
|
||
|
|
|
||
|
|
final class ControlClientTest extends TestCase
|
||
|
|
{
|
||
|
|
/** @var resource */
|
||
|
|
private $sidecar;
|
||
|
|
|
||
|
|
private ControlClient $client;
|
||
|
|
|
||
|
|
protected function setUp(): void
|
||
|
|
{
|
||
|
|
[$theirs, $ours] = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
|
||
|
|
$this->sidecar = $theirs;
|
||
|
|
$this->client = ControlClient::fromStream($ours);
|
||
|
|
}
|
||
|
|
|
||
|
|
private function sidecarSays(array ...$lines): void
|
||
|
|
{
|
||
|
|
foreach ($lines as $line) {
|
||
|
|
fwrite($this->sidecar, json_encode($line)."\n");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private function sidecarHeard(): array
|
||
|
|
{
|
||
|
|
return json_decode((string) fgets($this->sidecar), true);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_request_frames_json_lines_and_matches_the_reply_id(): void
|
||
|
|
{
|
||
|
|
$this->sidecarSays(['id' => 1, 'ok' => true, 'answer' => 'v=answer']);
|
||
|
|
|
||
|
|
$reply = $this->client->request('add_peer', ['room' => 'r1', 'peer' => 'p1', 'offer' => 'v=0']);
|
||
|
|
|
||
|
|
$this->assertSame('v=answer', $reply['answer']);
|
||
|
|
$this->assertSame(
|
||
|
|
['id' => 1, 'cmd' => 'add_peer', 'room' => 'r1', 'peer' => 'p1', 'offer' => 'v=0'],
|
||
|
|
$this->sidecarHeard(),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_pushed_events_are_buffered_not_mistaken_for_replies(): void
|
||
|
|
{
|
||
|
|
$this->sidecarSays(
|
||
|
|
['event' => 'peer_left', 'room' => 'r1', 'peer' => 'p9', 'seconds' => 12.5],
|
||
|
|
['id' => 1, 'ok' => true],
|
||
|
|
);
|
||
|
|
|
||
|
|
$this->client->request('ping');
|
||
|
|
|
||
|
|
$events = $this->client->drainEvents();
|
||
|
|
$this->assertCount(1, $events);
|
||
|
|
$this->assertSame('peer_left', $events[0]['event']);
|
||
|
|
$this->assertSame([], $this->client->drainEvents(), 'drain clears the buffer');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_ok_false_replies_throw_with_the_sidecar_error(): void
|
||
|
|
{
|
||
|
|
$this->sidecarSays(['id' => 1, 'ok' => false, 'error' => 'no such peer: r1/ghost']);
|
||
|
|
|
||
|
|
$this->expectException(SidecarException::class);
|
||
|
|
$this->expectExceptionMessage('no such peer: r1/ghost');
|
||
|
|
|
||
|
|
$this->client->request('mute_peer', ['room' => 'r1', 'peer' => 'ghost', 'muted' => true]);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_a_closed_sidecar_throws_instead_of_hanging(): void
|
||
|
|
{
|
||
|
|
// Half-close: the sidecar stops sending (EOF on our reads) but still
|
||
|
|
// accepts our write — exercising the read-path failure.
|
||
|
|
stream_socket_shutdown($this->sidecar, STREAM_SHUT_WR);
|
||
|
|
|
||
|
|
$this->expectException(SidecarException::class);
|
||
|
|
$this->expectExceptionMessage('closed or timed out');
|
||
|
|
|
||
|
|
$this->client->request('ping');
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_ids_increment_across_requests(): void
|
||
|
|
{
|
||
|
|
$this->sidecarSays(['id' => 1, 'ok' => true], ['id' => 2, 'ok' => true]);
|
||
|
|
|
||
|
|
$this->client->request('ping');
|
||
|
|
$this->client->request('ping');
|
||
|
|
|
||
|
|
$this->assertSame(1, $this->sidecarHeard()['id']);
|
||
|
|
$this->assertSame(2, $this->sidecarHeard()['id']);
|
||
|
|
}
|
||
|
|
}
|