use std::collections::HashMap;
use std::path::Path;
use std::{fs, path::PathBuf};
use similar_asserts::assert_eq;
pub trait PathKey: std::fmt::Display + PartialEq + Eq + std::hash::Hash + Clone + Sized {
fn all() -> &'static [Self];
fn local_results_prefix() -> &'static str {
"localRsResults"
}
fn public_results_prefix() -> &'static str {
"rsResults"
}
}
pub struct Paths<K: PathKey> {
local_results: PathBuf,
public_results: PathBuf,
paths: HashMap<K, PathBuf>,
}
impl<K: PathKey + 'static> Paths<K> {
pub fn new(input_path: &Path) -> std::io::Result<Self> {
let dir_name = input_path.parent().unwrap();
let local_results = dir_name.join(K::local_results_prefix());
let public_results = dir_name.join(K::public_results_prefix());
for result in &[&local_results, &public_results] {
fs::create_dir_all(result)?;
}
let file_name = input_path
.file_name()
.unwrap()
.to_string_lossy()
.to_string();
let paths: HashMap<_, _> = K::all()
.iter()
.map(|key| (key.clone(), PathBuf::from(format!("{}.{}", file_name, key))))
.collect();
for path in paths.values() {
let path = local_results.join(path);
if path.exists() {
fs::remove_file(path).expect("failed to cleanup result path");
}
}
Ok(Self {
local_results,
public_results,
paths,
})
}
pub fn path(&self, key: K) -> PathBuf {
self.local_results.join(self.paths.get(&key).unwrap())
}
pub fn finish(self) {
#[derive(PartialEq, Eq)]
enum Mode {
Check,
Bump,
}
let mode = std::env::var("LANG_UTIL_TEST")
.ok()
.map(|value| {
if value == "bump" {
Mode::Bump
} else {
Mode::Check
}
})
.unwrap_or(Mode::Check);
for (_k, name) in self.paths {
let local_result = self.local_results.join(&name);
let public_result = self.public_results.join(&name);
if local_result.exists() {
match mode {
Mode::Check => {
assert!(public_result.exists(), "missing snapshot");
let local = std::fs::read_to_string(&local_result)
.expect("failed to read local result");
let public = std::fs::read_to_string(&public_result)
.expect("failed to read snapshot");
assert_eq!(local, public, "snapshot mismatch");
}
Mode::Bump => {
std::fs::copy(local_result, public_result)
.expect("failed to bump result to snapshot");
}
}
} else {
assert!(!public_result.exists(), "missing local result");
}
}
}
}