capistrano 1.4.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/CHANGELOG +140 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README +22 -14
  4. data/bin/cap +1 -8
  5. data/bin/capify +77 -0
  6. data/examples/sample.rb +10 -109
  7. data/lib/capistrano.rb +1 -0
  8. data/lib/capistrano/callback.rb +41 -0
  9. data/lib/capistrano/cli.rb +17 -317
  10. data/lib/capistrano/cli/execute.rb +82 -0
  11. data/lib/capistrano/cli/help.rb +102 -0
  12. data/lib/capistrano/cli/help.txt +53 -0
  13. data/lib/capistrano/cli/options.rb +183 -0
  14. data/lib/capistrano/cli/ui.rb +28 -0
  15. data/lib/capistrano/command.rb +62 -29
  16. data/lib/capistrano/configuration.rb +25 -226
  17. data/lib/capistrano/configuration/actions/file_transfer.rb +35 -0
  18. data/lib/capistrano/configuration/actions/inspect.rb +46 -0
  19. data/lib/capistrano/configuration/actions/invocation.rb +127 -0
  20. data/lib/capistrano/configuration/callbacks.rb +148 -0
  21. data/lib/capistrano/configuration/connections.rb +159 -0
  22. data/lib/capistrano/configuration/execution.rb +126 -0
  23. data/lib/capistrano/configuration/loading.rb +112 -0
  24. data/lib/capistrano/configuration/namespaces.rb +190 -0
  25. data/lib/capistrano/configuration/roles.rb +51 -0
  26. data/lib/capistrano/configuration/servers.rb +75 -0
  27. data/lib/capistrano/configuration/variables.rb +127 -0
  28. data/lib/capistrano/errors.rb +15 -0
  29. data/lib/capistrano/extensions.rb +27 -8
  30. data/lib/capistrano/gateway.rb +54 -29
  31. data/lib/capistrano/logger.rb +11 -11
  32. data/lib/capistrano/recipes/compat.rb +32 -0
  33. data/lib/capistrano/recipes/deploy.rb +483 -0
  34. data/lib/capistrano/recipes/deploy/dependencies.rb +44 -0
  35. data/lib/capistrano/recipes/deploy/local_dependency.rb +46 -0
  36. data/lib/capistrano/recipes/deploy/remote_dependency.rb +65 -0
  37. data/lib/capistrano/recipes/deploy/scm.rb +19 -0
  38. data/lib/capistrano/recipes/deploy/scm/base.rb +180 -0
  39. data/lib/capistrano/recipes/deploy/scm/bzr.rb +86 -0
  40. data/lib/capistrano/recipes/deploy/scm/cvs.rb +151 -0
  41. data/lib/capistrano/recipes/deploy/scm/darcs.rb +85 -0
  42. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +129 -0
  43. data/lib/capistrano/recipes/deploy/scm/perforce.rb +126 -0
  44. data/lib/capistrano/recipes/deploy/scm/subversion.rb +103 -0
  45. data/lib/capistrano/recipes/deploy/strategy.rb +19 -0
  46. data/lib/capistrano/recipes/deploy/strategy/base.rb +64 -0
  47. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +20 -0
  48. data/lib/capistrano/recipes/deploy/strategy/copy.rb +143 -0
  49. data/lib/capistrano/recipes/deploy/strategy/export.rb +20 -0
  50. data/lib/capistrano/recipes/deploy/strategy/remote.rb +52 -0
  51. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +47 -0
  52. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +53 -0
  53. data/lib/capistrano/recipes/standard.rb +26 -276
  54. data/lib/capistrano/recipes/templates/maintenance.rhtml +1 -1
  55. data/lib/capistrano/recipes/upgrade.rb +33 -0
  56. data/lib/capistrano/server_definition.rb +51 -0
  57. data/lib/capistrano/shell.rb +125 -81
  58. data/lib/capistrano/ssh.rb +80 -36
  59. data/lib/capistrano/task_definition.rb +69 -0
  60. data/lib/capistrano/upload.rb +146 -0
  61. data/lib/capistrano/version.rb +13 -17
  62. data/test/cli/execute_test.rb +132 -0
  63. data/test/cli/help_test.rb +139 -0
  64. data/test/cli/options_test.rb +226 -0
  65. data/test/cli/ui_test.rb +28 -0
  66. data/test/cli_test.rb +17 -0
  67. data/test/command_test.rb +284 -25
  68. data/test/configuration/actions/file_transfer_test.rb +40 -0
  69. data/test/configuration/actions/inspect_test.rb +62 -0
  70. data/test/configuration/actions/invocation_test.rb +195 -0
  71. data/test/configuration/callbacks_test.rb +206 -0
  72. data/test/configuration/connections_test.rb +288 -0
  73. data/test/configuration/execution_test.rb +159 -0
  74. data/test/configuration/loading_test.rb +119 -0
  75. data/test/configuration/namespace_dsl_test.rb +283 -0
  76. data/test/configuration/roles_test.rb +47 -0
  77. data/test/configuration/servers_test.rb +90 -0
  78. data/test/configuration/variables_test.rb +180 -0
  79. data/test/configuration_test.rb +60 -212
  80. data/test/deploy/scm/base_test.rb +55 -0
  81. data/test/deploy/strategy/copy_test.rb +146 -0
  82. data/test/extensions_test.rb +69 -0
  83. data/test/fixtures/cli_integration.rb +5 -0
  84. data/test/fixtures/custom.rb +2 -2
  85. data/test/gateway_test.rb +167 -0
  86. data/test/logger_test.rb +123 -0
  87. data/test/server_definition_test.rb +108 -0
  88. data/test/shell_test.rb +64 -0
  89. data/test/ssh_test.rb +67 -154
  90. data/test/task_definition_test.rb +101 -0
  91. data/test/upload_test.rb +131 -0
  92. data/test/utils.rb +31 -39
  93. data/test/version_test.rb +24 -0
  94. metadata +145 -98
  95. data/THANKS +0 -4
  96. data/lib/capistrano/actor.rb +0 -567
  97. data/lib/capistrano/generators/rails/deployment/deployment_generator.rb +0 -25
  98. data/lib/capistrano/generators/rails/deployment/templates/capistrano.rake +0 -49
  99. data/lib/capistrano/generators/rails/deployment/templates/deploy.rb +0 -122
  100. data/lib/capistrano/generators/rails/loader.rb +0 -20
  101. data/lib/capistrano/scm/base.rb +0 -61
  102. data/lib/capistrano/scm/baz.rb +0 -118
  103. data/lib/capistrano/scm/bzr.rb +0 -70
  104. data/lib/capistrano/scm/cvs.rb +0 -129
  105. data/lib/capistrano/scm/darcs.rb +0 -27
  106. data/lib/capistrano/scm/mercurial.rb +0 -83
  107. data/lib/capistrano/scm/perforce.rb +0 -139
  108. data/lib/capistrano/scm/subversion.rb +0 -128
  109. data/lib/capistrano/transfer.rb +0 -97
  110. data/lib/capistrano/utils.rb +0 -26
  111. data/test/actor_test.rb +0 -402
  112. data/test/scm/cvs_test.rb +0 -196
  113. data/test/scm/subversion_test.rb +0 -145
