use super::*;
#[cfg(any(feature = "std", feature = "alloc"))]
use std::format;
#[test]
fn default_is_none() {
assert!(matches!(PixelFormat::default(), PixelFormat::None));
assert_eq!(PixelFormat::None.as_str(), "none");
assert_eq!("none".parse(), Ok(PixelFormat::None));
}
#[test]
fn round_trip_u32_for_known_variants() {
let all = [
PixelFormat::None,
PixelFormat::Yuv420p,
PixelFormat::Yuv444p,
PixelFormat::Yuv420p10Le,
PixelFormat::Yuv422p16Le,
PixelFormat::Yuva444p,
PixelFormat::Nv12,
PixelFormat::P010Le,
PixelFormat::P416Le,
PixelFormat::Yuyv422,
PixelFormat::V210,
PixelFormat::V410Be,
PixelFormat::Ayuv64Le,
PixelFormat::Rgb24,
PixelFormat::Bgra,
PixelFormat::Rgb565Le,
PixelFormat::Rgba64Le,
PixelFormat::Rgbf32Le,
PixelFormat::Gbrp,
PixelFormat::Gbrap16Le,
PixelFormat::Gbrapf32Le,
PixelFormat::Gray8,
PixelFormat::Gray16Le,
PixelFormat::Ya16Le,
PixelFormat::Monowhite,
PixelFormat::Pal8,
PixelFormat::BayerBggr8,
PixelFormat::BayerRggb16Le,
PixelFormat::BayerGrbg10Be,
PixelFormat::BayerBggr14Be,
];
for fmt in all {
assert_eq!(
PixelFormat::from_u32(fmt.to_u32().expect("named format has an id")),
Some(fmt.clone()),
"round-trip failed for {fmt:?}"
);
}
}
#[test]
fn garbage_u32_is_rejected_not_invented() {
assert_eq!(PixelFormat::from_u32(99_999), None);
assert_eq!(PixelFormat::from_u32(1), None);
assert_eq!(PixelFormat::from_u32(u32::MAX), None);
assert_eq!(PixelFormat::from_u32(0), Some(PixelFormat::None));
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[test]
fn display_uses_ffmpeg_lowercase_names() {
assert_eq!(format!("{}", PixelFormat::Yuv420p), "yuv420p");
assert_eq!(format!("{}", PixelFormat::Nv12), "nv12");
assert_eq!(format!("{}", PixelFormat::P010Le), "p010le");
assert_eq!(format!("{}", PixelFormat::Rgba64Le), "rgba64le");
assert_eq!(format!("{}", PixelFormat::None), "none");
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[test]
fn display_uses_lowercase_names_for_bayer_extensions() {
assert_eq!(format!("{}", PixelFormat::BayerBggr12Le), "bayer_bggr12le");
assert_eq!(format!("{}", PixelFormat::BayerRggb10Be), "bayer_rggb10be");
}
#[test]
fn is_bayer_partition() {
assert!(PixelFormat::BayerBggr8.is_bayer());
assert!(PixelFormat::BayerRggb16Le.is_bayer());
assert!(PixelFormat::BayerGrbg12Le.is_bayer());
assert!(PixelFormat::BayerGbrg10Be.is_bayer());
assert!(PixelFormat::BayerGrbg14Be.is_bayer());
assert!(!PixelFormat::Yuv420p.is_bayer());
assert!(!PixelFormat::Rgb24.is_bayer());
assert!(!PixelFormat::None.is_bayer());
}
#[test]
fn is_variant_helpers_compile() {
assert!(PixelFormat::Yuv420p.is_yuv_420_p());
assert!(PixelFormat::Nv12.is_nv_12());
assert!(PixelFormat::P010Le.is_p_010_le());
assert!(!PixelFormat::Yuv420p.is_none());
}
#[test]
fn clone_and_eq() {
let p = PixelFormat::Nv12;
let q = p.clone();
assert_eq!(p, q);
assert_ne!(p, PixelFormat::Yuv420p);
}
#[test]
fn canonical_resolves_yuvj_aliases_to_full_range() {
use crate::color::DynamicRange;
assert_eq!(
PixelFormat::Yuvj411p.canonical(),
(PixelFormat::Yuv411p, Some(DynamicRange::Full))
);
assert_eq!(
PixelFormat::Yuvj420p.canonical(),
(PixelFormat::Yuv420p, Some(DynamicRange::Full))
);
assert_eq!(
PixelFormat::Yuvj422p.canonical(),
(PixelFormat::Yuv422p, Some(DynamicRange::Full))
);
assert_eq!(
PixelFormat::Yuvj440p.canonical(),
(PixelFormat::Yuv440p, Some(DynamicRange::Full))
);
assert_eq!(
PixelFormat::Yuvj444p.canonical(),
(PixelFormat::Yuv444p, Some(DynamicRange::Full))
);
}
#[test]
fn canonical_resolves_gray_alpha_aliases_to_ya8() {
assert_eq!(PixelFormat::Gray8a.canonical(), (PixelFormat::Ya8, None));
assert_eq!(PixelFormat::Y400a.canonical(), (PixelFormat::Ya8, None));
}
#[test]
fn canonical_resolves_xv30le_to_v410le() {
assert_eq!(PixelFormat::Xv30Le.canonical(), (PixelFormat::V410Le, None));
}
#[test]
fn canonical_resolves_xv30be_to_v410be() {
assert_eq!(PixelFormat::Xv30Be.canonical(), (PixelFormat::V410Be, None));
assert_eq!(PixelFormat::V410Be.canonical(), (PixelFormat::V410Be, None));
}
#[test]
fn canonical_is_identity_for_non_aliases() {
for fmt in [
PixelFormat::None,
PixelFormat::Yuv420p,
PixelFormat::Yuv444p,
PixelFormat::V410Le,
PixelFormat::Ya8,
PixelFormat::Nv12,
PixelFormat::P010Le,
PixelFormat::Rgb24,
PixelFormat::Gray8,
PixelFormat::Gbrp,
PixelFormat::Pal8,
PixelFormat::BayerBggr8,
] {
assert_eq!(
fmt.clone().canonical(),
(fmt.clone(), None),
"non-alias {fmt:?} must be its own canonical form"
);
}
}
#[test]
fn canonical_is_idempotent() {
let aliases = [
PixelFormat::Yuvj411p,
PixelFormat::Yuvj420p,
PixelFormat::Yuvj422p,
PixelFormat::Yuvj440p,
PixelFormat::Yuvj444p,
PixelFormat::Gray8a,
PixelFormat::Y400a,
PixelFormat::Xv30Le,
];
for alias in aliases {
let (canon, _range) = alias.clone().canonical();
assert_eq!(
canon.clone().canonical(),
(canon.clone(), None),
"canonical form {canon:?} of alias {alias:?} must be a fixed point with no pinned range"
);
}
}
#[test]
fn every_named_pixel_format_round_trips_through_its_slug() {
let mut named = 0usize;
let mut codes = [0u32; 512];
for code in 0..=4096u32 {
let Some(value) = PixelFormat::from_u32(code) else {
continue;
};
let slug = value.as_str();
assert_eq!(
slug.parse::<PixelFormat>(),
Ok(value.clone()),
"slug {slug:?} does not parse back to {value:?}"
);
assert!(
!slug.bytes().any(|b| b.is_ascii_uppercase()),
"pixel-format slug {slug:?} is not lowercase-canonical"
);
{
let mut upper = [0u8; 64];
let n = slug.len();
upper[..n].copy_from_slice(slug.as_bytes());
upper[..n].make_ascii_uppercase();
let upper = core::str::from_utf8(&upper[..n]).unwrap();
assert_eq!(
upper.parse::<PixelFormat>(),
Ok(value.clone()),
"PixelFormat does not fold {upper:?} onto {slug:?}"
);
}
for prior in codes.iter().take(named) {
let prior = PixelFormat::from_u32(*prior).expect("recorded code names a format");
assert_ne!(
prior.as_str(),
slug,
"two pixel formats are spelled {slug:?}"
);
}
codes[named] = code;
named += 1;
}
assert!(
named > 200,
"sweep found only {named} named formats — the id range is wrong"
);
}
#[test]
fn ffmpeg_synonyms_are_accepted_but_never_emitted() {
for (synonym, canonical) in FFMPEG_SYNONYMS {
let from_synonym = synonym
.parse::<PixelFormat>()
.expect("a documented FFmpeg synonym parses");
assert_eq!(
from_synonym.as_str(),
*canonical,
"FFmpeg name {synonym:?} must parse to the variant spelled {canonical:?}"
);
assert_ne!(
from_synonym.as_str(),
*synonym,
"{synonym:?} is emitted by a variant — it is a canonical slug, not a synonym"
);
assert_eq!(
canonical.parse::<PixelFormat>(),
Ok(from_synonym.clone()),
"the canonical slug and its FFmpeg synonym must name one value"
);
let mut upper = [0u8; 64];
let n = synonym.len();
upper[..n].copy_from_slice(synonym.as_bytes());
upper[..n].make_ascii_uppercase();
let upper = core::str::from_utf8(&upper[..n]).unwrap();
assert_eq!(
upper.parse::<PixelFormat>(),
Ok(from_synonym),
"PixelFormat does not fold the synonym {upper:?}"
);
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[test]
fn an_unnamed_pixel_format_keeps_its_name() {
let vendor: PixelFormat = "yuv420q".parse().unwrap();
assert!(vendor.is_other());
assert_eq!(vendor.as_str(), "yuv420q");
assert_eq!(vendor.to_u32(), None);
assert_eq!("yuv420q".parse(), Ok(vendor));
assert_eq!(PixelFormat::other("YUV420Q").as_str(), "yuv420q");
}
#[cfg(not(any(feature = "std", feature = "alloc")))]
#[test]
fn an_unnamed_pixel_format_is_rejected_without_an_allocator() {
let err: ParsePixelFormatError = "yuv420q".parse::<PixelFormat>().unwrap_err();
let _ = err;
}
#[test]
fn rosters_are_well_formed() {
crate::roster_tests::check(PixelFormat::ROSTER, "PixelFormat", PixelFormat::as_str);
}
#[cfg(any(feature = "std", feature = "alloc"))]
#[test]
fn unnamed_slugs_parse_totally_at_this_tier() {
let Ok(v) = "not-a-pixel-format".parse::<PixelFormat>();
assert_eq!(v, PixelFormat::other("not-a-pixel-format"));
}