test(pf-encode): pin the typed-EINVAL classifier's chain-survival contract (Phase 8)
ci / docs-site (push) Failing after 52s
android / android (push) Failing after 6m28s
ci / web (push) Successful in 1m5s
ci / bench (push) Successful in 6m40s
decky / build-publish (push) Successful in 26s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 11s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 16s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 10s
arch / build-publish (push) Successful in 12m51s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 11s
ci / rust-arm64 (push) Successful in 9m51s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Failing after 42s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Failing after 17s
deb / build-publish-client-arm64 (push) Successful in 8m54s
deb / build-publish-host (push) Successful in 10m31s
deb / build-publish (push) Successful in 11m17s
windows-host / package (push) Successful in 10m41s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6m25s
docker / build-push-arm64cross (push) Skipped
docker / deploy-docs (push) Skipped
apple / swift (push) Successful in 5m25s
ci / rust (push) Successful in 22m21s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m7s
apple / screenshots (push) Successful in 23m50s

Rides on 25765c53 (the concurrent session landed the same typed-errno
fix first — this branch's twin commit was dropped in the rebase; these
are its surviving residuals):
- Two tests pinning what the ladder's step-down rests on: the typed
  ffmpeg::Error survives with_context layers as a downcastable source
  (an eager format! anywhere between open_with and the ladder would
  silently break it), and the phrase WITHOUT the type no longer
  classifies.
- The CudaHw::new eager-format guard note: those bail!s must NOT be
  converted to typed errors — a hwdevice/hwframes EINVAL is a config
  error no bitrate can fix, and enrolling it would burn ~10 doomed
  opens before surfacing the real failure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-26 10:13:49 +02:00
co-authored by Claude Opus 5
parent bf9fb3fb22
commit bf9386ecb2
2 changed files with 37 additions and 0 deletions
+32
View File
@@ -1814,6 +1814,38 @@ mod tests {
assert_eq!(trait_fns, impl_fns);
}
/// The typed-EINVAL classifier the bitrate ladder keys on (Phase 8): the `ffmpeg::Error`
/// must survive `with_context` layers as a downcastable source — pinned here because the
/// entire ladder's step-down behavior rests on it, and an eager `format!` anywhere between
/// `open_with` and the ladder would silently break it (the ladder would stop stepping and
/// 4K sessions would surface errors instead of degrading).
#[cfg(target_os = "linux")]
#[test]
fn nvenc_open_einval_survives_context_layers() {
use ffmpeg_next as ffmpeg;
let e = anyhow::Error::from(ffmpeg::Error::Other {
errno: ffmpeg::util::error::EINVAL,
})
.context("open hevc_nvenc (3840x2160@120, 400000000 bps)")
.context("outer");
assert!(nvenc_open_einval(&e));
// ENOSYS (or any other errno) must not step the ladder.
let e = anyhow::Error::from(ffmpeg::Error::Other {
errno: ffmpeg::util::error::ENOSYS,
})
.context("open");
assert!(!nvenc_open_einval(&e));
}
/// The phrase WITHOUT the type no longer classifies — the fragility that was removed: the
/// old string match trusted any error whose rendering contained "Invalid argument".
#[cfg(target_os = "linux")]
#[test]
fn nvenc_open_einval_ignores_untyped_text() {
let e = anyhow::anyhow!("driver said: Invalid argument (not a typed libav errno)");
assert!(!nvenc_open_einval(&e));
}
/// WP7.6: the resolver's full alias table, pinned. The panicking closure is the laziness
/// contract — an explicit pref must resolve WITHOUT running the auto probe (`/serverinfo`
/// polls through the mirrors; `gamestream/serverinfo.rs` litigated exactly that cost).