Backfilled unit tests for Windows guest support

- Fixed typo in helper test
- Removed extraneous machine.config prefix from Windows guest config validation
- Added WinRM communicator unit tests
- Added Windows guest capability unit tests
This commit is contained in:
Shawn Neal 2014-04-22 11:03:37 -07:00
parent a47b85c8c4
commit 929e41aa5c
9 changed files with 395 additions and 7 deletions

View File

@ -14,17 +14,16 @@ module VagrantPlugins
def validate(machine)
errors = []
errors << "windows.halt_timeout cannot be nil." if machine.config.windows.halt_timeout.nil?
errors << "windows.halt_check_interval cannot be nil." if machine.config.windows.halt_check_interval.nil?
errors << "windows.set_work_network cannot be nil." if machine.config.windows.set_work_network.nil?
errors << "windows.halt_timeout cannot be nil." if @halt_timeout.nil?
errors << "windows.halt_check_interval cannot be nil." if @halt_check_interval.nil?
errors << "windows.set_work_network cannot be nil." if @set_work_network.nil?
{ "Windows Guest" => errors }
end
def finalize!
@halt_timeout = 30 if @halt_timeout == UNSET_VALUE
@halt_check_interval = 1 if @halt_check_interval == UNSET_VALUE
@halt_timeout = 30 if @halt_timeout == UNSET_VALUE
@halt_check_interval = 1 if @halt_check_interval == UNSET_VALUE
@set_work_network = false if @set_work_network == UNSET_VALUE
end
end

View File

@ -0,0 +1,92 @@
require File.expand_path("../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/communicators/winrm/communicator")
describe VagrantPlugins::CommunicatorWinRM::Communicator do
include_context "unit"
let(:winrm) { double("winrm", :timeout => 1) }
let(:config) { double("config", :winrm => winrm) }
let(:machine) { double("machine", :config => config) }
let(:shell) { double("shell") }
subject do
comm = described_class.new(machine)
allow(comm).to receive(:create_shell).and_return(shell)
comm
end
describe ".ready?" do
it "returns true if hostname command executes without error" do
expect(shell).to receive(:powershell).with("hostname").and_return({ :exitcode => 0 })
expect(subject.ready?).to be_true
end
it "returns false if hostname command fails to execute without error" do
expect(shell).to receive(:powershell).with("hostname").and_raise(Vagrant::Errors::VagrantError)
expect(subject.ready?).to be_false
end
it "raises timeout error when hostname command takes longer then winrm timeout" do
expect(shell).to receive(:powershell).with("hostname") do
sleep 2 # winrm.timeout = 1
end
expect { subject.ready? }.to raise_error(Timeout::Error)
end
end
describe ".execute" do
it "defaults to running in powershell" do
expect(shell).to receive(:powershell).with(kind_of(String)).and_return({ :exitcode => 0 })
expect(subject.execute("dir")).to eq(0)
end
it "can use cmd shell" do
expect(shell).to receive(:cmd).with(kind_of(String)).and_return({ :exitcode => 0 })
expect(subject.execute("dir", { :shell => :cmd })).to eq(0)
end
it "raises error when error_check is true and exit code is non-zero" do
expect(shell).to receive(:powershell).with(kind_of(String)).and_return({ :exitcode => 1 })
expect { subject.execute("dir") }.to raise_error(
VagrantPlugins::CommunicatorWinRM::Errors::ExecutionError)
end
it "does not raise error when error_check is false and exit code is non-zero" do
expect(shell).to receive(:powershell).with(kind_of(String)).and_return({ :exitcode => 1 })
expect(subject.execute("dir", { :error_check => false })).to eq(1)
end
end
describe ".test" do
it "returns true when exit code is zero" do
expect(shell).to receive(:powershell).with(kind_of(String)).and_return({ :exitcode => 0 })
expect(subject.test("test -d c:/windows")).to be_true
end
it "returns false when exit code is non-zero" do
expect(shell).to receive(:powershell).with(kind_of(String)).and_return({ :exitcode => 1 })
expect(subject.test("test -d /tmp/foobar")).to be_false
end
it "returns false when command is testing for linux OS" do
expect(subject.test("uname -s | grep Debian")).to be_false
end
end
describe ".upload" do
it "calls upload on shell" do
expect(shell).to receive(:upload).with("from", "to")
subject.upload("from", "to")
end
end
describe ".download" do
it "calls download on shell" do
expect(shell).to receive(:download).with("from", "to")
subject.download("from", "to")
end
end
end

View File

