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?
|
||||
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
|
||||
# the return value of this method, then the stack will merge, instead
|
||||
# of being treated as a separate single middleware.
|
||||
|
@ -75,9 +67,9 @@ module Vagrant
|
|||
insert(index + 1, middleware, *args, &block)
|
||||
end
|
||||
|
||||
# Swaps out the given middlware object or index with the new
|
||||
# Replaces the given middlware object or index with the new
|
||||
# middleware.
|
||||
def swap(index, middleware, *args, &block)
|
||||
def replace(index, middleware, *args, &block)
|
||||
if index.is_a?(Integer)
|
||||
delete(index)
|
||||
insert(index, middleware, *args, &block)
|
||||
|
@ -93,6 +85,13 @@ module Vagrant
|
|||
stack.delete_at(index)
|
||||
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.
|
||||
#
|
||||
# @param [Object] object The item to find the index for
|
||||
|
@ -105,6 +104,14 @@ module Vagrant
|
|||
nil
|
||||
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.
|
||||
#
|
||||
# @param [Vagrant::Action::Environment] env The action environment
|
||||
|
@ -114,11 +121,6 @@ module Vagrant
|
|||
# and predictable behavior upon exceptions.
|
||||
Warden.new(stack.dup, env)
|
||||
end
|
||||
|
||||
# Runs the builder stack with the given environment.
|
||||
def call(env)
|
||||
to_app(env).call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,25 +7,6 @@ module Vagrant
|
|||
# some helper methods for accessing the environment as well
|
||||
# as being a hash, to store any additional options.
|
||||
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
|
||||
|
|
|
@ -34,13 +34,13 @@ module Vagrant
|
|||
# chain has been run.
|
||||
ui = environment[:ui] if environment.has_key?(:ui)
|
||||
int_callback = lambda do
|
||||
if environment.interrupted?
|
||||
if environment[:interrupted]
|
||||
ui.error I18n.t("vagrant.actions.runner.exit_immediately") if ui
|
||||
abort
|
||||
end
|
||||
|
||||
ui.warn I18n.t("vagrant.actions.runner.waiting_cleanup") if ui && !@@reported_interrupt
|
||||
environment.interrupt!
|
||||
environment[:interrupted] = true
|
||||
@@reported_interrupt = true
|
||||
end
|
||||
|
||||
|
|
|
@ -27,11 +27,11 @@ module Vagrant
|
|||
begin
|
||||
# Call the next middleware in the sequence, appending to the stack
|
||||
# of "recoverable" middlewares in case something goes wrong!
|
||||
raise Errors::VagrantInterrupt if env.interrupted?
|
||||
raise Errors::VagrantInterrupt if env[:interrupted]
|
||||
action = @actions.shift
|
||||
@logger.info("Calling action: #{action}")
|
||||
@stack.unshift(action).first.call(env)
|
||||
raise Errors::VagrantInterrupt if env.interrupted?
|
||||
raise Errors::VagrantInterrupt if env[:interrupted]
|
||||
rescue SystemExit
|
||||
# This means that an "exit" or "abort" was called. In these cases,
|
||||
# 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].should == "bar"
|
||||
end
|
||||
|
||||
it "should keep track of interrupted state" do
|
||||
instance.should_not be_interrupted
|
||||
instance.interrupt!
|
||||
instance.should be_interrupted
|
||||
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