@@ -0,0 +1,64 @@
1
+ require "#{File.dirname(__FILE__)}/utils"
2
+ require 'capistrano/configuration'
3
+ require 'capistrano/shell'
4
+
5
+ class ShellTest < Test::Unit::TestCase
6
+ def setup
7
+ @config = Capistrano::Configuration.new
8
+ @shell = Capistrano::Shell.new(@config)
9
+ @shell.stubs(:puts)
10
+ end
11
+
12
+ def test_readline_fallback_prompt_should_write_to_stdout_and_read_from_stdin
13
+ STDOUT.expects(:print).with("prompt> ")
14
+ STDOUT.expects(:flush)
15
+ STDIN.expects(:gets).returns("hi\n")
16
+ assert_equal "hi\n", Capistrano::Shell::ReadlineFallback.readline("prompt> ")
17
+ end
18
+
19
+ def test_question_mark_as_input_should_trigger_help
20
+ @shell.expects(:read_line).returns("?")
21
+ @shell.expects(:help)
22
+ assert @shell.read_and_execute
23
+ end
24
+
25
+ def test_help_as_input_should_trigger_help
26
+ @shell.expects(:read_line).returns("help")
27
+ @shell.expects(:help)
28
+ assert @shell.read_and_execute
29
+ end
30
+
31
+ def test_quit_as_input_should_cause_read_and_execute_to_return_false
32
+ @shell.expects(:read_line).returns("quit")
33
+ assert !@shell.read_and_execute
34
+ end
35
+
36
+ def test_exit_as_input_should_cause_read_and_execute_to_return_false
37
+ @shell.expects(:read_line).returns("exit")
38
+ assert !@shell.read_and_execute
39
+ end
40
+
41
+ def test_set_should_parse_flag_and_value_and_call_set_option
42
+ @shell.expects(:read_line).returns("set -v 5")
43
+ @shell.expects(:set_option).with("v", "5")
44
+ assert @shell.read_and_execute
45
+ end
46
+
47
+ def test_text_without_with_or_on_gets_processed_verbatim
48
+ @shell.expects(:read_line).returns("hello world")
49
+ @shell.expects(:process_command).with(nil, nil, "hello world")
50
+ assert @shell.read_and_execute
51
+ end
52
+
53
+ def test_text_with_with_gets_processed_with_with # lol
54
+ @shell.expects(:read_line).returns("with app,db hello world")
55
+ @shell.expects(:process_command).with("with", "app,db", "hello world")
56
+ assert @shell.read_and_execute
57
+ end
58
+
59
+ def test_text_with_on_gets_processed_with_on
60
+ @shell.expects(:read_line).returns("on app,db hello world")
61
+ @shell.expects(:process_command).with("on", "app,db", "hello world")
62
+ assert @shell.read_and_execute
63
+ end
64
+ end
@@ -1,184 +1,97 @@
1
- $:.unshift File.dirname(__FILE__) + "/../lib"
2
-
3
- require File.dirname(__FILE__) + "/utils"
4
- require 'test/unit'
1
+ require "#{File.dirname(__FILE__)}/utils"
5
2
  require 'capistrano/ssh'
