diff --git a/lib/vagrant/machine/remote.rb b/lib/vagrant/machine/remote.rb index f38c6d745..d52bcdb36 100644 --- a/lib/vagrant/machine/remote.rb +++ b/lib/vagrant/machine/remote.rb @@ -313,11 +313,16 @@ module Vagrant impl = :virtualbox sf = Vagrant::Plugin::Remote::SyncedFolder.new(client: f[:plugin]) # Set plugin, guestpath and hostpath from synced folder info - folders[impl] = {f[:folder][:destination] => f[:folder].merge({ + new_folder = {f[:folder][:destination] => f[:folder].merge({ plugin: sf, guestpath: f[:folder][:destination], hostpath: f[:folder][:source], })} + if folders[impl] + folders[impl].merge!(new_folder) + else + folders[impl] = new_folder + end end folders end diff --git a/test/unit/vagrant/machine/remote_test.rb b/test/unit/vagrant/machine/remote_test.rb new file mode 100644 index 000000000..79e3b39a1 --- /dev/null +++ b/test/unit/vagrant/machine/remote_test.rb @@ -0,0 +1,192 @@ +require File.expand_path("../../../base", __FILE__) + +describe Vagrant::Machine::Remote do + include_context "unit" + + let(:klass) { Class.new(Vagrant::Machine).tap { |c| c.prepend(described_class) }} + + # == Machine Setup + # + # This setup is all copied from Vagrant::Machine unit tests - the only + # difference is the above klass is used so we can prepend the remote stuff + + let(:name) { "foo" } + let(:provider) { new_provider_mock } + let(:provider_cls) do + obj = double("provider_cls") + allow(obj).to receive(:new).and_return(provider) + obj + end + let(:provider_config) { Object.new } + let(:provider_name) { :test } + let(:provider_options) { {} } + let(:base) { false } + let(:box) do + double("box").tap do |b| + allow(b).to receive(:name).and_return("foo") + allow(b).to receive(:provider).and_return(:dummy) + allow(b).to receive(:version).and_return("1.0") + end + end + + let(:config) { env.vagrantfile.config } + let(:data_dir) { Pathname.new(Dir.mktmpdir("vagrant-machine-data-dir")) } + let(:env) do + # We need to create a Vagrantfile so that this test environment + # has a proper root path + test_env.vagrantfile("") + + # Create the Vagrant::Environment instance + test_env.create_vagrant_env + end + + let(:test_env) { isolated_environment } + + let(:instance) { new_instance } + + after do + FileUtils.rm_rf(data_dir) if data_dir + end + + subject { instance } + + def new_provider_mock + double("provider").tap do |obj| + allow(obj).to receive(:_initialize) + .with(provider_name, anything).and_return(nil) + allow(obj).to receive(:machine_id_changed).and_return(nil) + allow(obj).to receive(:state).and_return(Vagrant::MachineState.new( + :created, "", "")) + end + end + + # Returns a new instance with the test data + def new_instance + klass.new(name, provider_name, provider_cls, provider_config, + provider_options, config, data_dir, box, + env, env.vagrantfile, base) + end + + # == Machine::Remote Setup + # + # Now we do the setup that's specific to the remote module. + let(:client) { double(:client) } + + + before do + allow(env).to receive(:get_target) { client } + allow(client).to receive(:box) { box } + allow(client).to receive(:data_dir) { data_dir } + end + + describe "#synced_folders" do + it "gets the synced_folders from the client" do + expect(client).to receive(:synced_folders) { [] } + subject.synced_folders + end + + it "returns a hash with synced_folders returned from the client" do + synced_folder_clients = [ + { + plugin: double("plugin"), + folder: { + disabled: false, + source: "/some/source", + destination: "/some/destination", + } + } + ] + allow(client).to receive(:synced_folders) { synced_folder_clients } + + output = subject.synced_folders + + expect(output).to match( + virtualbox: a_hash_including( + "/some/destination" => a_hash_including( + disabled: false, + guestpath: "/some/destination", + hostpath: "/some/source", + plugin: an_instance_of(Vagrant::Plugin::Remote::SyncedFolder), + ) + ) + ) + end + + it "works with multiple folders for a given impl" do + synced_folder_clients = [ + { + plugin: double("pluginone"), + folder: { + disabled: false, + source: "/one", + destination: "/first", + } + }, + { + plugin: double("plugintwo"), + folder: { + disabled: false, + source: "/two", + destination: "/second", + } + }, + ] + allow(client).to receive(:synced_folders) { synced_folder_clients } + + output = subject.synced_folders + + expect(output).to match( + virtualbox: a_hash_including( + "/first" => a_hash_including( + disabled: false, + guestpath: "/first", + hostpath: "/one", + plugin: an_instance_of(Vagrant::Plugin::Remote::SyncedFolder), + ), + "/second" => a_hash_including( + disabled: false, + guestpath: "/second", + hostpath: "/two", + plugin: an_instance_of(Vagrant::Plugin::Remote::SyncedFolder), + ), + ) + ) + end + + it "skips disabled folders" do + synced_folder_clients = [ + { + plugin: double("pluginone"), + folder: { + disabled: true, + source: "/notme", + destination: "/noway", + } + }, + { + plugin: double("plugintwo"), + folder: { + disabled: false, + source: "/yesme", + destination: "/pickme", + } + }, + ] + allow(client).to receive(:synced_folders) { synced_folder_clients } + + output = subject.synced_folders + + expect(output).to match( + virtualbox: a_hash_including( + "/pickme" => a_hash_including( + disabled: false, + guestpath: "/pickme", + hostpath: "/yesme", + plugin: an_instance_of(Vagrant::Plugin::Remote::SyncedFolder), + ), + ) + ) + expect(output[:virtualbox]).to_not have_key("/noway") + end + end +end