1 use std
::path
::PathBuf
;
3 use anyhow
::{bail, format_err, Error}
;
5 use proxmox_apt
::config
::APTConfig
;
7 use proxmox_apt
::repositories
::{
8 check_repositories
, get_current_release_codename
, standard_repositories
, APTRepositoryFile
,
9 APTRepositoryHandle
, APTRepositoryInfo
, APTStandardRepository
, DebianCodename
,
13 fn test_parse_write() -> Result
<(), Error
> {
14 test_parse_write_dir("sources.list.d")?
;
15 test_parse_write_dir("sources.list.d.expected")?
; // check if it's idempotent
20 fn test_parse_write_dir(read_dir
: &str) -> Result
<(), Error
> {
21 let test_dir
= std
::env
::current_dir()?
.join("tests");
22 let read_dir
= test_dir
.join(read_dir
);
23 let write_dir
= test_dir
.join("sources.list.d.actual");
24 let expected_dir
= test_dir
.join("sources.list.d.expected");
26 if write_dir
.is_dir() {
27 std
::fs
::remove_dir_all(&write_dir
)
28 .map_err(|err
| format_err
!("unable to remove dir {:?} - {}", write_dir
, err
))?
;
31 std
::fs
::create_dir_all(&write_dir
)
32 .map_err(|err
| format_err
!("unable to create dir {:?} - {}", write_dir
, err
))?
;
34 let mut files
= vec
![];
35 let mut errors
= vec
![];
37 for entry
in std
::fs
::read_dir(read_dir
)?
{
38 let path
= entry?
.path();
40 match APTRepositoryFile
::new(&path
)?
{
41 Some(mut file
) => match file
.parse() {
42 Ok(()) => files
.push(file
),
43 Err(err
) => errors
.push(err
),
45 None
=> bail
!("unexpected None for '{:?}'", path
),
49 assert
!(errors
.is_empty());
51 for file
in files
.iter_mut() {
52 let path
= PathBuf
::from(&file
.path
);
53 let new_path
= write_dir
.join(path
.file_name().unwrap());
54 file
.path
= new_path
.into_os_string().into_string().unwrap();
59 let mut expected_count
= 0;
61 for entry
in std
::fs
::read_dir(expected_dir
)?
{
64 let expected_path
= entry?
.path();
65 let actual_path
= write_dir
.join(expected_path
.file_name().unwrap());
67 let expected_contents
= std
::fs
::read(&expected_path
)
68 .map_err(|err
| format_err
!("unable to read {:?} - {}", expected_path
, err
))?
;
70 let actual_contents
= std
::fs
::read(&actual_path
)
71 .map_err(|err
| format_err
!("unable to read {:?} - {}", actual_path
, err
))?
;
74 expected_contents
, actual_contents
,
75 "Use\n\ndiff {:?} {:?}\n\nif you're not fluent in byte decimals",
76 expected_path
, actual_path
80 let actual_count
= std
::fs
::read_dir(write_dir
)?
.count();
82 assert_eq
!(expected_count
, actual_count
);
88 fn test_digest() -> Result
<(), Error
> {
89 let test_dir
= std
::env
::current_dir()?
.join("tests");
90 let read_dir
= test_dir
.join("sources.list.d");
91 let write_dir
= test_dir
.join("sources.list.d.digest");
93 if write_dir
.is_dir() {
94 std
::fs
::remove_dir_all(&write_dir
)
95 .map_err(|err
| format_err
!("unable to remove dir {:?} - {}", write_dir
, err
))?
;
98 std
::fs
::create_dir_all(&write_dir
)
99 .map_err(|err
| format_err
!("unable to create dir {:?} - {}", write_dir
, err
))?
;
101 let path
= read_dir
.join("standard.list");
103 let mut file
= APTRepositoryFile
::new(&path
)?
.unwrap();
106 let new_path
= write_dir
.join(path
.file_name().unwrap());
107 file
.path
= new_path
.clone().into_os_string().into_string().unwrap();
109 let old_digest
= file
.digest
.unwrap();
111 // file does not exist yet...
112 assert
!(file
.read_with_digest().is_err());
113 assert
!(file
.write().is_err());
115 // ...but it should work if there's no digest
119 // overwrite with old contents...
120 std
::fs
::copy(path
, new_path
)?
;
123 let mut repo
= file
.repositories
.first_mut().unwrap();
124 repo
.enabled
= !repo
.enabled
;
126 // ...then it should work
127 file
.digest
= Some(old_digest
);
130 // expect a different digest, because the repo was modified
131 let (_
, new_digest
) = file
.read_with_digest()?
;
132 assert_ne
!(old_digest
, new_digest
);
134 assert
!(file
.write().is_err());
140 fn test_empty_write() -> Result
<(), Error
> {
141 let test_dir
= std
::env
::current_dir()?
.join("tests");
142 let read_dir
= test_dir
.join("sources.list.d");
143 let write_dir
= test_dir
.join("sources.list.d.remove");
145 if write_dir
.is_dir() {
146 std
::fs
::remove_dir_all(&write_dir
)
147 .map_err(|err
| format_err
!("unable to remove dir {:?} - {}", write_dir
, err
))?
;
150 std
::fs
::create_dir_all(&write_dir
)
151 .map_err(|err
| format_err
!("unable to create dir {:?} - {}", write_dir
, err
))?
;
153 let path
= read_dir
.join("standard.list");
155 let mut file
= APTRepositoryFile
::new(&path
)?
.unwrap();
158 let new_path
= write_dir
.join(path
.file_name().unwrap());
159 file
.path
= new_path
.clone().into_os_string().into_string().unwrap();
165 assert
!(file
.exists());
167 file
.repositories
.clear();
171 assert
!(!file
.exists());
177 fn test_check_repositories() -> Result
<(), Error
> {
178 let test_dir
= std
::env
::current_dir()?
.join("tests");
179 let read_dir
= test_dir
.join("sources.list.d");
181 proxmox_apt
::config
::init(APTConfig
::new(
182 Some(&test_dir
.into_os_string().into_string().unwrap()),
186 let absolute_suite_list
= read_dir
.join("absolute_suite.list");
187 let mut file
= APTRepositoryFile
::new(&absolute_suite_list
)?
.unwrap();
190 let infos
= check_repositories(&vec
![file
], DebianCodename
::Bullseye
);
192 assert_eq
!(infos
.is_empty(), true);
193 let pve_list
= read_dir
.join("pve.list");
194 let mut file
= APTRepositoryFile
::new(&pve_list
)?
.unwrap();
197 let path_string
= pve_list
.into_os_string().into_string().unwrap();
200 "Debian", "Debian", "Proxmox", "Proxmox", "Proxmox", "Debian",
203 let mut expected_infos
= vec
![];
205 expected_infos
.push(APTRepositoryInfo
{
206 path
: path_string
.clone(),
209 kind
: "origin".to_string(),
210 message
: origins
[n
].to_string(),
213 expected_infos
.sort();
215 let mut infos
= check_repositories(&vec
![file
], DebianCodename
::Bullseye
);
218 assert_eq
!(infos
, expected_infos
);
220 let bad_sources
= read_dir
.join("bad.sources");
221 let mut file
= APTRepositoryFile
::new(&bad_sources
)?
.unwrap();
224 let path_string
= bad_sources
.into_os_string().into_string().unwrap();
226 let mut expected_infos
= vec
![
228 path
: path_string
.clone(),
230 property
: Some("Suites".to_string()),
231 kind
: "warning".to_string(),
232 message
: "suite 'sid' should not be used in production!".to_string(),
235 path
: path_string
.clone(),
237 property
: Some("Suites".to_string()),
238 kind
: "warning".to_string(),
239 message
: "old suite 'lenny' configured!".to_string(),
242 path
: path_string
.clone(),
244 property
: Some("Suites".to_string()),
245 kind
: "warning".to_string(),
246 message
: "old suite 'stretch' configured!".to_string(),
249 path
: path_string
.clone(),
251 property
: Some("Suites".to_string()),
252 kind
: "warning".to_string(),
253 message
: "use the name of the stable distribution instead of 'stable'!".to_string(),
256 path
: path_string
.clone(),
258 property
: Some("Suites".to_string()),
259 kind
: "ignore-pre-upgrade-warning".to_string(),
260 message
: "suite 'bookworm' should not be used in production!".to_string(),
263 path
: path_string
.clone(),
265 property
: Some("Suites".to_string()),
266 kind
: "warning".to_string(),
267 message
: "suite 'testing' should not be used in production!".to_string(),
271 expected_infos
.push(APTRepositoryInfo
{
272 path
: path_string
.clone(),
275 kind
: "origin".to_string(),
276 message
: "Debian".to_string(),
279 expected_infos
.sort();
281 let mut infos
= check_repositories(&vec
![file
], DebianCodename
::Bullseye
);
284 assert_eq
!(infos
, expected_infos
);
290 fn test_get_cached_origin() -> Result
<(), Error
> {
291 let test_dir
= std
::env
::current_dir()?
.join("tests");
292 let read_dir
= test_dir
.join("sources.list.d");
294 proxmox_apt
::config
::init(APTConfig
::new(
295 Some(&test_dir
.into_os_string().into_string().unwrap()),
299 let pve_list
= read_dir
.join("pve.list");
300 let mut file
= APTRepositoryFile
::new(&pve_list
)?
.unwrap();
304 Some("Debian".to_string()),
305 Some("Debian".to_string()),
306 Some("Proxmox".to_string()),
307 None
, // no cache file exists
308 None
, // no cache file exists
309 Some("Debian".to_string()),
312 assert_eq
!(file
.repositories
.len(), origins
.len());
314 for (n
, repo
) in file
.repositories
.iter().enumerate() {
315 assert_eq
!(repo
.get_cached_origin()?
, origins
[n
]);
322 fn test_standard_repositories() -> Result
<(), Error
> {
323 let test_dir
= std
::env
::current_dir()?
.join("tests");
324 let read_dir
= test_dir
.join("sources.list.d");
326 let mut expected
= vec
![
327 APTStandardRepository
::from(APTRepositoryHandle
::Enterprise
),
328 APTStandardRepository
::from(APTRepositoryHandle
::NoSubscription
),
329 APTStandardRepository
::from(APTRepositoryHandle
::Test
),
330 APTStandardRepository
::from(APTRepositoryHandle
::CephPacific
),
331 APTStandardRepository
::from(APTRepositoryHandle
::CephPacificTest
),
332 APTStandardRepository
::from(APTRepositoryHandle
::CephOctopus
),
333 APTStandardRepository
::from(APTRepositoryHandle
::CephOctopusTest
),
336 let absolute_suite_list
= read_dir
.join("absolute_suite.list");
337 let mut file
= APTRepositoryFile
::new(&absolute_suite_list
)?
.unwrap();
340 let std_repos
= standard_repositories(&vec
![file
], "pve", DebianCodename
::Bullseye
);
342 assert_eq
!(std_repos
, expected
);
344 let pve_list
= read_dir
.join("pve.list");
345 let mut file
= APTRepositoryFile
::new(&pve_list
)?
.unwrap();
348 let file_vec
= vec
![file
];
350 let std_repos
= standard_repositories(&file_vec
, "pbs", DebianCodename
::Bullseye
);
352 assert_eq
!(&std_repos
, &expected
[0..=2]);
354 expected
[0].status
= Some(false);
355 expected
[1].status
= Some(true);
357 let std_repos
= standard_repositories(&file_vec
, "pve", DebianCodename
::Bullseye
);
359 assert_eq
!(std_repos
, expected
);
361 let pve_alt_list
= read_dir
.join("pve-alt.list");
362 let mut file
= APTRepositoryFile
::new(&pve_alt_list
)?
.unwrap();
365 let file_vec
= vec
![file
];
367 expected
[0].status
= Some(true);
368 expected
[1].status
= Some(true);
369 expected
[2].status
= Some(false);
371 let std_repos
= standard_repositories(&file_vec
, "pve", DebianCodename
::Bullseye
);
373 assert_eq
!(std_repos
, expected
);
379 fn test_get_current_release_codename() -> Result
<(), Error
> {
380 let codename
= get_current_release_codename()?
;
382 assert
!(codename
== DebianCodename
::Bullseye
);