]> git.proxmox.com Git - proxmox-apt.git/blob - tests/repositories.rs
standard repos: allow conversion from handle and improve information
[proxmox-apt.git] / tests / repositories.rs
1 use std::path::PathBuf;
2
3 use anyhow::{bail, format_err, Error};
4
5 use proxmox_apt::config::APTConfig;
6
7 use proxmox_apt::repositories::{
8 check_repositories, standard_repositories, APTRepositoryFile, APTRepositoryHandle,
9 APTRepositoryInfo, APTStandardRepository,
10 };
11
12 #[test]
13 fn test_parse_write() -> Result<(), Error> {
14 let test_dir = std::env::current_dir()?.join("tests");
15 let read_dir = test_dir.join("sources.list.d");
16 let write_dir = test_dir.join("sources.list.d.actual");
17 let expected_dir = test_dir.join("sources.list.d.expected");
18
19 if write_dir.is_dir() {
20 std::fs::remove_dir_all(&write_dir)
21 .map_err(|err| format_err!("unable to remove dir {:?} - {}", write_dir, err))?;
22 }
23
24 std::fs::create_dir_all(&write_dir)
25 .map_err(|err| format_err!("unable to create dir {:?} - {}", write_dir, err))?;
26
27 let mut files = vec![];
28 let mut errors = vec![];
29
30 for entry in std::fs::read_dir(read_dir)? {
31 let path = entry?.path();
32
33 match APTRepositoryFile::new(&path)? {
34 Some(mut file) => match file.parse() {
35 Ok(()) => files.push(file),
36 Err(err) => errors.push(err),
37 },
38 None => bail!("unexpected None for '{:?}'", path),
39 }
40 }
41
42 assert!(errors.is_empty());
43
44 for file in files.iter_mut() {
45 let path = PathBuf::from(&file.path);
46 let new_path = write_dir.join(path.file_name().unwrap());
47 file.path = new_path.into_os_string().into_string().unwrap();
48 file.digest = None;
49 file.write()?;
50 }
51
52 let mut expected_count = 0;
53
54 for entry in std::fs::read_dir(expected_dir)? {
55 expected_count += 1;
56
57 let expected_path = entry?.path();
58 let actual_path = write_dir.join(expected_path.file_name().unwrap());
59
60 let expected_contents = std::fs::read(&expected_path)
61 .map_err(|err| format_err!("unable to read {:?} - {}", expected_path, err))?;
62
63 let actual_contents = std::fs::read(&actual_path)
64 .map_err(|err| format_err!("unable to read {:?} - {}", actual_path, err))?;
65
66 assert_eq!(
67 expected_contents, actual_contents,
68 "Use\n\ndiff {:?} {:?}\n\nif you're not fluent in byte decimals",
69 expected_path, actual_path
70 );
71 }
72
73 let actual_count = std::fs::read_dir(write_dir)?.count();
74
75 assert_eq!(expected_count, actual_count);
76
77 Ok(())
78 }
79
80 #[test]
81 fn test_digest() -> Result<(), Error> {
82 let test_dir = std::env::current_dir()?.join("tests");
83 let read_dir = test_dir.join("sources.list.d");
84 let write_dir = test_dir.join("sources.list.d.digest");
85
86 if write_dir.is_dir() {
87 std::fs::remove_dir_all(&write_dir)
88 .map_err(|err| format_err!("unable to remove dir {:?} - {}", write_dir, err))?;
89 }
90
91 std::fs::create_dir_all(&write_dir)
92 .map_err(|err| format_err!("unable to create dir {:?} - {}", write_dir, err))?;
93
94 let path = read_dir.join("standard.list");
95
96 let mut file = APTRepositoryFile::new(&path)?.unwrap();
97 file.parse()?;
98
99 let new_path = write_dir.join(path.file_name().unwrap());
100 file.path = new_path.clone().into_os_string().into_string().unwrap();
101
102 let old_digest = file.digest.unwrap();
103
104 // file does not exist yet...
105 assert!(file.read_with_digest().is_err());
106 assert!(file.write().is_err());
107
108 // ...but it should work if there's no digest
109 file.digest = None;
110 file.write()?;
111
112 // overwrite with old contents...
113 std::fs::copy(path, new_path)?;
114
115 // modify the repo
116 let mut repo = file.repositories.first_mut().unwrap();
117 repo.enabled = !repo.enabled;
118
119 // ...then it should work
120 file.digest = Some(old_digest);
121 file.write()?;
122
123 // expect a different digest, because the repo was modified
124 let (_, new_digest) = file.read_with_digest()?;
125 assert_ne!(old_digest, new_digest);
126
127 assert!(file.write().is_err());
128
129 Ok(())
130 }
131
132 #[test]
133 fn test_empty_write() -> Result<(), Error> {
134 let test_dir = std::env::current_dir()?.join("tests");
135 let read_dir = test_dir.join("sources.list.d");
136 let write_dir = test_dir.join("sources.list.d.remove");
137
138 if write_dir.is_dir() {
139 std::fs::remove_dir_all(&write_dir)
140 .map_err(|err| format_err!("unable to remove dir {:?} - {}", write_dir, err))?;
141 }
142
143 std::fs::create_dir_all(&write_dir)
144 .map_err(|err| format_err!("unable to create dir {:?} - {}", write_dir, err))?;
145
146 let path = read_dir.join("standard.list");
147
148 let mut file = APTRepositoryFile::new(&path)?.unwrap();
149 file.parse()?;
150
151 let new_path = write_dir.join(path.file_name().unwrap());
152 file.path = new_path.clone().into_os_string().into_string().unwrap();
153
154 file.digest = None;
155
156 file.write()?;
157
158 assert!(file.exists());
159
160 file.repositories.clear();
161
162 file.write()?;
163
164 assert!(!file.exists());
165
166 Ok(())
167 }
168
169 #[test]
170 fn test_check_repositories() -> Result<(), Error> {
171 let test_dir = std::env::current_dir()?.join("tests");
172 let read_dir = test_dir.join("sources.list.d");
173
174 proxmox_apt::config::init(APTConfig::new(
175 Some(&test_dir.into_os_string().into_string().unwrap()),
176 None,
177 ));
178
179 let absolute_suite_list = read_dir.join("absolute_suite.list");
180 let mut file = APTRepositoryFile::new(&absolute_suite_list)?.unwrap();
181 file.parse()?;
182
183 let infos = check_repositories(&vec![file])?;
184
185 assert_eq!(infos.is_empty(), true);
186 let pve_list = read_dir.join("pve.list");
187 let mut file = APTRepositoryFile::new(&pve_list)?.unwrap();
188 file.parse()?;
189
190 let path_string = pve_list.into_os_string().into_string().unwrap();
191
192 let origins = [
193 "Debian", "Debian", "Proxmox", "Proxmox", "Proxmox", "Debian",
194 ];
195
196 let mut expected_infos = vec![];
197 for n in 0..=5 {
198 expected_infos.push(APTRepositoryInfo {
199 path: path_string.clone(),
200 index: n,
201 property: None,
202 kind: "origin".to_string(),
203 message: origins[n].to_string(),
204 });
205 }
206 expected_infos.sort();
207
208 let mut infos = check_repositories(&vec![file])?;
209 infos.sort();
210
211 assert_eq!(infos, expected_infos);
212
213 let bad_sources = read_dir.join("bad.sources");
214 let mut file = APTRepositoryFile::new(&bad_sources)?.unwrap();
215 file.parse()?;
216
217 let path_string = bad_sources.into_os_string().into_string().unwrap();
218
219 let mut expected_infos = vec![
220 APTRepositoryInfo {
221 path: path_string.clone(),
222 index: 0,
223 property: Some("Suites".to_string()),
224 kind: "warning".to_string(),
225 message: "suite 'sid' should not be used in production!".to_string(),
226 },
227 APTRepositoryInfo {
228 path: path_string.clone(),
229 index: 1,
230 property: Some("Suites".to_string()),
231 kind: "warning".to_string(),
232 message: "old suite 'lenny' configured!".to_string(),
233 },
234 APTRepositoryInfo {
235 path: path_string.clone(),
236 index: 2,
237 property: Some("Suites".to_string()),
238 kind: "warning".to_string(),
239 message: "old suite 'stretch' configured!".to_string(),
240 },
241 APTRepositoryInfo {
242 path: path_string.clone(),
243 index: 3,
244 property: Some("Suites".to_string()),
245 kind: "warning".to_string(),
246 message: "use the name of the stable distribution instead of 'stable'!".to_string(),
247 },
248 APTRepositoryInfo {
249 path: path_string.clone(),
250 index: 4,
251 property: Some("Suites".to_string()),
252 kind: "ignore-pre-upgrade-warning".to_string(),
253 message: "suite 'bookworm' should not be used in production!".to_string(),
254 },
255 APTRepositoryInfo {
256 path: path_string.clone(),
257 index: 5,
258 property: Some("Suites".to_string()),
259 kind: "warning".to_string(),
260 message: "suite 'testing' should not be used in production!".to_string(),
261 },
262 ];
263 for n in 0..=5 {
264 expected_infos.push(APTRepositoryInfo {
265 path: path_string.clone(),
266 index: n,
267 property: None,
268 kind: "origin".to_string(),
269 message: "Debian".to_string(),
270 });
271 }
272 expected_infos.sort();
273
274 let mut infos = check_repositories(&vec![file])?;
275 infos.sort();
276
277 assert_eq!(infos, expected_infos);
278
279 Ok(())
280 }
281
282 #[test]
283 fn test_get_cached_origin() -> Result<(), Error> {
284 let test_dir = std::env::current_dir()?.join("tests");
285 let read_dir = test_dir.join("sources.list.d");
286
287 proxmox_apt::config::init(APTConfig::new(
288 Some(&test_dir.into_os_string().into_string().unwrap()),
289 None,
290 ));
291
292 let pve_list = read_dir.join("pve.list");
293 let mut file = APTRepositoryFile::new(&pve_list)?.unwrap();
294 file.parse()?;
295
296 let origins = [
297 Some("Debian".to_string()),
298 Some("Debian".to_string()),
299 Some("Proxmox".to_string()),
300 None, // no cache file exists
301 None, // no cache file exists
302 Some("Debian".to_string()),
303 ];
304
305 assert_eq!(file.repositories.len(), origins.len());
306
307 for (n, repo) in file.repositories.iter().enumerate() {
308 assert_eq!(repo.get_cached_origin()?, origins[n]);
309 }
310
311 Ok(())
312 }
313
314 #[test]
315 fn test_standard_repositories() -> Result<(), Error> {
316 let test_dir = std::env::current_dir()?.join("tests");
317 let read_dir = test_dir.join("sources.list.d");
318
319 let mut expected = vec![
320 APTStandardRepository::from(APTRepositoryHandle::Enterprise),
321 APTStandardRepository::from(APTRepositoryHandle::NoSubscription),
322 APTStandardRepository::from(APTRepositoryHandle::Test),
323 APTStandardRepository::from(APTRepositoryHandle::CephPacific),
324 APTStandardRepository::from(APTRepositoryHandle::CephPacificTest),
325 APTStandardRepository::from(APTRepositoryHandle::CephOctopus),
326 APTStandardRepository::from(APTRepositoryHandle::CephOctopusTest),
327 ];
328
329 let absolute_suite_list = read_dir.join("absolute_suite.list");
330 let mut file = APTRepositoryFile::new(&absolute_suite_list)?.unwrap();
331 file.parse()?;
332
333 let std_repos = standard_repositories("pve", &vec![file]);
334
335 assert_eq!(std_repos, expected);
336
337 let pve_list = read_dir.join("pve.list");
338 let mut file = APTRepositoryFile::new(&pve_list)?.unwrap();
339 file.parse()?;
340
341 let file_vec = vec![file];
342
343 let std_repos = standard_repositories("pbs", &file_vec);
344
345 assert_eq!(&std_repos, &expected[0..=2]);
346
347 expected[0].status = Some(false);
348 expected[1].status = Some(true);
349
350 let std_repos = standard_repositories("pve", &file_vec);
351
352 assert_eq!(std_repos, expected);
353
354 Ok(())
355 }