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.

130 lines
3.8 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. use std::error::Error;
  2. use std::fmt;
  3. use resources::Resource;
  4. use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
  5. pub struct Hook<A, B> where A: Symbol, B: Symbol {
  6. a: A,
  7. b: B
  8. }
  9. impl<A, B> Hook<A, B> where A: Symbol, B: Symbol {
  10. pub fn new(a: A, b: B) -> Self {
  11. Hook { a: a, b: b }
  12. }
  13. }
  14. impl<A, B> Symbol for Hook<A, B> where A: Symbol, B: Symbol {
  15. fn target_reached(&self) -> Result<bool, Box<Error>> {
  16. self.a.target_reached().and_then(|reached| if reached { self.b.target_reached() } else { Ok(reached) })
  17. }
  18. fn execute(&self) -> Result<(), Box<Error>> {
  19. try!(self.a.execute());
  20. self.b.execute()
  21. }
  22. fn get_prerequisites(&self) -> Vec<Resource> {
  23. let mut r = vec![];
  24. r.extend(self.a.get_prerequisites().into_iter());
  25. r.extend(self.b.get_prerequisites().into_iter());
  26. r
  27. }
  28. fn provides(&self) -> Option<Vec<Resource>> {
  29. let mut r = vec![];
  30. if let Some(provides) = self.a.provides() {
  31. r.extend(provides.into_iter());
  32. }
  33. if let Some(provides) = self.b.provides() {
  34. r.extend(provides.into_iter());
  35. }
  36. if r.len() > 0 { Some(r) } else { None }
  37. }
  38. fn as_action<'a>(&'a self, runner: &'a SymbolRunner) -> Box<Action + 'a> {
  39. Box::new(SymbolAction::new(runner, self))
  40. }
  41. fn into_action<'a>(self: Box<Self>, runner: &'a SymbolRunner) -> Box<Action + 'a> where Self: 'a {
  42. Box::new(OwnedSymbolAction::new(runner, *self))
  43. }
  44. }
  45. impl<A, B> fmt::Display for Hook<A, B> where A: Symbol, B: Symbol {
  46. fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{
  47. write!(f, "Hook {} and then {}", self.a, self.b)
  48. }
  49. }
  50. #[cfg(test)]
  51. mod test {
  52. use std::error::Error;
  53. use std::fmt;
  54. use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
  55. use symbols::hook::Hook;
  56. struct ErrSymbol(String);
  57. impl Symbol for ErrSymbol {
  58. fn target_reached(&self) -> Result<bool, Box<Error>> { Err(self.0.clone().into()) }
  59. fn execute(&self) -> Result<(), Box<Error>> { Err(self.0.clone().into()) }
  60. }
  61. impl fmt::Display for ErrSymbol { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ write!(f, "") } }
  62. struct OkSymbol(bool);
  63. impl Symbol for OkSymbol {
  64. fn target_reached(&self) -> Result<bool, Box<Error>> { Ok(self.0) }
  65. fn execute(&self) -> Result<(), Box<Error>> { Ok(()) }
  66. }
  67. impl fmt::Display for OkSymbol { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>{ write!(f, "") } }
  68. #[test]
  69. fn first_target_reached_fails() {
  70. let res = Hook::new(ErrSymbol("first".into()), ErrSymbol("second".into())).target_reached();
  71. assert_eq!(res.unwrap_err().description(), "first");
  72. }
  73. #[test]
  74. fn first_target_not_reached() {
  75. let res = Hook::new(OkSymbol(false), ErrSymbol("second".into())).target_reached();
  76. assert_eq!(res.unwrap(), false);
  77. }
  78. #[test]
  79. fn second_target_reached_fails() {
  80. let res = Hook::new(OkSymbol(true), ErrSymbol("second".into())).target_reached();
  81. assert_eq!(res.unwrap_err().description(), "second");
  82. }
  83. #[test]
  84. fn second_target_not_reached() {
  85. let res = Hook::new(OkSymbol(true), OkSymbol(false)).target_reached();
  86. assert_eq!(res.unwrap(), false);
  87. }
  88. #[test]
  89. fn everything_reached() {
  90. let res = Hook::new(OkSymbol(true), OkSymbol(true)).target_reached();
  91. assert_eq!(res.unwrap(), true);
  92. }
  93. #[test]
  94. fn first_execute_fails() {
  95. let res = Hook::new(ErrSymbol("first".into()), ErrSymbol("second".into())).execute();
  96. assert_eq!(res.unwrap_err().description(), "first");
  97. }
  98. #[test]
  99. fn second_execute_fails() {
  100. let res = Hook::new(OkSymbol(true), ErrSymbol("second".into())).execute();
  101. assert_eq!(res.unwrap_err().description(), "second");
  102. }
  103. #[test]
  104. fn everything_executes() {
  105. let res = Hook::new(OkSymbol(true), OkSymbol(true)).execute();
  106. assert_eq!(res.unwrap(), ());
  107. }
  108. }