sys_get_temp_dir().'/blax-sfu-never-'.getmypid().'.sock', 'auto_spawn' => false, ]); $this->assertFalse($supervisor->running()); $this->expectException(SidecarException::class); $this->expectExceptionMessage('webrtc:sidecar'); $supervisor->ensureRunning(); } public function test_args_mirror_the_config(): void { $supervisor = new SidecarSupervisor(new BinaryManager([]), [ 'socket' => '/run/sfu.sock', 'udp_ip' => '10.0.0.5', 'udp_port' => 41000, 'public_ip' => '203.0.113.9', ]); $this->assertSame( ['--socket', '/run/sfu.sock', '--udp-ip', '10.0.0.5', '--udp-port', '41000', '--public-ip', '203.0.113.9'], $supervisor->args(), ); } /** * REAL cross-language round-trip: plug-and-play spawn of the actual Rust * sidecar (local cargo build), the full control protocol through * RustMediaEngine, and a graceful stop. Skipped until rust/ is built. */ public function test_spawns_and_drives_the_real_sidecar(): void { $binary = \dirname(__DIR__).'/rust/target/debug/blax-webrtc-sfu'; if (! is_file($binary)) { $this->markTestSkipped('rust sidecar not built — run `cargo build` in rust/'); } $socket = sys_get_temp_dir().'/blax-sfu-e2e-'.getmypid().'.sock'; $config = [ 'socket' => $socket, 'binary' => $binary, 'auto_install' => false, 'udp_ip' => '127.0.0.1', 'log' => sys_get_temp_dir().'/blax-sfu-e2e-'.getmypid().'.log', 'spawn_timeout' => 15.0, ]; $supervisor = new SidecarSupervisor(new BinaryManager($config), $config); try { $this->assertFalse($supervisor->running()); $supervisor->ensureRunning(); // finds the binary + spawns detached $this->assertTrue($supervisor->running()); $engine = new RustMediaEngine($supervisor); // Empty stats on a fresh sidecar. $this->assertSame([], $engine->stats()); // A garbage offer must come back as a clean protocol error. try { $engine->addPeer('lobby', 'alice', 'this is not sdp'); $this->fail('expected the sidecar to reject a garbage offer'); } catch (SidecarException $e) { $this->assertStringContainsString('offer', $e->getMessage()); } // Unknown peers error cleanly too. try { $engine->mutePeer('lobby', 'ghost', true); $this->fail('expected a no-such-peer error'); } catch (SidecarException $e) { $this->assertStringContainsString('no such peer', $e->getMessage()); } // ensureRunning is idempotent while it lives. $supervisor->ensureRunning(); $this->assertTrue($supervisor->running()); } finally { $supervisor->stop(); @unlink($socket); @unlink($socket.'.lock'); @unlink($config['log']); } $this->assertFalse($supervisor->running(), 'graceful shutdown via the control socket'); } }