/src/test_cli.rs

https://github.com/mookid/diffr · Rust · 211 lines · 194 code · 17 blank · 0 comment · 10 complexity · 76efba57216fdbaf74806f9b77066fc0 MD5 · raw file

  1. use std::env;
  2. use std::path::PathBuf;
  3. use std::process::{Command, Stdio};
  4. use StringTest::*;
  5. enum StringTest {
  6. Empty,
  7. AtLeast(&'static str),
  8. Exactly(&'static str),
  9. }
  10. fn quote_or_empty(msg: &str) -> String {
  11. if msg.is_empty() {
  12. "<empty>".to_owned()
  13. } else {
  14. format!("\"{}\"", msg)
  15. }
  16. }
  17. impl StringTest {
  18. fn test(&self, actual: &str, prefix: &str) {
  19. match self {
  20. Empty => assert!(
  21. actual.is_empty(),
  22. format!(
  23. "{}: expected empty, got\n\n{}",
  24. quote_or_empty(prefix),
  25. quote_or_empty(actual)
  26. )
  27. ),
  28. AtLeast(exp) => assert!(
  29. actual.contains(exp),
  30. format!(
  31. "{}: expected at least\n\n{}\n\ngot\n\n{}",
  32. prefix,
  33. quote_or_empty(exp),
  34. quote_or_empty(actual)
  35. )
  36. ),
  37. Exactly(exp) => assert!(
  38. actual.trim() == exp.trim(),
  39. format!(
  40. "{}: expected\n\n{}\n\ngot\n\n{}",
  41. prefix,
  42. quote_or_empty(exp),
  43. quote_or_empty(actual)
  44. )
  45. ),
  46. }
  47. }
  48. }
  49. struct ProcessTest {
  50. args: &'static [&'static str],
  51. out: StringTest,
  52. err: StringTest,
  53. is_success: bool,
  54. }
  55. fn diffr_path_default() -> PathBuf {
  56. let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
  57. dir.push("target");
  58. dir.push("debug");
  59. dir.push(if cfg!(windows) { "diffr.exe" } else { "diffr" });
  60. dir
  61. }
  62. fn diffr_path() -> PathBuf {
  63. match env::var("DIFFR_TESTS_BINARY_PATH") {
  64. Err(_) => diffr_path_default(),
  65. Ok(path) => PathBuf::from(path),
  66. }
  67. }
  68. fn test_cli(descr: ProcessTest) {
  69. let mut cmd = Command::new(diffr_path());
  70. cmd.stdout(Stdio::piped());
  71. cmd.stderr(Stdio::piped());
  72. cmd.stdin(Stdio::piped());
  73. for arg in descr.args {
  74. cmd.arg(&*arg);
  75. }
  76. let child = cmd.spawn().expect("spawn");
  77. let output = child.wait_with_output().expect("wait_with_output");
  78. fn string_of_status(code: bool) -> &'static str {
  79. if code {
  80. "success"
  81. } else {
  82. "failure"
  83. }
  84. };
  85. assert!(
  86. descr.is_success == output.status.success(),
  87. format!(
  88. "unexpected status: expected {} got {}",
  89. string_of_status(descr.is_success),
  90. string_of_status(output.status.success()),
  91. )
  92. );
  93. descr
  94. .out
  95. .test(&String::from_utf8_lossy(&output.stdout), "stdout");
  96. descr
  97. .err
  98. .test(&String::from_utf8_lossy(&output.stderr), "stderr");
  99. }
  100. #[test]
  101. fn debug_flag() {
  102. test_cli(ProcessTest {
  103. args: &["--debug"],
  104. out: Empty,
  105. err: AtLeast("hunk processing time (ms)"),
  106. is_success: true,
  107. })
  108. }
  109. #[test]
  110. fn color_invalid_face_name() {
  111. test_cli(ProcessTest {
  112. args: &["--colors", "notafacename"],
  113. out: Empty,
  114. err: Exactly("unexpected face name: got 'notafacename', expected added|refine-added|removed|refine-removed"),
  115. is_success: false,
  116. })
  117. }
  118. #[test]
  119. fn color_only_face_name() {
  120. test_cli(ProcessTest {
  121. args: &["--colors", "added"],
  122. out: Empty,
  123. err: Exactly(""),
  124. is_success: true,
  125. })
  126. }
  127. #[test]
  128. fn color_invalid_attribute_name() {
  129. test_cli(ProcessTest {
  130. args: &["--colors", "added:bar"],
  131. out: Empty,
  132. err: Exactly("unexpected attribute name: got 'bar', expected foreground|background|italic|noitalic|bold|nobold|intense|nointense|underline|nounderline|none"),
  133. is_success: false,
  134. })
  135. }
  136. #[test]
  137. fn color_invalid_color_value_name() {
  138. test_cli(ProcessTest {
  139. args: &["--colors", "added:foreground:baz"],
  140. out: Empty,
  141. err: Exactly("unexpected color value: unrecognized color name 'baz'. Choose from: black, blue, green, red, cyan, magenta, yellow, white"),
  142. is_success: false,
  143. })
  144. }
  145. #[test]
  146. fn color_invalid_color_value_ansi() {
  147. test_cli(ProcessTest {
  148. args: &["--colors", "added:foreground:777"],
  149. out: Empty,
  150. err: AtLeast("unexpected color value: unrecognized ansi256 color number"),
  151. is_success: false,
  152. })
  153. }
  154. #[test]
  155. fn color_invalid_color_value_rgb() {
  156. test_cli(ProcessTest {
  157. args: &["--colors", "added:foreground:0,0,777"],
  158. out: Empty,
  159. err: AtLeast("unexpected color value: unrecognized RGB color triple"),
  160. is_success: false,
  161. })
  162. }
  163. #[test]
  164. fn color_invalid_color_not_done() {
  165. test_cli(ProcessTest {
  166. args: &["--colors", "added:foreground"],
  167. out: Empty,
  168. err: Exactly("error parsing color: missing color value for face 'added'"),
  169. is_success: false,
  170. })
  171. }
  172. #[test]
  173. fn color_ok() {
  174. test_cli(ProcessTest {
  175. args: &["--colors", "added:foreground:0"],
  176. out: Empty,
  177. err: Exactly(""),
  178. is_success: true,
  179. })
  180. }
  181. #[test]
  182. fn color_ok_multiple() {
  183. test_cli(ProcessTest {
  184. args: &[
  185. "--colors",
  186. "added:foreground:0",
  187. "--colors",
  188. "removed:background:red",
  189. ],
  190. out: Empty,
  191. err: Exactly(""),
  192. is_success: true,
  193. })
  194. }