@ -31,7 +31,7 @@ describe VagrantPlugins::CommunicatorWinRM::Helper do
expect(subject.winrm_address(machine)).to eq("bar")
end
it "raisee an exception if it can't detect a host" do
it "raise an exception if it can't detect a host" do
machine.stub(ssh_info: nil)
expect { subject.winrm_address(machine) }.
to raise_error(VagrantPlugins::CommunicatorWinRM::Errors::WinRMNotReady)

View File

@ -0,0 +1,58 @@
require File.expand_path("../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/communicators/winrm/shell")
describe VagrantPlugins::CommunicatorWinRM::WinRMShell do
include_context "unit"
let(:session) { double("winrm_session") }
subject do
comm = described_class.new('localhost', 'username', 'password')
allow(comm).to receive(:new_session).and_return(session)
comm
end
describe ".powershell" do
it "should call winrm powershell" do
expect(session).to receive(:powershell).with("dir").and_return({ :exitcode => 0 })
expect(subject.powershell("dir")[:exitcode]).to eq(0)
end
it "should raise auth error when exception message contains 401" do
expect(session).to receive(:powershell).with("dir").and_raise(
StandardError.new("Oh no! a 401 SOAP error!"))
expect { subject.powershell("dir") }.to raise_error(
VagrantPlugins::CommunicatorWinRM::Errors::AuthError)
end
it "should raise an execution error when an exception occurs" do
expect(session).to receive(:powershell).with("dir").and_raise(
StandardError.new("Oh no! a 500 SOAP error!"))
expect { subject.powershell("dir") }.to raise_error(
VagrantPlugins::CommunicatorWinRM::Errors::ExecutionError)
end
end
describe ".cmd" do
it "should call winrm cmd" do
expect(session).to receive(:cmd).with("dir").and_return({ :exitcode => 0 })
expect(subject.cmd("dir")[:exitcode]).to eq(0)
end
end
describe ".endpoint" do
it "should create winrm endpoint address" do
expect(subject.send(:endpoint)).to eq("http://localhost:5985/wsman")
end
end
describe ".endpoint_options" do
it "should create endpoint options" do
expect(subject.send(:endpoint_options)).to eq(
{ :user => "username", :pass => "password", :host => "localhost", :port => 5985,
:operation_timeout => 60, :basic_auth_only => true })
end
end
end

View File

@ -0,0 +1,29 @@
require File.expand_path("../../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/guests/windows/cap/change_host_name")
describe "VagrantPlugins::GuestWindows::Cap::ChangeHostName" do
let(:described_class) do
VagrantPlugins::GuestWindows::Plugin.components.guest_capabilities[:windows].get(:change_host_name)
end
let(:machine) { double("machine") }
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
let(:old_hostname) {'oldhostname.olddomain.tld' }
before do
allow(machine).to receive(:communicate).and_return(communicator)
end
after do
communicator.verify_expectations!
end
describe ".change_host_name" do
it "changes the hostname" do
communicator.expect_command('wmic computersystem where name="%COMPUTERNAME%" call rename name="newhostname.newdomain.tld"')
described_class.change_host_name(machine, 'newhostname.newdomain.tld')
end
end
end

View File

@ -0,0 +1,33 @@
require File.expand_path("../../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/guests/windows/cap/halt")
describe "VagrantPlugins::GuestWindows::Cap::Halt" do
let(:described_class) do
VagrantPlugins::GuestWindows::Plugin.components.guest_capabilities[:windows].get(:halt)
end
let(:machine) { double("machine") }
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
before do
allow(machine).to receive(:communicate).and_return(communicator)
end
after do
communicator.verify_expectations!
end
describe ".halt" do
it "cancels any existing scheduled shut down" do
communicator.expect_command("shutdown -a")
described_class.halt(machine)
end
it "shuts down immediately" do
communicator.expect_command('shutdown /s /t 1 /c "Vagrant Halt" /f /d p:4:1')
described_class.halt(machine)
end
end
end

View File