6
3
 
7
4
  class SSHTest < Test::Unit::TestCase
8
- class MockSSH
9
- AuthenticationFailed = Net::SSH::AuthenticationFailed
10
-
11
- class <<self
12
- attr_accessor :story
13
- attr_accessor :invocations
14
- end
5
+ def setup
6
+ @options = { :username => nil,
7
+ :password => nil,
8
+ :port => 22,
9
+ :auth_methods => %w(publickey hostbased) }
10
+ @server = server("capistrano")
11
+ end
15
12
 
16
- def self.start(server, opts, &block)
17
- @invocations << [server, opts, block]
18
- err = story.shift
19
- raise err if err
20
- end
13
+ def test_connect_with_bare_server_without_options_or_config_with_public_key_succeeding_should_only_loop_once
14
+ Net::SSH.expects(:start).with(@server.host, @options).returns(success = Object.new)
15
+ assert_equal success, Capistrano::SSH.connect(@server)
21
16
  end
22
17
 
23
- def setup
24
- @config = MockConfiguration.new
25
- @config[:user] = 'demo'
26
- @config[:password] = 'c0c0nutfr0st1ng'
27
- MockSSH.story = []
28
- MockSSH.invocations = []
18
+ def test_connect_with_bare_server_without_options_with_public_key_failing_should_try_password
19
+ Net::SSH.expects(:start).with(@server.host, @options).raises(Net::SSH::AuthenticationFailed)
20
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).returns(success = Object.new)
21
+ assert_equal success, Capistrano::SSH.connect(@server, :password => "f4b13n")
29
22
  end
30
23
 
31
- def test_publickey_auth_succeeds_default_port_no_block
32
- Net.const_during(:SSH, MockSSH) do
33
- Capistrano::SSH.connect('demo.server.i', @config)
24
+ def test_connect_with_bare_server_without_options_public_key_and_password_failing_should_raise_error
25
+ Net::SSH.expects(:start).with(@server.host, @options).raises(Net::SSH::AuthenticationFailed)
26
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).raises(Net::SSH::AuthenticationFailed)
27
+ assert_raises(Net::SSH::AuthenticationFailed) do
28
+ Capistrano::SSH.connect(@server, :password => "f4b13n")
34
29
  end
35
-
36
- assert_equal 1, MockSSH.invocations.length
37
- assert_equal 'demo.server.i', MockSSH.invocations.first[0]
38
- assert_equal 22, MockSSH.invocations.first[1][:port]
39
- assert_equal 'demo', MockSSH.invocations.first[1][:username]
40
- assert_nil MockSSH.invocations.first[1][:password]
41
- assert_equal %w(publickey hostbased),
42
- MockSSH.invocations.first[1][:auth_methods]
43
- assert_nil MockSSH.invocations.first[2]
44
30
  end
