A library for writing host-specific, single-binary configuration management and deployment tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.9 KiB

7 years ago
  1. use std::error::Error;
  2. use std::fmt;
  3. use symbols::Symbol;
  4. pub struct Hook<A, B> where A: Symbol, B: Symbol {
  5. a: A,
  6. b: B
  7. }
  8. impl<A, B> Hook<A, B> where A: Symbol, B: Symbol {
  9. pub fn new(a: A, b: B) -> Self {
  10. Hook { a: a, b: b }
  11. }
  12. }
  13. impl<A, B> Symbol for Hook<A, B> where A: Symbol, B: Symbol {
  14. fn target_reached(&self) -> Result<bool, Box<Error>> {
  15. self.a.target_reached().and_then(|reached| if reached { self.b.target_reached() } else { Ok(reached) })
  16. }
  17. fn execute(&self) -> Result<(), Box<Error>> {
  18. try!(self.a.execute());
  19. self.b.execute()
  20. }
  21. }
  22. impl<A, B> fmt::Display for Hook<A, B> where A: Symbol, B: Symbol {
  23. fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{
  24. write!(f, "Hook {} and then {}", self.a, self.b)
  25. }
  26. }
  27. #[cfg(test)]
  28. mod test {
  29. use std::error::Error;
  30. use std::fmt;
  31. use symbols::Symbol;
  32. use symbols::hook::Hook;
  33. struct ErrSymbol(String);
  34. impl Symbol for ErrSymbol {
  35. fn target_reached(&self) -> Result<bool, Box<Error>> { Err(self.0.clone().into()) }
  36. fn execute(&self) -> Result<(), Box<Error>> { Err(self.0.clone().into()) }
  37. }
  38. impl fmt::Display for ErrSymbol { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ write!(f, "") } }
  39. struct OkSymbol(bool);
  40. impl Symbol for OkSymbol {
  41. fn target_reached(&self) -> Result<bool, Box<Error>> { Ok(self.0) }
  42. fn execute(&self) -> Result<(), Box<Error>> { Ok(()) }
  43. }
  44. impl fmt::Display for OkSymbol { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ write!(f, "") } }
  45. #[test]
  46. fn first_target_reached_fails() {
  47. let res = Hook::new(ErrSymbol("first".into()), ErrSymbol("second".into())).target_reached();
  48. assert_eq!(res.unwrap_err().description(), "first");
  49. }
  50. #[test]
  51. fn first_target_not_reached() {
  52. let res = Hook::new(OkSymbol(false), ErrSymbol("second".into())).target_reached();
  53. assert_eq!(res.unwrap(), false);
  54. }
  55. #[test]
  56. fn second_target_reached_fails() {
  57. let res = Hook::new(OkSymbol(true), ErrSymbol("second".into())).target_reached();
  58. assert_eq!(res.unwrap_err().description(), "second");
  59. }
  60. #[test]
  61. fn second_target_not_reached() {
  62. let res = Hook::new(OkSymbol(true), OkSymbol(false)).target_reached();
  63. assert_eq!(res.unwrap(), false);
  64. }
  65. #[test]
  66. fn everything_reached() {
  67. let res = Hook::new(OkSymbol(true), OkSymbol(true)).target_reached();
  68. assert_eq!(res.unwrap(), true);
  69. }
  70. #[test]
  71. fn first_execute_fails() {
  72. let res = Hook::new(ErrSymbol("first".into()), ErrSymbol("second".into())).execute();
  73. assert_eq!(res.unwrap_err().description(), "first");
  74. }
  75. #[test]
  76. fn second_execute_fails() {
  77. let res = Hook::new(OkSymbol(true), ErrSymbol("second".into())).execute();
  78. assert_eq!(res.unwrap_err().description(), "second");
  79. }
  80. #[test]
  81. fn everything_executes() {
  82. let res = Hook::new(OkSymbol(true), OkSymbol(true)).execute();
  83. assert_eq!(res.unwrap(), ());
  84. }
  85. }