use crate::inspectors::mime_extension_lookup; use crate::mime_db::*; use crate::{extension_from_path, init_db, scan_directory, scan_from_walkdir}; use crate::parameters::{Parameters, ScanOpts}; use cfg_if::cfg_if; use mime_guess::mime::{APPLICATION_OCTET_STREAM, APPLICATION_PDF, IMAGE_JPEG, IMAGE_PNG}; use mime_guess::Mime; use smartstring::alias::String; use std::collections::HashMap; use std::path::Path; const JPEG_BYTES: &[u8] = b"\xFF\xD8\xFF"; const PNG_BYTES: &[u8] = b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"; const PDF_BYTES: &[u8] = b"%PDF-"; const ZIP_BYTES: &[u8] = b"PK\x03\x04"; cfg_if! { if #[cfg(any(all(unix, feature = "infer-backend"), all(not(unix), not(feature = "xdg-mime-backend"))))] { fn get_mime_db() -> InferDb { InferDb::init() } } else { fn get_mime_db() -> XdgDb { XdgDb::init() } } } fn application_zip() -> Mime { use std::str::FromStr; Mime::from_str("application/zip").unwrap() } #[test] fn get_ext() { let mut ext_checks = HashMap::new(); ext_checks.insert(Path::new("test.txt"), Some(String::from("txt"))); ext_checks.insert(Path::new("test.zip"), Some(String::from("zip"))); ext_checks.insert(Path::new("test.tar.gz"), Some(String::from("gz"))); ext_checks.insert(Path::new("test."), Some(String::from(""))); ext_checks.insert(Path::new("test"), None); ext_checks.insert(Path::new(".hidden"), None); for (path, ext) in ext_checks { assert_eq!(extension_from_path(path), ext) } } #[test] fn detect_type() { let db = get_mime_db(); assert_eq!(db.get_type(JPEG_BYTES), Some(IMAGE_JPEG)); assert_eq!(db.get_type(PNG_BYTES), Some(IMAGE_PNG)); assert_eq!(db.get_type(PDF_BYTES), Some(APPLICATION_PDF)); assert_eq!(db.get_type(ZIP_BYTES), Some(application_zip())); } #[test] fn recommend_ext() { assert!(mime_extension_lookup(IMAGE_JPEG) .unwrap() .contains(&String::from("jpg"))); assert!(mime_extension_lookup(IMAGE_PNG).unwrap().contains(&String::from("png"))); assert!(mime_extension_lookup(APPLICATION_PDF) .unwrap() .contains(&String::from("pdf"))); assert!(mime_extension_lookup(application_zip()) .unwrap() .contains(&String::from("zip"))); } #[test] fn simple_directory() { use std::fs::File; use std::io::Write; use tempfile::tempdir; let mut files = HashMap::new(); files.insert("test.jpg", JPEG_BYTES); files.insert("test.jpeg", JPEG_BYTES); files.insert("test.png", PNG_BYTES); files.insert("test.pdf", PDF_BYTES); files.insert("test.zip", ZIP_BYTES); files.insert("wrong.jpg", PNG_BYTES); let dir = tempdir().expect("Failed to create temporary directory."); for (name, bytes) in &files { let mut file = File::create(dir.path().join(name)).expect(&*format!("Failed to create file: {}", name)); file .write_all(bytes) .expect(&*format!("Failed to write to file: {}", name)); drop(file); } let scan_opts = ScanOpts{ hidden: true, extensionless: false }; let entries = scan_directory( &dir.path().to_path_buf(), &vec!["jpg", "jpeg", "png", "pdf", "zip"], &scan_opts, ) .expect("Directory scan failed."); assert_eq!(entries.len(), files.len()); // initialise global mime DB init_db(); let results = scan_from_walkdir(&entries); for result in results { let result = result.expect("Error while scanning file"); if !result.valid { // this should be "wrong.jpg", which is a misnamed png file // 1. ensure extension is "png" assert_eq!(extension_from_path(&*result.file).unwrap(), String::from("jpg")); // 2. ensure mime type detected is IMAGE_PNG assert_eq!(result.mime, IMAGE_PNG); // 3. ensure recommended extension is in the list of known extensions for PNG files assert!(mime_extension_lookup(IMAGE_PNG) .unwrap() .contains(&result.recommended_extension().unwrap())); continue; } // check if the recommended extension for this file is in the list of known extensions for its mimetype assert!(mime_extension_lookup(result.mime.clone()) .unwrap() .contains(&result.recommended_extension().unwrap())); // make sure the guessed mimetype is correct based on the extension of the scanned file assert_eq!( result.mime, match extension_from_path(&*result.file).as_deref() { Some("jpg") | Some("jpeg") => IMAGE_JPEG, Some("png") => IMAGE_PNG, Some("pdf") => APPLICATION_PDF, Some("zip") => application_zip(), Some(_) | None => APPLICATION_OCTET_STREAM, // general "fallback" type } ); } } #[test] fn argument_parsing() { use clap::Clap; // check if "jpg" is in the list of extensions to be considered when passing "-E images" let args: Parameters = Parameters::parse_from(vec!["fif", "-E", "images"]); assert!(args.extensions().contains(&"jpg")); // make sure "scan_hidden" is false assert!(!args.scan_hidden); // exts should be none assert!(args.exts.is_none()); }