45
-
46
- def test_explicit_ssh_ports_in_server_string_no_block
47
- Net.const_during(:SSH, MockSSH) do
48
- Capistrano::SSH.connect('demo.server.i:8088', @config)
49
- end
50
31
 
51
- assert_equal 1, MockSSH.invocations.length
52
- assert_equal 'demo.server.i', MockSSH.invocations.first[0]
53
- assert_equal '8088', MockSSH.invocations.first[1][:port]
54
- assert_equal 'demo', MockSSH.invocations.first[1][:username]
32
+ def test_connect_with_bare_server_and_user_via_public_key_should_pass_user_to_net_ssh
33
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "jamis")).returns(success = Object.new)
34
+ assert_equal success, Capistrano::SSH.connect(@server, :user => "jamis")
55
35
  end
56
-
57
- def test_explicit_ssh_username_in_server_string_no_block
58
- Net.const_during(:SSH, MockSSH) do
59
- Capistrano::SSH.connect('bob@demo.server.i', @config)
60
- end
61
36
 
62
- assert_equal 1, MockSSH.invocations.length
63
- assert_equal 'demo.server.i', MockSSH.invocations.first[0]
64
- assert_equal 22, MockSSH.invocations.first[1][:port]
65
- assert_equal 'bob', MockSSH.invocations.first[1][:username]
37
+ def test_connect_with_bare_server_and_user_via_password_should_pass_user_to_net_ssh
38
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "jamis")).raises(Net::SSH::AuthenticationFailed)
39
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "jamis", :password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).returns(success = Object.new)
40
+ assert_equal success, Capistrano::SSH.connect(@server, :user => "jamis", :password => "f4b13n")
66
41
  end
67
-
68
- def test_explicit_ssh_username_and_port_in_server_string_no_block
69
- Net.const_during(:SSH, MockSSH) do
70
- Capistrano::SSH.connect('bob@demo.server.i:8088', @config)
71
- end
72
42
 
73
- assert_equal 1, MockSSH.invocations.length
74
- assert_equal 'demo.server.i', MockSSH.invocations.first[0]
75
- assert_equal '8088', MockSSH.invocations.first[1][:port]
76
- assert_equal 'bob', MockSSH.invocations.first[1][:username]
43
+ def test_connect_with_bare_server_with_explicit_port_should_pass_port_to_net_ssh
44
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:port => 1234)).returns(success = Object.new)
45
+ assert_equal success, Capistrano::SSH.connect(@server, :port => 1234)
77
46
  end
78
47
 
79
- def test_publickey_auth_succeeds_explicit_port_no_block
80
- Net.const_during(:SSH, MockSSH) do
81
- Capistrano::SSH.connect('demo.server.i', @config, 23)
82
- end
83
-
84
- assert_equal 1, MockSSH.invocations.length
85
- assert_equal 23, MockSSH.invocations.first[1][:port]
86
- assert_nil MockSSH.invocations.first[2]
48
+ def test_connect_with_server_with_user_should_pass_user_to_net_ssh
49
+ server = server("jamis@capistrano")
50
+ Net::SSH.expects(:start).with(server.host, @options.merge(:username => "jamis")).returns(success = Object.new)
51
+ assert_equal success, Capistrano::SSH.connect(server)
87
52
  end
88
53
 
