minmb-capistrano 2.15.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. data/.gitignore +10 -0
  2. data/.travis.yml +7 -0
  3. data/CHANGELOG +1170 -0
  4. data/Gemfile +13 -0
  5. data/README.md +94 -0
  6. data/Rakefile +11 -0
  7. data/bin/cap +4 -0
  8. data/bin/capify +92 -0
  9. data/capistrano.gemspec +40 -0
  10. data/lib/capistrano.rb +5 -0
  11. data/lib/capistrano/callback.rb +45 -0
  12. data/lib/capistrano/cli.rb +47 -0
  13. data/lib/capistrano/cli/execute.rb +85 -0
  14. data/lib/capistrano/cli/help.rb +125 -0
  15. data/lib/capistrano/cli/help.txt +81 -0
  16. data/lib/capistrano/cli/options.rb +243 -0
  17. data/lib/capistrano/cli/ui.rb +40 -0
  18. data/lib/capistrano/command.rb +303 -0
  19. data/lib/capistrano/configuration.rb +57 -0
  20. data/lib/capistrano/configuration/actions/file_transfer.rb +50 -0
  21. data/lib/capistrano/configuration/actions/inspect.rb +46 -0
  22. data/lib/capistrano/configuration/actions/invocation.rb +329 -0
  23. data/lib/capistrano/configuration/alias_task.rb +26 -0
  24. data/lib/capistrano/configuration/callbacks.rb +147 -0
  25. data/lib/capistrano/configuration/connections.rb +237 -0
  26. data/lib/capistrano/configuration/execution.rb +142 -0
  27. data/lib/capistrano/configuration/loading.rb +205 -0
  28. data/lib/capistrano/configuration/log_formatters.rb +75 -0
  29. data/lib/capistrano/configuration/namespaces.rb +223 -0
  30. data/lib/capistrano/configuration/roles.rb +77 -0
  31. data/lib/capistrano/configuration/servers.rb +116 -0
  32. data/lib/capistrano/configuration/variables.rb +127 -0
  33. data/lib/capistrano/errors.rb +19 -0
  34. data/lib/capistrano/ext/multistage.rb +64 -0
  35. data/lib/capistrano/ext/string.rb +5 -0
  36. data/lib/capistrano/extensions.rb +57 -0
  37. data/lib/capistrano/fix_rake_deprecated_dsl.rb +8 -0
  38. data/lib/capistrano/logger.rb +166 -0
  39. data/lib/capistrano/processable.rb +57 -0
  40. data/lib/capistrano/recipes/compat.rb +32 -0
  41. data/lib/capistrano/recipes/deploy.rb +625 -0
  42. data/lib/capistrano/recipes/deploy/assets.rb +201 -0
  43. data/lib/capistrano/recipes/deploy/dependencies.rb +44 -0
  44. data/lib/capistrano/recipes/deploy/local_dependency.rb +54 -0
  45. data/lib/capistrano/recipes/deploy/remote_dependency.rb +117 -0
  46. data/lib/capistrano/recipes/deploy/scm.rb +19 -0
  47. data/lib/capistrano/recipes/deploy/scm/accurev.rb +169 -0
  48. data/lib/capistrano/recipes/deploy/scm/base.rb +200 -0
  49. data/lib/capistrano/recipes/deploy/scm/bzr.rb +86 -0
  50. data/lib/capistrano/recipes/deploy/scm/cvs.rb +153 -0
  51. data/lib/capistrano/recipes/deploy/scm/darcs.rb +96 -0
  52. data/lib/capistrano/recipes/deploy/scm/git.rb +293 -0
  53. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +137 -0
  54. data/lib/capistrano/recipes/deploy/scm/none.rb +55 -0
  55. data/lib/capistrano/recipes/deploy/scm/perforce.rb +152 -0
  56. data/lib/capistrano/recipes/deploy/scm/subversion.rb +121 -0
  57. data/lib/capistrano/recipes/deploy/strategy.rb +19 -0
  58. data/lib/capistrano/recipes/deploy/strategy/base.rb +92 -0
  59. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +20 -0
  60. data/lib/capistrano/recipes/deploy/strategy/copy.rb +338 -0
  61. data/lib/capistrano/recipes/deploy/strategy/export.rb +20 -0
  62. data/lib/capistrano/recipes/deploy/strategy/remote.rb +52 -0
  63. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +57 -0
  64. data/lib/capistrano/recipes/deploy/strategy/unshared_remote_cache.rb +21 -0
  65. data/lib/capistrano/recipes/standard.rb +37 -0
  66. data/lib/capistrano/recipes/templates/maintenance.rhtml +53 -0
  67. data/lib/capistrano/role.rb +102 -0
  68. data/lib/capistrano/server_definition.rb +56 -0
  69. data/lib/capistrano/shell.rb +265 -0
  70. data/lib/capistrano/ssh.rb +95 -0
  71. data/lib/capistrano/task_definition.rb +77 -0
  72. data/lib/capistrano/transfer.rb +218 -0
  73. data/lib/capistrano/version.rb +11 -0
  74. data/test/cli/execute_test.rb +132 -0
  75. data/test/cli/help_test.rb +165 -0
  76. data/test/cli/options_test.rb +329 -0
  77. data/test/cli/ui_test.rb +28 -0
  78. data/test/cli_test.rb +17 -0
  79. data/test/command_test.rb +322 -0
  80. data/test/configuration/actions/file_transfer_test.rb +61 -0
  81. data/test/configuration/actions/inspect_test.rb +76 -0
  82. data/test/configuration/actions/invocation_test.rb +288 -0
  83. data/test/configuration/alias_task_test.rb +118 -0
  84. data/test/configuration/callbacks_test.rb +201 -0
  85. data/test/configuration/connections_test.rb +439 -0
  86. data/test/configuration/execution_test.rb +175 -0
  87. data/test/configuration/loading_test.rb +148 -0
  88. data/test/configuration/namespace_dsl_test.rb +332 -0
  89. data/test/configuration/roles_test.rb +157 -0
  90. data/test/configuration/servers_test.rb +183 -0
  91. data/test/configuration/variables_test.rb +190 -0
  92. data/test/configuration_test.rb +77 -0
  93. data/test/deploy/local_dependency_test.rb +76 -0
  94. data/test/deploy/remote_dependency_test.rb +146 -0
  95. data/test/deploy/scm/accurev_test.rb +23 -0
  96. data/test/deploy/scm/base_test.rb +55 -0
  97. data/test/deploy/scm/bzr_test.rb +51 -0
  98. data/test/deploy/scm/darcs_test.rb +37 -0
  99. data/test/deploy/scm/git_test.rb +221 -0
  100. data/test/deploy/scm/mercurial_test.rb +134 -0
  101. data/test/deploy/scm/none_test.rb +35 -0
  102. data/test/deploy/scm/perforce_test.rb +23 -0
  103. data/test/deploy/scm/subversion_test.rb +40 -0
  104. data/test/deploy/strategy/copy_test.rb +360 -0
  105. data/test/extensions_test.rb +69 -0
  106. data/test/fixtures/cli_integration.rb +5 -0
  107. data/test/fixtures/config.rb +5 -0
  108. data/test/fixtures/custom.rb +3 -0
  109. data/test/logger_formatting_test.rb +149 -0
  110. data/test/logger_test.rb +134 -0
  111. data/test/recipes_test.rb +25 -0
  112. data/test/role_test.rb +11 -0
  113. data/test/server_definition_test.rb +121 -0
  114. data/test/shell_test.rb +96 -0
  115. data/test/ssh_test.rb +113 -0
  116. data/test/task_definition_test.rb +117 -0
  117. data/test/transfer_test.rb +168 -0
  118. data/test/utils.rb +37 -0
  119. metadata +316 -0
