History

[commitgraph] Ditch pre-generated test repos.

Always generate test repos on demand instead. This saves some repo space and keeps us from having to worry about fixture scripts being out of sync with the generated fixtures. It also lets us use git to inspect repos instead of hardcoding expected commit data. On the flip side, tests take ~400ms instead of ~20ms.

Conor Davis committed 6 years ago

Commit 1ce84681 parent 724f39141 files · +197 −265Browse files

Showing the changes to git-commitgraph/tests/commitgraph.rs (1 of 41 files). Show all

Unified · Split

git-commitgraph/tests/commitgraph.rs+146−2
@@ -1,8 +1,71 @@
1−use git_object::owned;
2−use std::path::PathBuf;
1+use git_commitgraph::{Graph, GraphPosition};
2+use git_object::{borrowed, owned};
3+use std::collections::{HashMap, HashSet};
4+use std::convert::{TryFrom, TryInto};
5+use std::hash::BuildHasher;
6+use std::io::{BufRead, Cursor};
7+use std::path::{Path, PathBuf};
8+use std::process::Command;
39
410 mod access;
511
12+pub fn check_common(cg: &Graph, expected: &HashMap<String, RefInfo, impl BuildHasher>) {
13+ assert_eq!(
14+ usize::try_from(cg.num_commits()).expect("an architecture able to hold 32 bits of integer"),
15+ expected.len()
16+ );
17+ for ref_info in expected.values() {
18+ assert_eq!(cg.id_at(ref_info.pos()), ref_info.id(), "id_at({})", ref_info.pos());
19+ assert_eq!(
20+ cg.lookup(ref_info.id()),
21+ Some(ref_info.pos()),
22+ "lookup({})",
23+ ref_info.id()
24+ );
25+
26+ let expected_parents: Vec<_> = ref_info
27+ .parent_ids()
28+ .into_iter()
29+ .map(|id| {
30+ expected
31+ .values()
32+ .find(|item| item.id() == id)
33+ .expect("find RefInfo by id")
34+ })
35+ .collect();
36+ let commit = cg.commit_at(ref_info.pos());
37+ assert_eq!(commit.id(), ref_info.id());
38+ assert_eq!(commit.root_tree_id(), ref_info.root_tree_id());
39+ assert_eq!(
40+ commit.parent1().expect("failed to access commit's parent1"),
41+ expected_parents.iter().map(|x| x.pos()).next()
42+ );
43+ assert_eq!(
44+ commit
45+ .iter_parents()
46+ .collect::<Result<Vec<_>, _>>()
47+ .expect("failed to access commit's parents"),
48+ expected_parents.iter().map(|x| x.pos()).collect::<Vec<_>>()
49+ );
50+ }
51+
52+ assert_eq!(
53+ cg.iter_ids().collect::<HashSet<_>>(),
54+ expected.values().map(|x| x.id()).collect::<HashSet<_>>()
55+ );
56+}
57+
58+pub fn create_repo(script_path: &str) -> tempfile::TempDir {
59+ let dir = tempfile::tempdir().expect("failed to create temp dir");
60+ let status = Command::new(fixture_path(script_path))
61+ .arg(dir.path())
62+ .env_remove("GIT_DIR")
63+ .status()
64+ .expect("failed to run repo script");
65+ assert!(status.success(), "repo script failed");
66+ dir
67+}
68+
669 pub fn fixture_path(path: &str) -> PathBuf {
770 PathBuf::from("tests").join("fixtures").join(path)
871 }
@@ -10,3 +73,84 @@ pub fn fixture_path(path: &str) -> PathBuf { · 1 unmodified line
1073 pub fn hex_to_id(hex: &[u8]) -> owned::Id {
1174 owned::Id::from_40_bytes_in_hex(hex).expect("40 bytes hex")
1275 }
76+
77+pub struct RefInfo {
78+ id: owned::Id,
79+ parent_ids: Vec<owned::Id>,
80+ pos: GraphPosition,
81+ root_tree_id: owned::Id,
82+}
83+
84+impl RefInfo {
85+ pub fn id(&self) -> borrowed::Id {
86+ self.id.to_borrowed()
87+ }
88+
89+ pub fn pos(&self) -> GraphPosition {
90+ self.pos
91+ }
92+
93+ pub fn parent_ids(&self) -> impl IntoIterator<Item = borrowed::Id> {
94+ self.parent_ids.iter().map(|x| x.to_borrowed())
95+ }
96+
97+ pub fn root_tree_id(&self) -> borrowed::Id {
98+ self.root_tree_id.to_borrowed()
99+ }
100+}
101+
102+pub fn inspect_refs(repo_dir: impl AsRef<Path>, refs: &[&'static str]) -> HashMap<String, RefInfo> {
103+ let output = Command::new("git")
104+ .arg("-C")
105+ .arg(repo_dir.as_ref())
106+ .arg("show")
107+ .arg("--no-patch")
108+ .arg("--pretty=format:%S %H %T %P")
109+ .args(refs)
110+ .arg("--")
111+ .env_remove("GIT_DIR")
112+ .output()
113+ .expect("failed to execute `git show`");
114+ // Output format: <refname> <id> <tree_id> <parent_ids>
115+ let mut infos: Vec<_> = Cursor::new(output.stdout)
116+ .lines()
117+ .map(|x| x.expect("failed to read `git show` output"))
118+ .map(|x| {
119+ let parts = x.trim_end().split(' ').collect::<Vec<_>>();
120+ (
121+ parts[0].to_string(),
122+ owned::Id::from_40_bytes_in_hex(parts[1].as_bytes()).expect("40 bytes hex"),
123+ owned::Id::from_40_bytes_in_hex(parts[2].as_bytes()).expect("40 bytes hex"),
124+ parts[3..]
125+ .iter()
126+ .map(|x| owned::Id::from_40_bytes_in_hex(x.as_bytes()).expect("40 bytes hex"))
127+ .collect(),
128+ )
129+ })
130+ .collect();
131+ infos.sort_by_key(|x| x.1);
132+
133+ let get_pos = |id: borrowed::Id| -> GraphPosition {
134+ let pos = infos
135+ .binary_search_by_key(&id, |x| x.1.to_borrowed())
136+ .expect("sorted_ids to contain id");
137+ let pos: u32 = pos.try_into().expect("graph position to fit in u32");
138+ GraphPosition(pos)
139+ };
140+
141+ infos
142+ .iter()
143+ .cloned()
144+ .map(|(name, id, root_tree_id, parent_ids)| {
145+ (
146+ name,
147+ RefInfo {
148+ id,
149+ parent_ids,
150+ root_tree_id,
151+ pos: get_pos(id.to_borrowed()),
152+ },
153+ )
154+ })
155+ .collect()
156+}