89
-
90
- def test_explicit_ssh_ports_in_server_string_with_block
91
- Net.const_during(:SSH, MockSSH) do
92
- Capistrano::SSH.connect('demo.server.i:8088', @config) do |session|
93
- end
94
- end
95
- assert_equal 'demo.server.i', MockSSH.invocations.first[0]
96
- assert_equal '8088', MockSSH.invocations.first[1][:port]
97
- assert_equal 1, MockSSH.invocations.length
98
- assert_instance_of Proc, MockSSH.invocations.first[2]
99
- end
100
-
101
- def test_explicit_ssh_username_in_server_string_with_block
102
- Net.const_during(:SSH, MockSSH) do
103
- Capistrano::SSH.connect('bob@demo.server.i', @config) do |session|
104
- end
105
- end
106
- assert_equal 'demo.server.i', MockSSH.invocations.first[0]
107
- assert_equal 22, MockSSH.invocations.first[1][:port]
108
- assert_equal 1, MockSSH.invocations.length
109
- assert_equal 'bob', MockSSH.invocations.first[1][:username]
110
- assert_instance_of Proc, MockSSH.invocations.first[2]
111
- end
112
-
113
- def test_explicit_ssh_username_and_port_in_server_string_with_block
114
- Net.const_during(:SSH, MockSSH) do
115
- Capistrano::SSH.connect('bob@demo.server.i:8088', @config) do |session|
116
- end
117
- end
118
- assert_equal 'demo.server.i', MockSSH.invocations.first[0]
119
- assert_equal '8088', MockSSH.invocations.first[1][:port]
120
- assert_equal 1, MockSSH.invocations.length
121
- assert_equal 'bob', MockSSH.invocations.first[1][:username]
122
- assert_instance_of Proc, MockSSH.invocations.first[2]
54
+ def test_connect_with_server_with_port_should_pass_port_to_net_ssh
55
+ server = server("capistrano:1235")
56
+ Net::SSH.expects(:start).with(server.host, @options.merge(:port => 1235)).returns(success = Object.new)
57
+ assert_equal success, Capistrano::SSH.connect(server)
123
58
  end
124
59
 
125
- def test_parse_server
126
- assert_equal(['bob', 'demo.server.i', '8088'],
127
- Capistrano::SSH.parse_server("bob@demo.server.i:8088"))
128
- assert_equal([nil, 'demo.server.i', '8088'],
129
- Capistrano::SSH.parse_server("demo.server.i:8088"))
130
- assert_equal(['bob', 'demo.server.i', nil],
131
- Capistrano::SSH.parse_server("bob@demo.server.i"))
132
- assert_equal([nil, 'demo.server.i', nil],
133
- Capistrano::SSH.parse_server("demo.server.i"))
134
- end
135
-
136
- def test_publickey_auth_succeeds_with_block
137
- Net.const_during(:SSH, MockSSH) do
138
- Capistrano::SSH.connect('demo.server.i', @config) do |session|
139
- end
140
- end
141
-
142
- assert_equal 1, MockSSH.invocations.length
143
- assert_instance_of Proc, MockSSH.invocations.first[2]
60
+ def test_connect_with_server_with_user_and_port_should_pass_user_and_port_to_net_ssh
61
+ server = server("jamis@capistrano:1235")
62
+ Net::SSH.expects(:start).with(server.host, @options.merge(:username => "jamis", :port => 1235)).returns(success = Object.new)
63
+ assert_equal success, Capistrano::SSH.connect(server)
144
64
  end
145
65
 
146
- def test_publickey_auth_fails
147
- MockSSH.story << Net::SSH::AuthenticationFailed
148
-
149
- Net.const_during(:SSH, MockSSH) do
150
- Capistrano::SSH.connect('demo.server.i', @config)
151
- end
152
-
153
- assert_equal 2, MockSSH.invocations.length
154
-
155
- assert_nil MockSSH.invocations.first[1][:password]
156
- assert_equal %w(publickey hostbased),
157
- MockSSH.invocations.first[1][:auth_methods]
158
-
159
- assert_equal 'c0c0nutfr0st1ng', MockSSH.invocations.last[1][:password]
160
- assert_equal %w(password keyboard-interactive),
161
- MockSSH.invocations.last[1][:auth_methods]
66
+ def test_connect_with_ssh_options_should_use_ssh_options
67
+ ssh_options = { :username => "JamisMan", :port => 8125 }
68
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "JamisMan", :port => 8125)).returns(success = Object.new)
69
+ assert_equal success, Capistrano::SSH.connect(@server, {:ssh_options => ssh_options})
162
70
  end
163
71
 
164
- def test_password_auth_fails
165
- MockSSH.story << Net::SSH::AuthenticationFailed
166
- MockSSH.story << Net::SSH::AuthenticationFailed
167
-
168
- Net.const_during(:SSH, MockSSH) do
169
- assert_raises(Net::SSH::AuthenticationFailed) do
170
- Capistrano::SSH.connect('demo.server.i', @config)
171
- end
172
- end
72
+ def test_connect_with_options_and_ssh_options_should_see_options_override_ssh_options
73
+ ssh_options = { :username => "JamisMan", :port => 8125, :forward_agent => true }
74
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "jamis", :port => 1235, :forward_agent => true)).returns(success = Object.new)
75
+ assert_equal success, Capistrano::SSH.connect(@server, {:ssh_options => ssh_options, :user => "jamis", :port => 1235})
76
+ end
173
77
 
