laravel-webrtc/tests/ControlClientTest.php

98 lines
3.1 KiB
PHP
Raw Permalink Normal View History

<?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']);
}
}