mbailey-capistrano 2.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +761 -0
- data/Manifest +104 -0
- data/README.rdoc +66 -0
- data/Rakefile +34 -0
- data/bin/cap +4 -0
- data/bin/capify +78 -0
- data/examples/sample.rb +14 -0
- data/lib/capistrano/callback.rb +45 -0
- data/lib/capistrano/cli/execute.rb +84 -0
- data/lib/capistrano/cli/help.rb +125 -0
- data/lib/capistrano/cli/help.txt +75 -0
- data/lib/capistrano/cli/options.rb +224 -0
- data/lib/capistrano/cli/ui.rb +40 -0
- data/lib/capistrano/cli.rb +47 -0
- data/lib/capistrano/command.rb +283 -0
- data/lib/capistrano/configuration/actions/file_transfer.rb +47 -0
- data/lib/capistrano/configuration/actions/inspect.rb +46 -0
- data/lib/capistrano/configuration/actions/invocation.rb +293 -0
- data/lib/capistrano/configuration/callbacks.rb +148 -0
- data/lib/capistrano/configuration/connections.rb +200 -0
- data/lib/capistrano/configuration/execution.rb +132 -0
- data/lib/capistrano/configuration/loading.rb +197 -0
- data/lib/capistrano/configuration/namespaces.rb +197 -0
- data/lib/capistrano/configuration/roles.rb +73 -0
- data/lib/capistrano/configuration/servers.rb +85 -0
- data/lib/capistrano/configuration/variables.rb +127 -0
- data/lib/capistrano/configuration.rb +43 -0
- data/lib/capistrano/errors.rb +15 -0
- data/lib/capistrano/extensions.rb +57 -0
- data/lib/capistrano/logger.rb +59 -0
- data/lib/capistrano/processable.rb +53 -0
- data/lib/capistrano/recipes/compat.rb +32 -0
- data/lib/capistrano/recipes/deploy/dependencies.rb +44 -0
- data/lib/capistrano/recipes/deploy/local_dependency.rb +54 -0
- data/lib/capistrano/recipes/deploy/remote_dependency.rb +105 -0
- data/lib/capistrano/recipes/deploy/scm/accurev.rb +169 -0
- data/lib/capistrano/recipes/deploy/scm/base.rb +196 -0
- data/lib/capistrano/recipes/deploy/scm/bzr.rb +83 -0
- data/lib/capistrano/recipes/deploy/scm/cvs.rb +152 -0
- data/lib/capistrano/recipes/deploy/scm/darcs.rb +85 -0
- data/lib/capistrano/recipes/deploy/scm/git.rb +271 -0
- data/lib/capistrano/recipes/deploy/scm/mercurial.rb +137 -0
- data/lib/capistrano/recipes/deploy/scm/none.rb +44 -0
- data/lib/capistrano/recipes/deploy/scm/perforce.rb +133 -0
- data/lib/capistrano/recipes/deploy/scm/subversion.rb +121 -0
- data/lib/capistrano/recipes/deploy/scm.rb +19 -0
- data/lib/capistrano/recipes/deploy/strategy/base.rb +79 -0
- data/lib/capistrano/recipes/deploy/strategy/checkout.rb +20 -0
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +210 -0
- data/lib/capistrano/recipes/deploy/strategy/export.rb +20 -0
- data/lib/capistrano/recipes/deploy/strategy/remote.rb +52 -0
- data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +56 -0
- data/lib/capistrano/recipes/deploy/strategy.rb +19 -0
- data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +53 -0
- data/lib/capistrano/recipes/deploy.rb +562 -0
- data/lib/capistrano/recipes/standard.rb +37 -0
- data/lib/capistrano/recipes/templates/maintenance.rhtml +53 -0
- data/lib/capistrano/recipes/upgrade.rb +33 -0
- data/lib/capistrano/role.rb +102 -0
- data/lib/capistrano/server_definition.rb +56 -0
- data/lib/capistrano/shell.rb +260 -0
- data/lib/capistrano/ssh.rb +99 -0
- data/lib/capistrano/task_definition.rb +70 -0
- data/lib/capistrano/transfer.rb +216 -0
- data/lib/capistrano/version.rb +18 -0
- data/lib/capistrano.rb +2 -0
- data/setup.rb +1346 -0
- data/test/cli/execute_test.rb +132 -0
- data/test/cli/help_test.rb +165 -0
- data/test/cli/options_test.rb +317 -0
- data/test/cli/ui_test.rb +28 -0
- data/test/cli_test.rb +17 -0
- data/test/command_test.rb +286 -0
- data/test/configuration/actions/file_transfer_test.rb +61 -0
- data/test/configuration/actions/inspect_test.rb +65 -0
- data/test/configuration/actions/invocation_test.rb +224 -0
- data/test/configuration/callbacks_test.rb +220 -0
- data/test/configuration/connections_test.rb +349 -0
- data/test/configuration/execution_test.rb +175 -0
- data/test/configuration/loading_test.rb +132 -0
- data/test/configuration/namespace_dsl_test.rb +311 -0
- data/test/configuration/roles_test.rb +144 -0
- data/test/configuration/servers_test.rb +121 -0
- data/test/configuration/variables_test.rb +184 -0
- data/test/configuration_test.rb +88 -0
- data/test/deploy/local_dependency_test.rb +76 -0
- data/test/deploy/remote_dependency_test.rb +114 -0
- data/test/deploy/scm/accurev_test.rb +23 -0
- data/test/deploy/scm/base_test.rb +55 -0
- data/test/deploy/scm/git_test.rb +167 -0
- data/test/deploy/scm/mercurial_test.rb +129 -0
- data/test/deploy/strategy/copy_test.rb +258 -0
- data/test/extensions_test.rb +69 -0
- data/test/fixtures/cli_integration.rb +5 -0
- data/test/fixtures/config.rb +5 -0
- data/test/fixtures/custom.rb +3 -0
- data/test/logger_test.rb +123 -0
- data/test/role_test.rb +11 -0
- data/test/server_definition_test.rb +121 -0
- data/test/shell_test.rb +90 -0
- data/test/ssh_test.rb +104 -0
- data/test/task_definition_test.rb +101 -0
- data/test/transfer_test.rb +160 -0
- data/test/utils.rb +38 -0
- metadata +205 -0
@@ -0,0 +1,175 @@
|
|
1
|
+
require "utils"
|
2
|
+
require 'capistrano/configuration/execution'
|
3
|
+
require 'capistrano/task_definition'
|
4
|
+
|
5
|
+
class ConfigurationExecutionTest < Test::Unit::TestCase
|
6
|
+
class MockConfig
|
7
|
+
attr_reader :tasks, :namespaces, :fully_qualified_name, :parent
|
8
|
+
attr_reader :state, :original_initialize_called
|
9
|
+
attr_accessor :logger, :default_task
|
10
|
+
|
11
|
+
def initialize(options={})
|
12
|
+
@original_initialize_called = true
|
13
|
+
@tasks = {}
|
14
|
+
@namespaces = {}
|
15
|
+
@state = {}
|
16
|
+
@fully_qualified_name = options[:fqn]
|
17
|
+
@parent = options[:parent]
|
18
|
+
@logger = options.delete(:logger)
|
19
|
+
end
|
20
|
+
|
21
|
+
include Capistrano::Configuration::Execution
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup
|
25
|
+
@config = MockConfig.new(:logger => stub(:debug => nil, :info => nil, :important => nil))
|
26
|
+
@config.stubs(:search_task).returns(nil)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_initialize_should_initialize_collections
|
30
|
+
assert_nil @config.rollback_requests
|
31
|
+
assert @config.original_initialize_called
|
32
|
+
assert @config.task_call_frames.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_execute_task_should_populate_call_stack
|
36
|
+
task = new_task @config, :testing
|
37
|
+
assert_nothing_raised { @config.execute_task(task) }
|
38
|
+
assert_equal %w(testing), @config.state[:testing][:stack]
|
39
|
+
assert_nil @config.state[:testing][:history]
|
40
|
+
assert @config.task_call_frames.empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_nested_execute_task_should_add_to_call_stack
|
44
|
+
testing = new_task @config, :testing
|
45
|
+
outer = new_task(@config, :outer) { execute_task(testing) }
|
46
|
+
|
47
|
+
assert_nothing_raised { @config.execute_task(outer) }
|
48
|
+
assert_equal %w(outer testing), @config.state[:testing][:stack]
|
49
|
+
assert_nil @config.state[:testing][:history]
|
50
|
+
assert @config.task_call_frames.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_execute_task_should_execute_in_scope_of_tasks_parent
|
54
|
+
ns = stub("namespace", :tasks => {}, :default_task => nil, :fully_qualified_name => "ns")
|
55
|
+
ns.expects(:instance_eval)
|
56
|
+
testing = new_task ns, :testing
|
57
|
+
@config.execute_task(testing)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_transaction_outside_of_task_should_raise_exception
|
61
|
+
assert_raises(ScriptError) { @config.transaction {} }
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_transaction_without_block_should_raise_argument_error
|
65
|
+
testing = new_task(@config, :testing) { transaction }
|
66
|
+
assert_raises(ArgumentError) { @config.execute_task(testing) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_transaction_should_initialize_transaction_history
|
70
|
+
@config.state[:inspector] = stack_inspector
|
71
|
+
testing = new_task(@config, :testing) { transaction { instance_eval(&state[:inspector]) } }
|
72
|
+
@config.execute_task(testing)
|
73
|
+
assert_equal [], @config.state[:testing][:history]
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_transaction_from_within_transaction_should_not_start_new_transaction
|
77
|
+
third = new_task(@config, :third, &stack_inspector)
|
78
|
+
second = new_task(@config, :second) { transaction { execute_task(third) } }
|
79
|
+
first = new_task(@config, :first) { transaction { execute_task(second) } }
|
80
|
+
# kind of fragile...not sure how else to check that transaction was only
|
81
|
+
# really run twice...but if the transaction was REALLY run, logger.info
|
82
|
+
# will be called once when it starts, and once when it finishes.
|
83
|
+
@config.logger = mock()
|
84
|
+
@config.logger.stubs(:debug)
|
85
|
+
@config.logger.expects(:info).times(2)
|
86
|
+
@config.execute_task(first)
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_on_rollback_should_have_no_effect_outside_of_transaction
|
90
|
+
aaa = new_task(@config, :aaa) { on_rollback { state[:rollback] = true }; raise "boom" }
|
91
|
+
assert_raises(RuntimeError) { @config.execute_task(aaa) }
|
92
|
+
assert_nil @config.state[:rollback]
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_exception_raised_in_transaction_should_call_all_registered_rollback_handlers_in_reverse_order
|
96
|
+
aaa = new_task(@config, :aaa) { on_rollback { (state[:rollback] ||= []) << :aaa } }
|
97
|
+
bbb = new_task(@config, :bbb) { on_rollback { (state[:rollback] ||= []) << :bbb } }
|
98
|
+
ccc = new_task(@config, :ccc) {}
|
99
|
+
ddd = new_task(@config, :ddd) { on_rollback { (state[:rollback] ||= []) << :ddd }; execute_task(bbb); execute_task(ccc) }
|
100
|
+
eee = new_task(@config, :eee) { transaction { execute_task(ddd); execute_task(aaa); raise "boom" } }
|
101
|
+
assert_raises(RuntimeError) do
|
102
|
+
@config.execute_task(eee)
|
103
|
+
end
|
104
|
+
assert_equal [:aaa, :bbb, :ddd], @config.state[:rollback]
|
105
|
+
assert_nil @config.rollback_requests
|
106
|
+
assert @config.task_call_frames.empty?
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_exception_during_rollback_should_simply_be_logged_and_ignored
|
110
|
+
aaa = new_task(@config, :aaa) { on_rollback { state[:aaa] = true; raise LoadError, "ouch" }; execute_task(bbb) }
|
111
|
+
bbb = new_task(@config, :bbb) { raise MadError, "boom" }
|
112
|
+
ccc = new_task(@config, :ccc) { transaction { execute_task(aaa) } }
|
113
|
+
assert_raises(NameError) do
|
114
|
+
@config.execute_task(ccc)
|
115
|
+
end
|
116
|
+
assert @config.state[:aaa]
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_on_rollback_called_twice_should_result_in_last_rollback_block_being_effective
|
120
|
+
aaa = new_task(@config, :aaa) do
|
121
|
+
transaction do
|
122
|
+
on_rollback { (state[:rollback] ||= []) << :first }
|
123
|
+
on_rollback { (state[:rollback] ||= []) << :second }
|
124
|
+
raise "boom"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
assert_raises(RuntimeError) do
|
129
|
+
@config.execute_task(aaa)
|
130
|
+
end
|
131
|
+
|
132
|
+
assert_equal [:second], @config.state[:rollback]
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_find_and_execute_task_should_raise_error_when_task_cannot_be_found
|
136
|
+
@config.expects(:find_task).with("path:to:task").returns(nil)
|
137
|
+
assert_raises(Capistrano::NoSuchTaskError) { @config.find_and_execute_task("path:to:task") }
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_find_and_execute_task_should_execute_task_when_task_is_found
|
141
|
+
@config.expects(:find_task).with("path:to:task").returns(:found)
|
142
|
+
@config.expects(:execute_task).with(:found)
|
143
|
+
assert_nothing_raised { @config.find_and_execute_task("path:to:task") }
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_find_and_execute_task_with_before_option_should_trigger_callback
|
147
|
+
@config.expects(:find_task).with("path:to:task").returns(:found)
|
148
|
+
@config.expects(:trigger).with(:incoming, :found)
|
149
|
+
@config.expects(:execute_task).with(:found)
|
150
|
+
@config.find_and_execute_task("path:to:task", :before => :incoming)
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_find_and_execute_task_with_after_option_should_trigger_callback
|
154
|
+
@config.expects(:find_task).with("path:to:task").returns(:found)
|
155
|
+
@config.expects(:trigger).with(:outgoing, :found)
|
156
|
+
@config.expects(:execute_task).with(:found)
|
157
|
+
@config.find_and_execute_task("path:to:task", :after => :outgoing)
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def stack_inspector
|
163
|
+
Proc.new do
|
164
|
+
(state[:trail] ||= []) << current_task.fully_qualified_name
|
165
|
+
data = state[current_task.name] = {}
|
166
|
+
data[:stack] = task_call_frames.map { |frame| frame.task.fully_qualified_name }
|
167
|
+
data[:history] = rollback_requests && rollback_requests.map { |frame| frame.task.fully_qualified_name }
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def new_task(namespace, name, options={}, &block)
|
172
|
+
block ||= stack_inspector
|
173
|
+
namespace.tasks[name] = Capistrano::TaskDefinition.new(name, namespace, &block)
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require "utils"
|
2
|
+
require 'capistrano/configuration/loading'
|
3
|
+
|
4
|
+
class ConfigurationLoadingTest < Test::Unit::TestCase
|
5
|
+
class MockConfig
|
6
|
+
attr_accessor :ping
|
7
|
+
attr_reader :original_initialize_called
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@original_initialize_called = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def ping!(value)
|
14
|
+
@ping = value
|
15
|
+
end
|
16
|
+
|
17
|
+
include Capistrano::Configuration::Loading
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup
|
21
|
+
@config = MockConfig.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def teardown
|
25
|
+
MockConfig.instance = nil
|
26
|
+
$LOADED_FEATURES.delete_if { |a| a =~ /fixtures\/custom\.rb$/ }
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_initialize_should_init_collections
|
30
|
+
assert @config.original_initialize_called
|
31
|
+
assert @config.load_paths.include?(".")
|
32
|
+
assert @config.load_paths.detect { |v| v =~ /capistrano\/recipes$/ }
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_load_with_options_and_block_should_raise_argument_error
|
36
|
+
assert_raises(ArgumentError) do
|
37
|
+
@config.load(:string => "foo") { something }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_load_with_arguments_and_block_should_raise_argument_error
|
42
|
+
assert_raises(ArgumentError) do
|
43
|
+
@config.load("foo") { something }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_load_from_string_should_eval_in_config_scope
|
48
|
+
@config.load :string => "ping! :here"
|
49
|
+
assert_equal :here, @config.ping
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_load_from_file_shoudld_respect_load_path
|
53
|
+
File.stubs(:file?).returns(false)
|
54
|
+
File.stubs(:file?).with("custom/path/for/file.rb").returns(true)
|
55
|
+
File.stubs(:read).with("custom/path/for/file.rb").returns("ping! :here")
|
56
|
+
|
57
|
+
@config.load_paths << "custom/path/for"
|
58
|
+
@config.load :file => "file.rb"
|
59
|
+
|
60
|
+
assert_equal :here, @config.ping
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_load_from_file_should_respect_load_path_and_appends_rb
|
64
|
+
File.stubs(:file?).returns(false)
|
65
|
+
File.stubs(:file?).with("custom/path/for/file.rb").returns(true)
|
66
|
+
File.stubs(:read).with("custom/path/for/file.rb").returns("ping! :here")
|
67
|
+
|
68
|
+
@config.load_paths << "custom/path/for"
|
69
|
+
@config.load :file => "file"
|
70
|
+
|
71
|
+
assert_equal :here, @config.ping
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_load_from_file_should_raise_load_error_if_file_cannot_be_found
|
75
|
+
File.stubs(:file?).returns(false)
|
76
|
+
assert_raises(LoadError) do
|
77
|
+
@config.load :file => "file"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_load_from_proc_should_eval_proc_in_config_scope
|
82
|
+
@config.load :proc => Proc.new { ping! :here }
|
83
|
+
assert_equal :here, @config.ping
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_load_with_block_should_treat_block_as_proc_parameter
|
87
|
+
@config.load { ping! :here }
|
88
|
+
assert_equal :here, @config.ping
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_load_with_unrecognized_option_should_raise_argument_error
|
92
|
+
assert_raises(ArgumentError) do
|
93
|
+
@config.load :url => "http://www.load-this.test"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_load_with_arguments_should_treat_arguments_as_files
|
98
|
+
File.stubs(:file?).returns(false)
|
99
|
+
File.stubs(:file?).with("./first.rb").returns(true)
|
100
|
+
File.stubs(:file?).with("./second.rb").returns(true)
|
101
|
+
File.stubs(:read).with("./first.rb").returns("ping! 'this'")
|
102
|
+
File.stubs(:read).with("./second.rb").returns("ping << 'that'")
|
103
|
+
assert_nothing_raised { @config.load "first", "second" }
|
104
|
+
assert_equal "thisthat", @config.ping
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_require_from_config_should_load_file_in_config_scope
|
108
|
+
assert_nothing_raised do
|
109
|
+
@config.require "#{File.dirname(__FILE__)}/../fixtures/custom"
|
110
|
+
end
|
111
|
+
assert_equal :custom, @config.ping
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_require_without_config_should_raise_load_error
|
115
|
+
assert_raises(LoadError) do
|
116
|
+
require "#{File.dirname(__FILE__)}/../fixtures/custom"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_require_from_config_should_return_false_when_called_a_second_time_with_same_args
|
121
|
+
assert @config.require("#{File.dirname(__FILE__)}/../fixtures/custom")
|
122
|
+
assert_equal false, @config.require("#{File.dirname(__FILE__)}/../fixtures/custom")
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_require_in_multiple_instances_should_load_recipes_in_each_instance
|
126
|
+
config2 = MockConfig.new
|
127
|
+
@config.require "#{File.dirname(__FILE__)}/../fixtures/custom"
|
128
|
+
config2.require "#{File.dirname(__FILE__)}/../fixtures/custom"
|
129
|
+
assert_equal :custom, @config.ping
|
130
|
+
assert_equal :custom, config2.ping
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,311 @@
|
|
1
|
+
require "utils"
|
2
|
+
require 'capistrano/configuration/namespaces'
|
3
|
+
|
4
|
+
class ConfigurationNamespacesDSLTest < Test::Unit::TestCase
|
5
|
+
class MockConfig
|
6
|
+
attr_reader :original_initialize_called, :options
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@original_initialize_called = true
|
10
|
+
@options = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
include Capistrano::Configuration::Namespaces
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup
|
17
|
+
@config = MockConfig.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_initialize_should_initialize_collections
|
21
|
+
assert @config.original_initialize_called
|
22
|
+
assert @config.tasks.empty?
|
23
|
+
assert @config.namespaces.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_unqualified_task_should_define_task_at_top_namespace
|
27
|
+
assert !@config.tasks.key?(:testing)
|
28
|
+
@config.task(:testing) { puts "something" }
|
29
|
+
assert @config.tasks.key?(:testing)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_qualification_should_define_task_within_namespace
|
33
|
+
@config.namespace(:testing) do
|
34
|
+
task(:nested) { puts "nested" }
|
35
|
+
end
|
36
|
+
|
37
|
+
assert !@config.tasks.key?(:nested)
|
38
|
+
assert @config.namespaces.key?(:testing)
|
39
|
+
assert @config.namespaces[:testing].tasks.key?(:nested)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_namespace_within_namespace_should_define_task_within_nested_namespace
|
43
|
+
@config.namespace :outer do
|
44
|
+
namespace :inner do
|
45
|
+
task :nested do
|
46
|
+
puts "nested"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
assert !@config.tasks.key?(:nested)
|
52
|
+
assert @config.namespaces.key?(:outer)
|
53
|
+
assert @config.namespaces[:outer].namespaces.key?(:inner)
|
54
|
+
assert @config.namespaces[:outer].namespaces[:inner].tasks.key?(:nested)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_pending_desc_should_apply_only_to_immediately_subsequent_task
|
58
|
+
@config.desc "A description"
|
59
|
+
@config.task(:testing) { puts "foo" }
|
60
|
+
@config.task(:another) { puts "bar" }
|
61
|
+
assert_equal "A description", @config.tasks[:testing].desc
|
62
|
+
assert_nil @config.tasks[:another].desc
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_pending_desc_should_apply_only_to_next_task_in_any_namespace
|
66
|
+
@config.desc "A description"
|
67
|
+
@config.namespace(:outer) { task(:testing) { puts "foo" } }
|
68
|
+
assert_equal "A description", @config.namespaces[:outer].tasks[:testing].desc
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_defining_task_without_block_should_raise_error
|
72
|
+
assert_raises(ArgumentError) do
|
73
|
+
@config.task(:testing)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_defining_task_that_shadows_existing_method_should_raise_error
|
78
|
+
assert_raises(ArgumentError) do
|
79
|
+
@config.task(:sprintf) { puts "foo" }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_defining_task_that_shadows_existing_namespace_should_raise_error
|
84
|
+
@config.namespace(:outer) {}
|
85
|
+
assert_raises(ArgumentError) do
|
86
|
+
@config.task(:outer) { puts "foo" }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_defining_namespace_that_shadows_existing_method_should_raise_error
|
91
|
+
assert_raises(ArgumentError) do
|
92
|
+
@config.namespace(:sprintf) {}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_defining_namespace_that_shadows_existing_task_should_raise_error
|
97
|
+
@config.task(:testing) { puts "foo" }
|
98
|
+
assert_raises(ArgumentError) do
|
99
|
+
@config.namespace(:testing) {}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_defining_task_that_shadows_existing_task_should_not_raise_error
|
104
|
+
@config.task(:original) { puts "foo" }
|
105
|
+
assert_nothing_raised do
|
106
|
+
@config.task(:original) { puts "bar" }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_defining_ask_should_add_task_as_method
|
111
|
+
assert !@config.methods.any? { |m| m.to_sym == :original }
|
112
|
+
@config.task(:original) { puts "foo" }
|
113
|
+
assert @config.methods.any? { |m| m.to_sym == :original }
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_calling_defined_task_should_delegate_to_execute_task
|
117
|
+
@config.task(:original) { puts "foo" }
|
118
|
+
@config.expects(:execute_task).with(@config.tasks[:original])
|
119
|
+
@config.original
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_role_inside_namespace_should_raise_error
|
123
|
+
assert_raises(NotImplementedError) do
|
124
|
+
@config.namespace(:outer) do
|
125
|
+
role :app, "hello"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_name_for_top_level_should_be_nil
|
131
|
+
assert_nil @config.name
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_parent_for_top_level_should_be_nil
|
135
|
+
assert_nil @config.parent
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_fqn_for_top_level_should_be_nil
|
139
|
+
assert_nil @config.fully_qualified_name
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_fqn_for_namespace_should_be_the_name_of_the_namespace
|
143
|
+
@config.namespace(:outer) {}
|
144
|
+
assert_equal "outer", @config.namespaces[:outer].fully_qualified_name
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_parent_for_namespace_should_be_the_top_level
|
148
|
+
@config.namespace(:outer) {}
|
149
|
+
assert_equal @config, @config.namespaces[:outer].parent
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_fqn_for_nested_namespace_should_be_color_delimited
|
153
|
+
@config.namespace(:outer) { namespace(:inner) {} }
|
154
|
+
assert_equal "outer:inner", @config.namespaces[:outer].namespaces[:inner].fully_qualified_name
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_parent_for_nested_namespace_should_be_the_nesting_namespace
|
158
|
+
@config.namespace(:outer) { namespace(:inner) {} }
|
159
|
+
assert_equal @config.namespaces[:outer], @config.namespaces[:outer].namespaces[:inner].parent
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_find_task_should_dereference_nested_tasks
|
163
|
+
@config.namespace(:outer) do
|
164
|
+
namespace(:inner) { task(:nested) { puts "nested" } }
|
165
|
+
end
|
166
|
+
|
167
|
+
task = @config.find_task("outer:inner:nested")
|
168
|
+
assert_not_nil task
|
169
|
+
assert_equal "outer:inner:nested", task.fully_qualified_name
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_find_task_should_return_nil_if_no_task_matches
|
173
|
+
assert_nil @config.find_task("outer:inner:nested")
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_find_task_should_return_default_if_deferences_to_namespace_and_namespace_has_default
|
177
|
+
@config.namespace(:outer) do
|
178
|
+
namespace(:inner) { task(:default) { puts "nested" } }
|
179
|
+
end
|
180
|
+
|
181
|
+
task = @config.find_task("outer:inner")
|
182
|
+
assert_not_nil task
|
183
|
+
assert_equal :default, task.name
|
184
|
+
assert_equal "outer:inner", task.namespace.fully_qualified_name
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_find_task_should_return_nil_if_deferences_to_namespace_and_namespace_has_no_default
|
188
|
+
@config.namespace(:outer) do
|
189
|
+
namespace(:inner) { task(:nested) { puts "nested" } }
|
190
|
+
end
|
191
|
+
|
192
|
+
assert_nil @config.find_task("outer:inner")
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_default_task_should_return_nil_for_top_level
|
196
|
+
@config.task(:default) {}
|
197
|
+
assert_nil @config.default_task
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_default_task_should_return_nil_for_namespace_without_default
|
201
|
+
@config.namespace(:outer) { task(:nested) { puts "nested" } }
|
202
|
+
assert_nil @config.namespaces[:outer].default_task
|
203
|
+
end
|
204
|
+
|
205
|
+
def test_default_task_should_return_task_for_namespace_with_default
|
206
|
+
@config.namespace(:outer) { task(:default) { puts "nested" } }
|
207
|
+
task = @config.namespaces[:outer].default_task
|
208
|
+
assert_not_nil task
|
209
|
+
assert_equal :default, task.name
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_task_list_should_return_only_tasks_immediately_within_namespace
|
213
|
+
@config.task(:first) { puts "here" }
|
214
|
+
@config.namespace(:outer) do
|
215
|
+
task(:second) { puts "here" }
|
216
|
+
namespace(:inner) do
|
217
|
+
task(:third) { puts "here" }
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
assert_equal %w(first), @config.task_list.map { |t| t.fully_qualified_name }
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_task_list_with_all_should_return_all_tasks_under_this_namespace_recursively
|
225
|
+
@config.task(:first) { puts "here" }
|
226
|
+
@config.namespace(:outer) do
|
227
|
+
task(:second) { puts "here" }
|
228
|
+
namespace(:inner) do
|
229
|
+
task(:third) { puts "here" }
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
assert_equal %w(first outer:inner:third outer:second), @config.task_list(:all).map { |t| t.fully_qualified_name }.sort
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_namespace_should_respond_to_its_parents_methods
|
237
|
+
@config.namespace(:outer) {}
|
238
|
+
ns = @config.namespaces[:outer]
|
239
|
+
assert ns.respond_to?(:original_initialize_called)
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_namespace_should_accept_respond_to_with_include_priv_parameter
|
243
|
+
@config.namespace(:outer) {}
|
244
|
+
ns = @config.namespaces[:outer]
|
245
|
+
assert ns.respond_to?(:original_initialize_called, true)
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_namespace_should_delegate_unknown_messages_to_its_parent
|
249
|
+
@config.namespace(:outer) {}
|
250
|
+
ns = @config.namespaces[:outer]
|
251
|
+
assert ns.original_initialize_called
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_namespace_should_not_understand_messages_that_neither_it_nor_its_parent_understands
|
255
|
+
@config.namespace(:outer) {}
|
256
|
+
ns = @config.namespaces[:outer]
|
257
|
+
assert_raises(NoMethodError) { ns.alskdfjlsf }
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_search_task_should_find_tasks_in_current_namespace
|
261
|
+
@config.namespace(:outer) do
|
262
|
+
namespace(:inner) do
|
263
|
+
task(:third) { puts "here" }
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
inner = @config.namespaces[:outer].namespaces[:inner]
|
268
|
+
assert_equal inner.tasks[:third], inner.search_task(:third)
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_search_task_should_find_tasks_in_parent_namespace
|
272
|
+
@config.task(:first) { puts "here" }
|
273
|
+
@config.namespace(:outer) do
|
274
|
+
task(:second) { puts "here" }
|
275
|
+
namespace(:inner) do
|
276
|
+
task(:third) { puts "here" }
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
inner = @config.namespaces[:outer].namespaces[:inner]
|
281
|
+
assert_equal @config.tasks[:first], inner.search_task(:first)
|
282
|
+
end
|
283
|
+
|
284
|
+
def test_search_task_should_return_nil_if_no_tasks_are_found
|
285
|
+
@config.namespace(:outer) { namespace(:inner) {} }
|
286
|
+
inner = @config.namespaces[:outer].namespaces[:inner]
|
287
|
+
assert_nil inner.search_task(:first)
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_top_should_return_self_if_self_is_top
|
291
|
+
assert_equal @config, @config.top
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_top_should_return_parent_if_parent_is_top
|
295
|
+
@config.namespace(:outer) {}
|
296
|
+
assert_equal @config, @config.namespaces[:outer].top
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_top_should_return_topmost_parent_if_self_is_deeply_nested
|
300
|
+
@config.namespace(:outer) { namespace(:middle) { namespace(:inner) {} } }
|
301
|
+
assert_equal @config, @config.namespaces[:outer].namespaces[:middle].namespaces[:inner].top
|
302
|
+
end
|
303
|
+
|
304
|
+
def test_find_task_should_return_nil_when_empty_inner_task
|
305
|
+
@config.namespace :outer do
|
306
|
+
namespace :inner do
|
307
|
+
end
|
308
|
+
end
|
309
|
+
assert_nil @config.find_task("outer::inner")
|
310
|
+
end
|
311
|
+
end
|