test/manual/test_forward.rb in net-ssh-2.9.1 vs test/manual/test_forward.rb in net-ssh-2.9.2.beta

- old
+ new

@@ -1,64 +1,64 @@ # $ ruby -Ilib -Itest -rrubygems test/manual/test_forward.rb # Tests for the following patch: # # http://github.com/net-ssh/net-ssh/tree/portfwfix -# +# # It fixes 3 issues, regarding closing forwarded ports: -# +# # 1.) if client closes a forwarded connection, but the server is reading, net-ssh terminates with IOError socket closed. # 2.) if client force closes (RST) a forwarded connection, but server is reading, net-ssh terminates with # 3.) if server closes the sending side, the on_eof is not handled. -# +# # More info: -# +# # http://net-ssh.lighthouseapp.com/projects/36253/tickets/7 require 'common' require 'net/ssh/buffer' require 'net/ssh' require 'timeout' require 'tempfile' class TestForward < Test::Unit::TestCase - + def localhost 'localhost' end - + def ssh_start_params [localhost ,ENV['USER'], {:keys => "~/.ssh/id_rsa", :verbose => :debug}] end - + def start_server_sending_lot_of_data(exceptions) server = TCPServer.open(0) Thread.start do loop do Thread.start(server.accept) do |client| begin - 10000.times do |i| + 10000.times do |i| client.puts "item#{i}" end client.close - rescue + rescue exceptions << $! raise end end end end return server end - + def start_server_closing_soon(exceptions=nil) server = TCPServer.open(0) Thread.start do loop do Thread.start(server.accept) do |client| begin - client.recv(1024) + client.recv(1024) client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii")) client.close rescue exceptions << $! raise @@ -66,35 +66,84 @@ end end end return server end - + def test_local_ephemeral_port_should_work_correctly session = Net::SSH.start(*ssh_start_params) - + assert_nothing_raised do assigned_port = session.forward.local(0, localhost, 22) assert_not_nil assigned_port assert_operator assigned_port, :>, 0 end end - + def test_remote_ephemeral_port_should_work_correctly session = Net::SSH.start(*ssh_start_params) - + assert_nothing_raised do session.forward.remote(22, localhost, 0, localhost) session.loop { !(session.forward.active_remotes.length > 0) } assigned_port = session.forward.active_remotes.first[0] assert_not_nil assigned_port assert_operator assigned_port, :>, 0 end end - + + def test_remote_callback_should_fire + session = Net::SSH.start(*ssh_start_params) + + assert_nothing_raised do + got_port = nil + session.forward.remote(22, localhost, 0, localhost) do |port| + got_port = port + end + session.loop { !(session.forward.active_remotes.length > 0) } + assert_operator session.forward.active_remote_destinations.length, :==, 1 + assert_operator session.forward.active_remote_destinations.keys.first, :==, [ 22, localhost ] + assert_operator session.forward.active_remote_destinations.values.first, :==, [ got_port, localhost ] + assert_operator session.forward.active_remotes.first, :==, [ got_port, localhost ] + assigned_port = session.forward.active_remotes.first[0] + assert_operator got_port, :==, assigned_port + assert_not_nil assigned_port + assert_operator assigned_port, :>, 0 + end + end + + def test_remote_callback_should_fire_on_error_and_still_throw_exception + session = Net::SSH.start(*ssh_start_params) + + assert_nothing_raised do + session.forward.remote(22, localhost, 22, localhost) do |port| + assert_operator port, :==, :error + end + end + assert_raises(Net::SSH::Exception) do + session.loop { true } + end + end + + def test_remote_callback_should_fire_on_error_but_not_throw_exception_if_asked_not_to + session = Net::SSH.start(*ssh_start_params) + + assert_nothing_raised do + got_port = nil + session.forward.remote(22, localhost, 22, localhost) do |port| + assert_operator port, :==, :error + got_port = port + :no_exception + end + session.loop { !got_port } + assert_operator port, :==, :error + assert_operator session.forward.active_remotes.length, :==, 0 + end + end + def test_loop_should_not_abort_when_local_side_of_forward_is_closed - session = Net::SSH.start(*ssh_start_params) + session = Net::SSH.start(*ssh_start_params) server_exc = Queue.new server = start_server_sending_lot_of_data(server_exc) remote_port = server.addr[1] local_port = 0 # request ephemeral port session.forward.local(local_port, localhost, remote_port) @@ -110,14 +159,14 @@ end end session.loop(0.1) { client_done.empty? } assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty? end - + def test_loop_should_not_abort_when_local_side_of_forward_is_reset session = Net::SSH.start(*ssh_start_params) - server_exc = Queue.new + server_exc = Queue.new server = start_server_sending_lot_of_data(server_exc) remote_port = server.addr[1] local_port = 0 # request ephemeral port session.forward.local(local_port, localhost, remote_port) client_done = Queue.new @@ -141,13 +190,13 @@ path = tempfile.path tempfile.delete yield UNIXServer.open(path) File.delete(path) end if defined?(UNIXServer) - + def test_forward_local_unix_socket_to_remote_port - session = Net::SSH.start(*ssh_start_params) + session = Net::SSH.start(*ssh_start_params) server_exc = Queue.new server = start_server_sending_lot_of_data(server_exc) remote_port = server.addr[1] client_data = nil @@ -172,31 +221,31 @@ assert_not_nil(client_data, "client should have received data") assert(client_data.match(/item\d/), 'client should have received the string item') end if defined?(UNIXSocket) def test_loop_should_not_abort_when_server_side_of_forward_is_closed - session = Net::SSH.start(*ssh_start_params) + session = Net::SSH.start(*ssh_start_params) server = start_server_closing_soon remote_port = server.addr[1] local_port = 0 # request ephemeral port session.forward.local(local_port, localhost, remote_port) client_done = Queue.new Thread.start do begin client = TCPSocket.new(localhost, local_port) - 1.times do |i| + 1.times do |i| client.puts "item#{i}" end client.close sleep(0.1) - ensure + ensure client_done << true end end session.loop(0.1) { client_done.empty? } end - + def start_server server = TCPServer.open(0) Thread.start do loop do Thread.start(server.accept) do |client| @@ -204,12 +253,12 @@ end end end return server end - + def test_server_eof_should_be_handled - session = Net::SSH.start(*ssh_start_params) + session = Net::SSH.start(*ssh_start_params) server = start_server do |client| client.write "This is a small message!" client.close end client_done = Queue.new