From daad5c708692c794dd65565ca5003cf5b518a392 Mon Sep 17 00:00:00 2001 From: Glenn Sarti Date: Fri, 10 Feb 2017 13:18:13 -0800 Subject: [PATCH] (POOLER-73) Add spec tests for check_pool Add spec tests for check_pool Previously the check_pool method would execute the loop indefinitely as it did not have a terminating condition. This made it impossible to test. This commit modifies the check_pool method so that it can take a maxloop and delay parameter so that it can be tested. --- lib/vmpooler/pool_manager.rb | 10 ++- spec/unit/pool_manager_spec.rb | 108 +++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 2 deletions(-) diff --git a/lib/vmpooler/pool_manager.rb b/lib/vmpooler/pool_manager.rb index f3280ab..2892adc 100644 --- a/lib/vmpooler/pool_manager.rb +++ b/lib/vmpooler/pool_manager.rb @@ -546,15 +546,21 @@ module Vmpooler finish end - def check_pool(pool) + def check_pool(pool,maxloop = 0, loop_delay = 5) $logger.log('d', "[*] [#{pool['name']}] starting worker thread") $vsphere[pool['name']] ||= Vmpooler::VsphereHelper.new $config, $metrics $threads[pool['name']] = Thread.new do + loop_count = 1 loop do _check_pool(pool, $vsphere[pool['name']]) - sleep(5) + sleep(loop_delay) + + unless maxloop.zero? + break if loop_count >= maxloop + loop_count = loop_count + 1 + end end end end diff --git a/spec/unit/pool_manager_spec.rb b/spec/unit/pool_manager_spec.rb index d6941a0..4354641 100644 --- a/spec/unit/pool_manager_spec.rb +++ b/spec/unit/pool_manager_spec.rb @@ -1129,6 +1129,114 @@ EOT end end + describe "#check_pool" do + let(:threads) {{}} + let(:vsphere) {{}} + + let(:config) { + YAML.load(<<-EOT +--- +:pools: + - name: #{pool} +EOT + ) + } + + let(:thread) { double('thread') } + let(:pool_object) { config[:pools][0] } + + before do + expect(subject).not_to be_nil + expect(Thread).to receive(:new).and_yield + end + + context 'on startup' do + before(:each) do + # Note the Vmpooler::VsphereHelper is not mocked + allow(subject).to receive(:_check_pool) + expect(logger).to receive(:log).with('d', "[*] [#{pool}] starting worker thread") + end + + after(:each) do + # Reset the global variable - Note this is a code smell + $threads = nil + $vsphere = nil + end + + it 'should log a message the worker thread is starting' do + subject.check_pool(pool_object,1,0) + end + + it 'should populate the vsphere global variable' do + subject.check_pool(pool_object,1,0) + + expect($vsphere[pool]).to_not be_nil + end + + it 'should populate the threads global variable' do + subject.check_pool(pool_object,1,0) + + # Unable to test for nil as the Thread is mocked + expect($threads.keys.include?(pool)) + end + end + + context 'delays between loops' do + let(:maxloop) { 2 } + let(:loop_delay) { 1 } + # Note a maxloop of zero can not be tested as it never terminates + + before(:each) do + allow(logger).to receive(:log) + # Note the Vmpooler::VsphereHelper is not mocked + allow(subject).to receive(:_check_pool) + end + + after(:each) do + # Reset the global variable - Note this is a code smell + $threads = nil + $vsphere = nil + end + + it 'when a non-default loop delay is specified' do + start_time = Time.now + subject.check_pool(pool_object,maxloop,loop_delay) + finish_time = Time.now + + # Use a generous delta to take into account various CPU load etc. + expect(finish_time - start_time).to be_within(0.75).of(maxloop * loop_delay) + end + end + + context 'loops specified number of times (5)' do + let(:maxloop) { 5 } + # Note a maxloop of zero can not be tested as it never terminates + before(:each) do + allow(logger).to receive(:log) + # Note the Vmpooler::VsphereHelper is not mocked + allow(subject).to receive(:_check_pool) + end + + after(:each) do + # Reset the global variable - Note this is a code smell + $threads = nil + $vsphere = nil + end + + it 'should run startup tasks only once' do + expect(logger).to receive(:log).with('d', "[*] [#{pool}] starting worker thread") + + subject.check_pool(pool_object,maxloop,0) + end + + it 'should run per thread tasks 5 times' do + expect(subject).to receive(:_check_pool).exactly(maxloop).times + + subject.check_pool(pool_object,maxloop,0) + end + end + end + describe '#_check_pool' do let(:pool_helper) { double('pool') } let(:vsphere) { {pool => pool_helper} }