use super::*;
use crate::common::params::ActivationPrecision;
use crate::dsp::oversample::OversampleFactor;
use std::path::PathBuf;
#[test]
fn test_v0_legacy_load() {
let v0_json = r#"{"input_gain_db": 3.0,"output_gain_db": -6.0,"gate_threshold_db": -50.0,"model_path": null,"bypass": false}"#;
let params = load_state(v0_json.as_bytes()).expect("v0 payload should load");
assert!((params.input_gain_db - 3.0).abs() < f32::EPSILON);
assert!((params.output_gain_db - (-6.0)).abs() < f32::EPSILON);
assert!((params.gate_threshold_db - (-50.0)).abs() < f32::EPSILON);
assert_eq!(params.model_path, None);
assert!(!params.bypass);
assert_eq!(params.ir_path, None);
}
#[test]
fn test_v0_legacy_load_with_missing_fields() {
let v0_json = r#"{"input_gain_db": 1.5}"#;
let params = load_state(v0_json.as_bytes()).expect("v0 with missing fields should load");
assert!((params.input_gain_db - 1.5).abs() < f32::EPSILON);
assert_eq!(params.output_gain_db, 0.0);
assert_eq!(params.gate_threshold_db, -70.0);
assert_eq!(params.model_path, None);
assert!(!params.bypass);
assert_eq!(params.ir_path, None);
}
#[test]
fn test_v1_round_trip() {
let original = NamPluginParams {
input_gain_db: 2.5,
output_gain_db: -3.0,
gate_threshold_db: -40.0,
model_path: Some(PathBuf::from("/tmp/test.nam")),
model_basename: None,
model_search_paths: Vec::new(),
bypass: true,
adaptive_compute: crate::common::params::AdaptiveComputeMode::Off,
slim_override: Default::default(),
oversample: OversampleFactor::Off,
ir_path: None,
activation_precision: ActivationPrecision::Standard,
};
let envelope = StateEnvelope {
version: CURRENT_STATE_VERSION,
params: original.clone(),
};
let json = serde_json::to_vec(&envelope).unwrap();
let restored = load_state(&json).expect("v1 payload should load");
assert_eq!(restored, original, "v1 round-trip should be idempotent");
}
#[test]
fn test_v1_save_format() {
let params = NamPluginParams::default();
let envelope = StateEnvelope {
version: CURRENT_STATE_VERSION,
params,
};
let json = serde_json::to_vec(&envelope).unwrap();
let parsed: serde_json::Value = serde_json::from_slice(&json).unwrap();
assert_eq!(parsed["version"], 1, "envelope should contain version: 1");
assert!(
parsed["params"].is_object(),
"envelope should contain params"
);
assert_eq!(parsed["params"]["ir_path"], serde_json::Value::Null);
}
#[test]
fn test_v0_legacy_load_new_fields_default() {
let v0_json = r#"{"input_gain_db": 3.0,"output_gain_db": -6.0,"gate_threshold_db": -50.0,"model_path": null,"bypass": false}"#;
let params = load_state(v0_json.as_bytes()).expect("v0 payload should load");
assert_eq!(params.model_basename, None);
assert!(params.model_search_paths.is_empty());
assert_eq!(params.ir_path, None);
}
#[test]
fn test_v1_round_trip_with_search_fields() {
let search_paths = vec![
std::path::PathBuf::from("/usr/share/nam-models"),
std::path::PathBuf::from("/home/user/models"),
];
let original = NamPluginParams {
input_gain_db: 2.5,
output_gain_db: -3.0,
gate_threshold_db: -40.0,
model_path: Some(PathBuf::from("/tmp/test.nam")),
model_basename: Some("test.nam".to_string()),
model_search_paths: search_paths.clone(),
bypass: true,
adaptive_compute: crate::common::params::AdaptiveComputeMode::Off,
slim_override: Default::default(),
oversample: OversampleFactor::Off,
ir_path: None,
activation_precision: ActivationPrecision::Standard,
};
let envelope = StateEnvelope {
version: CURRENT_STATE_VERSION,
params: original.clone(),
};
let json = serde_json::to_vec(&envelope).unwrap();
let restored = load_state(&json).expect("v1 payload should load");
assert_eq!(
restored, original,
"v1 round-trip with search fields should be idempotent"
);
}
#[test]
fn test_v1_search_fields_serialization_format() {
let params = NamPluginParams {
model_basename: Some("tone.nam".to_string()),
model_search_paths: vec![PathBuf::from("/models")],
..Default::default()
};
let envelope = StateEnvelope {
version: CURRENT_STATE_VERSION,
params,
};
let json = serde_json::to_vec(&envelope).unwrap();
let parsed: serde_json::Value = serde_json::from_slice(&json).unwrap();
assert_eq!(parsed["params"]["model_basename"], "tone.nam");
assert_eq!(parsed["params"]["model_search_paths"][0], "/models");
}
#[test]
fn test_v1_round_trip_with_ir_path() {
let original = NamPluginParams {
input_gain_db: 0.0,
output_gain_db: 0.0,
gate_threshold_db: -70.0,
model_path: None,
model_basename: None,
model_search_paths: Vec::new(),
bypass: false,
adaptive_compute: crate::common::params::AdaptiveComputeMode::Off,
slim_override: Default::default(),
oversample: OversampleFactor::Off,
ir_path: Some(PathBuf::from("/tmp/cab.wav")),
activation_precision: ActivationPrecision::Standard,
};
let envelope = StateEnvelope {
version: CURRENT_STATE_VERSION,
params: original.clone(),
};
let json = serde_json::to_vec(&envelope).unwrap();
let restored = load_state(&json).expect("v1 payload with ir_path should load");
assert_eq!(
restored, original,
"v1 round-trip with ir_path should be idempotent"
);
}
#[test]
fn test_v1_ir_path_serialization_format() {
let params = NamPluginParams {
ir_path: Some(PathBuf::from("/path/to/cab.wav")),
..Default::default()
};
let envelope = StateEnvelope {
version: CURRENT_STATE_VERSION,
params,
};
let json = serde_json::to_vec(&envelope).unwrap();
let parsed: serde_json::Value = serde_json::from_slice(&json).unwrap();
assert_eq!(parsed["params"]["ir_path"], "/path/to/cab.wav");
}