trigger_agent_spec.rb 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. require 'spec_helper'
  2. describe Agents::TriggerAgent do
  3. before do
  4. @valid_params = {
  5. 'name' => "my trigger agent",
  6. 'options' => {
  7. 'expected_receive_period_in_days' => 2,
  8. 'rules' => [{
  9. 'type' => "regex",
  10. 'value' => "a\\db",
  11. 'path' => "foo.bar.baz",
  12. }],
  13. 'message' => "I saw '<foo.bar.baz>' from <name>"
  14. }
  15. }
  16. @checker = Agents::TriggerAgent.new(@valid_params)
  17. @checker.user = users(:bob)
  18. @checker.save!
  19. @event = Event.new
  20. @event.agent = agents(:bob_rain_notifier_agent)
  21. @event.payload = { 'foo' => { "bar" => { 'baz' => "a2b" }},
  22. 'name' => "Joe" }
  23. end
  24. describe "validation" do
  25. before do
  26. @checker.should be_valid
  27. end
  28. it "should validate presence of options" do
  29. @checker.options['message'] = nil
  30. @checker.should_not be_valid
  31. end
  32. it "should validate the three fields in each rule" do
  33. @checker.options['rules'] << { 'path' => "foo", 'type' => "fake", 'value' => "6" }
  34. @checker.should_not be_valid
  35. @checker.options['rules'].last['type'] = "field>=value"
  36. @checker.should be_valid
  37. @checker.options['rules'].last.delete('value')
  38. @checker.should_not be_valid
  39. end
  40. end
  41. describe "#working?" do
  42. it "checks to see if the Agent has received any events in the last 'expected_receive_period_in_days' days" do
  43. @event.save!
  44. @checker.should_not be_working # no events have ever been received
  45. Agents::TriggerAgent.async_receive(@checker.id, [@event.id])
  46. @checker.reload.should be_working # Events received
  47. three_days_from_now = 3.days.from_now
  48. stub(Time).now { three_days_from_now }
  49. @checker.reload.should_not be_working # too much time has passed
  50. end
  51. end
  52. describe "#receive" do
  53. it "handles regex" do
  54. @event.payload['foo']['bar']['baz'] = "a222b"
  55. lambda {
  56. @checker.receive([@event])
  57. }.should_not change { Event.count }
  58. @event.payload['foo']['bar']['baz'] = "a2b"
  59. lambda {
  60. @checker.receive([@event])
  61. }.should change { Event.count }.by(1)
  62. end
  63. it "handles array of regex" do
  64. @event.payload['foo']['bar']['baz'] = "a222b"
  65. @checker.options['rules'][0] = {
  66. 'type' => "regex",
  67. 'value' => ["a\\db", "a\\Wb"],
  68. 'path' => "foo.bar.baz",
  69. }
  70. lambda {
  71. @checker.receive([@event])
  72. }.should_not change { Event.count }
  73. @event.payload['foo']['bar']['baz'] = "a2b"
  74. lambda {
  75. @checker.receive([@event])
  76. }.should change { Event.count }.by(1)
  77. @event.payload['foo']['bar']['baz'] = "a b"
  78. lambda {
  79. @checker.receive([@event])
  80. }.should change { Event.count }.by(1)
  81. end
  82. it "handles negated regex" do
  83. @event.payload['foo']['bar']['baz'] = "a2b"
  84. @checker.options['rules'][0] = {
  85. 'type' => "!regex",
  86. 'value' => "a\\db",
  87. 'path' => "foo.bar.baz",
  88. }
  89. lambda {
  90. @checker.receive([@event])
  91. }.should_not change { Event.count }
  92. @event.payload['foo']['bar']['baz'] = "a22b"
  93. lambda {
  94. @checker.receive([@event])
  95. }.should change { Event.count }.by(1)
  96. end
  97. it "handles array of negated regex" do
  98. @event.payload['foo']['bar']['baz'] = "a2b"
  99. @checker.options['rules'][0] = {
  100. 'type' => "!regex",
  101. 'value' => ["a\\db", "a2b"],
  102. 'path' => "foo.bar.baz",
  103. }
  104. lambda {
  105. @checker.receive([@event])
  106. }.should_not change { Event.count }
  107. @event.payload['foo']['bar']['baz'] = "a3b"
  108. lambda {
  109. @checker.receive([@event])
  110. }.should change { Event.count }.by(1)
  111. end
  112. it "puts can extract values into the message based on paths" do
  113. @checker.receive([@event])
  114. Event.last.payload['message'].should == "I saw 'a2b' from Joe"
  115. end
  116. it "handles numerical comparisons" do
  117. @event.payload['foo']['bar']['baz'] = "5"
  118. @checker.options['rules'].first['value'] = 6
  119. @checker.options['rules'].first['type'] = "field<value"
  120. lambda {
  121. @checker.receive([@event])
  122. }.should change { Event.count }.by(1)
  123. @checker.options['rules'].first['value'] = 3
  124. lambda {
  125. @checker.receive([@event])
  126. }.should_not change { Event.count }
  127. end
  128. it "handles array of numerical comparisons" do
  129. @event.payload['foo']['bar']['baz'] = "5"
  130. @checker.options['rules'].first['value'] = [6, 3]
  131. @checker.options['rules'].first['type'] = "field<value"
  132. lambda {
  133. @checker.receive([@event])
  134. }.should change { Event.count }.by(1)
  135. @checker.options['rules'].first['value'] = [4, 3]
  136. lambda {
  137. @checker.receive([@event])
  138. }.should_not change { Event.count }
  139. end
  140. it "handles exact comparisons" do
  141. @event.payload['foo']['bar']['baz'] = "hello world"
  142. @checker.options['rules'].first['type'] = "field==value"
  143. @checker.options['rules'].first['value'] = "hello there"
  144. lambda {
  145. @checker.receive([@event])
  146. }.should_not change { Event.count }
  147. @checker.options['rules'].first['value'] = "hello world"
  148. lambda {
  149. @checker.receive([@event])
  150. }.should change { Event.count }.by(1)
  151. end
  152. it "handles array of exact comparisons" do
  153. @event.payload['foo']['bar']['baz'] = "hello world"
  154. @checker.options['rules'].first['type'] = "field==value"
  155. @checker.options['rules'].first['value'] = ["hello there", "hello universe"]
  156. lambda {
  157. @checker.receive([@event])
  158. }.should_not change { Event.count }
  159. @checker.options['rules'].first['value'] = ["hello world", "hello universe"]
  160. lambda {
  161. @checker.receive([@event])
  162. }.should change { Event.count }.by(1)
  163. end
  164. it "handles negated comparisons" do
  165. @event.payload['foo']['bar']['baz'] = "hello world"
  166. @checker.options['rules'].first['type'] = "field!=value"
  167. @checker.options['rules'].first['value'] = "hello world"
  168. lambda {
  169. @checker.receive([@event])
  170. }.should_not change { Event.count }
  171. @checker.options['rules'].first['value'] = "hello there"
  172. lambda {
  173. @checker.receive([@event])
  174. }.should change { Event.count }.by(1)
  175. end
  176. it "handles array of negated comparisons" do
  177. @event.payload['foo']['bar']['baz'] = "hello world"
  178. @checker.options['rules'].first['type'] = "field!=value"
  179. @checker.options['rules'].first['value'] = ["hello world", "hello world"]
  180. lambda {
  181. @checker.receive([@event])
  182. }.should_not change { Event.count }
  183. @checker.options['rules'].first['value'] = ["hello there", "hello world"]
  184. lambda {
  185. @checker.receive([@event])
  186. }.should change { Event.count }.by(1)
  187. end
  188. it "does fine without dots in the path" do
  189. @event.payload = { 'hello' => "world" }
  190. @checker.options['rules'].first['type'] = "field==value"
  191. @checker.options['rules'].first['path'] = "hello"
  192. @checker.options['rules'].first['value'] = "world"
  193. lambda {
  194. @checker.receive([@event])
  195. }.should change { Event.count }.by(1)
  196. @checker.options['rules'].first['path'] = "foo"
  197. lambda {
  198. @checker.receive([@event])
  199. }.should_not change { Event.count }
  200. @checker.options['rules'].first['value'] = "hi"
  201. lambda {
  202. @checker.receive([@event])
  203. }.should_not change { Event.count }
  204. end
  205. it "handles multiple events" do
  206. event2 = Event.new
  207. event2.agent = agents(:bob_weather_agent)
  208. event2.payload = { 'foo' => { 'bar' => { 'baz' => "a2b" }}}
  209. event3 = Event.new
  210. event3.agent = agents(:bob_weather_agent)
  211. event3.payload = { 'foo' => { 'bar' => { 'baz' => "a222b" }}}
  212. lambda {
  213. @checker.receive([@event, event2, event3])
  214. }.should change { Event.count }.by(2)
  215. end
  216. it "handles ANDing rules together" do
  217. @checker.options['rules'] << {
  218. 'type' => "field>=value",
  219. 'value' => "4",
  220. 'path' => "foo.bing"
  221. }
  222. @event.payload['foo']["bing"] = "5"
  223. lambda {
  224. @checker.receive([@event])
  225. }.should change { Event.count }.by(1)
  226. @checker.options['rules'].last['value'] = 6
  227. lambda {
  228. @checker.receive([@event])
  229. }.should_not change { Event.count }
  230. end
  231. end
  232. end