174
- assert_equal 2, MockSSH.invocations.length
78
+ def test_connect_with_ssh_options_should_see_server_options_override_ssh_options
79
+ ssh_options = { :username => "JamisMan", :port => 8125, :forward_agent => true }
80
+ server = server("jamis@capistrano:1235")
81
+ Net::SSH.expects(:start).with(server.host, @options.merge(:username => "jamis", :port => 1235, :forward_agent => true)).returns(success = Object.new)
82
+ assert_equal success, Capistrano::SSH.connect(server, {:ssh_options => ssh_options})
83
+ end
175
84
 
176
- assert_nil MockSSH.invocations.first[1][:password]
177
- assert_equal %w(publickey hostbased),
178
- MockSSH.invocations.first[1][:auth_methods]
85
+ def test_connect_should_add_xserver_accessor_to_connection
86
+ Net::SSH.expects(:start).with(@server.host, @options).returns(success = Object.new)
87
+ assert_equal success, Capistrano::SSH.connect(@server)
88
+ assert success.respond_to?(:xserver)
89
+ assert success.respond_to?(:xserver)
90
+ assert_equal success.xserver, @server
91
+ end
179
92
 
180
- assert_equal 'c0c0nutfr0st1ng', MockSSH.invocations.last[1][:password]
181
- assert_equal %w(password keyboard-interactive),
182
- MockSSH.invocations.last[1][:auth_methods]
93
+ def test_connect_should_not_retry_if_custom_auth_methods_are_given
94
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:auth_methods => %w(publickey))).raises(Net::SSH::AuthenticationFailed)
95
+ assert_raises(Net::SSH::AuthenticationFailed) { Capistrano::SSH.connect(@server, :ssh_options => { :auth_methods => %w(publickey) }) }
183
96
  end
184
97
  end
