init v.1.0.0
All checks were successful
CI / Check / Test (push) Successful in 3m40s

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-08-06 20:11:22 +02:00
commit 15fdace324
38 changed files with 2883 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
#![allow(dead_code)]
use std::{
fs,
path::{Path, PathBuf},
};
pub const LOGO_BYTES: &[u8] = b"pretend png";
pub fn path(value: &str) -> Option<PathBuf> {
Some(PathBuf::from(value))
}
pub fn env_of(pairs: &[(&str, &str)]) -> impl Fn(&str) -> Option<PathBuf> + use<> {
let pairs: Vec<(String, PathBuf)> = pairs
.iter()
.map(|(key, value)| ((*key).to_owned(), PathBuf::from(value)))
.collect();
move |key| {
pairs
.iter()
.find(|(name, _)| name == key)
.map(|(_, value)| value.clone())
}
}
pub fn scratch(name: &str) -> PathBuf {
let directory = std::env::temp_dir().join(format!("dvd-thing-test-{name}"));
let _ = fs::remove_dir_all(&directory);
fs::create_dir_all(&directory).expect("temp directory must be creatable");
directory
}
pub fn write_logo(directory: &Path) -> PathBuf {
let file = directory.join("logo.png");
fs::write(&file, LOGO_BYTES).expect("temp file must be writable");
file
}

View File

@@ -0,0 +1,117 @@
mod common;
use assets::{Platform, config_path};
use common::{env_of, path};
#[test]
fn xdg_prefers_config_home() {
let env = env_of(&[("XDG_CONFIG_HOME", "/xdg"), ("HOME", "/home/user")]);
assert_eq!(
config_path(Platform::Xdg, env),
path("/xdg/dvd-thing/logo.png")
);
}
#[test]
fn xdg_falls_back_to_home_dot_config() {
let env = env_of(&[("HOME", "/home/user")]);
assert_eq!(
config_path(Platform::Xdg, env),
path("/home/user/.config/dvd-thing/logo.png")
);
}
#[test]
fn xdg_ignores_a_relative_config_home() {
let env = env_of(&[("XDG_CONFIG_HOME", "relative/dir"), ("HOME", "/home/user")]);
assert_eq!(
config_path(Platform::Xdg, env),
path("/home/user/.config/dvd-thing/logo.png")
);
}
#[test]
fn macos_uses_application_support() {
let env = env_of(&[("HOME", "/Users/gabriel")]);
assert_eq!(
config_path(Platform::MacOs, env),
path("/Users/gabriel/Library/Application Support/dvd-thing/logo.png")
);
}
#[test]
fn macos_still_honours_an_explicit_xdg_config_home() {
let env = env_of(&[("XDG_CONFIG_HOME", "/Users/gabriel/.config")]);
assert_eq!(
config_path(Platform::MacOs, env),
path("/Users/gabriel/.config/dvd-thing/logo.png")
);
}
#[test]
fn windows_prefers_appdata() {
let env = env_of(&[
("APPDATA", r"C:\Users\gabriel\AppData\Roaming"),
("USERPROFILE", r"C:\Users\gabriel"),
]);
assert_eq!(
config_path(Platform::Windows, env),
path(r"C:\Users\gabriel\AppData\Roaming/dvd-thing/logo.png")
);
}
#[test]
fn windows_falls_back_to_user_profile() {
let env = env_of(&[("USERPROFILE", r"C:\Users\gabriel")]);
assert_eq!(
config_path(Platform::Windows, env),
path(r"C:\Users\gabriel/AppData/Roaming/dvd-thing/logo.png")
);
}
#[test]
fn windows_ignores_unix_variables() {
let env = env_of(&[("HOME", "/home/user"), ("XDG_CONFIG_HOME", "/xdg")]);
assert_eq!(config_path(Platform::Windows, env), None);
}
#[test]
fn an_empty_environment_yields_no_path() {
for platform in [Platform::Xdg, Platform::MacOs, Platform::Windows] {
assert_eq!(config_path(platform, env_of(&[])), None);
}
}
#[test]
fn an_empty_variable_counts_as_unset() {
let env = env_of(&[("XDG_CONFIG_HOME", ""), ("HOME", "/home/user")]);
assert_eq!(
config_path(Platform::Xdg, env),
path("/home/user/.config/dvd-thing/logo.png")
);
}
#[test]
fn an_empty_home_does_not_produce_a_relative_path() {
assert_eq!(config_path(Platform::Xdg, env_of(&[("HOME", "")])), None);
assert_eq!(config_path(Platform::MacOs, env_of(&[("HOME", "")])), None);
}
#[test]
fn an_empty_appdata_falls_back_to_user_profile() {
let env = env_of(&[("APPDATA", ""), ("USERPROFILE", r"C:\Users\gabriel")]);
assert_eq!(
config_path(Platform::Windows, env),
path(r"C:\Users\gabriel/AppData/Roaming/dvd-thing/logo.png")
);
}

