capistrano-edge 2.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/CHANGELOG.rdoc +770 -0
  2. data/Manifest +104 -0
  3. data/README.rdoc +66 -0
  4. data/Rakefile +35 -0
  5. data/bin/cap +4 -0
  6. data/bin/capify +95 -0
  7. data/capistrano.gemspec +51 -0
  8. data/examples/sample.rb +14 -0
  9. data/lib/capistrano.rb +2 -0
  10. data/lib/capistrano/callback.rb +45 -0
  11. data/lib/capistrano/cli.rb +47 -0
  12. data/lib/capistrano/cli/execute.rb +84 -0
  13. data/lib/capistrano/cli/help.rb +125 -0
  14. data/lib/capistrano/cli/help.txt +75 -0
  15. data/lib/capistrano/cli/options.rb +224 -0
  16. data/lib/capistrano/cli/ui.rb +40 -0
  17. data/lib/capistrano/command.rb +283 -0
  18. data/lib/capistrano/configuration.rb +43 -0
  19. data/lib/capistrano/configuration/actions/file_transfer.rb +47 -0
  20. data/lib/capistrano/configuration/actions/inspect.rb +46 -0
  21. data/lib/capistrano/configuration/actions/invocation.rb +293 -0
  22. data/lib/capistrano/configuration/callbacks.rb +148 -0
  23. data/lib/capistrano/configuration/connections.rb +204 -0
  24. data/lib/capistrano/configuration/execution.rb +143 -0
  25. data/lib/capistrano/configuration/loading.rb +197 -0
  26. data/lib/capistrano/configuration/namespaces.rb +197 -0
  27. data/lib/capistrano/configuration/roles.rb +73 -0
  28. data/lib/capistrano/configuration/servers.rb +85 -0
  29. data/lib/capistrano/configuration/variables.rb +127 -0
  30. data/lib/capistrano/errors.rb +15 -0
  31. data/lib/capistrano/extensions.rb +57 -0
  32. data/lib/capistrano/logger.rb +59 -0
  33. data/lib/capistrano/processable.rb +53 -0
  34. data/lib/capistrano/recipes/compat.rb +32 -0
  35. data/lib/capistrano/recipes/deploy.rb +438 -0
  36. data/lib/capistrano/recipes/deploy/dependencies.rb +44 -0
  37. data/lib/capistrano/recipes/deploy/local_dependency.rb +54 -0
  38. data/lib/capistrano/recipes/deploy/remote_dependency.rb +105 -0
  39. data/lib/capistrano/recipes/deploy/scm.rb +19 -0
  40. data/lib/capistrano/recipes/deploy/scm/accurev.rb +169 -0
  41. data/lib/capistrano/recipes/deploy/scm/base.rb +196 -0
  42. data/lib/capistrano/recipes/deploy/scm/bzr.rb +83 -0
  43. data/lib/capistrano/recipes/deploy/scm/cvs.rb +152 -0
  44. data/lib/capistrano/recipes/deploy/scm/darcs.rb +85 -0
  45. data/lib/capistrano/recipes/deploy/scm/git.rb +274 -0
  46. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +137 -0
  47. data/lib/capistrano/recipes/deploy/scm/none.rb +44 -0
  48. data/lib/capistrano/recipes/deploy/scm/perforce.rb +138 -0
  49. data/lib/capistrano/recipes/deploy/scm/subversion.rb +121 -0
  50. data/lib/capistrano/recipes/deploy/strategy.rb +19 -0
  51. data/lib/capistrano/recipes/deploy/strategy/base.rb +79 -0
  52. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +20 -0
  53. data/lib/capistrano/recipes/deploy/strategy/copy.rb +210 -0
  54. data/lib/capistrano/recipes/deploy/strategy/export.rb +20 -0
  55. data/lib/capistrano/recipes/deploy/strategy/remote.rb +52 -0
  56. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +56 -0
  57. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +53 -0
  58. data/lib/capistrano/recipes/ext/rails-database-migrations.rb +50 -0
  59. data/lib/capistrano/recipes/ext/web-disable-enable.rb +40 -0
  60. data/lib/capistrano/recipes/standard.rb +37 -0
  61. data/lib/capistrano/recipes/templates/maintenance.rhtml +53 -0
  62. data/lib/capistrano/recipes/upgrade.rb +33 -0
  63. data/lib/capistrano/role.rb +102 -0
  64. data/lib/capistrano/server_definition.rb +56 -0
  65. data/lib/capistrano/shell.rb +260 -0
  66. data/lib/capistrano/ssh.rb +99 -0
  67. data/lib/capistrano/task_definition.rb +70 -0
  68. data/lib/capistrano/transfer.rb +216 -0
  69. data/lib/capistrano/version.rb +18 -0
  70. data/setup.rb +1346 -0
  71. data/test/cli/execute_test.rb +132 -0
  72. data/test/cli/help_test.rb +165 -0
  73. data/test/cli/options_test.rb +317 -0
  74. data/test/cli/ui_test.rb +28 -0
  75. data/test/cli_test.rb +17 -0
  76. data/test/command_test.rb +286 -0
  77. data/test/configuration/actions/file_transfer_test.rb +61 -0
  78. data/test/configuration/actions/inspect_test.rb +65 -0
  79. data/test/configuration/actions/invocation_test.rb +224 -0
  80. data/test/configuration/callbacks_test.rb +220 -0
  81. data/test/configuration/connections_test.rb +349 -0
  82. data/test/configuration/execution_test.rb +175 -0
  83. data/test/configuration/loading_test.rb +132 -0
  84. data/test/configuration/namespace_dsl_test.rb +311 -0
  85. data/test/configuration/roles_test.rb +144 -0
  86. data/test/configuration/servers_test.rb +121 -0
  87. data/test/configuration/variables_test.rb +184 -0
  88. data/test/configuration_test.rb +88 -0
  89. data/test/deploy/local_dependency_test.rb +76 -0
  90. data/test/deploy/remote_dependency_test.rb +114 -0
  91. data/test/deploy/scm/accurev_test.rb +23 -0
  92. data/test/deploy/scm/base_test.rb +55 -0
  93. data/test/deploy/scm/git_test.rb +184 -0
  94. data/test/deploy/scm/mercurial_test.rb +129 -0
  95. data/test/deploy/scm/none_test.rb +35 -0
  96. data/test/deploy/strategy/copy_test.rb +258 -0
  97. data/test/extensions_test.rb +69 -0
  98. data/test/fixtures/cli_integration.rb +5 -0
  99. data/test/fixtures/config.rb +5 -0
  100. data/test/fixtures/custom.rb +3 -0
  101. data/test/logger_test.rb +123 -0
  102. data/test/role_test.rb +11 -0
  103. data/test/server_definition_test.rb +121 -0
  104. data/test/shell_test.rb +90 -0
  105. data/test/ssh_test.rb +104 -0
  106. data/test/task_definition_test.rb +101 -0
  107. data/test/transfer_test.rb +160 -0
  108. data/test/utils.rb +38 -0
  109. metadata +321 -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