From 5143b6fc59a18c5d0ceec31dd8a531c1e0ac9885 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Tue, 4 Jul 2023 20:36:55 +0100 Subject: [PATCH] Add packfile unit tests against reference git binary --- Cargo.toml | 4 ++++ src/high_level.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/low_level.rs | 3 +-- src/snapshots/packfile__high_level__test__deterministic.snap | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/snapshots/packfile__high_level__test__git_verify_pack.snap | 16 ++++++++++++++++ 5 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 src/snapshots/packfile__high_level__test__deterministic.snap create mode 100644 src/snapshots/packfile__high_level__test__git_verify_pack.snap diff --git a/Cargo.toml b/Cargo.toml index 7cf6a2b..5e7824f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,5 +24,9 @@ time = "0.3.15" tokio-util = { version = "0.7", features = ["codec"], optional = true } tracing = "0.1" +[dev-dependencies] +insta = { version = "1.29", features = ["filters"] } +tempfile = "3.5" + [features] default = ["tokio-util"] diff --git a/src/high_level.rs b/src/high_level.rs index 08a4bd7..9e3035c 100644 --- a/src/high_level.rs +++ b/src/high_level.rs @@ -178,3 +178,79 @@ enum TreeItem { /// Refers to a nested directory Tree(Tree), } + +#[cfg(test)] +mod test { + use crate::{high_level::GitRepository, low_level::PackFile}; + use bytes::{Bytes, BytesMut}; + use std::process::{Command, Stdio}; + use tempfile::TempDir; + + #[test] + fn deterministic() { + let mut repo = GitRepository::default(); + repo.insert(&["a", "b"], "c.txt", Bytes::from("hello world!")) + .unwrap(); + repo.insert(&["c", "d"], "c.txt", Bytes::from("test")) + .unwrap(); + let (hash, packfile) = repo + .commit("me", "me@example.com", "initial commit") + .unwrap(); + + assert_eq!( + hex::encode(&hash), + "6ba08bda5731edfb2a0a00e602d1dd4bbd9d341c" + ); + insta::assert_debug_snapshot!(packfile); + } + + #[test] + fn git_verify_pack() { + let mut repo = GitRepository::default(); + repo.insert(&[], "c.txt", Bytes::from(vec![0; 256])) + .unwrap(); + repo.insert(&["e", "f"], "c.txt", Bytes::from("hiya")) + .unwrap(); + repo.insert(&["c", "d"], "c.txt", Bytes::from("hello world!")) + .unwrap(); + let (_hash, packfile) = repo + .commit("me", "me@example.com", "initial commit") + .unwrap(); + + let scratch_dir = TempDir::new().unwrap(); + let packfile_path = scratch_dir.path().join("example.pack"); + + let mut output = BytesMut::new(); + PackFile::new(&packfile).encode_to(&mut output).unwrap(); + + std::fs::write(&packfile_path, &output).unwrap(); + + let res = Command::new("git") + .arg("index-pack") + .arg(&packfile_path) + .stdout(Stdio::piped()) + .spawn() + .unwrap() + .wait() + .unwrap(); + assert!(res.success()); + + let command = Command::new("git") + .arg("verify-pack") + .arg("-v") + .stdout(Stdio::piped()) + .arg(&packfile_path) + .spawn() + .unwrap(); + + let out = command.wait_with_output().unwrap(); + assert!(out.status.success(), "git exited non-0"); + + let stdout = String::from_utf8_lossy(&out.stdout); + insta::with_settings!({filters => vec![ + (r#"/(.*)/example.pack"#, "/path/to/example.pack") + ]}, { + insta::assert_snapshot!(stdout); + }); + } +} diff --git a/src/low_level.rs b/src/low_level.rs index cdfe3d5..4d51d6c 100644 --- a/src/low_level.rs +++ b/src/low_level.rs @@ -319,7 +319,6 @@ impl PackFileEntry { } } - // wen const generics for RustCrypto? :-( #[instrument(skip(self), err)] pub fn hash(&self) -> Result { let size = self.uncompressed_size(); @@ -357,8 +356,8 @@ impl PackFileEntry { #[cfg(test)] mod test { mod packfile_entry { - use bytes::{Bytes, BytesMut}; use crate::low_level::PackFileEntry; + use bytes::{Bytes, BytesMut}; #[test] fn header_size_bytes_large() { diff --git a/src/snapshots/packfile__high_level__test__deterministic.snap b/src/snapshots/packfile__high_level__test__deterministic.snap new file mode 100644 index 0000000..048d4c5 --- /dev/null +++ b/src/snapshots/packfile__high_level__test__deterministic.snap @@ -0,0 +1,243 @@ +--- +source: src/high_level.rs +expression: packfile +--- +[ + Blob( + b"hello world!", + ), + Blob( + b"test", + ), + Tree( + [ + TreeItem { + kind: File, + name: Cow( + "c.txt", + ), + hash: [ + 188, + 119, + 116, + 167, + 177, + 141, + 235, + 29, + 123, + 208, + 33, + 45, + 52, + 36, + 106, + 155, + 18, + 96, + 174, + 23, + ], + sort_name: "c.txt", + }, + ], + ), + Tree( + [ + TreeItem { + kind: Directory, + name: Cow( + "b", + ), + hash: [ + 65, + 198, + 120, + 31, + 37, + 221, + 177, + 61, + 142, + 242, + 236, + 254, + 191, + 80, + 202, + 186, + 44, + 71, + 71, + 234, + ], + sort_name: "b/", + }, + ], + ), + Tree( + [ + TreeItem { + kind: File, + name: Cow( + "c.txt", + ), + hash: [ + 48, + 215, + 77, + 37, + 132, + 66, + 199, + 198, + 85, + 18, + 234, + 250, + 180, + 116, + 86, + 141, + 215, + 6, + 196, + 48, + ], + sort_name: "c.txt", + }, + ], + ), + Tree( + [ + TreeItem { + kind: Directory, + name: Cow( + "d", + ), + hash: [ + 72, + 157, + 22, + 218, + 2, + 209, + 127, + 99, + 17, + 32, + 172, + 39, + 148, + 57, + 221, + 204, + 132, + 195, + 168, + 129, + ], + sort_name: "d/", + }, + ], + ), + Tree( + [ + TreeItem { + kind: Directory, + name: Cow( + "a", + ), + hash: [ + 159, + 188, + 55, + 140, + 131, + 37, + 51, + 16, + 124, + 161, + 77, + 229, + 135, + 77, + 235, + 251, + 219, + 170, + 205, + 168, + ], + sort_name: "a/", + }, + TreeItem { + kind: Directory, + name: Cow( + "c", + ), + hash: [ + 40, + 81, + 135, + 177, + 189, + 171, + 157, + 76, + 228, + 114, + 5, + 171, + 120, + 67, + 95, + 184, + 109, + 93, + 6, + 109, + ], + sort_name: "c/", + }, + ], + ), + Commit( + Commit { + tree: [ + 116, + 147, + 237, + 243, + 146, + 103, + 126, + 119, + 24, + 44, + 0, + 155, + 212, + 236, + 177, + 214, + 30, + 171, + 22, + 210, + ], + author: CommitUserInfo { + name: "me", + email: "me@example.com", + time: 1970-01-01 0:00:00.0 +00:00:00, + }, + committer: CommitUserInfo { + name: "me", + email: "me@example.com", + time: 1970-01-01 0:00:00.0 +00:00:00, + }, + message: "initial commit", + }, + ), +] diff --git a/src/snapshots/packfile__high_level__test__git_verify_pack.snap b/src/snapshots/packfile__high_level__test__git_verify_pack.snap new file mode 100644 index 0000000..1b64d26 --- /dev/null +++ b/src/snapshots/packfile__high_level__test__git_verify_pack.snap @@ -0,0 +1,16 @@ +--- +source: src/high_level.rs +expression: stdout +--- +65f57c2ee985713476ac0b6e3483e6fe472e2176 blob 256 23 12 +556fdb625a861caa62cdb0ed1679b03605d4844e blob 4 14 35 +bc7774a7b18deb1d7bd0212d34246a9b1260ae17 blob 12 22 49 +6123a501156670e9ad772926ffde2d282782f60d tree 33 46 71 +b3d17d9cf721128fe605a8895ab375c17517896f tree 28 37 117 +41c6781f25ddb13d8ef2ecfebf50caba2c4747ea tree 33 46 154 +2c5a03f4e06322f845afffee2515c213df662f3d tree 28 37 200 +7c3b586d518694f71878ff437f1a271dad248f76 tree 89 102 237 +79d1ae79ac5da77976b123c848d31f15f564fe66 commit 134 107 339 +non delta: 9 objects +/path/to/example.pack: ok + -- libgit2 1.7.2