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 @@
1use git_object::owned;1use git_commitgraph::{Graph, GraphPosition};
2use std::path::PathBuf;2use git_object::{borrowed, owned};
3use std::collections::{HashMap, HashSet};
4use std::convert::{TryFrom, TryInto};
5use std::hash::BuildHasher;
6use std::io::{BufRead, Cursor};
7use std::path::{Path, PathBuf};
8use std::process::Command;
3 9
4mod access;10mod access;
5 11
12pub 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
58pub 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
6pub fn fixture_path(path: &str) -> PathBuf {69pub fn fixture_path(path: &str) -> PathBuf {
7 PathBuf::from("tests").join("fixtures").join(path)70 PathBuf::from("tests").join("fixtures").join(path)
8}71}
@@ -10,3 +73,84 @@ pub fn fixture_path(path: &str) -> PathBuf { · 1 unmodified line
10pub fn hex_to_id(hex: &[u8]) -> owned::Id {73pub fn hex_to_id(hex: &[u8]) -> owned::Id {
11 owned::Id::from_40_bytes_in_hex(hex).expect("40 bytes hex")74 owned::Id::from_40_bytes_in_hex(hex).expect("40 bytes hex")
12}75}
76
77pub struct RefInfo {
78 id: owned::Id,
79 parent_ids: Vec<owned::Id>,
80 pos: GraphPosition,
81 root_tree_id: owned::Id,
82}
83
84impl 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
102pub 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}