View File

@@ -0,0 +1,86 @@
mod common;
use application::LogoSourcePort;
use assets::{FileLogoSource, Platform};
use common::{LOGO_BYTES, env_of, scratch, write_logo};
#[test]
fn reads_an_explicit_path() {
let logo = write_logo(&scratch("explicit"));
let source = FileLogoSource::new(Some(logo), None).unwrap();
assert_eq!(source.load().unwrap(), Some(LOGO_BYTES));
}
#[test]
fn a_missing_explicit_path_is_an_error() {
let missing = scratch("explicit-missing").join("absent.png");
let error = FileLogoSource::new(Some(missing), None).unwrap_err();
assert!(error.to_string().contains("DVD_LOGO"));
}
#[test]
fn an_explicit_path_wins_over_the_configured_one() {
let directory = scratch("explicit-wins");
let explicit = directory.join("chosen.png");
std::fs::write(&explicit, b"chosen").unwrap();
let source = FileLogoSource::new(Some(explicit), Some(write_logo(&directory))).unwrap();
assert_eq!(source.load().unwrap(), Some(b"chosen".as_slice()));
}
#[test]
fn reads_the_configured_path() {
let logo = write_logo(&scratch("configured"));
let source = FileLogoSource::new(None, Some(logo)).unwrap();
assert_eq!(source.load().unwrap(), Some(LOGO_BYTES));
}
#[test]
fn a_missing_configured_path_is_not_an_error() {
let missing = scratch("configured-missing").join("absent.png");
let source = FileLogoSource::new(None, Some(missing)).unwrap();
assert_eq!(source.load().unwrap(), None);
}
#[test]
fn no_paths_at_all_yields_nothing() {
let source = FileLogoSource::new(None, None).unwrap();
assert_eq!(source.load().unwrap(), None);
}
#[test]
fn an_unreadable_configured_path_is_an_error() {
let directory = scratch("configured-unreadable");
std::fs::create_dir_all(directory.join("logo.png")).unwrap();
assert!(FileLogoSource::new(None, Some(directory.join("logo.png"))).is_err());
}
#[test]
fn an_empty_dvd_logo_variable_is_treated_as_unset() {
let env = env_of(&[("DVD_LOGO", ""), ("HOME", "")]);
let source = FileLogoSource::from_environment(Platform::Xdg, &env).unwrap();
assert_eq!(source.load().unwrap(), None);
}
#[test]
fn a_set_dvd_logo_variable_still_wins() {
let logo = write_logo(&scratch("env-explicit"));
let env = env_of(&[("DVD_LOGO", logo.to_str().unwrap()), ("HOME", "")]);
let source = FileLogoSource::from_environment(Platform::Xdg, &env).unwrap();
assert_eq!(source.load().unwrap(), Some(LOGO_BYTES));
}