History

refactor tests (#331)

Be closer to the (maybe future) layout of the crate itself, and similar to how it's done throughout gitoxide.

Sebastian Thiel committed 4 years ago

Commit f943d2a1 parent 322f82513 files · +397 −415Browse files

Unified · Split

13 files
  1. git-config/tests/config.rs +6 −0
  2. git-config/tests/git_config/mod.rs +0 −0
  3. git-config/tests/integration_tests/main.rs +0 −12
  4. git-config/tests/integration_tests/values_integration_tests.rs +0 −403
  5. git-config/tests/parser/mod.rs +0 −0
  6. git-config/tests/value/mod.rs +0 −0
  7. git-config/tests/values/boolean.rs +48 −0
  8. git-config/tests/values/color_attribute.rs +44 −0
  9. git-config/tests/values/color_value.rs +51 −0
  10. git-config/tests/values/integer.rs +84 −0
  11. git-config/tests/values/mod.rs +16 −0
  12. git-config/tests/values/normalize.rs +51 −0
  13. git-config/tests/values/path.rs +97 −0
git-config/tests/config.rs+6−0
@@ -0,0 +1,6 @@
1type Result = std::result::Result<(), Box<dyn std::error::Error>>;
2
3mod git_config;
4mod parser;
5mod value;
6mod values;
git-config/tests/git_config/mod.rsrenamed from git-config/tests/integration_tests/git_config_integration_tests.rs+0−0

File renamed without changes.

git-config/tests/integration_tests/main.rs+0−12
@@ -1,12 +0,0 @@
1// See https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html
2// for an explanation of why the integration tests are laid out like this.
3//
4// TL;DR single mod makes integration tests faster to compile, test, and with
5// less build artifacts.
6
7type Result = std::result::Result<(), Box<dyn std::error::Error>>;
8
9mod git_config_integration_tests;
10mod parser_integration_tests;
11mod value_integration_tests;
12mod values_integration_tests;
git-config/tests/integration_tests/values_integration_tests.rs+0−403
@@ -1,403 +0,0 @@
1/// Converts string to byte slice
2#[cfg(test)]
3fn b(s: &str) -> &[u8] {
4 s.as_bytes()
5}
6
7#[cfg(test)]
8mod normalize {
9 use git_config::values::normalize_str;
10 use std::borrow::Cow;
11
12 #[test]
13 fn not_modified_is_borrowed() {
14 assert_eq!(normalize_str("hello world"), Cow::Borrowed(b"hello world"));
15 }
16
17 #[test]
18 fn modified_is_owned() {
19 assert_eq!(
20 normalize_str("hello \"world\""),
21 Cow::<[u8]>::Owned(b"hello world".to_vec())
22 );
23 }
24
25 #[test]
26 fn all_quoted_is_optimized() {
27 assert_eq!(normalize_str("\"hello world\""), Cow::Borrowed(b"hello world"));
28 }
29
30 #[test]
31 fn all_quote_optimization_is_correct() {
32 assert_eq!(normalize_str(r#""hello" world\""#), Cow::Borrowed(b"hello world\""));
33 }
34
35 #[test]
36 fn quotes_right_next_to_each_other() {
37 assert_eq!(
38 normalize_str("\"hello\"\" world\""),
39 Cow::<[u8]>::Owned(b"hello world".to_vec())
40 );
41 }
42
43 #[test]
44 fn escaped_quotes_are_kept() {
45 assert_eq!(
46 normalize_str(r#""hello \"\" world""#),
47 Cow::<[u8]>::Owned(b"hello \"\" world".to_vec())
48 );
49 }
50
51 #[test]
52 fn empty_string() {
53 assert_eq!(normalize_str(""), Cow::Borrowed(b""));
54 }
55
56 #[test]
57 fn empty_normalized_string_is_optimized() {
58 assert_eq!(normalize_str("\"\""), Cow::Borrowed(b""));
59 }
60}
61
62#[cfg(test)]
63mod boolean {
64 use crate::values_integration_tests::b;
65 use git_config::values::{Boolean, TrueVariant};
66 use std::convert::TryFrom;
67
68 #[test]
69 fn from_str_false() {
70 assert_eq!(Boolean::try_from(b("no")), Ok(Boolean::False("no".into())));
71 assert_eq!(Boolean::try_from(b("off")), Ok(Boolean::False("off".into())));
72 assert_eq!(Boolean::try_from(b("false")), Ok(Boolean::False("false".into())));
73 assert_eq!(Boolean::try_from(b("zero")), Ok(Boolean::False("zero".into())));
74 assert_eq!(Boolean::try_from(b("\"\"")), Ok(Boolean::False("\"\"".into())));
75 }
76
77 #[test]
78 fn from_str_true() {
79 assert_eq!(
80 Boolean::try_from(b("yes")),
81 Ok(Boolean::True(TrueVariant::Explicit("yes".into())))
82 );
83 assert_eq!(
84 Boolean::try_from(b("on")),
85 Ok(Boolean::True(TrueVariant::Explicit("on".into())))
86 );
87 assert_eq!(
88 Boolean::try_from(b("true")),
89 Ok(Boolean::True(TrueVariant::Explicit("true".into())))
90 );
91 assert_eq!(
92 Boolean::try_from(b("one")),
93 Ok(Boolean::True(TrueVariant::Explicit("one".into())))
94 );
95 }
96
97 #[test]
98 fn ignores_case() {
99 // Random subset
100 for word in &["no", "yes", "off", "true", "zero"] {
101 let first: bool = Boolean::try_from(b(word)).unwrap().into();
102 let second: bool = Boolean::try_from(b(&*word.to_uppercase())).unwrap().into();
103 assert_eq!(first, second);
104 }
105 }
106
107 #[test]
108 fn from_str_err() {
109 assert!(Boolean::try_from(b("yesn't")).is_err());
110 assert!(Boolean::try_from(b("yesno")).is_err());
111 }
112}
113
114#[cfg(test)]
115mod integer {
116 use crate::values_integration_tests::b;
117 use git_config::values::{Integer, IntegerSuffix};
118 use std::convert::TryFrom;
119
120 #[test]
121 fn from_str_no_suffix() {
122 assert_eq!(Integer::try_from(b("1")).unwrap(), Integer { value: 1, suffix: None });
123
124 assert_eq!(
125 Integer::try_from(b("-1")).unwrap(),
126 Integer {
127 value: -1,
128 suffix: None
129 }
130 );
131 }
132
133 #[test]
134 fn from_str_with_suffix() {
135 assert_eq!(
136 Integer::try_from(b("1k")).unwrap(),
137 Integer {
138 value: 1,
139 suffix: Some(IntegerSuffix::Kibi),
140 }
141 );
142
143 assert_eq!(
144 Integer::try_from(b("1m")).unwrap(),
145 Integer {
146 value: 1,
147 suffix: Some(IntegerSuffix::Mebi),
148 }
149 );
150
151 assert_eq!(
152 Integer::try_from(b("1g")).unwrap(),
153 Integer {
154 value: 1,
155 suffix: Some(IntegerSuffix::Gibi),
156 }
157 );
158 }
159
160 #[test]
161 fn invalid_from_str() {
162 assert!(Integer::try_from(b("")).is_err());
163 assert!(Integer::try_from(b("-")).is_err());
164 assert!(Integer::try_from(b("k")).is_err());
165 assert!(Integer::try_from(b("m")).is_err());
166 assert!(Integer::try_from(b("g")).is_err());
167 assert!(Integer::try_from(b("123123123123123123123123")).is_err());
168 assert!(Integer::try_from(b("gg")).is_err());
169 }
170
171 #[test]
172 fn as_decimal() {
173 assert_eq!(
174 Integer::try_from(b("12")).unwrap().as_decimal().unwrap(),
175 12,
176 "works without suffix"
177 );
178 assert_eq!(
179 Integer::try_from(b("13k")).unwrap().as_decimal().unwrap(),
180 13 * 1024,
181 "works with kilobyte suffix"
182 );
183 assert_eq!(
184 Integer::try_from(b("14m")).unwrap().as_decimal().unwrap(),
185 14 * 1048576,
186 "works with megabyte suffix"
187 );
188 assert_eq!(
189 Integer::try_from(b("15g")).unwrap().as_decimal().unwrap(),
190 15 * 1073741824,
191 "works with gigabyte suffix"
192 );
193
194 let max_i64 = format!("{}g", i64::MAX);
195 assert!(
196 Integer::try_from(b(&max_i64)).unwrap().as_decimal().is_none(),
197 "overflow results in None"
198 );
199 }
200}
201
202#[cfg(test)]
203mod color_value {
204 use git_config::values::ColorValue;
205 use std::str::FromStr;
206
207 #[test]
208 fn non_bright() {
209 assert_eq!(ColorValue::from_str("normal"), Ok(ColorValue::Normal));
210 assert_eq!(ColorValue::from_str("black"), Ok(ColorValue::Black));
211 assert_eq!(ColorValue::from_str("red"), Ok(ColorValue::Red));
212 assert_eq!(ColorValue::from_str("green"), Ok(ColorValue::Green));
213 assert_eq!(ColorValue::from_str("yellow"), Ok(ColorValue::Yellow));
214 assert_eq!(ColorValue::from_str("blue"), Ok(ColorValue::Blue));
215 assert_eq!(ColorValue::from_str("magenta"), Ok(ColorValue::Magenta));
216 assert_eq!(ColorValue::from_str("cyan"), Ok(ColorValue::Cyan));
217 assert_eq!(ColorValue::from_str("white"), Ok(ColorValue::White));
218 }
219
220 #[test]
221 fn bright() {
222 assert_eq!(ColorValue::from_str("brightblack"), Ok(ColorValue::BrightBlack));
223 assert_eq!(ColorValue::from_str("brightred"), Ok(ColorValue::BrightRed));
224 assert_eq!(ColorValue::from_str("brightgreen"), Ok(ColorValue::BrightGreen));
225 assert_eq!(ColorValue::from_str("brightyellow"), Ok(ColorValue::BrightYellow));
226 assert_eq!(ColorValue::from_str("brightblue"), Ok(ColorValue::BrightBlue));
227 assert_eq!(ColorValue::from_str("brightmagenta"), Ok(ColorValue::BrightMagenta));
228 assert_eq!(ColorValue::from_str("brightcyan"), Ok(ColorValue::BrightCyan));
229 assert_eq!(ColorValue::from_str("brightwhite"), Ok(ColorValue::BrightWhite));
230 }
231
232 #[test]
233 fn ansi() {
234 assert_eq!(ColorValue::from_str("255"), Ok(ColorValue::Ansi(255)));
235 assert_eq!(ColorValue::from_str("0"), Ok(ColorValue::Ansi(0)));
236 }
237
238 #[test]
239 fn hex() {
240 assert_eq!(ColorValue::from_str("#ff0010"), Ok(ColorValue::Rgb(255, 0, 16)));
241 assert_eq!(ColorValue::from_str("#ffffff"), Ok(ColorValue::Rgb(255, 255, 255)));
242 assert_eq!(ColorValue::from_str("#000000"), Ok(ColorValue::Rgb(0, 0, 0)));
243 }
244
245 #[test]
246 fn invalid() {
247 assert!(ColorValue::from_str("brightnormal").is_err());
248 assert!(ColorValue::from_str("").is_err());
249 assert!(ColorValue::from_str("bright").is_err());
250 assert!(ColorValue::from_str("256").is_err());
251 assert!(ColorValue::from_str("#").is_err());
252 assert!(ColorValue::from_str("#fff").is_err());
253 assert!(ColorValue::from_str("#gggggg").is_err());
254 }
255}
256
257#[cfg(test)]
258mod color_attribute {
259 use git_config::values::ColorAttribute;
260 use std::str::FromStr;
261
262 #[test]
263 fn non_inverted() {
264 assert_eq!(ColorAttribute::from_str("bold"), Ok(ColorAttribute::Bold));
265 assert_eq!(ColorAttribute::from_str("dim"), Ok(ColorAttribute::Dim));
266 assert_eq!(ColorAttribute::from_str("ul"), Ok(ColorAttribute::Ul));
267 assert_eq!(ColorAttribute::from_str("blink"), Ok(ColorAttribute::Blink));
268 assert_eq!(ColorAttribute::from_str("reverse"), Ok(ColorAttribute::Reverse));
269 assert_eq!(ColorAttribute::from_str("italic"), Ok(ColorAttribute::Italic));
270 assert_eq!(ColorAttribute::from_str("strike"), Ok(ColorAttribute::Strike));
271 }
272
273 #[test]
274 fn inverted_no_dash() {
275 assert_eq!(ColorAttribute::from_str("nobold"), Ok(ColorAttribute::NoBold));
276 assert_eq!(ColorAttribute::from_str("nodim"), Ok(ColorAttribute::NoDim));
277 assert_eq!(ColorAttribute::from_str("noul"), Ok(ColorAttribute::NoUl));
278 assert_eq!(ColorAttribute::from_str("noblink"), Ok(ColorAttribute::NoBlink));
279 assert_eq!(ColorAttribute::from_str("noreverse"), Ok(ColorAttribute::NoReverse));
280 assert_eq!(ColorAttribute::from_str("noitalic"), Ok(ColorAttribute::NoItalic));
281 assert_eq!(ColorAttribute::from_str("nostrike"), Ok(ColorAttribute::NoStrike));
282 }
283
284 #[test]
285 fn inverted_dashed() {
286 assert_eq!(ColorAttribute::from_str("no-bold"), Ok(ColorAttribute::NoBold));
287 assert_eq!(ColorAttribute::from_str("no-dim"), Ok(ColorAttribute::NoDim));
288 assert_eq!(ColorAttribute::from_str("no-ul"), Ok(ColorAttribute::NoUl));
289 assert_eq!(ColorAttribute::from_str("no-blink"), Ok(ColorAttribute::NoBlink));
290 assert_eq!(ColorAttribute::from_str("no-reverse"), Ok(ColorAttribute::NoReverse));
291 assert_eq!(ColorAttribute::from_str("no-italic"), Ok(ColorAttribute::NoItalic));
292 assert_eq!(ColorAttribute::from_str("no-strike"), Ok(ColorAttribute::NoStrike));
293 }
294
295 #[test]
296 fn invalid() {
297 assert!(ColorAttribute::from_str("a").is_err());
298 assert!(ColorAttribute::from_str("no bold").is_err());
299 assert!(ColorAttribute::from_str("").is_err());
300 assert!(ColorAttribute::from_str("no").is_err());
301 assert!(ColorAttribute::from_str("no-").is_err());
302 }
303}
304#[cfg(test)]
305mod interpolate_tests {
306 use crate::values_integration_tests::b;
307 use git_config::values::path::interpolate;
308 use git_config::values::Path;
309 use std::borrow::Cow;
310
311 #[test]
312 fn no_interpolation_for_paths_without_tilde_or_prefix() {
313 let path = &b"/foo/bar"[..];
314 let actual = Path::from(Cow::Borrowed(path));
315 assert_eq!(&*actual, path);
316 assert!(
317 matches!(&actual.value, Cow::Borrowed(_)),
318 "it does not unnecessarily copy values"
319 );
320 }
321
322 #[test]
323 fn empty_path_is_error() {
324 assert!(matches!(
325 Path::from(Cow::Borrowed(b(""))).interpolate(None),
326 Err(interpolate::Error::Missing { what: "path" })
327 ));
328 }
329
330 #[test]
331 fn prefix_substitutes_git_install_dir() {
332 for git_install_dir in &["/tmp/git", "C:\\git"] {
333 for (val, expected) in &[
334 (&b"%(prefix)/foo/bar"[..], "foo/bar"),
335 (b"%(prefix)/foo\\bar", "foo\\bar"),
336 ] {
337 let expected =
338 &std::path::PathBuf::from(format!("{}{}{}", git_install_dir, std::path::MAIN_SEPARATOR, expected));
339 assert_eq!(
340 &*Path::from(Cow::Borrowed(*val))
341 .interpolate(Some(std::path::Path::new(git_install_dir)))
342 .unwrap(),
343 expected,
344 "prefix interpolation keeps separators as they are"
345 );
346 }
347 }
348 }
349
350 #[test]
351 fn prefix_substitution_skipped_with_dot_slash() {
352 let path = "./%(prefix)/foo/bar";
353 let git_install_dir = "/tmp/git";
354 assert_eq!(
355 Path::from(Cow::Borrowed(b(path)))
356 .interpolate(Some(std::path::Path::new(git_install_dir)))
357 .unwrap(),
358 std::path::Path::new(path)
359 );
360 }
361
362 #[test]
363 fn tilde_substitutes_current_user() {
364 let path = &b"~/foo/bar"[..];
365 let expected = format!(
366 "{}{}foo/bar",
367 dirs::home_dir().expect("empty home").display(),
368 std::path::MAIN_SEPARATOR
369 );
370 assert_eq!(
371 Path::from(Cow::Borrowed(path)).interpolate(None).unwrap().as_ref(),
372 std::path::Path::new(&expected),
373 "note that path separators are not turned into slashes as we work with `std::path::Path`"
374 );
375 }
376
377 #[cfg(target_os = "windows")]
378 #[test]
379 fn tilde_with_given_user_is_unsupported_on_windows() {
380 assert!(matches!(
381 Path::from(Cow::Borrowed(&b"~baz/foo/bar"[..])).interpolate(None),
382 Err(interpolate::Error::UserInterpolationUnsupported)
383 ));
384 }
385
386 #[cfg(not(target_os = "windows"))]
387 #[test]
388 fn tilde_with_given_user() {
389 let user = std::env::var("USER").unwrap();
390 let home = std::env::var("HOME").unwrap();
391 let specific_user_home = format!("~{}", user);
392
393 for path_suffix in &["foo/bar", "foo\\bar", ""] {
394 let path = format!("{}{}{}", specific_user_home, std::path::MAIN_SEPARATOR, path_suffix);
395 let expected = format!("{}{}{}", home, std::path::MAIN_SEPARATOR, path_suffix);
396 assert_eq!(
397 Path::from(Cow::Borrowed(b(&path))).interpolate(None).unwrap(),
398 std::path::Path::new(&expected),
399 "it keeps path separators as is"
400 );
401 }
402 }
403}
git-config/tests/parser/mod.rsrenamed from git-config/tests/integration_tests/parser_integration_tests.rs+0−0

File renamed without changes.

git-config/tests/value/mod.rsrenamed from git-config/tests/integration_tests/value_integration_tests.rs+0−0

File renamed without changes.

git-config/tests/values/boolean.rs+48−0
@@ -0,0 +1,48 @@
1use crate::values::b;
2use git_config::values::{Boolean, TrueVariant};
3use std::convert::TryFrom;
4
5#[test]
6fn from_str_false() {
7 assert_eq!(Boolean::try_from(b("no")), Ok(Boolean::False("no".into())));
8 assert_eq!(Boolean::try_from(b("off")), Ok(Boolean::False("off".into())));
9 assert_eq!(Boolean::try_from(b("false")), Ok(Boolean::False("false".into())));
10 assert_eq!(Boolean::try_from(b("zero")), Ok(Boolean::False("zero".into())));
11 assert_eq!(Boolean::try_from(b("\"\"")), Ok(Boolean::False("\"\"".into())));
12}
13
14#[test]
15fn from_str_true() {
16 assert_eq!(
17 Boolean::try_from(b("yes")),
18 Ok(Boolean::True(TrueVariant::Explicit("yes".into())))
19 );
20 assert_eq!(
21 Boolean::try_from(b("on")),
22 Ok(Boolean::True(TrueVariant::Explicit("on".into())))
23 );
24 assert_eq!(
25 Boolean::try_from(b("true")),
26 Ok(Boolean::True(TrueVariant::Explicit("true".into())))
27 );
28 assert_eq!(
29 Boolean::try_from(b("one")),
30 Ok(Boolean::True(TrueVariant::Explicit("one".into())))
31 );
32}
33
34#[test]
35fn ignores_case() {
36 // Random subset
37 for word in &["no", "yes", "off", "true", "zero"] {
38 let first: bool = Boolean::try_from(b(word)).unwrap().into();
39 let second: bool = Boolean::try_from(b(&*word.to_uppercase())).unwrap().into();
40 assert_eq!(first, second);
41 }
42}
43
44#[test]
45fn from_str_err() {
46 assert!(Boolean::try_from(b("yesn't")).is_err());
47 assert!(Boolean::try_from(b("yesno")).is_err());
48}
git-config/tests/values/color_attribute.rs+44−0
@@ -0,0 +1,44 @@
1use git_config::values::ColorAttribute;
2use std::str::FromStr;
3
4#[test]
5fn non_inverted() {
6 assert_eq!(ColorAttribute::from_str("bold"), Ok(ColorAttribute::Bold));
7 assert_eq!(ColorAttribute::from_str("dim"), Ok(ColorAttribute::Dim));
8 assert_eq!(ColorAttribute::from_str("ul"), Ok(ColorAttribute::Ul));
9 assert_eq!(ColorAttribute::from_str("blink"), Ok(ColorAttribute::Blink));
10 assert_eq!(ColorAttribute::from_str("reverse"), Ok(ColorAttribute::Reverse));
11 assert_eq!(ColorAttribute::from_str("italic"), Ok(ColorAttribute::Italic));
12 assert_eq!(ColorAttribute::from_str("strike"), Ok(ColorAttribute::Strike));
13}
14
15#[test]
16fn inverted_no_dash() {
17 assert_eq!(ColorAttribute::from_str("nobold"), Ok(ColorAttribute::NoBold));
18 assert_eq!(ColorAttribute::from_str("nodim"), Ok(ColorAttribute::NoDim));
19 assert_eq!(ColorAttribute::from_str("noul"), Ok(ColorAttribute::NoUl));
20 assert_eq!(ColorAttribute::from_str("noblink"), Ok(ColorAttribute::NoBlink));
21 assert_eq!(ColorAttribute::from_str("noreverse"), Ok(ColorAttribute::NoReverse));
22 assert_eq!(ColorAttribute::from_str("noitalic"), Ok(ColorAttribute::NoItalic));
23 assert_eq!(ColorAttribute::from_str("nostrike"), Ok(ColorAttribute::NoStrike));
24}
25
26#[test]
27fn inverted_dashed() {
28 assert_eq!(ColorAttribute::from_str("no-bold"), Ok(ColorAttribute::NoBold));
29 assert_eq!(ColorAttribute::from_str("no-dim"), Ok(ColorAttribute::NoDim));
30 assert_eq!(ColorAttribute::from_str("no-ul"), Ok(ColorAttribute::NoUl));
31 assert_eq!(ColorAttribute::from_str("no-blink"), Ok(ColorAttribute::NoBlink));
32 assert_eq!(ColorAttribute::from_str("no-reverse"), Ok(ColorAttribute::NoReverse));
33 assert_eq!(ColorAttribute::from_str("no-italic"), Ok(ColorAttribute::NoItalic));
34 assert_eq!(ColorAttribute::from_str("no-strike"), Ok(ColorAttribute::NoStrike));
35}
36
37#[test]
38fn invalid() {
39 assert!(ColorAttribute::from_str("a").is_err());
40 assert!(ColorAttribute::from_str("no bold").is_err());
41 assert!(ColorAttribute::from_str("").is_err());
42 assert!(ColorAttribute::from_str("no").is_err());
43 assert!(ColorAttribute::from_str("no-").is_err());
44}
git-config/tests/values/color_value.rs+51−0
@@ -0,0 +1,51 @@
1use git_config::values::ColorValue;
2use std::str::FromStr;
3
4#[test]
5fn non_bright() {
6 assert_eq!(ColorValue::from_str("normal"), Ok(ColorValue::Normal));
7 assert_eq!(ColorValue::from_str("black"), Ok(ColorValue::Black));
8 assert_eq!(ColorValue::from_str("red"), Ok(ColorValue::Red));
9 assert_eq!(ColorValue::from_str("green"), Ok(ColorValue::Green));
10 assert_eq!(ColorValue::from_str("yellow"), Ok(ColorValue::Yellow));
11 assert_eq!(ColorValue::from_str("blue"), Ok(ColorValue::Blue));
12 assert_eq!(ColorValue::from_str("magenta"), Ok(ColorValue::Magenta));
13 assert_eq!(ColorValue::from_str("cyan"), Ok(ColorValue::Cyan));
14 assert_eq!(ColorValue::from_str("white"), Ok(ColorValue::White));
15}
16
17#[test]
18fn bright() {
19 assert_eq!(ColorValue::from_str("brightblack"), Ok(ColorValue::BrightBlack));
20 assert_eq!(ColorValue::from_str("brightred"), Ok(ColorValue::BrightRed));
21 assert_eq!(ColorValue::from_str("brightgreen"), Ok(ColorValue::BrightGreen));
22 assert_eq!(ColorValue::from_str("brightyellow"), Ok(ColorValue::BrightYellow));
23 assert_eq!(ColorValue::from_str("brightblue"), Ok(ColorValue::BrightBlue));
24 assert_eq!(ColorValue::from_str("brightmagenta"), Ok(ColorValue::BrightMagenta));
25 assert_eq!(ColorValue::from_str("brightcyan"), Ok(ColorValue::BrightCyan));
26 assert_eq!(ColorValue::from_str("brightwhite"), Ok(ColorValue::BrightWhite));
27}
28
29#[test]
30fn ansi() {
31 assert_eq!(ColorValue::from_str("255"), Ok(ColorValue::Ansi(255)));
32 assert_eq!(ColorValue::from_str("0"), Ok(ColorValue::Ansi(0)));
33}
34
35#[test]
36fn hex() {
37 assert_eq!(ColorValue::from_str("#ff0010"), Ok(ColorValue::Rgb(255, 0, 16)));
38 assert_eq!(ColorValue::from_str("#ffffff"), Ok(ColorValue::Rgb(255, 255, 255)));
39 assert_eq!(ColorValue::from_str("#000000"), Ok(ColorValue::Rgb(0, 0, 0)));
40}
41
42#[test]
43fn invalid() {
44 assert!(ColorValue::from_str("brightnormal").is_err());
45 assert!(ColorValue::from_str("").is_err());
46 assert!(ColorValue::from_str("bright").is_err());
47 assert!(ColorValue::from_str("256").is_err());
48 assert!(ColorValue::from_str("#").is_err());
49 assert!(ColorValue::from_str("#fff").is_err());
50 assert!(ColorValue::from_str("#gggggg").is_err());
51}
git-config/tests/values/integer.rs+84−0
@@ -0,0 +1,84 @@
1use crate::values::b;
2use git_config::values::{Integer, IntegerSuffix};
3use std::convert::TryFrom;
4
5#[test]
6fn from_str_no_suffix() {
7 assert_eq!(Integer::try_from(b("1")).unwrap(), Integer { value: 1, suffix: None });
8
9 assert_eq!(
10 Integer::try_from(b("-1")).unwrap(),
11 Integer {
12 value: -1,
13 suffix: None
14 }
15 );
16}
17
18#[test]
19fn from_str_with_suffix() {
20 assert_eq!(
21 Integer::try_from(b("1k")).unwrap(),
22 Integer {
23 value: 1,
24 suffix: Some(IntegerSuffix::Kibi),
25 }
26 );
27
28 assert_eq!(
29 Integer::try_from(b("1m")).unwrap(),
30 Integer {
31 value: 1,
32 suffix: Some(IntegerSuffix::Mebi),
33 }
34 );
35
36 assert_eq!(
37 Integer::try_from(b("1g")).unwrap(),
38 Integer {
39 value: 1,
40 suffix: Some(IntegerSuffix::Gibi),
41 }
42 );
43}
44
45#[test]
46fn invalid_from_str() {
47 assert!(Integer::try_from(b("")).is_err());
48 assert!(Integer::try_from(b("-")).is_err());
49 assert!(Integer::try_from(b("k")).is_err());
50 assert!(Integer::try_from(b("m")).is_err());
51 assert!(Integer::try_from(b("g")).is_err());
52 assert!(Integer::try_from(b("123123123123123123123123")).is_err());
53 assert!(Integer::try_from(b("gg")).is_err());
54}
55
56#[test]
57fn as_decimal() {
58 assert_eq!(
59 Integer::try_from(b("12")).unwrap().as_decimal().unwrap(),
60 12,
61 "works without suffix"
62 );
63 assert_eq!(
64 Integer::try_from(b("13k")).unwrap().as_decimal().unwrap(),
65 13 * 1024,
66 "works with kilobyte suffix"
67 );
68 assert_eq!(
69 Integer::try_from(b("14m")).unwrap().as_decimal().unwrap(),
70 14 * 1048576,
71 "works with megabyte suffix"
72 );
73 assert_eq!(
74 Integer::try_from(b("15g")).unwrap().as_decimal().unwrap(),
75 15 * 1073741824,
76 "works with gigabyte suffix"
77 );
78
79 let max_i64 = format!("{}g", i64::MAX);
80 assert!(
81 Integer::try_from(b(&max_i64)).unwrap().as_decimal().is_none(),
82 "overflow results in None"
83 );
84}
git-config/tests/values/mod.rs+16−0
@@ -0,0 +1,16 @@
1/// Converts string to byte slice
2fn b(s: &str) -> &[u8] {
3 s.as_bytes()
4}
5
6mod normalize;
7
8mod boolean;
9
10mod integer;
11
12mod color_value;
13
14mod color_attribute;
15
16mod path;
git-config/tests/values/normalize.rs+51−0
@@ -0,0 +1,51 @@
1use git_config::values::normalize_str;
2use std::borrow::Cow;
3
4#[test]
5fn not_modified_is_borrowed() {
6 assert_eq!(normalize_str("hello world"), Cow::Borrowed(b"hello world"));
7}
8
9#[test]
10fn modified_is_owned() {
11 assert_eq!(
12 normalize_str("hello \"world\""),
13 Cow::<[u8]>::Owned(b"hello world".to_vec())
14 );
15}
16
17#[test]
18fn all_quoted_is_optimized() {
19 assert_eq!(normalize_str("\"hello world\""), Cow::Borrowed(b"hello world"));
20}
21
22#[test]
23fn all_quote_optimization_is_correct() {
24 assert_eq!(normalize_str(r#""hello" world\""#), Cow::Borrowed(b"hello world\""));
25}
26
27#[test]
28fn quotes_right_next_to_each_other() {
29 assert_eq!(
30 normalize_str("\"hello\"\" world\""),
31 Cow::<[u8]>::Owned(b"hello world".to_vec())
32 );
33}
34
35#[test]
36fn escaped_quotes_are_kept() {
37 assert_eq!(
38 normalize_str(r#""hello \"\" world""#),
39 Cow::<[u8]>::Owned(b"hello \"\" world".to_vec())
40 );
41}
42
43#[test]
44fn empty_string() {
45 assert_eq!(normalize_str(""), Cow::Borrowed(b""));
46}
47
48#[test]
49fn empty_normalized_string_is_optimized() {
50 assert_eq!(normalize_str("\"\""), Cow::Borrowed(b""));
51}
git-config/tests/values/path.rs+97−0
@@ -0,0 +1,97 @@
1use crate::values::b;
2use git_config::values::path::interpolate;
3use git_config::values::Path;
4use std::borrow::Cow;
5
6#[test]
7fn no_interpolation_for_paths_without_tilde_or_prefix() {
8 let path = &b"/foo/bar"[..];
9 let actual = Path::from(Cow::Borrowed(path));
10 assert_eq!(&*actual, path);
11 assert!(
12 matches!(&actual.value, Cow::Borrowed(_)),
13 "it does not unnecessarily copy values"
14 );
15}
16
17#[test]
18fn empty_path_is_error() {
19 assert!(matches!(
20 Path::from(Cow::Borrowed(b(""))).interpolate(None),
21 Err(interpolate::Error::Missing { what: "path" })
22 ));
23}
24
25#[test]
26fn prefix_substitutes_git_install_dir() {
27 for git_install_dir in &["/tmp/git", "C:\\git"] {
28 for (val, expected) in &[
29 (&b"%(prefix)/foo/bar"[..], "foo/bar"),
30 (b"%(prefix)/foo\\bar", "foo\\bar"),
31 ] {
32 let expected =
33 &std::path::PathBuf::from(format!("{}{}{}", git_install_dir, std::path::MAIN_SEPARATOR, expected));
34 assert_eq!(
35 &*Path::from(Cow::Borrowed(*val))
36 .interpolate(Some(std::path::Path::new(git_install_dir)))
37 .unwrap(),
38 expected,
39 "prefix interpolation keeps separators as they are"
40 );
41 }
42 }
43}
44
45#[test]
46fn prefix_substitution_skipped_with_dot_slash() {
47 let path = "./%(prefix)/foo/bar";
48 let git_install_dir = "/tmp/git";
49 assert_eq!(
50 Path::from(Cow::Borrowed(b(path)))
51 .interpolate(Some(std::path::Path::new(git_install_dir)))
52 .unwrap(),
53 std::path::Path::new(path)
54 );
55}
56
57#[test]
58fn tilde_substitutes_current_user() {
59 let path = &b"~/foo/bar"[..];
60 let expected = format!(
61 "{}{}foo/bar",
62 dirs::home_dir().expect("empty home").display(),
63 std::path::MAIN_SEPARATOR
64 );
65 assert_eq!(
66 Path::from(Cow::Borrowed(path)).interpolate(None).unwrap().as_ref(),
67 std::path::Path::new(&expected),
68 "note that path separators are not turned into slashes as we work with `std::path::Path`"
69 );
70}
71
72#[cfg(target_os = "windows")]
73#[test]
74fn tilde_with_given_user_is_unsupported_on_windows() {
75 assert!(matches!(
76 Path::from(Cow::Borrowed(&b"~baz/foo/bar"[..])).interpolate(None),
77 Err(interpolate::Error::UserInterpolationUnsupported)
78 ));
79}
80
81#[cfg(not(target_os = "windows"))]
82#[test]
83fn tilde_with_given_user() {
84 let user = std::env::var("USER").unwrap();
85 let home = std::env::var("HOME").unwrap();
86 let specific_user_home = format!("~{}", user);
87
88 for path_suffix in &["foo/bar", "foo\\bar", ""] {
89 let path = format!("{}{}{}", specific_user_home, std::path::MAIN_SEPARATOR, path_suffix);
90 let expected = format!("{}{}{}", home, std::path::MAIN_SEPARATOR, path_suffix);
91 assert_eq!(
92 Path::from(Cow::Borrowed(b(&path))).interpolate(None).unwrap(),
93 std::path::Path::new(&expected),
94 "it keeps path separators as is"
95 );
96 }
97}