Unit tests for Vagrant::Action::Builder
This commit is contained in:
parent
9f498ccb06
commit
3cd262ed75
|
@ -23,14 +23,6 @@ module Vagrant
|
||||||
instance_eval(&block) if block_given?
|
instance_eval(&block) if block_given?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the current stack of middlewares. You probably won't
|
|
||||||
# need to use this directly, and it's recommended that you don't.
|
|
||||||
#
|
|
||||||
# @return [Array]
|
|
||||||
def stack
|
|
||||||
@stack ||= []
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns a mergeable version of the builder. If `use` is called with
|
# Returns a mergeable version of the builder. If `use` is called with
|
||||||
# the return value of this method, then the stack will merge, instead
|
# the return value of this method, then the stack will merge, instead
|
||||||
# of being treated as a separate single middleware.
|
# of being treated as a separate single middleware.
|
||||||
|
@ -75,9 +67,9 @@ module Vagrant
|
||||||
insert(index + 1, middleware, *args, &block)
|
insert(index + 1, middleware, *args, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Swaps out the given middlware object or index with the new
|
# Replaces the given middlware object or index with the new
|
||||||
# middleware.
|
# middleware.
|
||||||
def swap(index, middleware, *args, &block)
|
def replace(index, middleware, *args, &block)
|
||||||
if index.is_a?(Integer)
|
if index.is_a?(Integer)
|
||||||
delete(index)
|
delete(index)
|
||||||
insert(index, middleware, *args, &block)
|
insert(index, middleware, *args, &block)
|
||||||
|
@ -93,6 +85,13 @@ module Vagrant
|
||||||
stack.delete_at(index)
|
stack.delete_at(index)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Runs the builder stack with the given environment.
|
||||||
|
def call(env)
|
||||||
|
to_app(env).call(env)
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
# Returns the numeric index for the given middleware object.
|
# Returns the numeric index for the given middleware object.
|
||||||
#
|
#
|
||||||
# @param [Object] object The item to find the index for
|
# @param [Object] object The item to find the index for
|
||||||
|
@ -105,6 +104,14 @@ module Vagrant
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns the current stack of middlewares. You probably won't
|
||||||
|
# need to use this directly, and it's recommended that you don't.
|
||||||
|
#
|
||||||
|
# @return [Array]
|
||||||
|
def stack
|
||||||
|
@stack ||= []
|
||||||
|
end
|
||||||
|
|
||||||
# Converts the builder stack to a runnable action sequence.
|
# Converts the builder stack to a runnable action sequence.
|
||||||
#
|
#
|
||||||
# @param [Vagrant::Action::Environment] env The action environment
|
# @param [Vagrant::Action::Environment] env The action environment
|
||||||
|
@ -114,11 +121,6 @@ module Vagrant
|
||||||
# and predictable behavior upon exceptions.
|
# and predictable behavior upon exceptions.
|
||||||
Warden.new(stack.dup, env)
|
Warden.new(stack.dup, env)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Runs the builder stack with the given environment.
|
|
||||||
def call(env)
|
|
||||||
to_app(env).call(env)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,25 +7,6 @@ module Vagrant
|
||||||
# some helper methods for accessing the environment as well
|
# some helper methods for accessing the environment as well
|
||||||
# as being a hash, to store any additional options.
|
# as being a hash, to store any additional options.
|
||||||
class Environment < Util::HashWithIndifferentAccess
|
class Environment < Util::HashWithIndifferentAccess
|
||||||
def initialize
|
|
||||||
@interrupted = false
|
|
||||||
end
|
|
||||||
|
|
||||||
# Marks an environment as interrupted (by an outside signal or
|
|
||||||
# anything). This will trigger any middleware sequences using this
|
|
||||||
# environment to halt. This is automatically set by {Action} when
|
|
||||||
# a SIGINT is captured.
|
|
||||||
def interrupt!
|
|
||||||
@interrupted = true
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns a boolean denoting if environment has been interrupted
|
|
||||||
# with a SIGINT.
|
|
||||||
#
|
|
||||||
# @return [Bool]
|
|
||||||
def interrupted?
|
|
||||||
!!@interrupted
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,13 +34,13 @@ module Vagrant
|
||||||
# chain has been run.
|
# chain has been run.
|
||||||
ui = environment[:ui] if environment.has_key?(:ui)
|
ui = environment[:ui] if environment.has_key?(:ui)
|
||||||
int_callback = lambda do
|
int_callback = lambda do
|
||||||
if environment.interrupted?
|
if environment[:interrupted]
|
||||||
ui.error I18n.t("vagrant.actions.runner.exit_immediately") if ui
|
ui.error I18n.t("vagrant.actions.runner.exit_immediately") if ui
|
||||||
abort
|
abort
|
||||||
end
|
end
|
||||||
|
|
||||||
ui.warn I18n.t("vagrant.actions.runner.waiting_cleanup") if ui && !@@reported_interrupt
|
ui.warn I18n.t("vagrant.actions.runner.waiting_cleanup") if ui && !@@reported_interrupt
|
||||||
environment.interrupt!
|
environment[:interrupted] = true
|
||||||
@@reported_interrupt = true
|
@@reported_interrupt = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,11 @@ module Vagrant
|
||||||
begin
|
begin
|
||||||
# Call the next middleware in the sequence, appending to the stack
|
# Call the next middleware in the sequence, appending to the stack
|
||||||
# of "recoverable" middlewares in case something goes wrong!
|
# of "recoverable" middlewares in case something goes wrong!
|
||||||
raise Errors::VagrantInterrupt if env.interrupted?
|
raise Errors::VagrantInterrupt if env[:interrupted]
|
||||||
action = @actions.shift
|
action = @actions.shift
|
||||||
@logger.info("Calling action: #{action}")
|
@logger.info("Calling action: #{action}")
|
||||||
@stack.unshift(action).first.call(env)
|
@stack.unshift(action).first.call(env)
|
||||||
raise Errors::VagrantInterrupt if env.interrupted?
|
raise Errors::VagrantInterrupt if env[:interrupted]
|
||||||
rescue SystemExit
|
rescue SystemExit
|
||||||
# This means that an "exit" or "abort" was called. In these cases,
|
# This means that an "exit" or "abort" was called. In these cases,
|
||||||
# we just exit immediately.
|
# we just exit immediately.
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
require File.expand_path("../../../base", __FILE__)
|
||||||
|
|
||||||
|
describe Vagrant::Action::Builder do
|
||||||
|
let(:data) { { :data => [] } }
|
||||||
|
let(:instance) { described_class.new }
|
||||||
|
|
||||||
|
# This returns a proc that can be used with the builder
|
||||||
|
# that simply appends data to an array in the env.
|
||||||
|
def appender_proc(data)
|
||||||
|
Proc.new { |env| env[:data] << data }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "basic `use`" do
|
||||||
|
it "should add items to the stack and make them callable" do
|
||||||
|
data = {}
|
||||||
|
proc = Proc.new { |env| env[:data] = true }
|
||||||
|
|
||||||
|
instance.use proc
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:data].should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be able to add multiple items" do
|
||||||
|
data = {}
|
||||||
|
proc1 = Proc.new { |env| env[:one] = true }
|
||||||
|
proc2 = Proc.new { |env| env[:two] = true }
|
||||||
|
|
||||||
|
instance.use proc1
|
||||||
|
instance.use proc2
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:one].should == true
|
||||||
|
data[:two].should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be able to add another builder" do
|
||||||
|
data = {}
|
||||||
|
proc1 = Proc.new { |env| env[:one] = true }
|
||||||
|
|
||||||
|
# Build the first builder
|
||||||
|
one = described_class.new
|
||||||
|
one.use proc1
|
||||||
|
|
||||||
|
# Add it to this builder
|
||||||
|
two = described_class.new
|
||||||
|
two.use one
|
||||||
|
|
||||||
|
# Call the 2nd and verify results
|
||||||
|
two.call(data)
|
||||||
|
data[:one].should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be able to set additional variables if using another builder" do
|
||||||
|
data = { }
|
||||||
|
proc1 = Proc.new { |env| env[:data] += 1 }
|
||||||
|
|
||||||
|
# Build the first builder
|
||||||
|
one = described_class.new
|
||||||
|
one.use proc1
|
||||||
|
|
||||||
|
# Add it to this builder
|
||||||
|
two = described_class.new
|
||||||
|
two.use one, :data => 10
|
||||||
|
|
||||||
|
# Call the 2nd and verify results
|
||||||
|
two.call(data)
|
||||||
|
data[:data].should == 11
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "inserting" do
|
||||||
|
it "can insert at an index" do
|
||||||
|
instance.use appender_proc(1)
|
||||||
|
instance.insert(0, appender_proc(2))
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:data].should == [2, 1]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can insert next to a previous object" do
|
||||||
|
proc2 = appender_proc(2)
|
||||||
|
instance.use appender_proc(1)
|
||||||
|
instance.use proc2
|
||||||
|
instance.insert(proc2, appender_proc(3))
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:data].should == [1, 3, 2]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can insert before" do
|
||||||
|
instance.use appender_proc(1)
|
||||||
|
instance.insert_before 0, appender_proc(2)
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:data].should == [2, 1]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can insert after" do
|
||||||
|
instance.use appender_proc(1)
|
||||||
|
instance.use appender_proc(3)
|
||||||
|
instance.insert_after 0, appender_proc(2)
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:data].should == [1, 2, 3]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an exception if an invalid object given" do
|
||||||
|
expect { instance.insert_after "object", appender_proc(1) }.
|
||||||
|
to raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "replace" do
|
||||||
|
it "can replace an object" do
|
||||||
|
proc1 = appender_proc(1)
|
||||||
|
proc2 = appender_proc(2)
|
||||||
|
|
||||||
|
instance.use proc1
|
||||||
|
instance.replace proc1, proc2
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:data].should == [2]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can replace by index" do
|
||||||
|
proc1 = appender_proc(1)
|
||||||
|
proc2 = appender_proc(2)
|
||||||
|
|
||||||
|
instance.use proc1
|
||||||
|
instance.replace 0, proc2
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:data].should == [2]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "deleting" do
|
||||||
|
it "can delete by object" do
|
||||||
|
proc1 = appender_proc(1)
|
||||||
|
|
||||||
|
instance.use proc1
|
||||||
|
instance.use appender_proc(2)
|
||||||
|
instance.delete proc1
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:data].should == [2]
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can delete by index" do
|
||||||
|
proc1 = appender_proc(1)
|
||||||
|
|
||||||
|
instance.use proc1
|
||||||
|
instance.use appender_proc(2)
|
||||||
|
instance.delete 0
|
||||||
|
instance.call(data)
|
||||||
|
|
||||||
|
data[:data].should == [2]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,10 +13,4 @@ describe Vagrant::Action::Environment do
|
||||||
instance["foo"] = "bar"
|
instance["foo"] = "bar"
|
||||||
instance[:foo].should == "bar"
|
instance[:foo].should == "bar"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should keep track of interrupted state" do
|
|
||||||
instance.should_not be_interrupted
|
|
||||||
instance.interrupt!
|
|
||||||
instance.should be_interrupted
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,207 +0,0 @@
|
||||||
require "test_helper"
|
|
||||||
require "logger"
|
|
||||||
|
|
||||||
class ActionBuilderTest < Test::Unit::TestCase
|
|
||||||
setup do
|
|
||||||
@klass = Vagrant::Action::Builder
|
|
||||||
end
|
|
||||||
|
|
||||||
context "initializing" do
|
|
||||||
should "setup empty middleware stack" do
|
|
||||||
builder = @klass.new
|
|
||||||
assert builder.stack.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
should "take block to setup stack" do
|
|
||||||
builder = @klass.new do
|
|
||||||
use Hash
|
|
||||||
use lambda { |i| i }
|
|
||||||
end
|
|
||||||
|
|
||||||
assert !builder.stack.empty?
|
|
||||||
assert_equal 2, builder.stack.length
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "with an instance" do
|
|
||||||
setup do
|
|
||||||
@instance = @klass.new
|
|
||||||
end
|
|
||||||
|
|
||||||
context "adding to the stack" do
|
|
||||||
should "return self" do
|
|
||||||
assert @instance.equal?(@instance.use(1))
|
|
||||||
end
|
|
||||||
|
|
||||||
should "add to the end" do
|
|
||||||
@instance.use 1
|
|
||||||
@instance.use 2
|
|
||||||
assert_equal [2, [], nil], @instance.stack.last
|
|
||||||
end
|
|
||||||
|
|
||||||
should "merge in other builder's stack" do
|
|
||||||
other = @klass.new do
|
|
||||||
use 2
|
|
||||||
use 3
|
|
||||||
end
|
|
||||||
|
|
||||||
@instance.use 1
|
|
||||||
@instance.use other
|
|
||||||
assert_equal 3, @instance.stack.length
|
|
||||||
end
|
|
||||||
|
|
||||||
should "prepend a set environment task for merging middlewares if given" do
|
|
||||||
other = @klass.new do
|
|
||||||
use 1
|
|
||||||
end
|
|
||||||
|
|
||||||
@instance.use 0
|
|
||||||
@instance.use(other, :foo => :bar)
|
|
||||||
assert_equal 3, @instance.stack.length
|
|
||||||
assert_equal Vagrant::Action::Env::Set, @instance.stack[1].first
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "flatten" do
|
|
||||||
should "return the flattened format of the builder" do
|
|
||||||
env = Vagrant::Action::Environment.new(nil)
|
|
||||||
env["logger"] = Logger.new(nil)
|
|
||||||
env.expects(:foo).once
|
|
||||||
|
|
||||||
func = lambda { |x| x.foo }
|
|
||||||
@instance.use func
|
|
||||||
proc = @instance.flatten
|
|
||||||
assert proc.respond_to?(:call)
|
|
||||||
proc.call(env)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "inserting" do
|
|
||||||
setup do
|
|
||||||
@instance.use "1"
|
|
||||||
@instance.use "2"
|
|
||||||
end
|
|
||||||
|
|
||||||
should "insert at the proper numeric index" do
|
|
||||||
@instance.insert(1, "3")
|
|
||||||
assert_equal "3", @instance.stack[1].first
|
|
||||||
end
|
|
||||||
|
|
||||||
should "insert next to the proper object if given" do
|
|
||||||
@instance.insert("2", "3")
|
|
||||||
assert_equal "3", @instance.stack[1].first
|
|
||||||
end
|
|
||||||
|
|
||||||
should "be able to call insert_before as well" do
|
|
||||||
@instance.insert_before("1", "0")
|
|
||||||
assert_equal "0", @instance.stack.first.first
|
|
||||||
end
|
|
||||||
|
|
||||||
should "be able to insert_after" do
|
|
||||||
@instance.insert_after("1", "0")
|
|
||||||
assert_equal "0", @instance.stack[1].first
|
|
||||||
end
|
|
||||||
|
|
||||||
should "be able to insert_after using numeric index" do
|
|
||||||
@instance.insert_after(1, "0")
|
|
||||||
assert_equal "0", @instance.stack[2].first
|
|
||||||
end
|
|
||||||
|
|
||||||
should "raise an exception if invalid index" do
|
|
||||||
assert_raises(RuntimeError) {
|
|
||||||
@instance.insert_after("15", "0")
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "swapping" do
|
|
||||||
setup do
|
|
||||||
@instance.use "1"
|
|
||||||
@instance.use "2"
|
|
||||||
end
|
|
||||||
|
|
||||||
should "be able to swap using the object" do
|
|
||||||
@instance.swap "1", "3"
|
|
||||||
assert_equal "3", @instance.stack.first.first
|
|
||||||
end
|
|
||||||
|
|
||||||
should "be able to swap using the index" do
|
|
||||||
@instance.swap 0, "3"
|
|
||||||
assert_equal "3", @instance.stack.first.first
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "deleting" do
|
|
||||||
setup do
|
|
||||||
@instance.use "1"
|
|
||||||
end
|
|
||||||
|
|
||||||
should "delete the proper object" do
|
|
||||||
@instance.delete("1")
|
|
||||||
assert @instance.stack.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
should "delete by index if given" do
|
|
||||||
@instance.delete(0)
|
|
||||||
assert @instance.stack.empty?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "getting an index of an object" do
|
|
||||||
should "return the proper index if it exists" do
|
|
||||||
@instance.use 1
|
|
||||||
@instance.use 2
|
|
||||||
@instance.use 3
|
|
||||||
assert_equal 1, @instance.index(2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "converting to an app" do
|
|
||||||
should "make non-classes lambdas" do
|
|
||||||
env = Vagrant::Action::Environment.new(nil)
|
|
||||||
env["logger"] = Logger.new(nil)
|
|
||||||
env.expects(:foo).once
|
|
||||||
|
|
||||||
func = lambda { |x| x.foo }
|
|
||||||
@instance.use func
|
|
||||||
@instance.to_app(env).call(env)
|
|
||||||
end
|
|
||||||
|
|
||||||
should "raise exception if given invalid middleware" do
|
|
||||||
@instance.use 7
|
|
||||||
assert_raises(RuntimeError) {
|
|
||||||
@instance.to_app(nil)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "calling" do
|
|
||||||
def mock_middleware
|
|
||||||
middleware = Class.new do
|
|
||||||
def initialize(app, env)
|
|
||||||
@app = app
|
|
||||||
end
|
|
||||||
|
|
||||||
def call(env)
|
|
||||||
@app.call(env)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
should "convert to an app then call with the env" do
|
|
||||||
mw = mock_middleware
|
|
||||||
mw.any_instance.expects(:call).with() do |env|
|
|
||||||
assert env.has_key?(:key)
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
env = Vagrant::Action::Environment.new(nil)
|
|
||||||
env["logger"] = Logger.new(nil)
|
|
||||||
env[:key] = :value
|
|
||||||
|
|
||||||
@instance.use(mw)
|
|
||||||
@instance.call(env)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in New Issue