@@ -0,0 +1,101 @@
1
+ require "#{File.dirname(__FILE__)}/utils"
2
+ require 'capistrano/task_definition'
3
+
4
+ class TaskDefinitionTest < Test::Unit::TestCase
5
+ def setup
6
+ @namespace = namespace
7
+ end
8
+
9
+ def test_fqn_at_top_level_should_be_task_name
10
+ task = new_task(:testing)
11
+ assert_equal "testing", task.fully_qualified_name
12
+ end
13
+
14
+ def test_fqn_in_namespace_should_include_namespace_fqn
15
+ ns = namespace("outer:inner")
16
+ task = new_task(:testing, ns)
17
+ assert_equal "outer:inner:testing", task.fully_qualified_name
18
+ end
19
+
20
+ def test_fqn_at_top_level_when_default_should_be_default
21
+ task = new_task(:default)
22
+ assert_equal "default", task.fully_qualified_name
23
+ end
24
+
25
+ def test_fqn_in_namespace_when_default_should_be_namespace_fqn
26
+ ns = namespace("outer:inner")
27
+ task = new_task(:default, ns)
28
+ ns.stubs(:default_task => task)
29
+ assert_equal "outer:inner", task.fully_qualified_name
30
+ end
31
+
32
+ def test_task_should_require_block
33
+ assert_raises(ArgumentError) do
34
+ Capistrano::TaskDefinition.new(:testing, @namespace)
35
+ end
36
+ end
37
+
38
+ def test_description_should_return_empty_string_if_not_given
39
+ assert_equal "", new_task(:testing).description
40
+ end
41
+
42
+ def test_description_should_return_desc_attribute
43
+ assert_equal "something", new_task(:testing, @namespace, :desc => "something").description
44
+ end
45
+
46
+ def test_description_should_strip_leading_and_trailing_whitespace
47
+ assert_equal "something", new_task(:testing, @namespace, :desc => " something ").description
48
+ end
49
+
50
+ def test_description_should_normalize_newlines
51
+ assert_equal "a\nb\nc", new_task(:testing, @namespace, :desc => "a\nb\r\nc").description
52
+ end
53
+
54
+ def test_description_should_detect_and_remove_indentation
55
+ desc = <<-DESC
56
+ Here is some indented text \
57
+ and I want all of this to \
58
+ run together on a single line, \
59
+ without any extraneous spaces.
60
+
61
+ additional indentation will
62
+ be preserved.
63
+ DESC
64
+
65
+ task = new_task(:testing, @namespace, :desc => desc)
66
+ assert_equal "Here is some indented text and I want all of this to run together on a single line, without any extraneous spaces.\n\n additional indentation will\n be preserved.", task.description
67
+ end
68
+
69
+ def test_description_munging_should_be_sensitive_to_code_blocks
70
+ desc = <<-DESC
71
+ Here is a line \
72
+ wrapped with spacing in it.
73
+
74
+ foo bar
75
+ baz bang
76
+ DESC
77
+
78
+ task = new_task(:testing, @namespace, :desc => desc)
79
+ assert_equal "Here is a line wrapped with spacing in it.\n\n foo bar\n baz bang", task.description
80
+ end
81
+
82
+ def test_brief_description_should_return_first_sentence_in_description
83
+ desc = "This is the task. It does all kinds of things."
84
+ task = new_task(:testing, @namespace, :desc => desc)
85
+ assert_equal "This is the task.", task.brief_description
86
+ end
87
+
88
+ def test_brief_description_should_truncate_if_length_given
89
+ desc = "This is the task that does all kinds of things. And then some."
90
+ task = new_task(:testing, @namespace, :desc => desc)
91
+ assert_equal "This is the task ...", task.brief_description(20)
92
+ end
93
+
94
+ def test_brief_description_should_not_break_at_period_in_middle_of_sentence
95
+ task = new_task(:testing, @namespace, :desc => "Take file.txt and copy it.")
96
+ assert_equal "Take file.txt and copy it.", task.brief_description
97
+
98
+ task = new_task(:testing, @namespace, :desc => "Take file.txt and copy it. Then do something else.")
99
+ assert_equal "Take file.txt and copy it.", task.brief_description
100
+ end
101
+ end
@@ -0,0 +1,131 @@
1
+ require "#{File.dirname(__FILE__)}/utils"
2
+ require 'capistrano/upload'
3
+
4
+ class UploadTest < Test::Unit::TestCase
5
+ def setup
6
+ @mode = IO::WRONLY | IO::CREAT | IO::TRUNC
7
+ end
8
+
9
+ def test_initialize_should_raise_error_if_data_is_missing
10
+ assert_raises(ArgumentError) do
11
+ Capistrano::Upload.new([], "test.txt", :foo => "bar")
12
+ end
13
+ end
14
+
15
+ def test_initialize_should_get_sftp_for_each_session
16
+ new_sftp = Proc.new do |state|
17
+ sftp = mock("sftp", :state => state, :open => nil)
18
+ sftp.expects(:connect) unless state == :open
19
+ sftp.stubs(:channel).returns({})
20
+ sftp
21
+ end
22
+
23
+ sessions = [mock("session", :xserver => server("a"), :sftp => new_sftp[:closed]),
24
+ mock("session", :xserver => server("b"), :sftp => new_sftp[:closed]),
25
+ mock("session", :xserver => server("c"), :sftp => new_sftp[:open])]
26
+ Capistrano::Upload.new(sessions, "test.txt", :data => "data")
27
+ end
28
+
29
+ def test_self_process_should_instantiate_uploader_and_start_process
30
+ Capistrano::Upload.expects(:new).with([:s1, :s2], "test.txt", :data => "data").returns(mock(:process! => nil))
31
+ Capistrano::Upload.process([:s1, :s2], "test.txt", :data => "data")
32
+ end
33
+
34
+ def test_process_when_sftp_open_fails_should_raise_error
35
+ sftp = mock_sftp
36
+ sftp.expects(:open).with("test.txt", @mode, 0660).yields(mock("status", :code => "bad status", :message => "bad status"), :file_handle)
37
+ session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
38
+ upload = Capistrano::Upload.new([session], "test.txt", :data => "data", :logger => stub_everything)
39
+ assert_raises(Capistrano::UploadError) { upload.process! }
40
+ assert_equal 1, upload.failed
41
+ assert_equal 1, upload.completed
42
+ end
43
+
44
+ def test_process_when_sftp_write_fails_should_raise_error
45
+ sftp = mock_sftp
46
+ sftp.expects(:open).with("test.txt", @mode, 0660).yields(mock("status1", :code => Net::SFTP::Session::FX_OK), :file_handle)
47
+ sftp.expects(:write).with(:file_handle, "data").yields(mock("status2", :code => "bad status", :message => "bad status"))
48
+ session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
49
+ upload = Capistrano::Upload.new([session], "test.txt", :data => "data", :logger => stub_everything)
50
+ assert_raises(Capistrano::UploadError) { upload.process! }
51
+ assert_equal 1, upload.failed
52
+ assert_equal 1, upload.completed
53
+ end
54
+
55
+ def test_upload_error_should_include_accessor_with_host_array
56
+ sftp = mock_sftp
57
+ sftp.expects(:open).with("test.txt", @mode, 0660).yields(mock("status1", :code => Net::SFTP::Session::FX_OK), :file_handle)
58
+ sftp.expects(:write).with(:file_handle, "data").yields(mock("status2", :code => "bad status", :message => "bad status"))
59
+ session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
60
+ upload = Capistrano::Upload.new([session], "test.txt", :data => "data", :logger => stub_everything)
61
+
62
+ begin
63
+ upload.process!
64
+ flunk "expected an exception to be raised"
65
+ rescue Capistrano::UploadError => e
66
+ assert e.respond_to?(:hosts)
67
+ assert_equal %w(capistrano), e.hosts.map { |h| h.to_s }
68
+ end
69
+ end
70
+
71
+ def test_process_when_sftp_succeeds_should_raise_nothing
72
+ sftp = mock_sftp
73
+ sftp.expects(:open).with("test.txt", @mode, 0660).yields(mock("status1", :code => Net::SFTP::Session::FX_OK), :file_handle)
74
+ sftp.expects(:write).with(:file_handle, "data").yields(mock("status2", :code => Net::SFTP::Session::FX_OK))
75
+ sftp.expects(:close_handle).with(:file_handle).yields
76
+ session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
77
+ upload = Capistrano::Upload.new([session], "test.txt", :data => "data", :logger => stub_everything)
78
+ assert_nothing_raised { upload.process! }
79
+ assert_equal 0, upload.failed
80
+ assert_equal 1, upload.completed
81
+ end
82
+
83
+ def test_process_should_loop_while_running
84
+ con = mock("connection")
85
+ con.expects(:process).with(true).times(10)
86
+ channel = {}
87
+ channel.expects(:connection).returns(con).times(10)
88
+ sftp = mock("sftp", :state => :open, :open => nil)
89
+ sftp.stubs(:channel).returns(channel)
90
+ session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
91
+ upload = Capistrano::Upload.new([session], "test.txt", :data => "data")
92
+ upload.expects(:running?).times(11).returns(*([true]*10 + [false]))
93
+ upload.process!
94
+ end
95
+
96
+ def test_process_should_loop_but_not_process_done_channels
97
+ new_sftp = Proc.new do |done|
98
+ channel = {}
99
+ channel[:needs_done] = done
100
+
101
+ if !done
102
+ con = mock("connection")
103
+ con.expects(:process).with(true).times(10)
104
+ channel.expects(:connection).returns(con).times(10)
105
+ end
106
+
107
+ sftp = mock("sftp", :state => :open, :open => nil)
108
+ sftp.stubs(:channel).returns(channel)
109
+ sftp
110
+ end
111
+
112
+ sessions = [stub("session", :sftp => new_sftp[true], :xserver => server("capistrano")),
113
+ stub("session", :sftp => new_sftp[false], :xserver => server("cap2"))]
114
+ upload = Capistrano::Upload.new(sessions, "test.txt", :data => "data")
115
+
116
+ # make sure the sftp channels we wanted to be done, start as done
117
+ # (Upload.new marks each channel as not-done, so we have to do it here)
118
+ sessions.each { |s| s.sftp.channel[:done] = true if s.sftp.channel[:needs_done] }
119
+ upload.expects(:running?).times(11).returns(*([true]*10 + [false]))
120
+ upload.process!
121
+ end
122
+
123
+ private
124
+
125
+ def mock_sftp
126
+ sftp = mock("sftp", :state => :open)
127
+ sftp.stubs(:channel).returns(Hash.new)
128
+ yield sftp if block_given?
129
+ sftp
130
+ end
131
+ end