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
= match &file
.path
{
56 let path
= PathBuf
::from(path
);
57 let new_path
= write_dir
.join(path
.file_name().unwrap());
58 file
.path
= Some(new_path
.into_os_string().into_string().unwrap());
63 let mut expected_count
= 0;
65 for entry
in std
::fs
::read_dir(expected_dir
)?
{
68 let expected_path
= entry?
.path();
69 let actual_path
= write_dir
.join(expected_path
.file_name().unwrap());
71 let expected_contents
= std
::fs
::read(&expected_path
)
72 .map_err(|err
| format_err
!("unable to read {:?} - {}", expected_path
, err
))?
;
74 let actual_contents
= std
::fs
::read(&actual_path
)
75 .map_err(|err
| format_err
!("unable to read {:?} - {}", actual_path
, err
))?
;
78 expected_contents
, actual_contents
,
79 "Use\n\ndiff {:?} {:?}\n\nif you're not fluent in byte decimals",
80 expected_path
, actual_path
84 let actual_count
= std
::fs
::read_dir(write_dir
)?
.count();
86 assert_eq
!(expected_count
, actual_count
);
92 fn test_digest() -> Result
<(), Error
> {
93 let test_dir
= std
::env
::current_dir()?
.join("tests");
94 let read_dir
= test_dir
.join("sources.list.d");
95 let write_dir
= test_dir
.join("sources.list.d.digest");
97 if write_dir
.is_dir() {
98 std
::fs
::remove_dir_all(&write_dir
)
99 .map_err(|err
| format_err
!("unable to remove dir {:?} - {}", write_dir
, err
))?
;
102 std
::fs
::create_dir_all(&write_dir
)
103 .map_err(|err
| format_err
!("unable to create dir {:?} - {}", write_dir
, err
))?
;
105 let path
= read_dir
.join("standard.list");
107 let mut file
= APTRepositoryFile
::new(&path
)?
.unwrap();
110 let new_path
= write_dir
.join(path
.file_name().unwrap());
111 file
.path
= Some(new_path
.clone().into_os_string().into_string().unwrap());
113 let old_digest
= file
.digest
.unwrap();
115 // file does not exist yet...
116 assert
!(file
.read_with_digest().is_err());
117 assert
!(file
.write().is_err());
119 // ...but it should work if there's no digest
123 // overwrite with old contents...
124 std
::fs
::copy(path
, new_path
)?
;
127 let mut repo
= file
.repositories
.first_mut().unwrap();
128 repo
.enabled
= !repo
.enabled
;
130 // ...then it should work
131 file
.digest
= Some(old_digest
);
134 // expect a different digest, because the repo was modified
135 let (_
, new_digest
) = file
.read_with_digest()?
;
136 assert_ne
!(old_digest
, new_digest
);
138 assert
!(file
.write().is_err());
144 fn test_empty_write() -> Result
<(), Error
> {
145 let test_dir
= std
::env
::current_dir()?
.join("tests");
146 let read_dir
= test_dir
.join("sources.list.d");
147 let write_dir
= test_dir
.join("sources.list.d.remove");
149 if write_dir
.is_dir() {
150 std
::fs
::remove_dir_all(&write_dir
)
151 .map_err(|err
| format_err
!("unable to remove dir {:?} - {}", write_dir
, err
))?
;
154 std
::fs
::create_dir_all(&write_dir
)
155 .map_err(|err
| format_err
!("unable to create dir {:?} - {}", write_dir
, err
))?
;
157 let path
= read_dir
.join("standard.list");
159 let mut file
= APTRepositoryFile
::new(&path
)?
.unwrap();
162 let new_path
= write_dir
.join(path
.file_name().unwrap());
163 file
.path
= Some(new_path
.into_os_string().into_string().unwrap());
169 assert
!(file
.exists());
171 file
.repositories
.clear();
175 assert
!(!file
.exists());
181 fn test_check_repositories() -> Result
<(), Error
> {
182 let test_dir
= std
::env
::current_dir()?
.join("tests");
183 let read_dir
= test_dir
.join("sources.list.d");
185 proxmox_apt
::config
::init(APTConfig
::new(
186 Some(&test_dir
.into_os_string().into_string().unwrap()),
190 let absolute_suite_list
= read_dir
.join("absolute_suite.list");
191 let mut file
= APTRepositoryFile
::new(&absolute_suite_list
)?
.unwrap();
194 let infos
= check_repositories(&[file
], DebianCodename
::Bullseye
);
196 assert
!(infos
.is_empty());
197 let pve_list
= read_dir
.join("pve.list");
198 let mut file
= APTRepositoryFile
::new(&pve_list
)?
.unwrap();
201 let path_string
= pve_list
.into_os_string().into_string().unwrap();
204 "Debian", "Debian", "Proxmox", "Proxmox", "Proxmox", "Debian",
207 let mut expected_infos
= vec
![];
208 for (n
, origin
) in origins
.into_iter().enumerate() {
209 expected_infos
.push(APTRepositoryInfo
{
210 path
: path_string
.clone(),
213 kind
: "origin".to_string(),
214 message
: origin
.to_string(),
217 expected_infos
.sort();
219 let mut infos
= check_repositories(&[file
], DebianCodename
::Bullseye
);
222 assert_eq
!(infos
, expected_infos
);
224 let bad_sources
= read_dir
.join("bad.sources");
225 let mut file
= APTRepositoryFile
::new(&bad_sources
)?
.unwrap();
228 let path_string
= bad_sources
.into_os_string().into_string().unwrap();
230 let mut expected_infos
= vec
![
232 path
: path_string
.clone(),
234 property
: Some("Suites".to_string()),
235 kind
: "warning".to_string(),
236 message
: "suite 'sid' should not be used in production!".to_string(),
239 path
: path_string
.clone(),
241 property
: Some("Suites".to_string()),
242 kind
: "warning".to_string(),
243 message
: "old suite 'lenny' configured!".to_string(),
246 path
: path_string
.clone(),
248 property
: Some("Suites".to_string()),
249 kind
: "warning".to_string(),
250 message
: "old suite 'stretch' configured!".to_string(),
253 path
: path_string
.clone(),
255 property
: Some("Suites".to_string()),
256 kind
: "warning".to_string(),
257 message
: "use the name of the stable distribution instead of 'stable'!".to_string(),
260 path
: path_string
.clone(),
262 property
: Some("Suites".to_string()),
263 kind
: "ignore-pre-upgrade-warning".to_string(),
264 message
: "suite 'bookworm' should not be used in production!".to_string(),
267 path
: path_string
.clone(),
269 property
: Some("Suites".to_string()),
270 kind
: "warning".to_string(),
271 message
: "suite 'testing' should not be used in production!".to_string(),
275 expected_infos
.push(APTRepositoryInfo
{
276 path
: path_string
.clone(),
279 kind
: "origin".to_string(),
280 message
: "Debian".to_string(),
283 expected_infos
.sort();
285 let mut infos
= check_repositories(&[file
], DebianCodename
::Bullseye
);
288 assert_eq
!(infos
, expected_infos
);
290 let bad_security
= read_dir
.join("bad-security.list");
291 let mut file
= APTRepositoryFile
::new(&bad_security
)?
.unwrap();
294 let path_string
= bad_security
.into_os_string().into_string().unwrap();
296 let mut expected_infos
= vec
![];
298 expected_infos
.push(APTRepositoryInfo
{
299 path
: path_string
.clone(),
301 property
: Some("Suites".to_string()),
302 kind
: "warning".to_string(),
303 message
: "expected suite 'bullseye-security'".to_string(),
307 expected_infos
.push(APTRepositoryInfo
{
308 path
: path_string
.clone(),
311 kind
: "origin".to_string(),
312 message
: "Debian".to_string(),
315 expected_infos
.sort();
317 let mut infos
= check_repositories(&[file
], DebianCodename
::Bullseye
);
320 assert_eq
!(infos
, expected_infos
);
325 fn test_get_cached_origin() -> Result
<(), Error
> {
326 let test_dir
= std
::env
::current_dir()?
.join("tests");
327 let read_dir
= test_dir
.join("sources.list.d");
329 proxmox_apt
::config
::init(APTConfig
::new(
330 Some(&test_dir
.into_os_string().into_string().unwrap()),
334 let pve_list
= read_dir
.join("pve.list");
335 let mut file
= APTRepositoryFile
::new(&pve_list
)?
.unwrap();
339 Some("Debian".to_string()),
340 Some("Debian".to_string()),
341 Some("Proxmox".to_string()),
342 None
, // no cache file exists
343 None
, // no cache file exists
344 Some("Debian".to_string()),
347 assert_eq
!(file
.repositories
.len(), origins
.len());
349 for (n
, repo
) in file
.repositories
.iter().enumerate() {
350 assert_eq
!(repo
.get_cached_origin()?
, origins
[n
]);
357 fn test_standard_repositories() -> Result
<(), Error
> {
358 let test_dir
= std
::env
::current_dir()?
.join("tests");
359 let read_dir
= test_dir
.join("sources.list.d");
361 let mut expected
= vec
![
362 APTStandardRepository
::from(APTRepositoryHandle
::Enterprise
),
363 APTStandardRepository
::from(APTRepositoryHandle
::NoSubscription
),
364 APTStandardRepository
::from(APTRepositoryHandle
::Test
),
365 APTStandardRepository
::from(APTRepositoryHandle
::CephQuincy
),
366 APTStandardRepository
::from(APTRepositoryHandle
::CephQuincyTest
),
367 APTStandardRepository
::from(APTRepositoryHandle
::CephPacific
),
368 APTStandardRepository
::from(APTRepositoryHandle
::CephPacificTest
),
369 APTStandardRepository
::from(APTRepositoryHandle
::CephOctopus
),
370 APTStandardRepository
::from(APTRepositoryHandle
::CephOctopusTest
),
373 let absolute_suite_list
= read_dir
.join("absolute_suite.list");
374 let mut file
= APTRepositoryFile
::new(&absolute_suite_list
)?
.unwrap();
377 let std_repos
= standard_repositories(&[file
], "pve", DebianCodename
::Bullseye
);
379 assert_eq
!(std_repos
, expected
);
381 let pve_list
= read_dir
.join("pve.list");
382 let mut file
= APTRepositoryFile
::new(&pve_list
)?
.unwrap();
385 let file_vec
= vec
![file
];
387 let std_repos
= standard_repositories(&file_vec
, "pbs", DebianCodename
::Bullseye
);
389 assert_eq
!(&std_repos
, &expected
[0..=2]);
391 expected
[0].status
= Some(false);
392 expected
[1].status
= Some(true);
394 let std_repos
= standard_repositories(&file_vec
, "pve", DebianCodename
::Bullseye
);
396 assert_eq
!(std_repos
, expected
);
398 let pve_alt_list
= read_dir
.join("pve-alt.list");
399 let mut file
= APTRepositoryFile
::new(&pve_alt_list
)?
.unwrap();
402 let file_vec
= vec
![file
];
404 expected
[0].status
= Some(true);
405 expected
[1].status
= Some(true);
406 expected
[2].status
= Some(false);
408 let std_repos
= standard_repositories(&file_vec
, "pve", DebianCodename
::Bullseye
);
410 assert_eq
!(std_repos
, expected
);
416 fn test_get_current_release_codename() -> Result
<(), Error
> {
417 let codename
= get_current_release_codename()?
;
419 assert
!(codename
== DebianCodename
::Bullseye
);