lang_util_dev/
test_util.rs1use std::collections::HashMap;
4use std::path::Path;
5use std::{fs, path::PathBuf};
6
7use similar_asserts::assert_eq;
8
9pub trait PathKey: std::fmt::Display + PartialEq + Eq + std::hash::Hash + Clone + Sized {
11 fn all() -> &'static [Self];
13 fn local_results_prefix() -> &'static str {
15 "localRsResults"
16 }
17 fn public_results_prefix() -> &'static str {
19 "rsResults"
20 }
21}
22
23pub struct Paths<K: PathKey> {
25 local_results: PathBuf,
27 public_results: PathBuf,
29 paths: HashMap<K, PathBuf>,
31}
32
33impl<K: PathKey + 'static> Paths<K> {
34 pub fn new(input_path: &Path) -> std::io::Result<Self> {
40 let dir_name = input_path.parent().unwrap();
42
43 let local_results = dir_name.join(K::local_results_prefix());
44 let public_results = dir_name.join(K::public_results_prefix());
45
46 for result in &[&local_results, &public_results] {
47 fs::create_dir_all(result)?;
48 }
49
50 let file_name = input_path
51 .file_name()
52 .unwrap()
53 .to_string_lossy()
54 .to_string();
55
56 let paths: HashMap<_, _> = K::all()
57 .iter()
58 .map(|key| (key.clone(), PathBuf::from(format!("{}.{}", file_name, key))))
59 .collect();
60
61 for path in paths.values() {
63 let path = local_results.join(path);
64 if path.exists() {
65 fs::remove_file(path).expect("failed to cleanup result path");
66 }
67 }
68
69 Ok(Self {
70 local_results,
71 public_results,
72 paths,
73 })
74 }
75
76 pub fn path(&self, key: K) -> PathBuf {
78 self.local_results.join(self.paths.get(&key).unwrap())
79 }
80
81 pub fn finish(self) {
88 #[derive(PartialEq, Eq)]
89 enum Mode {
90 Check,
91 Bump,
92 }
93
94 let mode = std::env::var("LANG_UTIL_TEST")
95 .ok()
96 .map(|value| {
97 if value == "bump" {
98 Mode::Bump
99 } else {
100 Mode::Check
101 }
102 })
103 .unwrap_or(Mode::Check);
104
105 for (_k, name) in self.paths {
106 let local_result = self.local_results.join(&name);
108 let public_result = self.public_results.join(&name);
109
110 if local_result.exists() {
111 match mode {
112 Mode::Check => {
113 assert!(public_result.exists(), "missing snapshot");
114
115 let local = std::fs::read_to_string(&local_result)
116 .expect("failed to read local result");
117 let public = std::fs::read_to_string(&public_result)
118 .expect("failed to read snapshot");
119
120 assert_eq!(local, public, "snapshot mismatch");
121 }
122 Mode::Bump => {
123 std::fs::copy(local_result, public_result)
124 .expect("failed to bump result to snapshot");
125 }
126 }
127 } else {
128 assert!(!public_result.exists(), "missing local result");
129 }
130 }
131 }
132}