2005-08-03 08:59:03 -04:00
|
|
|
$:.unshift File.dirname(__FILE__) + "/../lib"
|
|
|
|
|
|
|
|
require 'stringio'
|
|
|
|
require 'test/unit'
|
|
|
|
require 'switchtower/actor'
|
|
|
|
require 'switchtower/logger'
|
2006-01-07 16:02:25 -05:00
|
|
|
require 'switchtower/configuration'
|
2005-08-03 08:59:03 -04:00
|
|
|
|
2005-08-06 15:35:25 -04:00
|
|
|
class ActorTest < Test::Unit::TestCase
|
2005-08-03 08:59:03 -04:00
|
|
|
|
2005-08-06 15:35:25 -04:00
|
|
|
class TestingConnectionFactory
|
|
|
|
def initialize(config)
|
2005-08-03 08:59:03 -04:00
|
|
|
end
|
|
|
|
|
2005-08-06 15:35:25 -04:00
|
|
|
def connect_to(server)
|
|
|
|
server
|
2005-08-03 08:59:03 -04:00
|
|
|
end
|
2005-08-06 15:35:25 -04:00
|
|
|
end
|
2005-08-03 08:59:03 -04:00
|
|
|
|
2005-08-06 15:35:25 -04:00
|
|
|
class GatewayConnectionFactory
|
|
|
|
def connect_to(server)
|
|
|
|
server
|
2005-08-03 08:59:03 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-08-06 15:35:25 -04:00
|
|
|
class TestingCommand
|
2005-08-03 08:59:03 -04:00
|
|
|
def self.invoked!
|
|
|
|
@invoked = true
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.invoked?
|
|
|
|
@invoked
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.reset!
|
|
|
|
@invoked = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize(*args)
|
|
|
|
end
|
|
|
|
|
|
|
|
def process!
|
|
|
|
self.class.invoked!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-08-06 15:35:25 -04:00
|
|
|
class TestActor < SwitchTower::Actor
|
|
|
|
attr_reader :factory
|
|
|
|
|
|
|
|
self.connection_factory = TestingConnectionFactory
|
|
|
|
self.command_factory = TestingCommand
|
|
|
|
|
|
|
|
def establish_gateway
|
|
|
|
GatewayConnectionFactory.new
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-08-03 08:59:03 -04:00
|
|
|
class MockConfiguration
|
|
|
|
Role = Struct.new(:host, :options)
|
|
|
|
|
|
|
|
attr_accessor :gateway, :pretend
|
|
|
|
|
|
|
|
def delegated_method
|
|
|
|
"result of method"
|
|
|
|
end
|
|
|
|
|
|
|
|
ROLES = { :db => [ Role.new("01.example.com", :primary => true),
|
|
|
|
Role.new("02.example.com", {}),
|
|
|
|
Role.new("all.example.com", {})],
|
|
|
|
:web => [ Role.new("03.example.com", {}),
|
|
|
|
Role.new("04.example.com", {}),
|
|
|
|
Role.new("all.example.com", {})],
|
|
|
|
:app => [ Role.new("05.example.com", {}),
|
|
|
|
Role.new("06.example.com", {}),
|
|
|
|
Role.new("07.example.com", {}),
|
|
|
|
Role.new("all.example.com", {})] }
|
|
|
|
|
|
|
|
def roles
|
|
|
|
ROLES
|
|
|
|
end
|
|
|
|
|
|
|
|
def logger
|
|
|
|
@logger ||= SwitchTower::Logger.new(:output => StringIO.new)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2006-02-18 17:09:05 -05:00
|
|
|
module CustomExtension
|
|
|
|
def do_something_extra(a, b, c)
|
|
|
|
run "echo '#{a} :: #{b} :: #{c}'"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-08-03 08:59:03 -04:00
|
|
|
def setup
|
2005-08-06 15:35:25 -04:00
|
|
|
TestingCommand.reset!
|
|
|
|
@actor = TestActor.new(MockConfiguration.new)
|
2005-08-03 08:59:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_define_task_creates_method
|
|
|
|
@actor.define_task :hello do
|
|
|
|
"result"
|
|
|
|
end
|
|
|
|
assert @actor.respond_to?(:hello)
|
|
|
|
assert_equal "result", @actor.hello
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_define_task_with_successful_transaction
|
|
|
|
class << @actor
|
|
|
|
attr_reader :rolled_back
|
|
|
|
attr_reader :history
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.define_task :hello do
|
|
|
|
(@history ||= []) << :hello
|
|
|
|
on_rollback { @rolled_back = true }
|
|
|
|
"hello"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.define_task :goodbye do
|
|
|
|
(@history ||= []) << :goodbye
|
|
|
|
transaction do
|
|
|
|
hello
|
|
|
|
end
|
|
|
|
"goodbye"
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_nothing_raised { @actor.goodbye }
|
|
|
|
assert !@actor.rolled_back
|
|
|
|
assert_equal [:goodbye, :hello], @actor.history
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_define_task_with_failed_transaction
|
|
|
|
class << @actor
|
|
|
|
attr_reader :rolled_back
|
|
|
|
attr_reader :history
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.define_task :hello do
|
|
|
|
(@history ||= []) << :hello
|
|
|
|
on_rollback { @rolled_back = true }
|
|
|
|
"hello"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.define_task :goodbye do
|
|
|
|
(@history ||= []) << :goodbye
|
|
|
|
transaction do
|
|
|
|
hello
|
|
|
|
raise "ouch"
|
|
|
|
end
|
|
|
|
"goodbye"
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_raise(RuntimeError) do
|
|
|
|
@actor.goodbye
|
|
|
|
end
|
|
|
|
|
|
|
|
assert @actor.rolled_back
|
|
|
|
assert_equal [:goodbye, :hello], @actor.history
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_delegates_to_configuration
|
|
|
|
@actor.define_task :hello do
|
|
|
|
delegated_method
|
|
|
|
end
|
|
|
|
assert_equal "result of method", @actor.hello
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_task_servers_with_duplicates
|
|
|
|
@actor.define_task :foo do
|
|
|
|
run "do this"
|
|
|
|
end
|
|
|
|
|
2006-02-18 11:57:04 -05:00
|
|
|
assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com 05.example.com 06.example.com 07.example.com all.example.com), @actor.tasks[:foo].servers.sort
|
2005-08-03 08:59:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_run_in_task_without_explicit_roles_selects_all_roles
|
|
|
|
@actor.define_task :foo do
|
|
|
|
run "do this"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.foo
|
|
|
|
assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com 05.example.com 06.example.com 07.example.com all.example.com), @actor.sessions.keys.sort
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_run_in_task_with_single_role_selects_that_role
|
|
|
|
@actor.define_task :foo, :roles => :db do
|
|
|
|
run "do this"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.foo
|
|
|
|
assert_equal %w(01.example.com 02.example.com all.example.com), @actor.sessions.keys.sort
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_run_in_task_with_multiple_roles_selects_those_roles
|
|
|
|
@actor.define_task :foo, :roles => [:db, :web] do
|
|
|
|
run "do this"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.foo
|
|
|
|
assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com all.example.com), @actor.sessions.keys.sort
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_run_in_task_with_only_restricts_selected_roles
|
|
|
|
@actor.define_task :foo, :roles => :db, :only => { :primary => true } do
|
|
|
|
run "do this"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.foo
|
|
|
|
assert_equal %w(01.example.com), @actor.sessions.keys.sort
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_establish_connection_uses_gateway_if_specified
|
|
|
|
@actor.configuration.gateway = "10.example.com"
|
|
|
|
@actor.define_task :foo, :roles => :db do
|
|
|
|
run "do this"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.foo
|
2005-08-06 15:35:25 -04:00
|
|
|
assert_instance_of GatewayConnectionFactory, @actor.factory
|
2005-08-03 08:59:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_run_when_not_pretend
|
|
|
|
@actor.define_task :foo do
|
|
|
|
run "do this"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.configuration.pretend = false
|
|
|
|
@actor.foo
|
2005-08-06 15:35:25 -04:00
|
|
|
assert TestingCommand.invoked?
|
2005-08-03 08:59:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_run_when_pretend
|
|
|
|
@actor.define_task :foo do
|
|
|
|
run "do this"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.configuration.pretend = true
|
|
|
|
@actor.foo
|
2005-08-06 15:35:25 -04:00
|
|
|
assert !TestingCommand.invoked?
|
2005-08-03 08:59:03 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_task_before_hook
|
|
|
|
history = []
|
|
|
|
@actor.define_task :foo do
|
|
|
|
history << "foo"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.define_task :before_foo do
|
|
|
|
history << "before_foo"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.foo
|
|
|
|
assert_equal %w(before_foo foo), history
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_task_after_hook
|
|
|
|
history = []
|
|
|
|
@actor.define_task :foo do
|
|
|
|
history << "foo"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.define_task :after_foo do
|
|
|
|
history << "after_foo"
|
|
|
|
end
|
|
|
|
|
|
|
|
@actor.foo
|
|
|
|
assert_equal %w(foo after_foo), history
|
|
|
|
end
|
2006-01-07 16:02:25 -05:00
|
|
|
|
|
|
|
def test_uppercase_variables
|
|
|
|
config = SwitchTower::Configuration.new(TestActor)
|
|
|
|
config.set :HELLO, "world"
|
|
|
|
assert_equal "world", config.actor.instance_eval("HELLO")
|
|
|
|
config.set :HELLO, "test"
|
|
|
|
assert_equal "test", config.actor.instance_eval("HELLO")
|
|
|
|
end
|
2006-01-11 23:37:08 -05:00
|
|
|
|
|
|
|
def test_connect_when_no_matching_servers
|
|
|
|
@actor.define_task :foo, :roles => :db, :only => { :fnoofy => true } do
|
|
|
|
run "do this"
|
|
|
|
end
|
|
|
|
|
|
|
|
assert_raises(RuntimeError) { @actor.foo }
|
|
|
|
end
|
2006-02-18 17:09:05 -05:00
|
|
|
|
|
|
|
def test_custom_extension
|
|
|
|
assert SwitchTower.plugin(:custom, CustomExtension)
|
|
|
|
@actor.define_task :foo, :roles => :db do
|
|
|
|
custom.do_something_extra(1, 2, 3)
|
|
|
|
end
|
|
|
|
assert_nothing_raised { @actor.foo }
|
|
|
|
assert TestingCommand.invoked?
|
|
|
|
assert SwitchTower.remove_plugin(:custom)
|
|
|
|
end
|
2005-08-03 08:59:03 -04:00
|
|
|
end
|