@ -0,0 +1,82 @@
require File.expand_path("../../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/guests/windows/cap/mount_shared_folder")
describe "VagrantPlugins::GuestWindows::Cap::MountSharedFolder" do
let(:machine) { double("machine") }
let(:communicator) { double(:execute) }
before do
allow(machine).to receive(:communicate).and_return(communicator)
allow(communicator).to receive(:execute)
end
describe "virtualbox" do
let(:described_class) do
VagrantPlugins::GuestWindows::Plugin.components.guest_capabilities[:windows].get(:mount_virtualbox_shared_folder)
end
describe ".mount_shared_folder" do
it "should call mount_volume script with correct args" do
expect(Vagrant::Util::TemplateRenderer).to receive(:render).with(
/.+scripts\/mount_volume.ps1/, options: {
mount_point: "guestpath",
share_name: "name",
vm_provider_unc_path: "\\\\vboxsrv\\name",
})
described_class.mount_virtualbox_shared_folder(machine, 'name', 'guestpath', {})
end
it "should replace invalid Windows share chars" do
expect(Vagrant::Util::TemplateRenderer).to receive(:render).with(
kind_of(String), options: {
mount_point: kind_of(String),
share_name: "invalid-windows_sharename",
vm_provider_unc_path: "\\\\vboxsrv\\invalid-windows_sharename",
})
described_class.mount_virtualbox_shared_folder(machine, "/invalid-windows/sharename", "guestpath", {})
end
end
end
describe "vmware" do
let(:described_class) do
VagrantPlugins::GuestWindows::Plugin.components.guest_capabilities[:windows].get(:mount_vmware_shared_folder)
end
describe ".mount_shared_folder" do
it "should call mount_volume script with correct args" do
expect(Vagrant::Util::TemplateRenderer).to receive(:render).with(
/.+scripts\/mount_volume.ps1/, options: {
mount_point: "guestpath",
share_name: "name",
vm_provider_unc_path: "\\\\vmware-host\\Shared Folders\\name",
})
described_class.mount_vmware_shared_folder(machine, 'name', 'guestpath', {})
end
end
end
describe "parallels" do
let(:described_class) do
VagrantPlugins::GuestWindows::Plugin.components.guest_capabilities[:windows].get(:mount_parallels_shared_folder)
end
describe ".mount_shared_folder" do
it "should call mount_volume script with correct args" do
expect(Vagrant::Util::TemplateRenderer).to receive(:render).with(
/.+scripts\/mount_volume.ps1/, options: {
mount_point: "guestpath",
share_name: "name",
vm_provider_unc_path: "\\\\psf\\name",
})
described_class.mount_parallels_shared_folder(machine, 'name', 'guestpath', {})
end
end
end
end

View File

@ -0,0 +1,54 @@
require File.expand_path("../../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/guests/windows/cap/reboot")
describe "VagrantPlugins::GuestWindows::Cap::Reboot" do
let(:described_class) do
VagrantPlugins::GuestWindows::Plugin.components.guest_capabilities[:windows].get(:wait_for_reboot)
end
let(:vm) { double("vm") }
let(:config) { double("config") }
let(:machine) { double("machine") }
let(:communicator) { double(:execute) }
before do
allow(machine).to receive(:communicate).and_return(communicator)
allow(machine).to receive(:config).and_return(config)
allow(config).to receive(:vm).and_return(vm)
end
describe "winrm communicator" do
before do
allow(vm).to receive(:communicator).and_return(:winrm)
end
describe ".wait_for_reboot" do
it "runs reboot detect script" do
expect(communicator).to receive(:execute) do |cmd|
expect(cmd).to include("SM_SHUTTINGDOWN")
end.and_return(0)
described_class.wait_for_reboot(machine)
end
end
end
describe "ssh communicator" do
before do
allow(vm).to receive(:communicator).and_return(:ssh)
end
describe ".wait_for_reboot" do
it "runs reboot detect script" do
expect(communicator).to_not receive(:execute)
described_class.wait_for_reboot(machine)
end
end
end
end

View File

@ -0,0 +1,41 @@
require File.expand_path("../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/guests/windows/config")
describe VagrantPlugins::GuestWindows::Config do
let(:machine) { double("machine") }
subject { described_class.new }
it "is valid by default" do
subject.finalize!
result = subject.validate(machine)
expect(result["Windows Guest"]).to be_empty
end
describe "default values" do
before { subject.finalize! }
its("halt_timeout") { should == 30 }
its("halt_check_interval") { should == 1 }
its("set_work_network") { should == false }
end
describe "attributes" do
[:halt_timeout, :halt_check_interval, :set_work_network].each do |attribute|
it "should not default #{attribute} if overridden" do
subject.send("#{attribute}=".to_sym, 10)
subject.finalize!
subject.send(attribute).should == 10
end
it "should return error #{attribute} if nil" do
subject.send("#{attribute}=".to_sym, nil)
subject.finalize!
result = subject.validate(machine)
expect(result["Windows Guest"]).to include("windows.#{attribute} cannot be nil.")
end
end
end
end