Files
MusicFS/crates/musicfs-test-utils/src/fixtures.rs
T
2026-05-13 20:34:14 +02:00

254 lines
6.8 KiB
Rust

use musicfs_cache::TreeBuilder;
use musicfs_cas::{CasConfig, CasStore};
use musicfs_core::{AudioFormat, AudioMeta, FileId, FileMeta, OriginId, RealPath, VirtualPath};
use std::path::{Path, PathBuf};
use std::sync::{Arc, RwLock};
use std::time::SystemTime;
use tempfile::TempDir;
pub fn make_file_meta(id: i64, vpath: &str, size: u64) -> FileMeta {
FileMeta {
id: FileId(id),
virtual_path: VirtualPath::new(vpath),
real_path: RealPath {
origin_id: OriginId::from("test"),
path: PathBuf::from(vpath),
},
size,
mtime: SystemTime::now(),
content_hash: None,
audio: None,
}
}
pub fn make_file_meta_with_origin(id: i64, vpath: &str, size: u64, origin_id: &str) -> FileMeta {
FileMeta {
id: FileId(id),
virtual_path: VirtualPath::new(vpath),
real_path: RealPath {
origin_id: OriginId::from(origin_id),
path: PathBuf::from(vpath),
},
size,
mtime: SystemTime::now(),
content_hash: None,
audio: None,
}
}
pub fn make_audio_meta(artist: &str, album: &str, title: &str) -> AudioMeta {
AudioMeta {
title: Some(title.to_string()),
artist: Some(artist.to_string()),
album: Some(album.to_string()),
album_artist: None,
genre: None,
year: None,
track: None,
disc: None,
duration_ms: Some(180_000),
bitrate: Some(320),
sample_rate: Some(44100),
format: AudioFormat::Flac,
}
}
pub fn make_audio_file(
id: i64,
vpath: &str,
size: u64,
artist: &str,
album: &str,
title: &str,
) -> FileMeta {
FileMeta {
id: FileId(id),
virtual_path: VirtualPath::new(vpath),
real_path: RealPath {
origin_id: OriginId::from("test"),
path: PathBuf::from(vpath),
},
size,
mtime: SystemTime::now(),
content_hash: None,
audio: Some(make_audio_meta(artist, album, title)),
}
}
pub fn make_audio_file_full(
id: i64,
vpath: &str,
size: u64,
artist: &str,
album: &str,
title: &str,
track: u32,
year: u32,
) -> FileMeta {
let mut audio = make_audio_meta(artist, album, title);
audio.track = Some(track);
audio.year = Some(year);
FileMeta {
id: FileId(id),
virtual_path: VirtualPath::new(vpath),
real_path: RealPath {
origin_id: OriginId::from("test"),
path: PathBuf::from(vpath),
},
size,
mtime: SystemTime::now(),
content_hash: None,
audio: Some(audio),
}
}
pub struct TestCasStore {
pub store: Arc<CasStore>,
pub dir: TempDir,
}
pub async fn setup_test_cas() -> TestCasStore {
let dir = TempDir::new().expect("Failed to create temp dir for CAS");
let config = CasConfig {
chunks_dir: dir.path().join("chunks"),
max_size: 100 * 1024 * 1024,
shard_levels: 2,
};
let store = CasStore::open(config)
.await
.expect("Failed to open CAS store");
TestCasStore {
store: Arc::new(store),
dir,
}
}
pub async fn setup_test_cas_with_size(max_size: u64) -> TestCasStore {
let dir = TempDir::new().expect("Failed to create temp dir for CAS");
let config = CasConfig {
chunks_dir: dir.path().join("chunks"),
max_size,
shard_levels: 2,
};
let store = CasStore::open(config)
.await
.expect("Failed to open CAS store");
TestCasStore {
store: Arc::new(store),
dir,
}
}
pub fn setup_test_tree(files: &[FileMeta]) -> Arc<RwLock<musicfs_cache::VirtualTree>> {
let mut builder = TreeBuilder::new();
for file in files {
builder.add_file(file);
}
Arc::new(RwLock::new(builder.build()))
}
pub fn create_test_file(dir: &Path, relative_path: &str, content: &[u8]) -> PathBuf {
let full_path = dir.join(relative_path);
if let Some(parent) = full_path.parent() {
std::fs::create_dir_all(parent).expect("Failed to create parent directories");
}
std::fs::write(&full_path, content).expect("Failed to write test file");
full_path
}
pub fn create_test_dir_structure(base: &Path, structure: &[&str]) {
for path in structure {
let full_path = base.join(path);
if path.ends_with('/') {
std::fs::create_dir_all(&full_path).expect("Failed to create directory");
} else {
if let Some(parent) = full_path.parent() {
std::fs::create_dir_all(parent).expect("Failed to create parent");
}
std::fs::write(&full_path, format!("content of {}", path))
.expect("Failed to write file");
}
}
}
pub struct TestOriginDir {
pub dir: TempDir,
}
impl TestOriginDir {
pub fn new() -> Self {
Self {
dir: TempDir::new().expect("Failed to create origin temp dir"),
}
}
pub fn add_file(&self, path: &str, content: &[u8]) -> PathBuf {
create_test_file(self.dir.path(), path, content)
}
pub fn add_audio_file(&self, path: &str) -> PathBuf {
let fake_audio = b"FAKE_FLAC_HEADER_FOR_TESTING_ONLY";
self.add_file(path, fake_audio)
}
pub fn path(&self) -> &Path {
self.dir.path()
}
}
impl Default for TestOriginDir {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_make_file_meta() {
let meta = make_file_meta(1, "/Artist/Album/Track.flac", 1000);
assert_eq!(meta.id.0, 1);
assert_eq!(meta.virtual_path.as_str(), "/Artist/Album/Track.flac");
assert_eq!(meta.size, 1000);
assert!(meta.audio.is_none());
}
#[test]
fn test_make_audio_file() {
let meta = make_audio_file(1, "/path.flac", 5000, "Artist", "Album", "Title");
assert!(meta.audio.is_some());
let audio = meta.audio.unwrap();
assert_eq!(audio.artist, Some("Artist".to_string()));
assert_eq!(audio.album, Some("Album".to_string()));
assert_eq!(audio.title, Some("Title".to_string()));
}
#[tokio::test]
async fn test_setup_test_cas() {
let test_cas = setup_test_cas().await;
let hash = test_cas.store.put(b"test data").await.unwrap();
assert!(test_cas.store.exists(&hash));
}
#[test]
fn test_setup_test_tree() {
let files = vec![
make_file_meta(1, "/A/B/1.flac", 100),
make_file_meta(2, "/A/B/2.flac", 200),
];
let tree = setup_test_tree(&files);
let guard = tree.read().unwrap();
assert!(guard.file_count() > 0);
}
#[test]
fn test_origin_dir() {
let origin = TestOriginDir::new();
let path = origin.add_file("artist/album/track.flac", b"content");
assert!(path.exists());
}
}