artifact_app/user/
project.rs1use dev_prefix::*;
4use types::*;
5
6impl Project {
9 pub fn equal(&self, other: &Project) -> Result<()> {
11 names_equal(&self.artifacts, &other.artifacts)?;
12 attr_equal(
13 "path",
14 &self.artifacts,
15 &other.artifacts,
16 &|a: &Artifact| &a.def,
17 )?;
18 attr_equal(
19 "text",
20 &self.artifacts,
21 &other.artifacts,
22 &|a: &Artifact| &a.text,
23 )?;
24 attr_equal(
25 "partof",
26 &self.artifacts,
27 &other.artifacts,
28 &|a: &Artifact| &a.partof,
29 )?;
30 attr_equal(
31 "parts",
32 &self.artifacts,
33 &other.artifacts,
34 &|a: &Artifact| &a.parts,
35 )?;
36 attr_equal(
37 "done",
38 &self.artifacts,
39 &other.artifacts,
40 &|a: &Artifact| &a.done,
41 )?;
42 float_equal(
43 "completed",
44 &self.artifacts,
45 &other.artifacts,
46 &|a: &Artifact| a.completed,
47 )?;
48 float_equal(
49 "tested",
50 &self.artifacts,
51 &other.artifacts,
52 &|a: &Artifact| a.tested,
53 )?;
54 proj_attr_equal("origin", &self.origin, &other.origin)?;
55 proj_attr_equal("settings", &self.settings, &other.settings)?;
56 proj_attr_equal("files", &self.files, &other.files)?;
57 proj_attr_equal("dne_locs", &self.dne_locs, &other.dne_locs)?;
58 proj_attr_equal("repo_map", &self.repo_map, &other.repo_map)?;
59 Ok(())
60 }
61}
62
63fn names_equal(a: &Artifacts, b: &Artifacts) -> Result<()> {
67 let a_keys: HashSet<NameRc> = a.keys().cloned().collect();
68 let b_keys: HashSet<NameRc> = b.keys().cloned().collect();
69 if b_keys != a_keys {
70 let missing = a_keys.symmetric_difference(&b_keys).collect::<Vec<_>>();
71 let msg = format!(
72 "missing artifacts: {:?}\nFIRST:\n{:?}\nSECOND:\n{:?}",
73 missing,
74 a_keys,
75 b_keys
76 );
77 Err(ErrorKind::NotEqual(msg).into())
78 } else {
79 Ok(())
80 }
81}
82
83fn attr_equal<T, F>(attr: &str, a: &Artifacts, b: &Artifacts, get_attr: &F) -> Result<()>
89where
90 T: Debug + PartialEq,
91 F: Fn(&Artifact) -> &T,
92{
93 let mut diff: Vec<String> = Vec::new();
94
95 for (a_name, a_art) in a.iter() {
96 let b_art = b.get(a_name).unwrap();
97 let a_attr = get_attr(a_art);
98 let b_attr = get_attr(b_art);
99 if a_attr != b_attr {
100 let mut a_str = format!("{:?}", a_attr);
101 let mut b_str = format!("{:?}", b_attr);
102 let a_big = if a_str.len() > 100 { "..." } else { "" };
103 let b_big = if b_str.len() > 100 { "..." } else { "" };
104 a_str.truncate(100);
105 b_str.truncate(100);
106 diff.push(format!(
107 "[{}: {}{} != {}{}]",
108 a_name,
109 a_str,
110 a_big,
111 b_str,
112 b_big
113 ));
114 }
115 }
116
117 if diff.is_empty() {
118 Ok(())
119 } else {
120 Err(
121 ErrorKind::NotEqual(format!("{} different: {:?}", attr, diff)).into(),
122 )
123 }
124}
125
126fn float_equal<F>(attr: &str, a: &Artifacts, b: &Artifacts, get_num: &F) -> Result<()>
128where
129 F: Fn(&Artifact) -> f32,
130{
131 let mut diff: Vec<String> = Vec::new();
132 fn thous(f: f32) -> i64 {
133 (f * 1000.) as i64
134 }
135
136 for (a_name, a_art) in a.iter() {
137 let b_art = b.get(a_name).unwrap();
138 let a_attr = get_num(a_art);
139 let b_attr = get_num(b_art);
140 if thous(a_attr) != thous(b_attr) {
141 let mut a_str = format!("{:?}", a_attr);
142 let mut b_str = format!("{:?}", b_attr);
143 a_str.truncate(50);
144 b_str.truncate(50);
145 diff.push(format!("({}, {} != {})", a_name, a_str, b_str));
146 }
147 }
148
149 if diff.is_empty() {
150 Ok(())
151 } else {
152 Err(
153 ErrorKind::NotEqual(format!("{} different: {:?}", attr, diff)).into(),
154 )
155 }
156}
157
158fn proj_attr_equal<T>(attr: &str, a: &T, b: &T) -> Result<()>
159where
160 T: Debug + PartialEq,
161{
162 if a != b {
163 Err(
164 ErrorKind::NotEqual(format!("{} FIRST:\n{:?}\n\nSECOND:\n{:?}", attr, a, b)).into(),
165 )
166 } else {
167 Ok(())
168 }
169}