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.

136 lines
4.0 KiB

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