From 1edf7be6a47d4afa451d494ae23a7b76cd72b58d Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 12 Jan 2025 17:47:09 +0100 Subject: [PATCH 01/16] git-checks: use `Default::` for builder methods `cargo-mutants` complains that the test suite cannot detect using `Default::default()` instead of the typed version. Rely on `cargo-semver-checks` to recognize issues here. --- git-checks/src/allow_robot.rs | 2 +- git-checks/src/bad_commit.rs | 2 +- git-checks/src/bad_commits.rs | 2 +- git-checks/src/changelog.rs | 2 +- git-checks/src/check_end_of_line.rs | 2 +- git-checks/src/check_executable_permissions.rs | 2 +- git-checks/src/check_size.rs | 2 +- git-checks/src/check_whitespace.rs | 2 +- git-checks/src/commit_subject.rs | 2 +- git-checks/src/fast_forward.rs | 2 +- git-checks/src/formatting.rs | 2 +- git-checks/src/invalid_paths.rs | 2 +- git-checks/src/invalid_utf8.rs | 2 +- git-checks/src/lfs_pointer.rs | 2 +- git-checks/src/reject_bidi.rs | 2 +- git-checks/src/reject_binaries.rs | 2 +- git-checks/src/reject_conflict_paths.rs | 2 +- git-checks/src/reject_merges.rs | 2 +- git-checks/src/reject_separate_root.rs | 2 +- git-checks/src/reject_symlinks.rs | 2 +- git-checks/src/release_branch.rs | 2 +- git-checks/src/restricted_path.rs | 2 +- git-checks/src/submodule_available.rs | 2 +- git-checks/src/submodule_rewind.rs | 2 +- git-checks/src/submodule_watch.rs | 2 +- git-checks/src/third_party.rs | 2 +- git-checks/src/valid_name.rs | 2 +- 27 files changed, 27 insertions(+), 27 deletions(-) diff --git a/git-checks/src/allow_robot.rs b/git-checks/src/allow_robot.rs index c50f46a4..4897c4ad 100644 --- a/git-checks/src/allow_robot.rs +++ b/git-checks/src/allow_robot.rs @@ -24,7 +24,7 @@ pub struct AllowRobot { impl AllowRobot { /// Create a new builder. pub fn builder() -> AllowRobotBuilder { - AllowRobotBuilder::default() + Default::default() } } diff --git a/git-checks/src/bad_commit.rs b/git-checks/src/bad_commit.rs index ff0bf634..01eb4075 100644 --- a/git-checks/src/bad_commit.rs +++ b/git-checks/src/bad_commit.rs @@ -49,7 +49,7 @@ pub struct BadCommit { impl BadCommit { /// Create a new builder. pub fn builder() -> BadCommitBuilder { - BadCommitBuilder::default() + Default::default() } fn apply(&self, result: &mut CheckResult) { diff --git a/git-checks/src/bad_commits.rs b/git-checks/src/bad_commits.rs index a4878cd3..dee774c9 100644 --- a/git-checks/src/bad_commits.rs +++ b/git-checks/src/bad_commits.rs @@ -58,7 +58,7 @@ impl BadCommitsBuilder { impl BadCommits { /// Create a new builder. pub fn builder() -> BadCommitsBuilder { - BadCommitsBuilder::default() + Default::default() } } diff --git a/git-checks/src/changelog.rs b/git-checks/src/changelog.rs index 4cdce51f..4ce86eec 100644 --- a/git-checks/src/changelog.rs +++ b/git-checks/src/changelog.rs @@ -178,7 +178,7 @@ pub struct Changelog { impl Changelog { /// Create a new builder. pub fn builder() -> ChangelogBuilder { - ChangelogBuilder::default() + Default::default() } } diff --git a/git-checks/src/check_end_of_line.rs b/git-checks/src/check_end_of_line.rs index 25887706..ef4cf3fd 100644 --- a/git-checks/src/check_end_of_line.rs +++ b/git-checks/src/check_end_of_line.rs @@ -16,7 +16,7 @@ pub struct CheckEndOfLine {} impl CheckEndOfLine { /// Create a new builder. pub fn builder() -> CheckEndOfLineBuilder { - CheckEndOfLineBuilder::default() + Default::default() } } diff --git a/git-checks/src/check_executable_permissions.rs b/git-checks/src/check_executable_permissions.rs index e2fb5064..cd388012 100644 --- a/git-checks/src/check_executable_permissions.rs +++ b/git-checks/src/check_executable_permissions.rs @@ -43,7 +43,7 @@ impl CheckExecutablePermissionsBuilder { impl CheckExecutablePermissions { /// Create a new builder. pub fn builder() -> CheckExecutablePermissionsBuilder { - CheckExecutablePermissionsBuilder::default() + Default::default() } } diff --git a/git-checks/src/check_size.rs b/git-checks/src/check_size.rs index 71fa2c22..1f3dd655 100644 --- a/git-checks/src/check_size.rs +++ b/git-checks/src/check_size.rs @@ -43,7 +43,7 @@ pub struct CheckSize { impl CheckSize { /// Create a new builder. pub fn builder() -> CheckSizeBuilder { - CheckSizeBuilder::default() + Default::default() } } diff --git a/git-checks/src/check_whitespace.rs b/git-checks/src/check_whitespace.rs index e17c8d56..3a581003 100644 --- a/git-checks/src/check_whitespace.rs +++ b/git-checks/src/check_whitespace.rs @@ -26,7 +26,7 @@ pub struct CheckWhitespace {} impl CheckWhitespace { /// Create a new builder. pub fn builder() -> CheckWhitespaceBuilder { - CheckWhitespaceBuilder::default() + Default::default() } fn diff_tree( diff --git a/git-checks/src/commit_subject.rs b/git-checks/src/commit_subject.rs index 930abec3..0935cbda 100644 --- a/git-checks/src/commit_subject.rs +++ b/git-checks/src/commit_subject.rs @@ -147,7 +147,7 @@ impl CommitSubjectBuilder { impl CommitSubject { /// Create a new builder. pub fn builder() -> CommitSubjectBuilder { - CommitSubjectBuilder::default() + Default::default() } /// Whether the summary is generated or not. diff --git a/git-checks/src/fast_forward.rs b/git-checks/src/fast_forward.rs index ee2b5b7b..c49fb6f1 100644 --- a/git-checks/src/fast_forward.rs +++ b/git-checks/src/fast_forward.rs @@ -63,7 +63,7 @@ pub struct FastForward { impl FastForward { /// Create a new builder. pub fn builder() -> FastForwardBuilder { - FastForwardBuilder::default() + Default::default() } } diff --git a/git-checks/src/formatting.rs b/git-checks/src/formatting.rs index 9ff3488f..97e99509 100644 --- a/git-checks/src/formatting.rs +++ b/git-checks/src/formatting.rs @@ -201,7 +201,7 @@ impl FormattingBuilder { impl Formatting { /// Create a new builder. pub fn builder() -> FormattingBuilder { - FormattingBuilder::default() + Default::default() } /// Check a path using the formatter. diff --git a/git-checks/src/invalid_paths.rs b/git-checks/src/invalid_paths.rs index d1514e21..84ee4269 100644 --- a/git-checks/src/invalid_paths.rs +++ b/git-checks/src/invalid_paths.rs @@ -51,7 +51,7 @@ const WINDOWS_FORBIDDEN_NAMES: &[&[u8]] = &[ impl InvalidPaths { /// Create a new builder. pub fn builder() -> InvalidPathsBuilder { - InvalidPathsBuilder::default() + Default::default() } fn disallowed_whitespace(&self, c: char) -> bool { diff --git a/git-checks/src/invalid_utf8.rs b/git-checks/src/invalid_utf8.rs index aacb6028..155d901a 100644 --- a/git-checks/src/invalid_utf8.rs +++ b/git-checks/src/invalid_utf8.rs @@ -21,7 +21,7 @@ pub struct InvalidUtf8 {} impl InvalidUtf8 { /// Create a new builder. pub fn builder() -> InvalidUtf8Builder { - InvalidUtf8Builder::default() + Default::default() } } diff --git a/git-checks/src/lfs_pointer.rs b/git-checks/src/lfs_pointer.rs index 311f8998..d4830475 100644 --- a/git-checks/src/lfs_pointer.rs +++ b/git-checks/src/lfs_pointer.rs @@ -21,7 +21,7 @@ pub struct LfsPointer {} impl LfsPointer { /// Create a new builder. pub fn builder() -> LfsPointerBuilder { - LfsPointerBuilder::default() + Default::default() } fn check_line( diff --git a/git-checks/src/reject_bidi.rs b/git-checks/src/reject_bidi.rs index f9a08b04..e23ca0b6 100644 --- a/git-checks/src/reject_bidi.rs +++ b/git-checks/src/reject_bidi.rs @@ -34,7 +34,7 @@ pub struct RejectBiDi { impl RejectBiDi { /// Create a new builder. pub fn builder() -> RejectBiDiBuilder { - RejectBiDiBuilder::default() + Default::default() } } diff --git a/git-checks/src/reject_binaries.rs b/git-checks/src/reject_binaries.rs index c8f32325..18e714ed 100644 --- a/git-checks/src/reject_binaries.rs +++ b/git-checks/src/reject_binaries.rs @@ -24,7 +24,7 @@ pub struct RejectBinaries {} impl RejectBinaries { /// Create a new builder. pub fn builder() -> RejectBinariesBuilder { - RejectBinariesBuilder::default() + Default::default() } } diff --git a/git-checks/src/reject_conflict_paths.rs b/git-checks/src/reject_conflict_paths.rs index 4fd14b32..138ad8c5 100644 --- a/git-checks/src/reject_conflict_paths.rs +++ b/git-checks/src/reject_conflict_paths.rs @@ -44,7 +44,7 @@ const ORIG_SUFFIX: &str = ".orig"; impl RejectConflictPaths { /// Create a new builder. pub fn builder() -> RejectConflictPathsBuilder { - RejectConflictPathsBuilder::default() + Default::default() } fn check_conflict_path_name( diff --git a/git-checks/src/reject_merges.rs b/git-checks/src/reject_merges.rs index baad3d64..871a3c79 100644 --- a/git-checks/src/reject_merges.rs +++ b/git-checks/src/reject_merges.rs @@ -17,7 +17,7 @@ pub struct RejectMerges {} impl RejectMerges { /// Create a new builder. pub fn builder() -> RejectMergesBuilder { - RejectMergesBuilder::default() + Default::default() } } diff --git a/git-checks/src/reject_separate_root.rs b/git-checks/src/reject_separate_root.rs index 18248678..61eb367b 100644 --- a/git-checks/src/reject_separate_root.rs +++ b/git-checks/src/reject_separate_root.rs @@ -17,7 +17,7 @@ pub struct RejectSeparateRoot {} impl RejectSeparateRoot { /// Create a new builder. pub fn builder() -> RejectSeparateRootBuilder { - RejectSeparateRootBuilder::default() + Default::default() } } diff --git a/git-checks/src/reject_symlinks.rs b/git-checks/src/reject_symlinks.rs index 7fc272b4..ab84ef7f 100644 --- a/git-checks/src/reject_symlinks.rs +++ b/git-checks/src/reject_symlinks.rs @@ -17,7 +17,7 @@ pub struct RejectSymlinks {} impl RejectSymlinks { /// Create a new builder. pub fn builder() -> RejectSymlinksBuilder { - RejectSymlinksBuilder::default() + Default::default() } } diff --git a/git-checks/src/release_branch.rs b/git-checks/src/release_branch.rs index d67da70c..f13ff04c 100644 --- a/git-checks/src/release_branch.rs +++ b/git-checks/src/release_branch.rs @@ -65,7 +65,7 @@ pub struct ReleaseBranch { impl ReleaseBranch { /// Create a new builder. pub fn builder() -> ReleaseBranchBuilder { - ReleaseBranchBuilder::default() + Default::default() } } diff --git a/git-checks/src/restricted_path.rs b/git-checks/src/restricted_path.rs index 4f26ba45..73fe0158 100644 --- a/git-checks/src/restricted_path.rs +++ b/git-checks/src/restricted_path.rs @@ -29,7 +29,7 @@ pub struct RestrictedPath { impl RestrictedPath { /// Create a new builder. pub fn builder() -> RestrictedPathBuilder { - RestrictedPathBuilder::default() + Default::default() } } diff --git a/git-checks/src/submodule_available.rs b/git-checks/src/submodule_available.rs index 18e554f5..e05ba18c 100644 --- a/git-checks/src/submodule_available.rs +++ b/git-checks/src/submodule_available.rs @@ -68,7 +68,7 @@ pub struct SubmoduleAvailable { impl SubmoduleAvailable { /// Create a new builder. pub fn builder() -> SubmoduleAvailableBuilder { - SubmoduleAvailableBuilder::default() + Default::default() } } diff --git a/git-checks/src/submodule_rewind.rs b/git-checks/src/submodule_rewind.rs index 23f39ffa..e7f31a30 100644 --- a/git-checks/src/submodule_rewind.rs +++ b/git-checks/src/submodule_rewind.rs @@ -47,7 +47,7 @@ pub struct SubmoduleRewind {} impl SubmoduleRewind { /// Create a new builder. pub fn builder() -> SubmoduleRewindBuilder { - SubmoduleRewindBuilder::default() + Default::default() } } diff --git a/git-checks/src/submodule_watch.rs b/git-checks/src/submodule_watch.rs index 04aa6147..aebd2a5a 100644 --- a/git-checks/src/submodule_watch.rs +++ b/git-checks/src/submodule_watch.rs @@ -30,7 +30,7 @@ pub struct SubmoduleWatch { impl SubmoduleWatch { /// Checks that submodules in the project are available. pub fn builder() -> SubmoduleWatchBuilder { - SubmoduleWatchBuilder::default() + Default::default() } } diff --git a/git-checks/src/third_party.rs b/git-checks/src/third_party.rs index 931a1981..38ebec80 100644 --- a/git-checks/src/third_party.rs +++ b/git-checks/src/third_party.rs @@ -126,7 +126,7 @@ pub struct ThirdParty { impl ThirdParty { /// Create a new third party import configuration. pub fn builder() -> ThirdPartyBuilder { - ThirdPartyBuilder::default() + Default::default() } } diff --git a/git-checks/src/valid_name.rs b/git-checks/src/valid_name.rs index e70d42e2..1f7d5394 100644 --- a/git-checks/src/valid_name.rs +++ b/git-checks/src/valid_name.rs @@ -217,7 +217,7 @@ impl ValidNameError { impl ValidName { /// Create a new builder. pub fn builder() -> ValidNameBuilder { - ValidNameBuilder::default() + Default::default() } /// Check that a name is valid. -- GitLab From 480e6d57e49ca48c7d0f638136e25046afe7be39 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 12 Jan 2025 17:48:10 +0100 Subject: [PATCH 02/16] git-checks-core: make `CheckResult` `impl Clone` --- git-checks-core/CHANGELOG.md | 4 ++++ git-checks-core/src/check.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/git-checks-core/CHANGELOG.md b/git-checks-core/CHANGELOG.md index e5d1eef9..f51b6d42 100644 --- a/git-checks-core/CHANGELOG.md +++ b/git-checks-core/CHANGELOG.md @@ -1,3 +1,7 @@ +# v1.3.1 (unreleased) + + * `CheckResult` now has an `impl Clone`. + # v1.3.0 * `GitCheckConfiguration::run_topic_multi_base` has been added to exclude diff --git a/git-checks-core/src/check.rs b/git-checks-core/src/check.rs index a8dd5c66..a60a9dc8 100644 --- a/git-checks-core/src/check.rs +++ b/git-checks-core/src/check.rs @@ -15,7 +15,7 @@ use crate::commit::{Commit, Content, Topic}; use crate::context::CheckGitContext; /// The results of a check. -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct CheckResult { /// The warnings from running checks. warnings: Vec, -- GitLab From bf53679b54649dde2d036654d24098ae2f818f1b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 12 Jan 2025 17:49:12 +0100 Subject: [PATCH 03/16] test: unit test `CheckResult` members --- git-checks-core/src/check.rs | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/git-checks-core/src/check.rs b/git-checks-core/src/check.rs index a60a9dc8..d0539296 100644 --- a/git-checks-core/src/check.rs +++ b/git-checks-core/src/check.rs @@ -248,3 +248,48 @@ where self.check(ctx, topic) } } + +#[cfg(test)] +mod tests { + use crate::CheckResult; + + #[test] + fn test_check_result_add_warning() { + let mut result = CheckResult::new(); + assert!(result.warnings().is_empty()); + result.add_warning("warning"); + assert!(!result.warnings().is_empty()); + } + + #[test] + fn test_check_result_add_error() { + let mut result = CheckResult::new(); + assert!(result.errors().is_empty()); + result.add_error("error"); + assert!(!result.errors().is_empty()); + } + + #[test] + fn test_check_result_add_alert() { + let mut result = CheckResult::new(); + assert!(result.alerts().is_empty()); + result.add_alert("error", true); + assert!(!result.alerts().is_empty()); + } + + #[test] + fn test_check_result_make_temporary() { + let mut result = CheckResult::new(); + assert!(!result.temporary()); + result.make_temporary(); + assert!(result.temporary()); + } + + #[test] + fn test_check_result_whitelist() { + let mut result = CheckResult::new(); + assert!(!result.allowed()); + result.whitelist(); + assert!(result.allowed()); + } +} -- GitLab From 419beecaa565b6f0dd7e2b7f9461d3213401948c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 12 Jan 2025 17:49:48 +0100 Subject: [PATCH 04/16] test: unit test `PartialEq` for `FileName` --- git-checks-core/src/commit.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/git-checks-core/src/commit.rs b/git-checks-core/src/commit.rs index d896b6e5..95955785 100644 --- a/git-checks-core/src/commit.rs +++ b/git-checks-core/src/commit.rs @@ -1005,6 +1005,17 @@ mod tests { } } + #[test] + fn test_filename_partial_eq() { + let fn_a1 = FileName::new("a").unwrap(); + let fn_a2 = FileName::new("a").unwrap(); + let fn_b = FileName::new("b").unwrap(); + + assert_eq!(fn_a1, fn_a2); + assert_ne!(fn_a1, fn_b); + assert_ne!(fn_a2, fn_b); + } + const BAD_COMMIT: &str = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; #[test] -- GitLab From 04ce065f4b3e6a49d1051f254096eff9aa76ae44 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 12 Jan 2025 17:50:22 +0100 Subject: [PATCH 05/16] test: test `combine` with `make_temporary` logic --- git-checks-core/src/check.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/git-checks-core/src/check.rs b/git-checks-core/src/check.rs index d0539296..57c2b068 100644 --- a/git-checks-core/src/check.rs +++ b/git-checks-core/src/check.rs @@ -292,4 +292,25 @@ mod tests { result.whitelist(); assert!(result.allowed()); } + + #[test] + fn test_check_result_combine_temporary() { + let temp_result = { + let mut result = CheckResult::new(); + result.make_temporary(); + result + }; + let non_temp_result = CheckResult::new(); + + let items = &[ + (&temp_result, &non_temp_result, true), + (&temp_result, &temp_result, true), + (&non_temp_result, &non_temp_result, false), + (&non_temp_result, &temp_result, true), + ]; + + for (l, r, e) in items { + assert_eq!((**l).clone().combine((**r).clone()).temporary(), *e); + } + } } -- GitLab From f7f510be65754d426ab1ef20382a9149732b1130 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 12 Jan 2025 23:29:28 +0100 Subject: [PATCH 06/16] bad_commits: test the `Check` name --- git-checks/src/bad_commits.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/git-checks/src/bad_commits.rs b/git-checks/src/bad_commits.rs index dee774c9..70b39e42 100644 --- a/git-checks/src/bad_commits.rs +++ b/git-checks/src/bad_commits.rs @@ -208,7 +208,7 @@ pub(crate) mod config { #[cfg(test)] mod tests { - use git_checks_core::TopicCheck; + use git_checks_core::{Check, TopicCheck}; use git_workarea::CommitId; use crate::test::*; @@ -232,6 +232,15 @@ mod tests { .is_ok()); } + #[test] + fn test_bad_commits_name_commit() { + let check = BadCommits::builder() + .bad_commits([BAD_COMMIT].iter().copied().map(CommitId::new)) + .build() + .unwrap(); + assert_eq!(Check::name(&check), "bad-commits"); + } + #[test] fn test_bad_commits_name_topic() { let check = BadCommits::builder() -- GitLab From fc936d11e3cd4edd9621dff52c92a2bf9d2d658d Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 12 Jan 2025 23:29:48 +0100 Subject: [PATCH 07/16] binary_format: use reslicing instead of addition --- git-checks/src/binary_format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-checks/src/binary_format.rs b/git-checks/src/binary_format.rs index 0498a02a..71448ebc 100644 --- a/git-checks/src/binary_format.rs +++ b/git-checks/src/binary_format.rs @@ -53,7 +53,7 @@ fn detect_pe(file: &[u8]) -> bool { // Find the offset in the file. let mut offset = [0; PE_OFFSET_SIZE]; - offset.copy_from_slice(&file[PE_OFFSET..PE_OFFSET + PE_OFFSET_SIZE]); + offset.copy_from_slice(&file[PE_OFFSET..][..PE_OFFSET_SIZE]); // Read the offset. It is in native-endian order and we don't know the endianness of the // binary, so try it as big- and little-endian. -- GitLab From 5e03bb4fda98e956499cc268a6e1c6f848ee478e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 12 Jan 2025 23:30:01 +0100 Subject: [PATCH 08/16] binary_format: unit test format detection routines --- git-checks/src/binary_format.rs | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/git-checks/src/binary_format.rs b/git-checks/src/binary_format.rs index 71448ebc..1566bbe5 100644 --- a/git-checks/src/binary_format.rs +++ b/git-checks/src/binary_format.rs @@ -20,6 +20,7 @@ type PeOffset = u32; const PE_OFFSET_SIZE: usize = mem::size_of::(); const PE_MAGIC: &[u8] = &[0x50, 0x45, 0x00, 0x00]; // PE 0x00 0x00 +#[derive(Debug, Clone, Copy, PartialEq)] pub(crate) enum BinaryFormat { Ar, Elf, @@ -92,3 +93,59 @@ fn detect_binary_format_impl(content: &[u8]) -> Option { None } } + +#[cfg(test)] +mod tests { + use crate::binary_format::{detect_binary_format, BinaryFormat}; + + #[test] + fn test_detect_binary_format_elf() { + assert_eq!(detect_binary_format(b"\x7fELF"), Some(BinaryFormat::Elf)); + } + + #[test] + fn test_detect_binary_format_ar() { + assert_eq!(detect_binary_format(b"!\n"), Some(BinaryFormat::Ar)); + } + + #[test] + fn test_detect_binary_format_macho() { + assert_eq!( + detect_binary_format(b"\xcf\xfa\xed\xfe"), + Some(BinaryFormat::MachO), + ); + assert_eq!( + detect_binary_format(b"\xfe\xed\xfa\xcf"), + Some(BinaryFormat::MachO), + ); + assert_eq!( + detect_binary_format(b"\xca\xfe\xba\xbe"), + Some(BinaryFormat::MachO), + ); + assert_eq!( + detect_binary_format(b"\xbe\xba\xfe\xca"), + Some(BinaryFormat::MachO), + ); + } + + #[test] + fn test_detect_pe() { + use super::{detect_pe, PE_OFFSET, PE_OFFSET_SIZE}; + + assert!(!detect_pe(&[])); + assert!(!detect_pe(&[0; PE_OFFSET])); + assert!(!detect_pe(&[0; PE_OFFSET + PE_OFFSET_SIZE - 1])); + assert!(!detect_pe(&[0; PE_OFFSET + PE_OFFSET_SIZE])); + } + + #[test] + fn test_detect_binary_format_pe() { + let pe_craft_be = + b"buffer_PE\x00\x000123456789012345678901234567890123456789012345678\x00\x00\x00\x07"; + let pe_craft_le = + b"buffer_PE\x00\x000123456789012345678901234567890123456789012345678\x07\x00\x00\x00"; + + assert_eq!(detect_binary_format(pe_craft_be), Some(BinaryFormat::Pe)); + assert_eq!(detect_binary_format(pe_craft_le), Some(BinaryFormat::Pe)); + } +} -- GitLab From d13137fdab34f3d0a4abc5d1e015d4b47db935e6 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 13 Jan 2025 00:22:27 +0100 Subject: [PATCH 09/16] test: test `combine` with `whitelist` logic --- git-checks-core/src/check.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/git-checks-core/src/check.rs b/git-checks-core/src/check.rs index 57c2b068..51fb7973 100644 --- a/git-checks-core/src/check.rs +++ b/git-checks-core/src/check.rs @@ -313,4 +313,25 @@ mod tests { assert_eq!((**l).clone().combine((**r).clone()).temporary(), *e); } } + + #[test] + fn test_check_result_combine_whitelist() { + let temp_result = { + let mut result = CheckResult::new(); + result.whitelist(); + result + }; + let non_temp_result = CheckResult::new(); + + let items = &[ + (&temp_result, &non_temp_result, true), + (&temp_result, &temp_result, true), + (&non_temp_result, &non_temp_result, false), + (&non_temp_result, &temp_result, true), + ]; + + for (l, r, e) in items { + assert_eq!((**l).clone().combine((**r).clone()).allowed(), *e); + } + } } -- GitLab From 65c0321e3ebaac5382a66a129256558ae86e138a Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 13 Jan 2025 00:22:41 +0100 Subject: [PATCH 10/16] check: test `impl *Check` for `ContentCheck` Make sure it calls through to the base check logic. --- git-checks-core/src/check.rs | 111 +++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/git-checks-core/src/check.rs b/git-checks-core/src/check.rs index 51fb7973..ab6622f3 100644 --- a/git-checks-core/src/check.rs +++ b/git-checks-core/src/check.rs @@ -334,4 +334,115 @@ mod tests { assert_eq!((**l).clone().combine((**r).clone()).allowed(), *e); } } + + mod mock { + use std::sync::Mutex; + + use crate::impl_prelude::*; + + #[derive(Debug)] + pub struct MockCheck { + checked: Mutex, + } + + impl Default for MockCheck { + fn default() -> Self { + Self { + checked: Mutex::new(false), + } + } + } + + impl Drop for MockCheck { + fn drop(&mut self) { + let flag = self.checked.lock().expect("poisoned mock check lock"); + assert!(*flag); + } + } + + impl MockCheck { + fn trip(&self) { + let mut flag = self.checked.lock().expect("poisoned mock check lock"); + *flag = true; + } + } + + impl ContentCheck for MockCheck { + fn name(&self) -> &str { + self.trip(); + "mock-check" + } + + fn check( + &self, + _: &CheckGitContext, + _: &dyn Content, + ) -> Result> { + self.trip(); + Ok(CheckResult::new()) + } + } + } + + const TARGET_COMMIT: &str = "27ff3ef5532d76afa046f76f4dd8f588dc3e83c3"; + const SIMPLE_COMMIT: &str = "43adb8173eb6d7a39f98e1ec3351cf27414c9aa1"; + + fn test_run_check(conf: &crate::GitCheckConfiguration, name: &str) { + use std::path::Path; + + use git_workarea::{CommitId, GitContext, Identity}; + + let gitdir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../.git")); + if !gitdir.exists() { + panic!("The tests must be run from a git checkout."); + } + + let ctx = GitContext::new(gitdir); + let identity = Identity::new( + "Rust Git Checks Core Tests", + "rust-git-checks-core@example.com", + ); + conf.run_topic( + &ctx, + name, + &CommitId::new(TARGET_COMMIT), + &CommitId::new(SIMPLE_COMMIT), + &identity, + ) + .unwrap(); + } + + #[test] + fn test_impl_check_for_content_name() { + use crate::{Check, ContentCheck}; + + let check = mock::MockCheck::default(); + + assert_eq!(Check::name(&check), ContentCheck::name(&check)); + } + + #[test] + fn test_impl_check_for_content_check() { + let check = mock::MockCheck::default(); + let mut conf = crate::GitCheckConfiguration::new(); + conf.add_check(&check); + test_run_check(&conf, "test_impl_check_for_content_check"); + } + + #[test] + fn test_impl_topiccheck_for_content_name() { + use crate::{ContentCheck, TopicCheck}; + + let check = mock::MockCheck::default(); + + assert_eq!(TopicCheck::name(&check), ContentCheck::name(&check)); + } + + #[test] + fn test_impl_topiccheck_for_content_check() { + let check = mock::MockCheck::default(); + let mut conf = crate::GitCheckConfiguration::new(); + conf.add_topic_check(&check); + test_run_check(&conf, "test_impl_topiccheck_for_content_check"); + } } -- GitLab From 8c4c45adb34af22153eab41806785b4ba28aed78 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 13 Jan 2025 00:23:10 +0100 Subject: [PATCH 11/16] commit: ensure `impl Content` calls through to the base object --- git-checks-core/src/commit.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/git-checks-core/src/commit.rs b/git-checks-core/src/commit.rs index 95955785..a36954e6 100644 --- a/git-checks-core/src/commit.rs +++ b/git-checks-core/src/commit.rs @@ -2504,4 +2504,35 @@ mod tests { assert_eq!(topic.diffs.len(), 0); } + + #[test] + fn test_impl_content_for_commit_path_diff() { + let ctx = make_context(); + + let commit = Commit::new(&ctx, &CommitId::new(CHANGES_COMMIT)).unwrap(); + let file = FileName::Normal("src/context.rs".into()); + + assert_eq!( + Content::path_diff(&commit, &file).unwrap(), + commit.path_diff(&file).unwrap(), + ); + } + + #[test] + fn test_impl_content_for_topic_path_diff() { + let ctx = make_context(); + + let topic = Topic::new( + &ctx, + &CommitId::new(ROOT_COMMIT), + &CommitId::new(CHANGES_COMMIT), + ) + .unwrap(); + let file = FileName::Normal("src/context.rs".into()); + + assert_eq!( + Content::path_diff(&topic, &file).unwrap(), + topic.path_diff(&file).unwrap(), + ); + } } -- GitLab From 8d9fbfbfe06cdb4766e621873e0e5ba88cc09dce Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 13 Jan 2025 00:23:33 +0100 Subject: [PATCH 12/16] valid_name: add a note to use new `Duration` APIs when available --- git-checks/src/valid_name.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/git-checks/src/valid_name.rs b/git-checks/src/valid_name.rs index 1f7d5394..0e9aa2eb 100644 --- a/git-checks/src/valid_name.rs +++ b/git-checks/src/valid_name.rs @@ -56,8 +56,10 @@ impl ValidNameFullNamePolicy { const LOCK_POISONED: &str = "DNS cache lock poisoned"; const DEFAULT_TTL_CACHE_SIZE: usize = 100; // 24 hours +// XXX(rust-???): use `Duration::from_days(1); https://github.com/rust-lang/rust/issues/120301 const DEFAULT_TTL_CACHE_HIT_DURATION: Duration = Duration::from_secs(24 * 60 * 60); // 5 minutes +// XXX(rust-???): use `Duration::from_mins(5); https://github.com/rust-lang/rust/issues/120301 const DEFAULT_TTL_CACHE_MISS_DURATION: Duration = Duration::from_secs(5 * 60); lazy_static! { -- GitLab From 155ee71601a8b9eb26f7d026f824873a52e6833a Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 13 Jan 2025 00:23:58 +0100 Subject: [PATCH 13/16] valid_name: update test names for `trust_domains` rename Also add a test for the deprecated field. --- git-checks/src/valid_name.rs | 37 +++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/git-checks/src/valid_name.rs b/git-checks/src/valid_name.rs index 0e9aa2eb..7e844f77 100644 --- a/git-checks/src/valid_name.rs +++ b/git-checks/src/valid_name.rs @@ -658,9 +658,10 @@ mod tests { } #[test] + #[allow(deprecated)] fn test_valid_name_whitelist() { let check = ValidName::builder() - .trust_domains(["baddomain.invalid"].iter().cloned()) + .whitelisted_domains(["baddomain.invalid"].iter().cloned()) .build() .unwrap(); let result = run_check("test_valid_name_whitelist", BAD_TOPIC, check); @@ -683,6 +684,32 @@ mod tests { ]); } + #[test] + fn test_valid_name_trust_domains() { + let check = ValidName::builder() + .trust_domains(["baddomain.invalid"].iter().cloned()) + .build() + .unwrap(); + let result = run_check("test_valid_name_trust_domains", BAD_TOPIC, check); + test_result_errors(result, &[ + "The author name (`Mononym`) for commit edac4e5b3a00eac60280a78ee84b5ef8d4cce97a has \ + no space in it. A full name is required for contribution. Please set the `user.name` \ + Git configuration value.", + "The author email (`bademail`) for commit 9de4928f5ec425eef414ee7620d0692fda56ebb0 \ + has an unknown domain. Please set the `user.email` Git configuration value.", + "The committer name (`Mononym`) for commit 1debf1735a6e28880ef08f13baeea4b71a08a846 \ + has no space in it. A full name is required for contribution. Please set the \ + `user.name` Git configuration value.", + "The committer email (`bademail`) for commit da71ae048e5a387d6809558d59ad073d0e4fb089 \ + has an unknown domain. Please set the `user.email` Git configuration value.", + "The given name (`Mononym`) for commit 91d9fceb226bfc0faeb8a4e54b4f0b5a1ffd39e8 has \ + no space in it. A full name is required for contribution. Please set the `user.name` \ + Git configuration value.", + "The given email (`bademail`) for commit 91d9fceb226bfc0faeb8a4e54b4f0b5a1ffd39e8 has \ + an unknown domain. Please set the `user.email` Git configuration value.", + ]); + } + #[test] fn test_valid_name_preferred() { let check = ValidName::builder() @@ -762,13 +789,13 @@ mod tests { } #[test] - fn test_valid_name_branch_whitelist() { + fn test_valid_name_branch_trust_domains() { let check = ValidName::builder() .trust_domains(["baddomain.invalid"].iter().cloned()) .build() .unwrap(); run_branch_check_ok( - "test_valid_name_branch_whitelist/ok", + "test_valid_name_branch_trust_domains/ok", BAD_TOPIC, check.clone(), ); @@ -783,7 +810,7 @@ mod tests { for contribution. Please set the `user.name` Git configuration value.", ]); let result = run_branch_check_ident( - "test_valid_name_branch_whitelist/bademail", + "test_valid_name_branch_trust_domains/bademail", BAD_TOPIC, check.clone(), bademail_ident(), @@ -796,7 +823,7 @@ mod tests { ], ); run_branch_check_ident_ok( - "test_valid_name_branch_whitelist/bademail_mx", + "test_valid_name_branch_trust_domains/bademail_mx", BAD_TOPIC, check, bademail_mx_ident(), -- GitLab From 0d2c5de4d55828d39193f7a6985e0cf144aa9bc8 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 13 Jan 2025 00:24:22 +0100 Subject: [PATCH 14/16] valid_name: test `HostLookup::cache_duration` --- git-checks/src/valid_name.rs | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/git-checks/src/valid_name.rs b/git-checks/src/valid_name.rs index 7e844f77..b52bd3ea 100644 --- a/git-checks/src/valid_name.rs +++ b/git-checks/src/valid_name.rs @@ -601,6 +601,8 @@ pub(crate) mod config { #[cfg(test)] mod tests { + use std::time::{Duration, Instant}; + use git_checks_core::{BranchCheck, Check}; use git_workarea::Identity; @@ -947,4 +949,52 @@ mod tests { assert_eq!(cloned.dns_cache.lock().unwrap().iter().count(), 0); assert_eq!(cloned.trust_domains, check.trust_domains); } + + #[test] + fn test_host_lookup_cache_duration() { + use super::HostLookup; + + let items = [ + (HostLookup::Hit, super::DEFAULT_TTL_CACHE_HIT_DURATION), + ( + HostLookup::Miss { + valid_until: None, + }, + super::DEFAULT_TTL_CACHE_MISS_DURATION, + ), + ]; + + for (l, d) in items { + assert_eq!(l.cache_duration(), d); + } + + let short_timeout = Duration::from_secs(60); + let soon = Instant::now() + short_timeout; + let long_timeout = Duration::from_secs(10000); + let later = Instant::now() + long_timeout; + + let range_items = [ + ( + HostLookup::Miss { + valid_until: Some(soon), + }, + short_timeout, + ), + ( + HostLookup::Miss { + valid_until: Some(later), + }, + long_timeout, + ), + ]; + + for (l, d) in range_items { + let duration = l.cache_duration(); + // Make sure the duration is less than the given timeout. + assert!(duration <= d); + // But also "close" to the given timeout. If a platform takes longer than 1 second to + // get here, there are other performance issues to consider first. + assert!(d - duration <= Duration::from_secs(1)); + } + } } -- GitLab From fd75a77fa9e0e595aaa02d2136b894b2bb47dde6 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 13 Jan 2025 00:24:44 +0100 Subject: [PATCH 15/16] submodule_rewind: simplify skip check The diff status cannot be `Deleted` if the `new_mode` is not `160000`. Combine the checks. --- git-checks/src/submodule_rewind.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/git-checks/src/submodule_rewind.rs b/git-checks/src/submodule_rewind.rs index e7f31a30..0e877ffa 100644 --- a/git-checks/src/submodule_rewind.rs +++ b/git-checks/src/submodule_rewind.rs @@ -60,13 +60,9 @@ impl Check for SubmoduleRewind { let mut result = CheckResult::new(); for diff in &commit.diffs { - // Ignore diffs which are not submodules on the new side. - if diff.new_mode != "160000" { - continue; - } - - // Ignore submodules which have not been modified. - if diff.status == StatusChange::Deleted || diff.status == StatusChange::Added { + // Ignore diffs which are not submodules on the new side and submodules without a + // history. + if diff.new_mode != "160000" || diff.status == StatusChange::Added { continue; } -- GitLab From f32ec05a35ea8147f67f9d86615ca0c20b96e59b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 13 Jan 2025 00:50:22 +0100 Subject: [PATCH 16/16] git-checks: use `Default::` for check builder methods --- git-checks/src/check_end_of_line.rs | 2 +- git-checks/src/check_whitespace.rs | 2 +- git-checks/src/invalid_utf8.rs | 2 +- git-checks/src/lfs_pointer.rs | 2 +- git-checks/src/reject_binaries.rs | 2 +- git-checks/src/reject_merges.rs | 2 +- git-checks/src/reject_separate_root.rs | 2 +- git-checks/src/reject_symlinks.rs | 2 +- git-checks/src/submodule_rewind.rs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/git-checks/src/check_end_of_line.rs b/git-checks/src/check_end_of_line.rs index ef4cf3fd..e6f206ac 100644 --- a/git-checks/src/check_end_of_line.rs +++ b/git-checks/src/check_end_of_line.rs @@ -97,7 +97,7 @@ pub(crate) mod config { type Check = CheckEndOfLine; fn into_check(self) -> Self::Check { - CheckEndOfLine::default() + Default::default() } } diff --git a/git-checks/src/check_whitespace.rs b/git-checks/src/check_whitespace.rs index 3a581003..bbd7d371 100644 --- a/git-checks/src/check_whitespace.rs +++ b/git-checks/src/check_whitespace.rs @@ -121,7 +121,7 @@ pub(crate) mod config { type Check = CheckWhitespace; fn into_check(self) -> Self::Check { - CheckWhitespace::default() + Default::default() } } diff --git a/git-checks/src/invalid_utf8.rs b/git-checks/src/invalid_utf8.rs index 155d901a..e39acbcf 100644 --- a/git-checks/src/invalid_utf8.rs +++ b/git-checks/src/invalid_utf8.rs @@ -105,7 +105,7 @@ pub(crate) mod config { type Check = InvalidUtf8; fn into_check(self) -> Self::Check { - InvalidUtf8::default() + Default::default() } } diff --git a/git-checks/src/lfs_pointer.rs b/git-checks/src/lfs_pointer.rs index d4830475..37cb19fb 100644 --- a/git-checks/src/lfs_pointer.rs +++ b/git-checks/src/lfs_pointer.rs @@ -348,7 +348,7 @@ pub(crate) mod config { type Check = LfsPointer; fn into_check(self) -> Self::Check { - LfsPointer::default() + Default::default() } } diff --git a/git-checks/src/reject_binaries.rs b/git-checks/src/reject_binaries.rs index 18e714ed..7e248627 100644 --- a/git-checks/src/reject_binaries.rs +++ b/git-checks/src/reject_binaries.rs @@ -118,7 +118,7 @@ pub(crate) mod config { type Check = RejectBinaries; fn into_check(self) -> Self::Check { - RejectBinaries::default() + Default::default() } } diff --git a/git-checks/src/reject_merges.rs b/git-checks/src/reject_merges.rs index 871a3c79..eda2b19c 100644 --- a/git-checks/src/reject_merges.rs +++ b/git-checks/src/reject_merges.rs @@ -62,7 +62,7 @@ pub(crate) mod config { type Check = RejectMerges; fn into_check(self) -> Self::Check { - RejectMerges::default() + Default::default() } } diff --git a/git-checks/src/reject_separate_root.rs b/git-checks/src/reject_separate_root.rs index 61eb367b..bd226bcf 100644 --- a/git-checks/src/reject_separate_root.rs +++ b/git-checks/src/reject_separate_root.rs @@ -61,7 +61,7 @@ pub(crate) mod config { type Check = RejectSeparateRoot; fn into_check(self) -> Self::Check { - RejectSeparateRoot::default() + Default::default() } } diff --git a/git-checks/src/reject_symlinks.rs b/git-checks/src/reject_symlinks.rs index ab84ef7f..c3a9dac3 100644 --- a/git-checks/src/reject_symlinks.rs +++ b/git-checks/src/reject_symlinks.rs @@ -74,7 +74,7 @@ pub(crate) mod config { type Check = RejectSymlinks; fn into_check(self) -> Self::Check { - RejectSymlinks::default() + Default::default() } } diff --git a/git-checks/src/submodule_rewind.rs b/git-checks/src/submodule_rewind.rs index 0e877ffa..23fd8e77 100644 --- a/git-checks/src/submodule_rewind.rs +++ b/git-checks/src/submodule_rewind.rs @@ -155,7 +155,7 @@ pub(crate) mod config { type Check = SubmoduleRewind; fn into_check(self) -> Self::Check { - SubmoduleRewind::default() + Default::default() } } -- GitLab