@@ -0,0 +1,148 @@
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.expand_path(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.expand_path(File.dirname(__FILE__))}/../fixtures/custom")
122
+ assert_equal false, @config.require("#{File.expand_path(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.expand_path(File.dirname(__FILE__))}/../fixtures/custom"
128
+ config2.require "#{File.expand_path(File.dirname(__FILE__))}/../fixtures/custom"
129
+ assert_equal :custom, @config.ping
130
+ assert_equal :custom, config2.ping
131
+ end
132
+
133
+ def test_file_in_load_path_returns_true_when_file_is_in_load_path
134
+ File.stubs(:file?).returns(false)
135
+ File.stubs(:file?).with("custom/path/for/file.rb").returns(true)
136
+
137
+ @config.load_paths << "custom/path/for"
138
+ assert_equal true, @config.file_in_load_path?("file")
139
+ end
140
+
141
+ def test_file_in_load_path_returns_false_when_file_is_not_in_load_path
142
+ File.stubs(:file?).returns(false)
143
+ File.stubs(:file?).with("custom/path/for/file.rb").returns(false)
144
+
145
+ @config.load_paths << "custom/path/for"
146
+ assert_equal false, @config.file_in_load_path?("file")
147
+ end
148
+ end
@@ -0,0 +1,332 @@
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
+
312
+ def test_kernel_method_clashing_should_not_affect_method_delegation_to_parent
313
+ @config.class.class_eval do
314
+ def some_weird_method() 'config' end
315
+ end
316
+
317
+ @config.namespace(:clash) {}
318
+ namespace = @config.namespaces[:clash]
319
+ assert_equal 'config', namespace.some_weird_method
320
+
321
+ Kernel.module_eval do
322
+ def some_weird_method() 'kernel' end
323
+ end
324
+
325
+ @config.namespace(:clash2) {}
326
+ namespace = @config.namespaces[:clash2]
327
+ assert_equal 'config', namespace.some_weird_method
328
+
329
+ Kernel.send :remove_method, :some_weird_method
330
+ @config.class.send :remove_method, :some_weird_method
331
+ end
332
+ end