Nenhuma Descrição http://j1x-huginn.herokuapp.com

trigger_agent_spec.rb 10KB

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