From 5d76e1d2c0dfefd3780e2278789d201d6b4a9abf Mon Sep 17 00:00:00 2001 From: Jamis Buck Date: Thu, 21 Aug 2008 14:29:28 -0600 Subject: [PATCH] make tests pass --- lib/capistrano/command.rb | 16 +++- .../configuration/actions/invocation.rb | 2 +- test/command_test.rb | 79 +++++++++---------- test/configuration/actions/invocation_test.rb | 25 ++---- test/configuration_test.rb | 9 ++- 5 files changed, 66 insertions(+), 65 deletions(-) diff --git a/lib/capistrano/command.rb b/lib/capistrano/command.rb index ae108e1d..8e0c61b3 100644 --- a/lib/capistrano/command.rb +++ b/lib/capistrano/command.rb @@ -142,7 +142,13 @@ module Capistrano # * +data+: (optional), a string to be sent to the command via it's stdin # * +env+: (optional), a string or hash to be interpreted as environment # variables that should be defined for this command invocation. - def initialize(tree, sessions, options={}) + def initialize(tree, sessions, options={}, &block) + if String === tree + tree = Tree.new(nil) { |t| t.else(tree, &block) } + elsif block + raise ArgumentError, "block given with tree argument" + end + @tree = tree @sessions = sessions @options = options @@ -160,9 +166,10 @@ module Capistrano logger.trace "command finished" if logger if (failed = @channels.select { |ch| ch[:status] != 0 }).any? - hosts = failed.map { |ch| ch[:server] } - error = CommandError.new("command #{command.inspect} failed on #{hosts.join(',')}") - error.hosts = hosts + commands = failed.inject({}) { |map, ch| (map[ch[:command]] ||= []) << ch[:server]; map } + message = commands.map { |command, list| "#{command.inspect} on #{list.join(',')}" }.join("; ") + error = CommandError.new("failed: #{message}") + error.hosts = commands.values.flatten raise error end @@ -207,6 +214,7 @@ module Capistrano end command_line = [environment, shell, cmd].compact.join(" ") + ch[:command] = command_line ch.exec(command_line) ch.send_data(options[:data]) if options[:data] diff --git a/lib/capistrano/configuration/actions/invocation.rb b/lib/capistrano/configuration/actions/invocation.rb index feca7a8f..d2d1f2ed 100644 --- a/lib/capistrano/configuration/actions/invocation.rb +++ b/lib/capistrano/configuration/actions/invocation.rb @@ -50,7 +50,7 @@ module Capistrano # stdout), and the data that was received. def run(cmd, options={}, &block) block ||= self.class.default_io_proc - tree = Command::Tree.new(self) { |t| t.else(cmd, block) } + tree = Command::Tree.new(self) { |t| t.else(cmd, &block) } run_tree(tree, options) end diff --git a/test/command_test.rb b/test/command_test.rb index 655ee73c..fd48ca3b 100644 --- a/test/command_test.rb +++ b/test/command_test.rb @@ -1,22 +1,21 @@ require "utils" require 'capistrano/command' +require 'capistrano/configuration' class CommandTest < Test::Unit::TestCase def test_command_should_open_channels_on_all_sessions - s1 = mock(:open_channel => nil) - s2 = mock(:open_channel => nil) - s3 = mock(:open_channel => nil) - assert_equal "ls", Capistrano::Command.new("ls", [s1, s2, s3]).command + s1, s2, s3 = mock_session, mock_session, mock_session + assert_equal "ls", Capistrano::Command.new("ls", [s1, s2, s3]).tree.fallback.command end def test_command_with_newlines_should_be_properly_escaped - cmd = Capistrano::Command.new("ls\necho", [mock(:open_channel => nil)]) - assert_equal "ls\\\necho", cmd.command + cmd = Capistrano::Command.new("ls\necho", [mock_session]) + assert_equal "ls\\\necho", cmd.tree.fallback.command end def test_command_with_windows_newlines_should_be_properly_escaped - cmd = Capistrano::Command.new("ls\r\necho", [mock(:open_channel => nil)]) - assert_equal "ls\\\necho", cmd.command + cmd = Capistrano::Command.new("ls\r\necho", [mock_session]) + assert_equal "ls\\\necho", cmd.tree.fallback.command end def test_command_with_pty_should_request_pty_and_register_success_callback @@ -76,25 +75,17 @@ class CommandTest < Test::Unit::TestCase end def test_open_channel_should_set_host_key_on_channel - session = mock(:xserver => server("capistrano")) - channel = stub_everything - - session.expects(:open_channel).yields(channel) - channel.expects(:[]=).with(:host, "capistrano") - channel.stubs(:[]).with(:host).returns("capistrano") - + channel = nil + session = setup_for_extracting_channel_action { |ch| channel = ch } Capistrano::Command.new("ls", [session]) + assert_equal "capistrano", channel[:host] end def test_open_channel_should_set_options_key_on_channel - session = mock(:xserver => server("capistrano")) - channel = stub_everything - - session.expects(:open_channel).yields(channel) - channel.expects(:[]=).with(:options, {:data => "here we go"}) - channel.stubs(:[]).with(:host).returns("capistrano") - + channel = nil + session = setup_for_extracting_channel_action { |ch| channel = ch } Capistrano::Command.new("ls", [session], :data => "here we go") + assert_equal({ :data => 'here we go' }, channel[:options]) end def test_successful_channel_should_send_command @@ -157,17 +148,17 @@ class CommandTest < Test::Unit::TestCase def test_on_request_should_record_exit_status data = mock(:read_long => 5) - session = setup_for_extracting_channel_action([:on_request, "exit-status"], data) do |ch| - ch.expects(:[]=).with(:status, 5) - end + channel = nil + session = setup_for_extracting_channel_action([:on_request, "exit-status"], data) { |ch| channel = ch } Capistrano::Command.new("ls", [session]) + assert_equal 5, channel[:status] end def test_on_close_should_set_channel_closed - session = setup_for_extracting_channel_action(:on_close) do |ch| - ch.expects(:[]=).with(:closed, true) - end + channel = nil + session = setup_for_extracting_channel_action(:on_close) { |ch| channel = ch } Capistrano::Command.new("ls", [session]) + assert channel[:closed] end def test_stop_should_close_all_open_channels @@ -228,10 +219,8 @@ class CommandTest < Test::Unit::TestCase def test_process_should_instantiate_command_and_process! cmd = mock("command", :process! => nil) - Capistrano::Command.expects(:new).with("ls -l", %w(a b c), {:foo => "bar"}).yields(:command).returns(cmd) - parameter = nil - Capistrano::Command.process("ls -l", %w(a b c), :foo => "bar") { |cmd| parameter = cmd } - assert_equal :command, parameter + Capistrano::Command.expects(:new).with("ls -l", %w(a b c), {:foo => "bar"}).returns(cmd) + Capistrano::Command.process("ls -l", %w(a b c), :foo => "bar") end def test_process_with_host_placeholder_should_substitute_placeholder_with_each_host @@ -254,16 +243,20 @@ class CommandTest < Test::Unit::TestCase stub('session', :open_channel => channel, :preprocess => true, :postprocess => true, - :listeners => {}) + :listeners => {}, + :xserver => server("capistrano")) + end + + class MockChannel < Hash + def close + end end def new_channel(closed, status=nil) - ch = mock("channel") - ch.expects(:[]).with(:closed).returns(closed) - ch.expects(:[]).with(:status).returns(status) if status + ch = MockChannel.new + ch.update({ :closed => closed, :host => "capistrano", :server => server("capistrano") }) + ch[:status] = status if status ch.expects(:close) unless closed - ch.stubs(:[]).with(:host).returns("capistrano") - ch.stubs(:[]).with(:server).returns(server("capistrano")) ch end @@ -271,11 +264,15 @@ class CommandTest < Test::Unit::TestCase s = server("capistrano") session = mock("session", :xserver => s) - channel = stub_everything + channel = {} session.expects(:open_channel).yields(channel) - channel.stubs(:[]).with(:server).returns(s) - channel.stubs(:[]).with(:host).returns(s.host) + channel.stubs(:on_data) + channel.stubs(:on_extended_data) + channel.stubs(:on_request) + channel.stubs(:on_close) + channel.stubs(:exec) + channel.stubs(:send_data) if action action = Array(action) diff --git a/test/configuration/actions/invocation_test.rb b/test/configuration/actions/invocation_test.rb index 6e09495f..0b927dc5 100644 --- a/test/configuration/actions/invocation_test.rb +++ b/test/configuration/actions/invocation_test.rb @@ -47,22 +47,6 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase @config.run "ls", :foo => "bar" end - def test_run_without_block_should_use_default_io_proc - @config.expects(:execute_on_servers).yields(%w(s1 s2 s3).map { |s| server(s) }) - @config.expects(:sessions).returns(Hash.new { |h,k| h[k] = k.host.to_sym }).times(3) - prepare_command("ls", [:s1, :s2, :s3], {:logger => @config.logger}) - MockConfig.default_io_proc = inspectable_proc - @config.run "ls" - end - - def test_run_with_block_should_use_block - @config.expects(:execute_on_servers).yields(%w(s1 s2 s3).map { |s| mock(:host => s) }) - @config.expects(:sessions).returns(Hash.new { |h,k| h[k] = k.host.to_sym }).times(3) - prepare_command("ls", [:s1, :s2, :s3], {:logger => @config.logger}) - MockConfig.default_io_proc = Proc.new { |a,b,c| raise "shouldn't get here" } - @config.run("ls", &inspectable_proc) - end - def test_add_default_command_options_should_return_bare_options_if_there_is_no_env_or_shell_specified assert_equal({:foo => "bar"}, @config.add_default_command_options(:foo => "bar")) end @@ -182,7 +166,7 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase a = mock("channel", :called => true) b = mock("stream", :called => true) c = mock("data", :called => true) - + callback[a, b, c] end @@ -210,6 +194,11 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase a = mock("channel", :called => true) b = mock("stream", :called => true) c = mock("data", :called => true) - Capistrano::Command.expects(:process).with(command, sessions, options).yields(a, b, c) + + compare_args = Proc.new do |tree, sess, opts| + tree.fallback.command == command && sess == sessions && opts == options + end + + Capistrano::Command.expects(:process).with(&compare_args) end end diff --git a/test/configuration_test.rb b/test/configuration_test.rb index 74bbb269..d0f88acf 100644 --- a/test/configuration_test.rb +++ b/test/configuration_test.rb @@ -12,7 +12,14 @@ class ConfigurationTest < Test::Unit::TestCase def test_connections_execution_loading_namespaces_roles_and_variables_modules_should_integrate_correctly Capistrano::SSH.expects(:connect).with { |s,c| s.host == "www.capistrano.test" && c == @config }.returns(:session) - Capistrano::Command.expects(:process).with("echo 'hello world'", [:session], :logger => @config.logger) + + process_args = Proc.new do |tree, session, opts| + tree.fallback.command == "echo 'hello world'" && + session == [:session] && + opts == { :logger => @config.logger } + end + + Capistrano::Command.expects(:process).with(&process_args) @config.load do role :test, "www.capistrano.test"