|
25 | 25 | "schedule" => default_schedule,
|
26 | 26 | "urls" => default_urls,
|
27 | 27 | "codec" => "json",
|
28 |
| - "metadata_target" => metadata_target |
| 28 | + "metadata_target" => metadata_target, |
| 29 | + "pool_max" => 3, "pool_max_per_route" => 1, 'keepalive' => false |
29 | 30 | }
|
30 | 31 | }
|
31 |
| - let(:klass) { LogStash::Inputs::HTTP_Poller } |
| 32 | + let(:opts) { default_opts } |
32 | 33 |
|
| 34 | + subject(:plugin) { described_class.new(opts) } |
33 | 35 |
|
34 | 36 | describe "instances" do
|
35 |
| - subject { klass.new(default_opts) } |
| 37 | + subject { described_class.new(default_opts) } |
36 | 38 |
|
37 |
| - before do |
38 |
| - subject.register |
39 |
| - end |
| 39 | + before { subject.register } |
| 40 | + after { subject.stop } |
40 | 41 |
|
41 | 42 | describe "#run" do
|
42 | 43 | it "should setup a scheduler" do
|
|
189 | 190 | "metadata_target" => metadata_target
|
190 | 191 | }
|
191 | 192 | }
|
192 |
| - it "should run at the schedule" do |
193 |
| - instance = klass.new(opts) |
194 |
| - instance.register |
| 193 | + |
| 194 | + before do |
195 | 195 | Timecop.travel(Time.new(2000,1,1,0,0,0,'+00:00'))
|
196 | 196 | Timecop.scale(60)
|
197 |
| - queue = Queue.new |
198 |
| - runner = Thread.new do |
199 |
| - instance.run(queue) |
200 |
| - end |
201 |
| - sleep 3 |
202 |
| - instance.stop |
203 |
| - runner.kill |
204 |
| - runner.join |
205 |
| - expect(queue.size).to eq(2) |
| 197 | + end |
| 198 | + |
| 199 | + after do |
206 | 200 | Timecop.return
|
207 | 201 | end
|
| 202 | + |
| 203 | + it "should run at the schedule" do |
| 204 | + run_plugin_and_yield_queue(plugin, sleep: 3) do |queue| |
| 205 | + try(5) { expect(queue.size).to be >= 2 } |
| 206 | + end |
| 207 | + end |
208 | 208 | end
|
209 | 209 |
|
210 | 210 | context "given 'at' expression" do
|
|
216 | 216 | "metadata_target" => metadata_target
|
217 | 217 | }
|
218 | 218 | }
|
219 |
| - it "should run at the schedule" do |
220 |
| - instance = klass.new(opts) |
221 |
| - instance.register |
| 219 | + |
| 220 | + before do |
222 | 221 | Timecop.travel(Time.new(2000,1,1,0,0,0,'+00:00'))
|
223 |
| - Timecop.scale(60 * 5) |
224 |
| - queue = Queue.new |
225 |
| - runner = Thread.new do |
226 |
| - instance.run(queue) |
227 |
| - end |
228 |
| - sleep 2 |
229 |
| - instance.stop |
230 |
| - runner.kill |
231 |
| - runner.join |
232 |
| - expect(queue.size).to eq(1) |
| 222 | + Timecop.scale (60 * 5) / 2 |
| 223 | + end |
| 224 | + |
| 225 | + after do |
233 | 226 | Timecop.return
|
234 | 227 | end
|
| 228 | + |
| 229 | + it "should run at the schedule" do |
| 230 | + run_plugin_and_yield_queue(plugin, sleep: 2) do |queue| |
| 231 | + try(5) { expect(queue.size).to eq(1) } |
| 232 | + end |
| 233 | + end |
235 | 234 | end
|
236 | 235 |
|
237 | 236 | context "given 'every' expression" do
|
|
244 | 243 | }
|
245 | 244 | }
|
246 | 245 | it "should run at the schedule" do
|
247 |
| - instance = klass.new(opts) |
248 |
| - instance.register |
249 |
| - queue = Queue.new |
250 |
| - runner = Thread.new do |
251 |
| - instance.run(queue) |
| 246 | + run_plugin_and_yield_queue(plugin, sleep: 5) do |queue| |
| 247 | + #T 0123456 |
| 248 | + #events x x x x |
| 249 | + #expects 3 events at T=5 |
| 250 | + try(5) { expect(queue.size).to be_between(2, 3) } |
252 | 251 | end
|
253 |
| - #T 0123456 |
254 |
| - #events x x x x |
255 |
| - #expects 3 events at T=5 |
256 |
| - sleep 5 |
257 |
| - instance.stop |
258 |
| - runner.kill |
259 |
| - runner.join |
260 |
| - expect(queue.size).to be_between(2, 3) |
261 | 252 | end
|
262 | 253 | end
|
263 | 254 |
|
|
271 | 262 | }
|
272 | 263 | }
|
273 | 264 | it "should run at the schedule" do
|
274 |
| - instance = klass.new(opts) |
275 |
| - instance.register |
276 |
| - queue = Queue.new |
277 |
| - runner = Thread.new do |
278 |
| - instance.run(queue) |
| 265 | + run_plugin_and_yield_queue(plugin, sleep: 2.5) do |queue| |
| 266 | + try(5) { expect(queue.size).to eq(1) } |
279 | 267 | end
|
280 |
| - sleep 3 |
281 |
| - instance.stop |
282 |
| - runner.kill |
283 |
| - runner.join |
284 |
| - expect(queue.size).to eq(1) |
285 | 268 | end
|
286 | 269 | end
|
287 | 270 | end
|
288 | 271 |
|
| 272 | + def run_plugin_and_yield_queue(plugin, sleep: nil) |
| 273 | + plugin.register |
| 274 | + queue = Queue.new |
| 275 | + begin |
| 276 | + runner = Thread.new do |
| 277 | + plugin.run(queue) |
| 278 | + end |
| 279 | + sleep(sleep) if sleep |
| 280 | + yield(queue) |
| 281 | + ensure |
| 282 | + plugin.stop |
| 283 | + runner.join if runner |
| 284 | + end |
| 285 | + end |
| 286 | + |
289 | 287 | describe "events", :ecs_compatibility_support, :aggregate_failures do
|
290 | 288 | ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do |ecs_select|
|
291 | 289 | before do
|
|
339 | 337 | event # materialize the subject
|
340 | 338 | end
|
341 | 339 |
|
| 340 | + after { poller.stop } |
| 341 | + |
342 | 342 | it "should enqueue a message" do
|
343 | 343 | expect(event).to be_a(LogStash::Event)
|
344 | 344 | end
|
|
399 | 399 | let(:payload) { {"a" => 2, "hello" => ["a", "b", "c"]} }
|
400 | 400 | let(:response_body) { LogStash::Json.dump(payload) }
|
401 | 401 | let(:opts) { default_opts }
|
402 |
| - let(:instance) { |
403 |
| - klass.new(opts) |
404 |
| - } |
405 | 402 | let(:name) { default_name }
|
406 | 403 | let(:url) { default_url }
|
407 | 404 | let(:code) { 202 }
|
|
411 | 408 | }
|
412 | 409 |
|
413 | 410 | before do
|
414 |
| - instance.register |
| 411 | + plugin.register |
415 | 412 | u = url.is_a?(Hash) ? url["url"] : url # handle both complex specs and simple string URLs
|
416 |
| - instance.client.stub(u, |
| 413 | + plugin.client.stub(u, |
417 | 414 | :body => response_body,
|
418 | 415 | :code => code
|
419 | 416 | )
|
420 |
| - allow(instance).to receive(:decorate) |
421 |
| - instance.send(:run_once, queue) |
| 417 | + allow(plugin).to receive(:decorate) |
| 418 | + plugin.send(:run_once, queue) |
422 | 419 | end
|
423 | 420 |
|
424 | 421 | it "should have a matching message" do
|
425 | 422 | expect(event.to_hash).to include(payload)
|
426 | 423 | end
|
427 | 424 |
|
428 | 425 | it "should decorate the event" do
|
429 |
| - expect(instance).to have_received(:decorate).once |
| 426 | + expect(plugin).to have_received(:decorate).once |
430 | 427 | end
|
431 | 428 |
|
432 | 429 | include_examples("matching metadata")
|
433 | 430 |
|
434 | 431 | context "with an empty body" do
|
435 | 432 | let(:response_body) { "" }
|
436 | 433 | it "should return an empty event" do
|
437 |
| - instance.send(:run_once, queue) |
| 434 | + plugin.send(:run_once, queue) |
438 | 435 | headers_field = ecs_select[disabled: "[#{metadata_target}][response_headers]",
|
439 | 436 | v1: "[#{metadata_target}][input][http_poller][response][headers]"]
|
440 | 437 | expect(event.get("#{headers_field}[content-length]")).to eql("0")
|
|
449 | 446 | }
|
450 | 447 |
|
451 | 448 | it "should not have any metadata on the event" do
|
452 |
| - instance.send(:run_once, queue) |
| 449 | + plugin.send(:run_once, queue) |
453 | 450 | expect(event.get(metadata_target)).to be_nil
|
454 | 451 | end
|
455 | 452 | end
|
|
555 | 552 |
|
556 | 553 | describe "stopping" do
|
557 | 554 | let(:config) { default_opts }
|
558 |
| - it_behaves_like "an interruptible input plugin" |
| 555 | + it_behaves_like "an interruptible input plugin" do |
| 556 | + let(:allowed_lag) { 10 } # CI: wait till scheduler shuts down |
| 557 | + end |
559 | 558 | end
|
560 | 559 | end
|
0 commit comments