Files
oak-editor/crates/oak-worker/tests/worker.rs
T
Mike-Solar 431b9ed2b1 feat(oakrender): render-process isolation S1 - dispatcher, scheduler, real worker
Per the M15 design (docs/zh/plans/riir/M15-render-process-isolation.md):

- ipc.rs moved into oakrender with protocol v2: hello_caps,
  render_batch, batch_accepted, frame_failed; main-process-assigned
  slots; BGRA8 slot format. POSIX shm verified to 1GiB on macOS.
- ProcessDispatcher: spawns oak-worker processes, handshake, stdio
  NDJSON control, shm segment lifecycle with generation-tagged keys,
  crash detection with bounded restart and frame redispatch, zero-copy
  ShmFrameRef delivery and copy counters.
- PreviewScheduler: interleaved batch claiming (frame % W per worker,
  no work stealing), seek > playback-distance > background priority,
  credit-based flow control, crash recovery.
- oak-worker renders for real: graph snapshot deserialization, montage
  decode+composite straight into the assigned shm slot, F32->BGRA8
  final conversion in-worker, OFX plugin executor installed in-worker,
  crash hooks for isolation testing.

Thread pool coexists for now (S2 removes it). Integration tests cover
two-worker zero-copy rendering, crash isolation with redelivery, and
real H.264 footage decode into slots.
2026-08-18 18:58:38 +08:00

72 lines
2.5 KiB
Rust

// Oak Video Editor - Non-Linear Video Editor
// Copyright (C) 2026 Oak Team
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//! Binary-level tests for `oak-worker`: the process exit contract and the
//! headless CPU mode's startup behavior. The NDJSON control-loop behavior
//! itself is exercised in-process in `src/worker.rs`; end-to-end runs
//! against the main-process dispatcher live in
//! `tests/procpool_integration.rs`.
use std::process::{Command, Stdio};
fn bin() -> &'static str {
env!("CARGO_BIN_EXE_oak-worker")
}
#[test]
fn backend_none_exits_one_like_the_cpp_main() {
// Mirrors oakengine_worker_main(): without a renderer the worker cannot
// do anything and exits 1.
let out = Command::new(bin())
.args(["--backend", "none"])
.output()
.expect("spawn oak-worker");
assert_eq!(out.status.code(), Some(1));
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
stderr.contains("no renderer initialized"),
"stderr: {stderr}"
);
}
#[test]
fn backend_cpu_is_headless_but_fully_operational() {
// M15 S1: the "cpu" backend skips the renderer like "none" but the
// session stays up — it writes the startup handshake and exits 0 on
// EOF. (Also exercises the plugin-runtime install in the binary.)
let mut child = Command::new(bin())
.args(["--backend", "cpu"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("spawn oak-worker");
// Close stdin right away: EOF ends the control loop.
drop(child.stdin.take());
let out = child.wait_with_output().expect("wait oak-worker");
assert_eq!(out.status.code(), Some(0));
let stdout = String::from_utf8_lossy(&out.stdout);
let first = stdout.lines().next().unwrap_or("");
assert!(
first.contains("\"type\":\"handshake\""),
"startup handshake on stdout, got: {stdout:?}"
);
assert!(
first.contains("\"protocol_version\":1"),
"protocol version 1, got: {first:?}"
);
}