spec/inputs/snmp_spec.rb in logstash-input-snmp-1.2.7 vs spec/inputs/snmp_spec.rb in logstash-input-snmp-1.2.8

- old
+ new

@@ -169,7 +169,97 @@ event = input(config) { |_, queue| queue.pop } expect(event.get("host")).to eq("udp:127.0.0.1/161,public") end end + + context "StoppableIntervalRunner" do + let(:stop_holder) { Struct.new(:value).new(false) } + + before(:each) do + allow(plugin).to receive(:stop?) { stop_holder.value } + end + + let(:plugin) do + double("Plugin").tap do |dbl| + allow(dbl).to receive(:logger).and_return(double("Logger").as_null_object) + allow(dbl).to receive(:stop?) { stop_holder.value } + end + end + + subject(:interval_runner) { LogStash::Inputs::Snmp::StoppableIntervalRunner.new(plugin) } + + context "#every" do + context "when the plugin is stopped" do + let(:interval_seconds) { 2 } + it 'does not yield the block' do + stop_holder.value = true + expect { |yielder| interval_runner.every(interval_seconds, &yielder) }.to_not yield_control + end + end + + context "when the yield takes shorter than the interval" do + let(:duration_seconds) { 1 } + let(:interval_seconds) { 2 } + + it 'sleeps off the remainder' do + allow(interval_runner).to receive(:sleep).and_call_original + + interval_runner.every(interval_seconds) do + Kernel::sleep(duration_seconds) # non-stoppable + stop_holder.value = true # prevent re-runs + end + + expect(interval_runner).to have_received(:sleep).with(a_value_within(0.1).of(1)) + end + end + + context "when the yield takes longer than the interval" do + let(:duration_seconds) { 2 } + let(:interval_seconds) { 1 } + + it 'logs a warning to the plugin' do + allow(interval_runner).to receive(:sleep).and_call_original + + interval_runner.every(interval_seconds) do + Kernel::sleep(duration_seconds) # non-stoppable + stop_holder.value = true # prevent re-runs + end + + expect(interval_runner).to_not have_received(:sleep) + + expect(plugin.logger).to have_received(:warn).with(a_string_including("took longer"), a_hash_including(:interval_seconds => interval_seconds, :duration_seconds => a_value_within(0.1).of(duration_seconds))) + end + end + + it 'runs regularly until the plugin is stopped' do + timestamps = [] + + thread = Thread.new do + interval_runner.every(1) do + timestamps << Time.now + Kernel::sleep(Random::rand(0.8)) + end + end + + Kernel::sleep(5) + expect(thread).to be_alive + + stop_holder.value = true + Kernel::sleep(1) + + aggregate_failures do + expect(thread).to_not be_alive + expect(timestamps.count).to be_within(1).of(5) + + timestamps.each_cons(2) do |previous, current| + # ensure each start time is very close to 1s after the previous. + expect(current - previous).to be_within(0.05).of(1) + end + + thread.kill if thread.alive? + end + end + end + end end