use zenavif::DecoderConfig;
#[cfg(feature = "encode")]
use zenavif::{EncoderConfig, ValidationError};
#[test]
fn decoder_default_validates() {
DecoderConfig::default()
.validate()
.expect("default DecoderConfig must validate");
}
#[cfg(feature = "encode")]
#[test]
fn encoder_default_validates() {
EncoderConfig::default()
.validate()
.expect("default EncoderConfig must validate");
}
#[cfg(feature = "encode")]
#[test]
fn encoder_typical_config_validates() {
let cfg = EncoderConfig::new()
.quality(85.0)
.speed(6)
.alpha_quality(80.0)
.threads(Some(4))
.rotation(2)
.mirror(0);
cfg.validate().expect("typical config must validate");
}
#[cfg(feature = "__expert")]
#[test]
fn expert_default_internal_params_validates() {
use zenavif::expert::InternalParams;
InternalParams::default()
.validate()
.expect("default InternalParams must validate");
}
#[cfg(feature = "__expert")]
#[test]
fn expert_internal_params_well_formed_validates() {
use zenavif::expert::InternalParams;
let mut p = InternalParams::default();
p.partition_range = Some((8, 32));
p.lrf = Some(true);
p.fast_deblock = Some(false);
p.complex_prediction_modes = Some(true);
p.validate()
.expect("well-formed InternalParams must validate");
}
#[cfg(feature = "encode")]
#[test]
fn quality_out_of_range_high() {
let cfg = EncoderConfig::new().quality(150.0);
match cfg.validate() {
Err(ValidationError::QualityOutOfRange { value, valid }) => {
assert_eq!(value, 150.0);
assert_eq!(*valid.start(), 0.0);
assert_eq!(*valid.end(), 100.0);
}
other => panic!("expected QualityOutOfRange, got {other:?}"),
}
}
#[cfg(feature = "encode")]
#[test]
fn quality_out_of_range_negative() {
let cfg = EncoderConfig::new().quality(-1.0);
assert!(matches!(
cfg.validate(),
Err(ValidationError::QualityOutOfRange { .. })
));
}
#[cfg(feature = "encode")]
#[test]
fn quality_nan() {
let cfg = EncoderConfig::new().quality(f32::NAN);
assert!(matches!(
cfg.validate(),
Err(ValidationError::QualityOutOfRange { .. })
));
}
#[cfg(feature = "encode")]
#[test]
fn alpha_quality_out_of_range() {
let cfg = EncoderConfig::new().alpha_quality(101.0);
assert!(matches!(
cfg.validate(),
Err(ValidationError::AlphaQualityOutOfRange { .. })
));
}
#[cfg(feature = "encode")]
#[test]
fn speed_out_of_range_zero() {
let cfg = EncoderConfig::new().speed(0);
match cfg.validate() {
Err(ValidationError::SpeedOutOfRange { value, valid }) => {
assert_eq!(value, 0);
assert_eq!(*valid.start(), 1);
assert_eq!(*valid.end(), 10);
}
other => panic!("expected SpeedOutOfRange, got {other:?}"),
}
}
#[cfg(feature = "encode")]
#[test]
fn speed_out_of_range_high() {
let cfg = EncoderConfig::new().speed(11);
assert!(matches!(
cfg.validate(),
Err(ValidationError::SpeedOutOfRange { .. })
));
}
#[cfg(feature = "encode")]
#[test]
fn encoder_threads_zero() {
let cfg = EncoderConfig::new().threads(Some(0));
assert!(matches!(
cfg.validate(),
Err(ValidationError::EncoderThreadsZero)
));
}
#[cfg(feature = "encode")]
#[test]
fn encoder_threads_none_ok() {
let cfg = EncoderConfig::new().threads(None);
cfg.validate().expect("threads=None must validate");
}
#[cfg(feature = "encode")]
#[test]
fn rotation_invalid() {
let cfg = EncoderConfig::new().rotation(90);
match cfg.validate() {
Err(ValidationError::RotationInvalid { value }) => assert_eq!(value, 90),
other => panic!("expected RotationInvalid, got {other:?}"),
}
}
#[cfg(feature = "encode")]
#[test]
fn rotation_quarter_turn_codes_ok() {
for code in 0u8..=3 {
let cfg = EncoderConfig::new().rotation(code);
cfg.validate()
.unwrap_or_else(|e| panic!("rotation={code} must validate, got {e:?}"));
}
}
#[cfg(feature = "encode")]
#[test]
fn mirror_invalid() {
let cfg = EncoderConfig::new().mirror(2);
match cfg.validate() {
Err(ValidationError::MirrorInvalid { value }) => assert_eq!(value, 2),
other => panic!("expected MirrorInvalid, got {other:?}"),
}
}
#[cfg(feature = "encode")]
#[test]
fn cicp_color_primaries_reserved() {
let cfg = EncoderConfig::new().color_primaries(3);
match cfg.validate() {
Err(ValidationError::CicpReserved { field, value }) => {
assert_eq!(field, "color_primaries");
assert_eq!(value, 3);
}
other => panic!("expected CicpReserved, got {other:?}"),
}
}
#[cfg(feature = "encode")]
#[test]
fn cicp_transfer_characteristics_reserved() {
let cfg = EncoderConfig::new().transfer_characteristics(3);
assert!(matches!(
cfg.validate(),
Err(ValidationError::CicpReserved {
field: "transfer_characteristics",
..
})
));
}
#[cfg(feature = "encode")]
#[test]
fn cicp_matrix_coefficients_reserved() {
let cfg = EncoderConfig::new().matrix_coefficients(3);
assert!(matches!(
cfg.validate(),
Err(ValidationError::CicpReserved {
field: "matrix_coefficients",
..
})
));
}
#[cfg(feature = "encode-imazen")]
#[test]
fn vaq_strength_out_of_range_high() {
let cfg = EncoderConfig::new().with_vaq(true, 5.0);
match cfg.validate() {
Err(ValidationError::VaqStrengthOutOfRange { value, valid }) => {
assert_eq!(value, 5.0);
assert_eq!(*valid.start(), 0.0);
assert_eq!(*valid.end(), 4.0);
}
other => panic!("expected VaqStrengthOutOfRange, got {other:?}"),
}
}
#[cfg(feature = "encode-imazen")]
#[test]
fn vaq_strength_out_of_range_negative() {
let cfg = EncoderConfig::new().with_vaq(true, -0.1);
assert!(matches!(
cfg.validate(),
Err(ValidationError::VaqStrengthOutOfRange { .. })
));
}
#[cfg(feature = "encode-imazen")]
#[test]
fn seg_boost_below_half() {
let cfg = EncoderConfig::new().with_seg_boost(Some(0.4));
match cfg.validate() {
Err(ValidationError::SegBoostOutOfRange { value, valid }) => {
assert_eq!(value, 0.4);
assert_eq!(*valid.start(), 0.5);
assert_eq!(*valid.end(), 4.0);
}
other => panic!("expected SegBoostOutOfRange, got {other:?}"),
}
}
#[cfg(feature = "encode-imazen")]
#[test]
fn seg_boost_above_four() {
let cfg = EncoderConfig::new().with_seg_boost(Some(4.5));
assert!(matches!(
cfg.validate(),
Err(ValidationError::SegBoostOutOfRange { .. })
));
}
#[cfg(feature = "encode-imazen")]
#[test]
fn seg_boost_one_ok() {
let cfg = EncoderConfig::new().with_seg_boost(Some(1.0));
cfg.validate().expect("seg_boost=1.0 (off) must validate");
}
#[cfg(feature = "encode-imazen")]
#[test]
fn lossless_and_vaq_mutually_exclusive() {
let cfg = EncoderConfig::new().with_lossless(true).with_vaq(true, 1.0);
match cfg.validate() {
Err(ValidationError::MutuallyExclusive { a, b }) => {
assert_eq!(a, "lossless");
assert_eq!(b, "vaq");
}
other => panic!("expected MutuallyExclusive, got {other:?}"),
}
}
#[cfg(feature = "encode-imazen")]
#[test]
fn lossless_alone_ok() {
let cfg = EncoderConfig::new().with_lossless(true);
cfg.validate().expect("lossless alone must validate");
}
#[cfg(feature = "__expert")]
#[test]
fn partition_range_min_gt_max() {
use zenavif::expert::InternalParams;
let mut p = InternalParams::default();
p.partition_range = Some((32, 8));
match p.validate() {
Err(ValidationError::PartitionRangeInvalid { min, max }) => {
assert_eq!(min, 32);
assert_eq!(max, 8);
}
other => panic!("expected PartitionRangeInvalid, got {other:?}"),
}
}
#[cfg(feature = "__expert")]
#[test]
fn partition_range_invalid_size() {
use zenavif::expert::InternalParams;
let mut p = InternalParams::default();
p.partition_range = Some((4, 7)); assert!(matches!(
p.validate(),
Err(ValidationError::PartitionRangeInvalid { .. })
));
}
#[cfg(feature = "__expert")]
#[test]
fn partition_range_128_rejected() {
use zenavif::expert::InternalParams;
let mut p = InternalParams::default();
p.partition_range = Some((4, 128)); match p.validate() {
Err(ValidationError::PartitionRangeInvalid { min, max }) => {
assert_eq!(min, 4);
assert_eq!(max, 128);
}
other => panic!("expected PartitionRangeInvalid for 128, got {other:?}"),
}
}
#[cfg(feature = "__expert")]
#[test]
fn partition_range_valid_combinations() {
use zenavif::expert::InternalParams;
let valid_pairs: &[(u8, u8)] = &[(4, 4), (4, 64), (8, 16), (16, 32), (32, 64), (64, 64)];
for &(min, max) in valid_pairs {
let mut p = InternalParams::default();
p.partition_range = Some((min, max));
p.validate()
.unwrap_or_else(|e| panic!("({min},{max}) must validate, got {e:?}"));
}
}
#[cfg(feature = "__expert")]
#[test]
fn encoder_config_forwards_partition_validation() {
use zenavif::expert::InternalParams;
let mut p = InternalParams::default();
p.partition_range = Some((128, 128));
let cfg = EncoderConfig::new().with_internal_params(p);
assert!(matches!(
cfg.validate(),
Err(ValidationError::PartitionRangeInvalid { .. })
));
}
#[test]
fn decoder_threads_zero_ok() {
DecoderConfig::new()
.threads(0)
.validate()
.expect("threads=0 (auto) must validate");
}
#[test]
fn decoder_frame_size_limit_zero_ok() {
DecoderConfig::new()
.frame_size_limit(0)
.validate()
.expect("frame_size_limit=0 (no limit) must validate");
}