-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgain_plugin_smoke.rs
More file actions
110 lines (93 loc) · 3.73 KB
/
Copy pathgain_plugin_smoke.rs
File metadata and controls
110 lines (93 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// SPDX-FileCopyrightText: © 2025 StreamKit Contributors
//
// SPDX-License-Identifier: MPL-2.0
//! End-to-end smoke test driving the prebuilt gain example plugin through the
//! WASI 0.3 async host. Ignored by default because it requires the example
//! component to be built first:
//!
//! ```sh
//! cargo build --release --target wasm32-wasip2 \
//! --manifest-path examples/plugins/gain-wasm-rust/Cargo.toml
//! ```
#![allow(clippy::unwrap_used, clippy::expect_used)]
use std::collections::HashMap;
use std::path::PathBuf;
use streamkit_core::node::{OutputRouting, OutputSender};
use streamkit_core::types::{AudioFrame, Packet};
use streamkit_core::{NodeContext, PipelineMode};
use streamkit_plugin_wasm::{PluginRuntime, PluginRuntimeConfig};
use tokio::sync::mpsc;
fn example_plugin_path(relative: &str) -> PathBuf {
let path =
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../examples/plugins").join(relative);
assert!(path.exists(), "{} not found; build the example first", path.display());
path
}
async fn run_gain_plugin(path: PathBuf, expected_kind: &str) {
let runtime = PluginRuntime::new(PluginRuntimeConfig::default()).expect("runtime");
let plugin = runtime.load_plugin(&path).expect("load plugin");
assert_eq!(plugin.metadata().kind, expected_kind);
let node =
plugin.create_node(Some(&serde_json::json!({"gain_db": 6.0206}))).expect("create node");
let (input_tx, input_rx) = mpsc::channel(8);
let (state_tx, _state_rx) = mpsc::channel(32);
let (_control_tx, control_rx) = mpsc::channel(8);
let (routed_tx, mut routed_rx) = mpsc::channel(64);
let mut inputs = HashMap::new();
inputs.insert("in".to_string(), input_rx);
let context = NodeContext {
inputs,
input_types: HashMap::new(),
control_rx,
output_sender: OutputSender::new("gain".to_string(), OutputRouting::Routed(routed_tx)),
batch_size: 1,
state_tx,
stats_tx: None,
telemetry_tx: None,
session_id: None,
cancellation_token: None,
pin_management_rx: None,
audio_pool: None,
video_pool: None,
pipeline_mode: PipelineMode::Oneshot,
view_data_tx: None,
engine_control_tx: None,
asset_root: std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
};
let handle = tokio::spawn(async move { node.run(context).await });
input_tx
.send(Packet::Audio(AudioFrame::new(48000, 1, vec![0.5f32; 4])))
.await
.expect("send input");
drop(input_tx);
let (_node, pin, packet) =
tokio::time::timeout(std::time::Duration::from_secs(10), routed_rx.recv())
.await
.expect("timed out waiting for plugin output")
.expect("output channel closed without packet");
assert_eq!(&*pin, "out");
match packet {
Packet::Audio(frame) => {
for sample in frame.samples.iter() {
assert!((sample - 1.0).abs() < 1e-3, "expected ~2x gain, got {sample}");
}
},
other => panic!("unexpected packet: {other:?}"),
}
handle.await.expect("join").expect("node run");
}
#[tokio::test(flavor = "multi_thread")]
#[ignore = "requires the gain example component to be prebuilt"]
async fn rust_gain_plugin_processes_audio_through_async_host() {
run_gain_plugin(
example_plugin_path("gain-wasm-rust/target/wasm32-wasip2/release/gain_plugin.wasm"),
"gain_filter_rust",
)
.await;
}
#[tokio::test(flavor = "multi_thread")]
#[ignore = "requires the gain example component to be prebuilt"]
async fn c_gain_plugin_processes_audio_through_async_host() {
run_gain_plugin(example_plugin_path("gain-wasm-c/build/gain_plugin_c.wasm"), "gain_filter_c")
.await;
}