Files
vagrant-libvirt/spec/unit/action/shutdown_domain_spec.rb
Darragh Bailey df55c78010 Reorder qemu agent usage for use with sessions (#1396)
Adjust the order of checks around use of qemu sessions to allow use of
the agent as a priority when enabled, which should remove the need to
retrieve the address from the system connection when enabled.

Additionally adjust the call to the agent to ensure it uses the default
connection to retrieve the correct domain, rather than forcing the
system connection, which will fail to find the domain if it was created
via a user session.

Add tests that validate most of this behaviour, as well as resulting in
some minor fixes around downcasing the mac address for comparisons, and
also using instance mocks with rspec instead of pure doubles to help
catch false positives where mocks are allowing calls that done exist.

Related: #1342
2021-11-08 11:31:04 +00:00

161 lines
5.0 KiB
Ruby

require 'spec_helper'
require 'support/sharedcontext'
require 'support/libvirt_context'
require 'vagrant-libvirt/action/shutdown_domain'
describe VagrantPlugins::ProviderLibvirt::Action::StartShutdownTimer do
subject { described_class.new(app, env) }
include_context 'unit'
describe '#call' do
it 'should set shutdown_start_time' do
expect(env[:shutdown_start_time]).to eq(nil)
expect(subject.call(env)).to eq(nil)
expect(env[:shutdown_start_time]).to_not eq(nil)
end
end
end
describe VagrantPlugins::ProviderLibvirt::Action::ShutdownDomain do
subject { described_class.new(app, env, target_state, current_state) }
include_context 'unit'
include_context 'libvirt'
let(:driver) { double('driver') }
let(:libvirt_domain) { double('libvirt_domain') }
let(:servers) { double('servers') }
let(:current_state) { :running }
let(:target_state) { :shutoff }
before do
allow(machine.provider).to receive('driver').and_return(driver)
allow(driver).to receive(:created?).and_return(true)
allow(driver).to receive(:connection).and_return(connection)
end
describe '#call' do
before do
allow(connection).to receive(:servers).and_return(servers)
allow(servers).to receive(:get).and_return(domain)
allow(ui).to receive(:info).with('Attempting direct shutdown of domain...')
allow(env).to receive(:[]).and_call_original
allow(env).to receive(:[]).with(:shutdown_start_time).and_return(Time.now)
end
context "when state is shutoff" do
before do
allow(driver).to receive(:state).and_return(:shutoff)
end
it "should not shutdown" do
expect(domain).not_to receive(:poweroff)
subject.call(env)
end
it "should not print shutdown message" do
expect(ui).not_to receive(:info)
subject.call(env)
end
it "should provide a true result" do
subject.call(env)
expect(env[:result]).to be_truthy
end
end
context "when state is running" do
before do
allow(driver).to receive(:state).and_return(:running)
end
it "should shutdown" do
expect(domain).to receive(:wait_for)
expect(domain).to receive(:shutdown)
subject.call(env)
end
it "should print shutdown message" do
expect(domain).to receive(:wait_for)
expect(domain).to receive(:shutdown)
expect(ui).to receive(:info).with('Attempting direct shutdown of domain...')
subject.call(env)
end
context "when final state is not shutoff" do
before do
expect(driver).to receive(:state).and_return(:running).exactly(3).times
expect(domain).to receive(:wait_for)
expect(domain).to receive(:shutdown)
end
it "should provide a false result" do
subject.call(env)
expect(env[:result]).to be_falsey
end
end
context "when final state is shutoff" do
before do
expect(driver).to receive(:state).and_return(:running).exactly(2).times
expect(driver).to receive(:state).and_return(:shutoff).exactly(1).times
expect(domain).to receive(:wait_for)
expect(domain).to receive(:shutdown)
end
it "should provide a true result" do
subject.call(env)
expect(env[:result]).to be_truthy
end
end
context "when timeout exceeded" do
before do
expect(machine).to receive_message_chain('config.vm.graceful_halt_timeout').and_return(1)
expect(Time).to receive(:now).and_return(env[:shutdown_start_time] + 2)
expect(driver).to receive(:state).and_return(:running).exactly(1).times
expect(domain).to_not receive(:wait_for)
expect(domain).to_not receive(:shutdown)
end
it "should provide a false result" do
subject.call(env)
expect(env[:result]).to be_falsey
end
end
context "when timeout not exceeded" do
before do
expect(machine).to receive_message_chain('config.vm.graceful_halt_timeout').and_return(2)
expect(Time).to receive(:now).and_return(env[:shutdown_start_time] + 1.5)
expect(driver).to receive(:state).and_return(:running).exactly(3).times
expect(domain).to receive(:wait_for) do |time|
expect(time).to be < 1
expect(time).to be > 0
end
expect(domain).to receive(:shutdown)
end
it "should wait for the reduced time" do
subject.call(env)
expect(env[:result]).to be_falsey
end
end
end
context "when required action not run" do
before do
expect(env).to receive(:[]).with(:shutdown_start_time).and_call_original
end
it "should raise an exception" do
expect { subject.call(env) }.to raise_error(
VagrantPlugins::ProviderLibvirt::Errors::CallChainError,
/Invalid action chain, must ensure that '.*ShutdownTimer' is called prior to calling '.*ShutdownDomain'/
)
end
end
end
end