mirror of
https://github.com/openai/codex.git
synced 2026-09-11 20:36:49 +00:00
## Why The voice helper previously supported only handshake and shutdown, without validating that its packaged native runtime could be initialized safely. ## What changed - Add an `initializeRuntime` protocol exchange that loads GStreamer and the required plugins from physical package paths without opening audio devices. - Restrict plugin discovery, registry access, and native library search paths, and keep loaded libraries alive until the helper exits. - Give initialization a dedicated deadline and terminate the owned helper when initialization is cancelled or fails. - Allow binary-only Rust targets to disable the default Bazel library target. ## Testing - Cover helper-only packages, cancellation, and environment filtering. - Add an ignored integration test for initialization from a relocated prepared runtime and rejection of duplicate initialization. GitOrigin-RevId: 8fff68fe26e52cb2e0722dc98fb5f124eddb0d4d
89 lines
3.2 KiB
Rust
89 lines
3.2 KiB
Rust
//! Exercise native initialization with real prepared libraries in a relocated package.
|
|
|
|
use std::fs;
|
|
use std::time::Duration;
|
|
|
|
use anyhow::Context;
|
|
use anyhow::Result;
|
|
use anyhow::ensure;
|
|
use codex_install_context::InstallContext;
|
|
use codex_realtime_webrtc::VoiceHost;
|
|
use codex_utils_cargo_bin::cargo_bin;
|
|
use tokio::process::Command;
|
|
use tokio::time::timeout;
|
|
|
|
const DEADLINE: Duration = Duration::from_secs(/*secs*/ 10);
|
|
|
|
#[tokio::test]
|
|
#[ignore = "requires CODEX_TEST_VOICE_RUNTIME containing real prepared native libraries"]
|
|
async fn relocated_runtime_initializes_closes_and_rejects_duplicate_initialization() -> Result<()> {
|
|
let source = std::env::var_os("CODEX_TEST_VOICE_RUNTIME")
|
|
.context("set CODEX_TEST_VOICE_RUNTIME to a matching prepared runtime")?;
|
|
let source = fs::canonicalize(source)?;
|
|
ensure!(
|
|
source.join("runtime.json").is_file(),
|
|
"prepared runtime receipt missing"
|
|
);
|
|
let directory = tempfile::Builder::new()
|
|
.prefix("voice native package ")
|
|
.tempdir()?;
|
|
let root = directory.path().join("staging");
|
|
let runtime = root.join("codex-resources/voice");
|
|
fs::create_dir_all(&runtime)?;
|
|
let mut pending = vec![(source, runtime.clone())];
|
|
while let Some((source, destination)) = pending.pop() {
|
|
for entry in fs::read_dir(source)? {
|
|
let entry = entry?;
|
|
let target = destination.join(entry.file_name());
|
|
let kind = entry.file_type()?;
|
|
if kind.is_dir() {
|
|
fs::create_dir(&target)?;
|
|
pending.push((entry.path(), target));
|
|
} else {
|
|
ensure!(kind.is_file(), "runtime inputs must be physical files");
|
|
fs::copy(entry.path(), target)?;
|
|
}
|
|
}
|
|
}
|
|
let helper_source = cargo_bin("codex-voice-host")?;
|
|
let name = helper_source.file_name().context("helper filename")?;
|
|
fs::create_dir_all(runtime.join("bin"))?;
|
|
fs::copy(&helper_source, runtime.join("bin").join(name))?;
|
|
fs::create_dir(root.join("bin"))?;
|
|
let app_name = if cfg!(windows) { "codex.exe" } else { "codex" };
|
|
fs::write(root.join("bin").join(app_name), [])?;
|
|
fs::write(root.join("codex-package.json"), "{}")?;
|
|
let moved = directory.path().join("relocated package");
|
|
fs::rename(root, &moved)?;
|
|
let package = InstallContext::from_exe(
|
|
/*is_macos*/ cfg!(target_os = "macos"),
|
|
Some(&moved.join("bin").join(app_name)),
|
|
/*method_override*/ None,
|
|
)
|
|
.package_layout
|
|
.context("package layout")?;
|
|
let output = timeout(
|
|
DEADLINE,
|
|
Command::new(&helper_source)
|
|
.arg("--build-commit")
|
|
.kill_on_drop(true)
|
|
.output(),
|
|
)
|
|
.await??;
|
|
ensure!(output.status.success(), "helper build identity failed");
|
|
let build_commit = String::from_utf8(output.stdout)?.trim().to_owned();
|
|
VoiceHost::connect(&package, &build_commit)
|
|
.await?
|
|
.initialize_runtime()
|
|
.await?
|
|
.close()
|
|
.await?;
|
|
|
|
let host = VoiceHost::connect(&package, &build_commit)
|
|
.await?
|
|
.initialize_runtime()
|
|
.await?;
|
|
assert!(host.initialize_runtime().await.is_err());
|
|
Ok(())
|
|
}
|