From ac67762a3b10eddcaa0f75fdff7b9c3371b85ad9 Mon Sep 17 00:00:00 2001 From: Bloxx12 Date: Sun, 15 Jun 2025 17:54:56 +0200 Subject: [PATCH 1/6] gitignore: add mutants.out --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1afea7e..1897bab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.direnv /target /result +/mutants.out From 955a2baa6a5c6f031680a0e38fa33733e42dc41b Mon Sep 17 00:00:00 2001 From: Bloxx12 Date: Sun, 15 Jun 2025 17:54:56 +0200 Subject: [PATCH 2/6] tests: diff: init --- src/diff.rs | 2 +- src/lib.rs | 2 ++ src/tests/diff.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 1 + src/version.rs | 11 +++++- 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/tests/diff.rs create mode 100644 src/tests/mod.rs diff --git a/src/diff.rs b/src/diff.rs index 9f5ef3f..f3b19d9 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -231,7 +231,7 @@ pub fn write_paths_diffln( /// deduplicate_versions(&mut versions); /// assert_eq!(*versions, &["1.0 ×2", "2.3 ×3", "4.8"]); /// ``` -fn deduplicate_versions(versions: &mut Vec) { +pub fn deduplicate_versions(versions: &mut Vec) { versions.sort_unstable(); let mut deduplicated = Vec::new(); diff --git a/src/lib.rs b/src/lib.rs index c7aa4cf..2c5403a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,8 @@ mod store; mod version; use version::Version; +#[cfg(test)] mod tests; + #[derive(Deref, Debug, Clone, Copy, PartialEq, Eq, Hash)] struct DerivationId(i64); diff --git a/src/tests/diff.rs b/src/tests/diff.rs new file mode 100644 index 0000000..1c96d9a --- /dev/null +++ b/src/tests/diff.rs @@ -0,0 +1,86 @@ +use std::{ + fmt, + io, +}; + +use size::Size; + +use crate::{ + Version, + diff, +}; + +struct WriteFmt(W); + +impl fmt::Write for WriteFmt { + fn write_str(&mut self, string: &str) -> fmt::Result { + self.0.write_all(string.as_bytes()).map_err(|_| fmt::Error) + } +} + +#[test] +fn test_deduplicate_versions() { + let mut versions_pre: Vec = vec![ + "2.3".into(), + "1.0".into(), + "2.3".into(), + "4.8".into(), + "2.3".into(), + "1.0".into(), + ]; + let versions_post: Vec = + vec!["1.0 ×2".into(), "2.3 ×3".into(), "4.8".into()]; + diff::deduplicate_versions(&mut versions_pre); + + assert_eq!(versions_pre, versions_post); +} + +#[test] +fn test_deduplicate_versions_empty() { + let mut versions_pre: Vec = vec![]; + let versions_post: Vec = vec![]; + diff::deduplicate_versions(&mut versions_pre); + + assert_eq!(versions_pre, versions_post); +} + +#[test] +fn test_write_size_diffln() { + let size_old = Size::from_bytes(10_i32); + let size_new = Size::from_bytes(20_i32); + + let expected_output = + "\u{1b}[1mSIZE\u{1b}[0m: \u{1b}[31m10 bytes\u{1b}[0m -> \u{1b}[32m20 \ + bytes\u{1b}[0m\n\u{1b}[1mDIFF\u{1b}[0m: \u{1b}[32m10 bytes\u{1b}[0m\n"; + + let mut buf = WriteFmt(io::BufWriter::new(Vec::new())); + + let _ = diff::write_size_diffln(&mut buf, size_old, size_new); + + let buf_writer = buf.0; + + let vec = buf_writer.into_inner().expect("Failed to unwrap BufWriter"); + let result = String::from_utf8(vec).expect("Invalid UTF-8"); + + assert_eq!(result, expected_output); +} + +#[test] +fn test_write_size_diffln_empty() { + let size_old = Size::from_bytes(0_i32); + let size_new = Size::from_bytes(0_i32); + + let expected_output = + "\u{1b}[1mSIZE\u{1b}[0m: \u{1b}[31m0 bytes\u{1b}[0m -> \u{1b}[32m0 \ + bytes\u{1b}[0m\n\u{1b}[1mDIFF\u{1b}[0m: \u{1b}[31m0 bytes\u{1b}[0m\n"; + let mut buf = WriteFmt(io::BufWriter::new(Vec::new())); + + let _ = diff::write_size_diffln(&mut buf, size_old, size_new); + + let buf_writer = buf.0; + + let vec = buf_writer.into_inner().expect("Failed to unwrap BufWriter"); + let result = String::from_utf8(vec).expect("Invalid UTF-8"); + + assert_eq!(result, expected_output); +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 0000000..576285b --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1 @@ +mod diff; diff --git a/src/version.rs b/src/version.rs index b15f2cf..b3b49ab 100644 --- a/src/version.rs +++ b/src/version.rs @@ -5,9 +5,12 @@ use derive_more::{ DerefMut, Display, From, + FromStr, }; -#[derive(Deref, DerefMut, Display, Debug, Clone, PartialEq, Eq, From)] +#[derive( + Deref, DerefMut, Display, Debug, Clone, PartialEq, Eq, From, FromStr, +)] pub struct Version(String); impl PartialOrd for Version { @@ -25,6 +28,12 @@ impl cmp::Ord for Version { } } +impl From<&str> for Version { + fn from(s: &str) -> Self { + Self(s.to_owned()) + } +} + impl<'a> IntoIterator for &'a Version { type Item = Result, &'a str>; From 4b9714136de2a76e075bd54fcc4c992fee7430fe Mon Sep 17 00:00:00 2001 From: Bloxx12 Date: Sun, 15 Jun 2025 18:48:05 +0200 Subject: [PATCH 3/6] diff: cleanup --- src/diff.rs | 463 ++++++++++++++++++++++++++-------------------------- 1 file changed, 232 insertions(+), 231 deletions(-) diff --git a/src/diff.rs b/src/diff.rs index f3b19d9..9a49373 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -77,7 +77,7 @@ impl PartialOrd for DiffStatus { impl cmp::Ord for DiffStatus { fn cmp(&self, other: &Self) -> cmp::Ordering { - #[expect(unreachable_patterns)] + #[expect(unreachable_patterns, clippy::match_same_arms)] match (*self, *other) { (Self::Changed(_), Self::Changed(_)) => cmp::Ordering::Equal, (Self::Changed(_), _) => cmp::Ordering::Less, @@ -271,7 +271,6 @@ pub fn deduplicate_versions(versions: &mut Vec) { *versions = deduplicated; } -#[expect(clippy::cognitive_complexity, clippy::too_many_lines)] fn write_packages_diffln( writer: &mut impl fmt::Write, paths_old: impl Iterator, @@ -282,66 +281,15 @@ fn write_packages_diffln( let mut paths = HashMap::>>::new(); // Collect the names of old and new paths. - let system_derivations_old: HashSet = system_paths_old - .filter_map(|path| { - match path.parse_name_and_version() { - Ok((name, _)) => Some(name.into()), - Err(error) => { - log::warn!("error parsing old system path name and version: {error}"); - None - }, - } - }) - .collect(); - - let system_derivations_new: HashSet = system_paths_new - .filter_map(|path| { - match path.parse_name_and_version() { - Ok((name, _)) => Some(name.into()), - Err(error) => { - log::warn!("error parsing new system path name and version: {error}"); - None - }, - } - }) - .collect(); + let system_derivations_old = get_system_derivations(system_paths_old); + let system_derivations_new = get_system_derivations(system_paths_new); for path in paths_old { - match path.parse_name_and_version() { - Ok((name, version)) => { - log::debug!("parsed name: {name}"); - log::debug!("parsed version: {version:?}"); - - paths - .entry(name.into()) - .or_default() - .old - .push(version.unwrap_or_else(|| Version::from("".to_owned()))); - }, - - Err(error) => { - log::warn!("error parsing old path name and version: {error}"); - }, - } + push_parsed_name_and_version_old(&path, &mut paths); } for path in paths_new { - match path.parse_name_and_version() { - Ok((name, version)) => { - log::debug!("parsed name: {name}"); - log::debug!("parsed version: {version:?}"); - - paths - .entry(name.into()) - .or_default() - .new - .push(version.unwrap_or_else(|| Version::from("".to_owned()))); - }, - - Err(error) => { - log::warn!("error parsing new path name and version: {error}"); - }, - } + push_parsed_name_and_version_new(&path, &mut paths); } let mut diffs = paths @@ -350,51 +298,14 @@ fn write_packages_diffln( deduplicate_versions(&mut versions.old); deduplicate_versions(&mut versions.new); - let status = match (versions.old.len(), versions.new.len()) { - (0, 0) => unreachable!(), - (0, _) => DiffStatus::Added, - (_, 0) => DiffStatus::Removed, - _ => { - let mut saw_upgrade = false; - let mut saw_downgrade = false; - - for diff in - Itertools::zip_longest(versions.old.iter(), versions.new.iter()) - { - match diff { - EitherOrBoth::Left(_) => saw_downgrade = true, - EitherOrBoth::Right(_) => saw_upgrade = true, - - EitherOrBoth::Both(old, new) => { - match old.cmp(new) { - cmp::Ordering::Less => saw_upgrade = true, - cmp::Ordering::Greater => saw_downgrade = true, - cmp::Ordering::Equal => {}, - } - - if saw_upgrade && saw_downgrade { - break; - } - }, - } - } - - DiffStatus::Changed(match (saw_upgrade, saw_downgrade) { - (true, true) => Change::UpgradeDowngrade, - (true, false) => Change::Upgraded, - (false, true) => Change::Downgraded, - _ => return None, - }) - }, - }; - let selection = DerivationSelectionStatus::from_names( &name, &system_derivations_old, &system_derivations_new, ); - Some((name, versions, status, selection)) + get_status_from_versions(&versions) + .map(|status| (name, versions, status, selection)) }) .collect::>(); @@ -440,144 +351,21 @@ fn write_packages_diffln( write!(writer, "[{status}{selection}] {name: { - if oldwrote { - write!(oldacc, ", ")?; - } else { - write!(oldacc, " ")?; - oldwrote = true; - } - - for old_comp in old_version { - match old_comp { - Ok(old_comp) => write!(oldacc, "{old}", old = old_comp.red())?, - Err(ignored) => write!(oldacc, "{ignored}")?, - } - } - }, - - EitherOrBoth::Right(new_version) => { - if newwrote { - write!(newacc, ", ")?; - } else { - write!(newacc, " ")?; - newwrote = true; - } + if let Ok((oldacc, newacc)) = collect_diffs(versions) { + let oldacc = oldacc.join(", "); + let newacc = newacc.join(", "); - for new_comp in new_version { - match new_comp { - Ok(new_comp) => write!(newacc, "{new}", new = new_comp.green())?, - Err(ignored) => write!(newacc, "{ignored}")?, - } - } - }, - - EitherOrBoth::Both(old_version, new_version) => { - if old_version == new_version { - continue; - } - - if oldwrote { - write!(oldacc, ", ")?; - } else { - write!(oldacc, " ")?; - oldwrote = true; - } - if newwrote { - write!(newacc, ", ")?; - } else { - write!(newacc, " ")?; - newwrote = true; - } - - for diff in Itertools::zip_longest( - old_version.into_iter(), - new_version.into_iter(), - ) { - match diff { - EitherOrBoth::Left(old_comp) => { - match old_comp { - Ok(old_comp) => { - write!(oldacc, "{old}", old = old_comp.red())?; - }, - Err(ignored) => { - write!(oldacc, "{ignored}")?; - }, - } - }, - - EitherOrBoth::Right(new_comp) => { - match new_comp { - Ok(new_comp) => { - write!(newacc, "{new}", new = new_comp.green())?; - }, - Err(ignored) => { - write!(newacc, "{ignored}")?; - }, - } - }, - - EitherOrBoth::Both(old_comp, new_comp) => { - match (old_comp, new_comp) { - (Ok(old_comp), Ok(new_comp)) => { - for char in diff::chars(*old_comp, *new_comp) { - match char { - diff::Result::Left(old_part) => { - write!(oldacc, "{old}", old = old_part.red())?; - }, - diff::Result::Right(new_part) => { - write!(newacc, "{new}", new = new_part.green())?; - }, - - diff::Result::Both(old_part, new_part) => { - write!(oldacc, "{old}", old = old_part.yellow())?; - write!(newacc, "{new}", new = new_part.yellow())?; - }, - } - } - }, - - (old_comp, new_comp) => { - match old_comp { - Ok(old_comp) => { - write!(oldacc, "{old}", old = old_comp.yellow())?; - }, - Err(old_comp) => write!(oldacc, "{old_comp}")?, - } - - match new_comp { - Ok(new_comp) => { - write!(newacc, "{new}", new = new_comp.yellow())?; - }, - Err(new_comp) => write!(newacc, "{new_comp}")?, - } - }, - } - }, - } - } - }, - } + write!( + writer, + "{oldacc}{arrow}{newacc}", + arrow = if !oldacc.is_empty() && !newacc.is_empty() { + " -> " + } else { + "" + } + )?; } - write!( - writer, - "{oldacc}{arrow}{newacc}", - arrow = if !oldacc.is_empty() && !newacc.is_empty() { - " ->" - } else { - "" - } - )?; - writeln!(writer)?; } @@ -637,3 +425,216 @@ pub fn write_size_diffln( }, ) } + +fn get_system_derivations( + system_paths: impl Iterator, +) -> HashSet { + system_paths + .filter_map(|path| { + match path.parse_name_and_version() { + Ok((name, _)) => Some(name.into()), + Err(error) => { + log::warn!("error parsing system path name and version: {error}"); + None + }, + } + }) + .collect() +} + +fn push_parsed_name_and_version_old( + path: &StorePath, + paths: &mut HashMap>>, +) { + match path.parse_name_and_version() { + Ok((name, version)) => { + log::debug!("parsed name: {name}"); + log::debug!("parsed version: {version:?}"); + + paths + .entry(name.into()) + .or_default() + .old + .push(version.unwrap_or_else(|| Version::from("".to_owned()))); + }, + + Err(error) => { + log::warn!("error parsing path name and version: {error}"); + }, + } +} +fn push_parsed_name_and_version_new( + path: &StorePath, + paths: &mut HashMap>>, +) { + match path.parse_name_and_version() { + Ok((name, version)) => { + log::debug!("parsed name: {name}"); + log::debug!("parsed version: {version:?}"); + + paths + .entry(name.into()) + .or_default() + .new + .push(version.unwrap_or_else(|| Version::from("".to_owned()))); + }, + + Err(error) => { + log::warn!("error parsing path name and version: {error}"); + }, + } +} + +fn get_status_from_versions( + versions: &Diff>, +) -> Option { + let result = match (versions.old.len(), versions.new.len()) { + (0, 0) => unreachable!(), + (0, _) => DiffStatus::Added, + (_, 0) => DiffStatus::Removed, + _ => { + let mut saw_upgrade = false; + let mut saw_downgrade = false; + + for diff in + Itertools::zip_longest(versions.old.iter(), versions.new.iter()) + { + match diff { + EitherOrBoth::Left(_) => saw_downgrade = true, + EitherOrBoth::Right(_) => saw_upgrade = true, + + EitherOrBoth::Both(old, new) => { + match old.cmp(new) { + cmp::Ordering::Less => saw_upgrade = true, + cmp::Ordering::Greater => saw_downgrade = true, + cmp::Ordering::Equal => {}, + } + + if saw_upgrade && saw_downgrade { + break; + } + }, + } + } + + DiffStatus::Changed(match (saw_upgrade, saw_downgrade) { + (true, true) => Change::UpgradeDowngrade, + (true, false) => Change::Upgraded, + (false, true) => Change::Downgraded, + // FIXME: This is borked + _ => return None, + }) + }, + }; + Some(result) +} + +fn collect_diffs( + versions: &Diff>, +) -> Result<(Vec, Vec), fmt::Error> { + let mut old_versions = Vec::::new(); + let mut new_versions = Vec::::new(); + + for diff in Itertools::zip_longest(versions.old.iter(), versions.new.iter()) { + match diff { + EitherOrBoth::Left(old_version) => { + let mut acc = String::new(); + + for old_comp in old_version { + match old_comp { + Ok(old_comp) => write!(acc, "{old}", old = old_comp.red())?, + Err(ignored) => write!(acc, "{ignored}")?, + } + } + old_versions.push(acc); + }, + + EitherOrBoth::Right(new_version) => { + let mut acc = String::new(); + + for new_comp in new_version { + match new_comp { + Ok(new_comp) => write!(acc, "{new}", new = new_comp.red())?, + Err(ignored) => write!(acc, "{ignored}")?, + } + } + old_versions.push(acc); + }, + + EitherOrBoth::Both(old_version, new_version) => { + if old_version == new_version { + continue; + } + let mut oldacc = String::new(); + let mut newacc = String::new(); + + for diff in Itertools::zip_longest( + old_version.into_iter(), + new_version.into_iter(), + ) { + match diff { + EitherOrBoth::Left(old_comp) => { + match old_comp { + Ok(old_comp) => write!(oldacc, "{old}", old = old_comp.red())?, + Err(ignored) => write!(oldacc, "{ignored}")?, + } + }, + + EitherOrBoth::Right(new_comp) => { + match new_comp { + Ok(new_comp) => { + write!(newacc, "{new}", new = new_comp.green())?; + }, + Err(ignored) => write!(newacc, "{ignored}")?, + } + }, + + EitherOrBoth::Both(old_comp, new_comp) => { + match (old_comp, new_comp) { + (Ok(old_comp), Ok(new_comp)) => { + for char in diff::chars(*old_comp, *new_comp) { + match char { + diff::Result::Left(old_part) => { + write!(oldacc, "{old}", old = old_part.red())?; + }, + diff::Result::Right(new_part) => { + write!(newacc, "{new}", new = new_part.green())?; + }, + + diff::Result::Both(old_part, new_part) => { + write!(oldacc, "{old}", old = old_part.yellow())?; + write!(newacc, "{new}", new = new_part.yellow())?; + }, + } + } + }, + + (old_comp, new_comp) => { + match old_comp { + Ok(old_comp) => { + write!(oldacc, "{old}", old = old_comp.yellow())?; + }, + + Err(old_comp) => write!(oldacc, "{old_comp}")?, + } + + match new_comp { + Ok(new_comp) => { + write!(newacc, "{new}", new = new_comp.yellow())?; + }, + + Err(new_comp) => write!(newacc, "{new_comp}")?, + } + }, + } + }, + } + } + old_versions.push(oldacc); + new_versions.push(newacc); + }, + } + } + + Ok((old_versions, new_versions)) +} From e0711d88fe01348f69b4bf2632a73ccbc0a01c0a Mon Sep 17 00:00:00 2001 From: Bloxx12 Date: Sun, 15 Jun 2025 21:24:32 +0200 Subject: [PATCH 4/6] diff: add more tests --- src/diff.rs | 17 ++++---- src/tests/diff.rs | 106 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 9 deletions(-) diff --git a/src/diff.rs b/src/diff.rs index 9a49373..40386aa 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -38,20 +38,20 @@ use crate::{ }; #[derive(Debug, Default)] -struct Diff { - old: T, - new: T, +pub struct Diff { + pub old: T, + pub new: T, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum Change { +pub enum Change { UpgradeDowngrade, Upgraded, Downgraded, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum DiffStatus { +pub enum DiffStatus { Changed(Change), Added, Removed, @@ -442,7 +442,7 @@ fn get_system_derivations( .collect() } -fn push_parsed_name_and_version_old( +pub fn push_parsed_name_and_version_old( path: &StorePath, paths: &mut HashMap>>, ) { @@ -463,7 +463,8 @@ fn push_parsed_name_and_version_old( }, } } -fn push_parsed_name_and_version_new( + +pub fn push_parsed_name_and_version_new( path: &StorePath, paths: &mut HashMap>>, ) { @@ -485,7 +486,7 @@ fn push_parsed_name_and_version_new( } } -fn get_status_from_versions( +pub fn get_status_from_versions( versions: &Diff>, ) -> Option { let result = match (versions.old.len(), versions.new.len()) { diff --git a/src/tests/diff.rs b/src/tests/diff.rs index 1c96d9a..a889441 100644 --- a/src/tests/diff.rs +++ b/src/tests/diff.rs @@ -1,15 +1,33 @@ use std::{ + collections::HashMap, fmt, io, + path::{ + Path, + PathBuf, + }, }; use size::Size; +use yansi::Paint; use crate::{ + StorePath, Version, - diff, + diff::{ + self, + Diff, + push_parsed_name_and_version_new, + push_parsed_name_and_version_old, + }, }; +impl diff::Diff { + fn new(old: T, new: T) -> diff::Diff { + Diff { old, new } + } +} + struct WriteFmt(W); impl fmt::Write for WriteFmt { @@ -84,3 +102,89 @@ fn test_write_size_diffln_empty() { assert_eq!(result, expected_output); } + +#[test] +fn test_get_status_from_versions() { + let versions_1: Diff> = Diff { + old: vec!["1.0".into()], + new: vec!["1.0".into()], + }; + let versions_2: Diff> = Diff { + old: vec![], + new: vec!["1.0".into()], + }; + let versions_3: Diff> = Diff { + old: vec!["1.0".into()], + new: vec![], + }; + let versions_4: Diff> = Diff { + old: vec!["1.0".into()], + new: vec!["1.1".into()], + }; + let versions_5: Diff> = Diff { + old: vec!["1.0".into()], + new: vec!["0.9".into()], + }; + let versions_6: Diff> = Diff { + old: vec!["1.0".into(), "2.0".into()], + new: vec!["1.1".into(), "1.9".into()], + }; + + assert_eq!(diff::get_status_from_versions(&versions_1), None); + assert_eq!( + diff::get_status_from_versions(&versions_2), + Some(diff::DiffStatus::Added) + ); + assert_eq!( + diff::get_status_from_versions(&versions_3), + Some(diff::DiffStatus::Removed) + ); + assert_eq!( + diff::get_status_from_versions(&versions_4), + Some(diff::DiffStatus::Changed(diff::Change::Upgraded)) + ); + assert_eq!( + diff::get_status_from_versions(&versions_5), + Some(diff::DiffStatus::Changed(diff::Change::Downgraded)) + ); + assert_eq!( + diff::get_status_from_versions(&versions_6), + Some(diff::DiffStatus::Changed(diff::Change::UpgradeDowngrade)) + ); +} + +#[test] +fn test_push_parsed_name_and_version_old() { + let path: StorePath = StorePath::try_from(PathBuf::from( + "/nix/store/cg09nslw3w6afyynjw484b86d47ic1cb-coreutils-9.7", + )) + .expect("Could not create path"); + + let mut paths: HashMap>> = HashMap::new(); + let () = diff::push_parsed_name_and_version_old(&path, &mut paths); + + assert_eq!(paths.keys().count(), 1); + assert_eq!(paths.values().count(), 1); + assert_eq!(paths.keys().take(1).next().unwrap(), "coreutils"); + assert_eq!(paths.values().take(1).next().unwrap().old, vec![ + "9.7".into() + ]); +} + +#[test] +fn test_push_parsed_name_and_version_new() { + let path: StorePath = StorePath::try_from(PathBuf::from( + "/nix/store/6d4dp25lani18z9sbnb5shwzzc3y5yh8-bacon-3.12.0", + )) + .expect("Could not create path"); + + let mut paths: HashMap>> = HashMap::new(); + let () = diff::push_parsed_name_and_version_new(&path, &mut paths); + + assert_eq!(paths.keys().count(), 1); + assert_eq!(paths.values().count(), 1); + assert_eq!(paths.keys().take(1).next().unwrap(), "bacon"); + assert_eq!(paths.values().take(1).next().unwrap().new, vec![ + "3.12.0".into() + ]); +} From d718ed1a76650bc7cca695d555805ae9b9d6471a Mon Sep 17 00:00:00 2001 From: Bloxx12 Date: Sun, 15 Jun 2025 21:57:01 +0200 Subject: [PATCH 5/6] gitignore: add mutants.out.old --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1897bab..08d8e49 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /target /result /mutants.out +/mutants.out.old From 186018e647949a74df44e1f8b0c48225cd0e8ebb Mon Sep 17 00:00:00 2001 From: Bloxx12 Date: Sun, 15 Jun 2025 21:57:35 +0200 Subject: [PATCH 6/6] diff: even more tests --- src/diff.rs | 4 +- src/tests/diff.rs | 104 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 89 insertions(+), 19 deletions(-) diff --git a/src/diff.rs b/src/diff.rs index 40386aa..3d5edff 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -426,7 +426,7 @@ pub fn write_size_diffln( ) } -fn get_system_derivations( +pub fn get_system_derivations( system_paths: impl Iterator, ) -> HashSet { system_paths @@ -530,7 +530,7 @@ pub fn get_status_from_versions( Some(result) } -fn collect_diffs( +pub fn collect_diffs( versions: &Diff>, ) -> Result<(Vec, Vec), fmt::Error> { let mut old_versions = Vec::::new(); diff --git a/src/tests/diff.rs b/src/tests/diff.rs index a889441..3b1df15 100644 --- a/src/tests/diff.rs +++ b/src/tests/diff.rs @@ -1,15 +1,14 @@ use std::{ - collections::HashMap, + collections::{ + HashMap, + HashSet, + }, fmt, io, - path::{ - Path, - PathBuf, - }, + path::PathBuf, }; use size::Size; -use yansi::Paint; use crate::{ StorePath, @@ -17,17 +16,9 @@ use crate::{ diff::{ self, Diff, - push_parsed_name_and_version_new, - push_parsed_name_and_version_old, }, }; -impl diff::Diff { - fn new(old: T, new: T) -> diff::Diff { - Diff { old, new } - } -} - struct WriteFmt(W); impl fmt::Write for WriteFmt { @@ -42,12 +33,33 @@ fn test_deduplicate_versions() { "2.3".into(), "1.0".into(), "2.3".into(), - "4.8".into(), + "1.0.18343".into(), + "1.0.18343".into(), + "1.823.348".into(), + "1.0.18343".into(), + "1.823.348".into(), + "A".into(), + "B".into(), + "B".into(), + "1.823.348".into(), "2.3".into(), + "1.0.18343".into(), + "1.823.348".into(), + "4.8".into(), + "1.823.348".into(), "1.0".into(), + "0".into(), + ]; + let versions_post: Vec = vec![ + "A".into(), + "B ×2".into(), + "0".into(), + "1.0 ×2".into(), + "1.0.18343 ×4".into(), + "1.823.348 ×5".into(), + "2.3 ×3".into(), + "4.8".into(), ]; - let versions_post: Vec = - vec!["1.0 ×2".into(), "2.3 ×3".into(), "4.8".into()]; diff::deduplicate_versions(&mut versions_pre); assert_eq!(versions_pre, versions_post); @@ -188,3 +200,61 @@ fn test_push_parsed_name_and_version_new() { "3.12.0".into() ]); } + +#[test] +fn test_get_system_derivations() { + let paths = vec![ + StorePath::try_from(PathBuf::from( + "/nix/store/6d4dp25lani18z9sbnb5shwzzc3y5yh8-bacon-3.12.0", + )) + .unwrap(), + StorePath::try_from(PathBuf::from( + "/nix/store/cg09nslw3w6afyynjw484b86d47ic1cb-coreutils-9.7", + )) + .unwrap(), + StorePath::try_from(PathBuf::from( + "/nix/store/6d4dp25lani18z9sbnb5shwzzc3y5yh8-cool_package-189", + )) + .unwrap(), + ]; + + let mut names: HashSet = HashSet::new(); + names.insert("coreutils".to_owned()); + names.insert("bacon".to_owned()); + names.insert("cool_package".to_owned()); + + let system_paths = paths.into_iter(); + + let bla = diff::get_system_derivations(system_paths); + + assert_eq!(bla, names); +} + +#[test] +fn test_collect_diffs() { + let old_versions: Vec = vec![ + "6.14.8".into(), + "6.14.8-modules".into(), + "6.14.8-modules-shrunk".into(), + "11.1".into(), + "11.1-man".into(), + ]; + let new_versions: Vec = vec![ + "6.14.9".into(), + "6.24.3-modules".into(), + "6.12.9-modules-shrunk".into(), + "11.0".into(), + "11.3-man".into(), + ]; + + let versions = Diff { + old: old_versions, + new: new_versions, + }; + + let (diff_pre, diff_post) = diff::collect_diffs(&versions).unwrap(); + + assert_ne!(diff_pre, diff_post); + assert_eq!(diff_pre, diff_pre); + assert_eq!(diff_post, diff_post); +}