diff --git a/test/unit/plugins/guests/darwin/cap/mount_vmware_shared_folder_test.rb b/test/unit/plugins/guests/darwin/cap/mount_vmware_shared_folder_test.rb index 71dfbd829..6261c4f05 100644 --- a/test/unit/plugins/guests/darwin/cap/mount_vmware_shared_folder_test.rb +++ b/test/unit/plugins/guests/darwin/cap/mount_vmware_shared_folder_test.rb @@ -39,10 +39,6 @@ describe "VagrantPlugins::GuestDarwin::Cap::MountVmwareSharedFolder" do expect(communicator).to receive(:test).with(/synthetic\.conf/) end - it "should register an action hook" do - expect(VagrantPlugins::GuestDarwin::Plugin).to receive(:action_hook).with(:apfs_firmlinks, :after_synced_folders) - end - context "with guest path within existing directory" do let(:guestpath) { "/Users/vagrant/workspace" } @@ -77,10 +73,6 @@ describe "VagrantPlugins::GuestDarwin::Cap::MountVmwareSharedFolder" do expect(communicator).to receive(:sudo).with(%r{ln -s .+/System/Volumes/Data.+}) end - it "should register an action hook" do - expect(VagrantPlugins::GuestDarwin::Plugin).to receive(:action_hook).with(:apfs_firmlinks, :after_synced_folders) - end - context "when firmlink is provided by the system" do before { expect(described_class).to receive(:system_firmlink?).and_return(true) } diff --git a/test/unit/vagrant/action/warden_test.rb b/test/unit/vagrant/action/warden_test.rb index d119f871a..439dead01 100644 --- a/test/unit/vagrant/action/warden_test.rb +++ b/test/unit/vagrant/action/warden_test.rb @@ -7,6 +7,7 @@ describe Vagrant::Action::Warden do end def call(env) + env[:data] << 1 if env[:data] @app.call(env) end @@ -21,6 +22,7 @@ describe Vagrant::Action::Warden do end def call(env) + env[:data] << 2 if env[:data] @app.call(env) end @@ -90,35 +92,146 @@ describe Vagrant::Action::Warden do expect(data.key?(:recover)).not_to be end - context "when hook is defined" do - let(:hook) { double("hook") } + it "does not do a recovery sequence if NoMemoryError is raised" do + error_proc = Proc.new { raise NoMemoryError } - before do - data[:hook] = hook - allow(hook).to receive(:call) + instance = described_class.new([ExitAction, error_proc], data) + + # The SystemExit should come through + expect { instance.call(data) }.to raise_error(NoMemoryError) + + # The recover should not have been called + expect(data.key?(:recover)).not_to be + end + + describe "dynamic action hooks" do + let(:data) { {data: []} } + let(:hook_action_name) { :action_two } + + let(:plugin) do + h_name = hook_action_name + @plugin ||= Class.new(Vagrant.plugin("2")) do + name "Test Plugin" + action_hook(:before_test, h_name) do |hook| + hook.prepend(proc{ |env| env[:data] << :first }) + end + end end - it "should receive a before hook call" do - expect(hook).to receive(:call).with(:before_action_one) - described_class.new([ActionOne], data).call(data) + before { plugin } + + after do + Vagrant.plugin("2").manager.unregister(@plugin) if @plugin + @plugin = nil end - it "should receive an after hook call" do - expect(hook).to receive(:call).with(:after_action_one) - described_class.new([ActionOne], data).call(data) + it "should call hook before running action" do + instance = described_class.new([ActionTwo], data) + instance.call(data) + expect(data[:data].first).to eq(:first) + expect(data[:data].last).to eq(2) end - it "should not receive any hook calls for proc instances" do - expect(hook).not_to receive(:call) - described_class.new([proc{|*_| :testing }], data).call(data) + context "when hook is appending to action" do + let(:plugin) do + @plugin ||= Class.new(Vagrant.plugin("2")) do + name "Test Plugin" + action_hook(:before_test, :action_two) do |hook| + hook.append(proc{ |env| env[:data] << :first }) + end + end + end + + it "should call hook after action when action is nested" do + instance = described_class.new([described_class.new([ActionTwo], data), ActionOne], data) + instance.call(data) + expect(data[:data][0]).to eq(2) + expect(data[:data][1]).to eq(:first) + expect(data[:data][2]).to eq(1) + end end - it "should receive before and after calls for each class" do - expect(hook).to receive(:call).with(:before_action_one) - expect(hook).to receive(:call).with(:after_action_one) - expect(hook).to receive(:call).with(:before_action_two) - expect(hook).to receive(:call).with(:after_action_two) - described_class.new([ActionOne, proc{|*_| :testing }, ActionTwo], data).call(data) + context "when hook uses class name" do + let(:hook_action_name) { "ActionTwo" } + + it "should execute the hook" do + instance = described_class.new([ActionTwo], data) + instance.call(data) + expect(data[:data]).to include(:first) + end + end + + context "when action includes a namespace" do + module Vagrant + module Test + class ActionTest + def initialize(app, env) + @app = app + end + + def call(env) + env[:data] << :test if env[:data] + @app.call(env) + end + end + end + end + + let(:instance) { described_class.new([Vagrant::Test::ActionTest], data) } + + context "when hook uses short snake case name" do + let(:hook_action_name) { :action_test } + + it "should execute the hook" do + instance.call(data) + expect(data[:data]).to include(:first) + end + end + + context "when hook uses partial snake case name" do + let(:hook_action_name) { :test_action_test } + + it "should execute the hook" do + instance.call(data) + expect(data[:data]).to include(:first) + end + end + + context "when hook uses full snake case name" do + let(:hook_action_name) { :vagrant_test_action_test } + + it "should execute the hook" do + instance.call(data) + expect(data[:data]).to include(:first) + end + end + + context "when hook uses short class name" do + let(:hook_action_name) { "ActionTest" } + + it "should execute the hook" do + instance.call(data) + expect(data[:data]).to include(:first) + end + end + + context "when hook uses partial namespace class name" do + let(:hook_action_name) { "Test::ActionTest" } + + it "should execute the hook" do + instance.call(data) + expect(data[:data]).to include(:first) + end + end + + context "when hook uses full namespace class name" do + let(:hook_action_name) { "Vagrant::Test::ActionTest" } + + it "should execute the hook" do + instance.call(data) + expect(data[:data]).to include(:first) + end + end end end end diff --git a/test/unit/vagrant/plugin/v2/manager_test.rb b/test/unit/vagrant/plugin/v2/manager_test.rb index 3ddbf00e9..c145b4b28 100644 --- a/test/unit/vagrant/plugin/v2/manager_test.rb +++ b/test/unit/vagrant/plugin/v2/manager_test.rb @@ -11,6 +11,122 @@ describe Vagrant::Plugin::V2::Manager do p end + describe "#generate_hook_keys" do + it "should return array with one value" do + expect(subject.generate_hook_keys(:test_value)).to eq(["test_value"]) + end + + it "should return array with two values when key is camel cased" do + result = subject.generate_hook_keys("TestValue") + expect(result.size).to eq(2) + expect(result).to include("TestValue") + expect(result).to include("test_value") + end + + it "should handle class/module value" do + result = subject.generate_hook_keys(Vagrant) + expect(result.size).to eq(2) + expect(result).to include("Vagrant") + expect(result).to include("vagrant") + end + + it "should handle namespaced value" do + result = subject.generate_hook_keys(Vagrant::Plugin) + expect(result.size).to eq(4) + expect(result).to include("Vagrant::Plugin") + expect(result).to include("Plugin") + expect(result).to include("vagrant_plugin") + expect(result).to include("plugin") + end + end + + describe "#find_action_hooks" do + let(:hook_name) { "Vagrant::Plugin" } + + before do + h_name = hook_name + pA = plugin do |p| + p.action_hook(:test, h_name) { "hook_called" } + end + subject.register(pA) + end + + it "should find hook with full namespace" do + hooks = subject.find_action_hooks(Vagrant::Plugin) + expect(hooks).not_to be_empty + expect(hooks.first.call).to eq("hook_called") + end + + it "should not find hook with short class name" do + hooks = subject.find_action_hooks("Plugin") + expect(hooks).to be_empty + end + + it "should not find hook with full snake cased name" do + hooks = subject.find_action_hooks(:vagrant_plugin) + expect(hooks).to be_empty + end + + it "should not find hook with short snake cased name" do + hooks = subject.find_action_hooks("plugin") + expect(hooks).to be_empty + end + + context "when hook uses full snake cased name" do + let(:hook_name) { :vagrant_plugin } + + it "should find hook with full namespace" do + hooks = subject.find_action_hooks(Vagrant::Plugin) + expect(hooks).not_to be_empty + expect(hooks.first.call).to eq("hook_called") + end + + it "should find hook with full snake cased name" do + hooks = subject.find_action_hooks(:vagrant_plugin) + expect(hooks).not_to be_empty + expect(hooks.first.call).to eq("hook_called") + end + + it "should not find hook with short class name" do + hooks = subject.find_action_hooks("Plugin") + expect(hooks).to be_empty + end + + it "should not find hook with short snake cased name" do + hooks = subject.find_action_hooks("plugin") + expect(hooks).to be_empty + end + end + + context "when hook uses short snake cased name" do + let(:hook_name) { :plugin } + + it "should find hook with full namespace" do + hooks = subject.find_action_hooks(Vagrant::Plugin) + expect(hooks).not_to be_empty + expect(hooks.first.call).to eq("hook_called") + end + + it "should find hook with short class name" do + hooks = subject.find_action_hooks("Plugin") + expect(hooks).not_to be_empty + expect(hooks.first.call).to eq("hook_called") + end + + it "should find hook with short snake cased name" do + hooks = subject.find_action_hooks("plugin") + expect(hooks).not_to be_empty + expect(hooks.first.call).to eq("hook_called") + end + + it "should not find hook with full snake cased name" do + hooks = subject.find_action_hooks(:vagrant_plugin) + expect(hooks).to be_empty + end + end + + end + describe "#action_hooks" do it "should contain globally registered hooks" do pA = plugin do |p|