use super::*;
use crate::native::NativeMediaPlugin;
use znippy_common::plugin::{ArchiveTypePlugin, ExtensionValue};
const PNG: &[u8] = include_bytes!("../tests/fixtures/tiny.png");
const JPG: &[u8] = include_bytes!("../tests/fixtures/exif.jpg");
const WAV: &[u8] = include_bytes!("../tests/fixtures/tiny.wav");
const MP3: &[u8] = include_bytes!("../tests/fixtures/tiny.mp3");
const MP4: &[u8] = include_bytes!("../tests/fixtures/tiny.mp4");
const WEBM: &[u8] = include_bytes!("../tests/fixtures/tiny.webm");
#[test]
fn png_dimensions_and_color() {
let m = extract_media_metadata("a/tiny.png", PNG).expect("png parses");
assert_eq!(m.kind, Some(MediaKind::Image));
assert_eq!(m.format.as_deref(), Some("png"));
assert_eq!(m.width, Some(4));
assert_eq!(m.height, Some(2));
assert_eq!(m.color.as_deref(), Some("rgb8"));
}
#[test]
fn jpeg_exif_camera_orientation_datetime() {
let m = extract_media_metadata("photos/exif.jpg", JPG).expect("jpg parses");
assert_eq!(m.kind, Some(MediaKind::Image));
assert_eq!(m.width, Some(8));
assert_eq!(m.height, Some(6));
let cam = m.camera.expect("camera present");
assert!(cam.contains("ACME"), "camera make in {cam:?}");
assert!(cam.contains("ZoomCam"), "camera model in {cam:?}");
assert_eq!(m.orientation, Some(6));
assert_eq!(m.datetime.as_deref(), Some("2021-01-02 03:04:05"));
}
#[test]
fn wav_duration_rate_channels() {
let m = extract_media_metadata("snd/tiny.wav", WAV).expect("wav parses");
assert_eq!(m.kind, Some(MediaKind::Audio));
assert_eq!(m.format.as_deref(), Some("wav"));
assert_eq!(m.sample_rate, Some(8000));
assert_eq!(m.channels, Some(1));
let d = m.duration_ms.expect("duration");
assert!((80..=140).contains(&d), "wav duration_ms={d}");
}
#[test]
fn mp3_tags_and_properties() {
let m = extract_media_metadata("music/tiny.mp3", MP3).expect("mp3 parses");
assert_eq!(m.kind, Some(MediaKind::Audio));
assert_eq!(m.format.as_deref(), Some("mpeg"));
assert_eq!(m.sample_rate, Some(44100));
assert_eq!(m.channels, Some(2));
assert_eq!(m.title.as_deref(), Some("T1"));
assert_eq!(m.artist.as_deref(), Some("A1"));
assert_eq!(m.album.as_deref(), Some("Alb1"));
assert!(m.duration_ms.unwrap_or(0) > 0);
}
#[test]
fn mp4_video_dims_codecs_framerate() {
let m = extract_media_metadata("vid/tiny.mp4", MP4).expect("mp4 parses");
assert_eq!(m.kind, Some(MediaKind::Video));
assert_eq!(m.format.as_deref(), Some("mp4"));
assert_eq!(m.width, Some(16));
assert_eq!(m.height, Some(16));
assert_eq!(m.video_codec.as_deref(), Some("h264"));
assert_eq!(m.audio_codec.as_deref(), Some("aac"));
assert_eq!(m.framerate.as_deref(), Some("10.000"));
assert!(m.duration_ms.unwrap_or(0) > 0);
}
#[test]
fn webm_matroska_dims_codecs_audio() {
let m = extract_media_metadata("vid/tiny.webm", WEBM).expect("webm parses");
assert_eq!(m.kind, Some(MediaKind::Video));
assert_eq!(m.format.as_deref(), Some("webm"));
assert_eq!(m.width, Some(16));
assert_eq!(m.height, Some(16));
assert!(m.video_codec.as_deref().unwrap_or("").contains("vp8"), "vcodec={:?}", m.video_codec);
assert!(
m.audio_codec.as_deref().unwrap_or("").contains("vorbis"),
"acodec={:?}",
m.audio_codec
);
assert_eq!(m.sample_rate, Some(44100));
}
#[test]
fn plugin_meta_and_matching() {
let p = NativeMediaPlugin::new();
assert_eq!(p.name(), "media");
assert_eq!(p.type_id(), MEDIA_TYPE_ID);
let meta = p.meta();
assert!(meta.aliases.contains(&"image".to_string()));
assert!(meta.aliases.contains(&"audio".to_string()));
assert!(meta.aliases.contains(&"video".to_string()));
assert!(p.matches_path("x/y.PNG"), "case-insensitive match");
assert!(p.matches_path("a.mp4"));
assert!(!p.matches_path("a.tar.gz"));
}
#[test]
fn plugin_schema_matches_row_keys() {
let p = NativeMediaPlugin::new();
let fields: Vec<String> = p.schema_fields().iter().map(|f| f.name().clone()).collect();
let by_name = |n: &str| p.schema_fields().iter().find(|f| f.name() == n).cloned();
use znippy_common::arrow::datatypes::DataType;
for num in ["width", "height", "duration_ms", "sample_rate", "channels", "bitrate", "orientation"] {
assert_eq!(by_name(num).unwrap().data_type(), &DataType::UInt32, "{num} is UInt32");
}
let row = p.extract_metadata("vid/tiny.mp4", MP4).expect("row");
for k in row.fields.keys() {
assert!(fields.contains(k), "row key {k} not in schema");
}
assert_eq!(row.fields.get("width"), Some(&ExtensionValue::U32(16)));
assert_eq!(
row.fields.get("media_kind"),
Some(&ExtensionValue::Str("video".to_string()))
);
}
#[test]
fn non_media_path_is_ignored() {
assert!(extract_media_metadata("readme.txt", b"hello").is_none());
assert!(!is_media_path("foo.crate"));
}