Hello community,

here is the log from the commit of package rubygem-net-ssh for openSUSE:Factory 
checked in at 2016-02-05 00:31:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-net-ssh (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-net-ssh.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-net-ssh"

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-net-ssh/rubygem-net-ssh.changes  
2015-09-30 05:53:22.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.rubygem-net-ssh.new/rubygem-net-ssh.changes     
2016-02-05 00:31:31.000000000 +0100
@@ -1,0 +2,13 @@
+Thu Jan 21 05:40:56 UTC 2016 - [email protected]
+
+- updated to version 3.0.2
+ see installed CHANGES.txt
+
+  === 3.0.2
+  === 3.0.2.rc1
+  
+  * fixed rare WaitWritable error with proxy commands [Miklos Fazkas, Andre 
Meij]]
+  * if Net::SSH.start user is nil and config has no entry we default to 
Etc.getlogin
+  * Bugfix: CHANNEL_CLOSE was sent before draining ouput buffer #280 
[Christopher F. Auston]
+
+-------------------------------------------------------------------

Old:
----
  net-ssh-3.0.1.gem

New:
----
  net-ssh-3.0.2.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-net-ssh.spec ++++++
--- /var/tmp/diff_new_pack.nTQb5r/_old  2016-02-05 00:31:32.000000000 +0100
+++ /var/tmp/diff_new_pack.nTQb5r/_new  2016-02-05 00:31:32.000000000 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-net-ssh
 #
-# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-net-ssh
-Version:        3.0.1
+Version:        3.0.2
 Release:        0
 %define mod_name net-ssh
 %define mod_full_name %{mod_name}-%{version}

++++++ net-ssh-3.0.1.gem -> net-ssh-3.0.2.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CHANGES.txt new/CHANGES.txt
--- old/CHANGES.txt     2015-09-25 21:35:53.000000000 +0200
+++ new/CHANGES.txt     2015-12-30 10:07:47.000000000 +0100
@@ -1,3 +1,10 @@
+=== 3.0.2
+=== 3.0.2.rc1
+
+* fixed rare WaitWritable error with proxy commands [Miklos Fazkas, Andre 
Meij]]
+* if Net::SSH.start user is nil and config has no entry we default to 
Etc.getlogin
+* Bugfix: CHANNEL_CLOSE was sent before draining ouput buffer #280 
[Christopher F. Auston]
+
 === 3.0.1
 === 3.0.1.rc1
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/README.rdoc new/README.rdoc
--- old/README.rdoc     2015-09-25 21:35:53.000000000 +0200
+++ new/README.rdoc     2015-12-30 10:07:47.000000000 +0100
@@ -1,4 +1,4 @@
-= Net::SSH 2.x
+= Net::SSH 3.x
 
 <em><b>Please note: this project is in maintenance mode. It is not under 
active development but pull requests are very much welcome. Just be sure to 
include tests! -- delano</b></em>
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Rakefile new/Rakefile
--- old/Rakefile        2015-09-25 21:35:53.000000000 +0200
+++ new/Rakefile        2015-12-30 10:07:47.000000000 +0100
@@ -74,7 +74,11 @@
 
 require 'rake/testtask'
 Rake::TestTask.new do |t|
-  t.libs = ["lib", "test"]
+  if ENV['NET_SSH_RUN_INTEGRATION_TESTS']
+    t.libs = ["lib","test","test/integration"]
+  else
+    t.libs = ["lib", "test"]
+  end
 end
 
 Rake::TestTask.new(:'integration-test') do |t|
Files old/checksums.yaml.gz and new/checksums.yaml.gz differ
Files old/checksums.yaml.gz.sig and new/checksums.yaml.gz.sig differ
Files old/data.tar.gz.sig and new/data.tar.gz.sig differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/net/ssh/authentication/key_manager.rb 
new/lib/net/ssh/authentication/key_manager.rb
--- old/lib/net/ssh/authentication/key_manager.rb       2015-09-25 
21:35:53.000000000 +0200
+++ new/lib/net/ssh/authentication/key_manager.rb       2015-12-30 
10:07:47.000000000 +0100
@@ -232,16 +232,13 @@
                 identity
               end
 
-            rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, 
OpenSSL::PKey::ECError => e
+            rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, 
OpenSSL::PKey::ECError, ArgumentError => e
               if ignore_decryption_errors
                 identity
               else
                 process_identity_loading_error(identity, e)
                 nil
               end
-            rescue ArgumentError => e
-              process_identity_loading_error(identity, e)
-              nil
             rescue Exception => e
               process_identity_loading_error(identity, e)
               nil
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/net/ssh/connection/channel.rb 
new/lib/net/ssh/connection/channel.rb
--- old/lib/net/ssh/connection/channel.rb       2015-09-25 21:35:53.000000000 
+0200
+++ new/lib/net/ssh/connection/channel.rb       2015-12-30 10:07:47.000000000 
+0100
@@ -126,7 +126,7 @@
       @pending_requests = []
       @on_open_failed = @on_data = @on_extended_data = @on_process = @on_close 
= @on_eof = nil
       @on_request = {}
-      @closing = @eof = @sent_eof = false
+      @closing = @eof = @sent_eof = @local_closed = @remote_closed = false
     end
 
     # A shortcut for accessing properties of the channel (see #properties).
@@ -269,14 +269,28 @@
       connection.loop { active? }
     end
 
-    # Returns true if the channel is currently closing, but not actually
-    # closed. A channel is closing when, for instance, #close has been
-    # invoked, but the server has not yet responded with a CHANNEL_CLOSE
-    # packet of its own.
+    # True if close() has been called; NOTE: if the channel has data waiting to
+    # be sent then the channel will close after all the data is sent. See
+    # closed?() to determine if we have actually sent CHANNEL_CLOSE to server.
+    # This may be true for awhile before closed? returns true if we are still
+    # sending buffered output to server.
     def closing?
       @closing
     end
 
+    # True if we have sent CHANNEL_CLOSE to the remote server.
+    def local_closed?
+      @local_closed
+    end
+
+    def remote_closed?
+      @remote_closed
+    end
+
+    def remote_closed!
+      @remote_closed = true
+    end
+
     # Requests that the channel be closed. If the channel is already closing,
     # this does nothing, nor does it do anything if the channel has not yet
     # been confirmed open (see #do_open_confirmation). Otherwise, it sends a
@@ -285,7 +299,6 @@
       return if @closing
       if remote_id
         @closing = true
-        connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, 
remote_id))
       end
     end
 
@@ -311,10 +324,16 @@
       @on_process.call(self) if @on_process
       enqueue_pending_output
 
-      if @eof and not @sent_eof and output.empty? and remote_id
+      if @eof and not @sent_eof and output.empty? and remote_id and not 
@local_closed
         connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, 
remote_id))
         @sent_eof = true
       end
+
+      if @closing and not @local_closed and output.empty? and remote_id
+        connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, 
remote_id))
+        @local_closed = true
+        connection.cleanup_channel(self)
+      end
     end
 
     # Registers a callback to be invoked when data packets are received by the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/net/ssh/connection/session.rb 
new/lib/net/ssh/connection/session.rb
--- old/lib/net/ssh/connection/session.rb       2015-09-25 21:35:53.000000000 
+0200
+++ new/lib/net/ssh/connection/session.rb       2015-12-30 10:07:47.000000000 
+0100
@@ -220,7 +220,7 @@
     def preprocess
       return false if block_given? && !yield(self)
       dispatch_incoming_packets
-      channels.each { |id, channel| channel.process unless channel.closing? }
+      channels.each { |id, channel| channel.process unless 
channel.local_closed? }
       return false if block_given? && !yield(self)
       return true
     end
@@ -455,6 +455,14 @@
       old
     end
 
+    def cleanup_channel(channel)
+        if channel.local_closed? and channel.remote_closed?
+          info { "#{host} delete channel #{channel.local_id} which closed 
locally and remotely" }
+          channels.delete(channel.local_id)
+      end
+    end
+
+
     private
 
       # Read all pending packets from the connection and dispatch them as
@@ -583,9 +591,10 @@
         info { "channel_close: #{packet[:local_id]}" }
 
         channel = channels[packet[:local_id]]
+        channel.remote_closed!
         channel.close
 
-        channels.delete(packet[:local_id])
+        cleanup_channel(channel)
         channel.do_close
       end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/net/ssh/proxy/command.rb 
new/lib/net/ssh/proxy/command.rb
--- old/lib/net/ssh/proxy/command.rb    2015-09-25 21:35:53.000000000 +0200
+++ new/lib/net/ssh/proxy/command.rb    2015-12-30 10:07:47.000000000 +0100
@@ -79,11 +79,26 @@
         end
       else
         def io.send(data, flag)
-          write_nonblock(data)
+          begin
+            result = write_nonblock(data)
+          rescue IO::WaitWritable, Errno::EINTR
+            IO.select(nil, [self])
+            retry
+          end
+          result
         end
 
         def io.recv(size)
-          read_nonblock(size)
+          begin
+            result = read_nonblock(size)
+          rescue IO::WaitReadable, Errno::EINTR
+            timeout_in_seconds = 20
+            if IO.select([self], nil, [self], timeout_in_seconds) == nil
+              raise "Unexpected spurious read wakeup"
+            end
+            retry
+          end
+          result
         end
       end
       io
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/net/ssh/version.rb new/lib/net/ssh/version.rb
--- old/lib/net/ssh/version.rb  2015-09-25 21:35:53.000000000 +0200
+++ new/lib/net/ssh/version.rb  2015-12-30 10:07:47.000000000 +0100
@@ -51,7 +51,7 @@
     MINOR = 0
 
     # The tiny component of this version of the Net::SSH library
-    TINY  = 1
+    TINY  = 2
 
     # The prerelease component of this version of the Net::SSH library 
     # nil allowed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/net/ssh.rb new/lib/net/ssh.rb
--- old/lib/net/ssh.rb  2015-09-25 21:35:53.000000000 +0200
+++ new/lib/net/ssh.rb  2015-12-30 10:07:47.000000000 +0100
@@ -188,7 +188,10 @@
     #   password auth method
     # * :non_interactive => non interactive applications should set it to true
     #   to prefer failing a password/etc auth methods vs asking for password
-    def self.start(host, user, options={}, &block)
+    #
+    # If +user+ parameter is nil it defaults to USER from ssh_config, or
+    # local username
+    def self.start(host, user=nil, options={}, &block)
       invalid_options = options.keys - VALID_OPTIONS
       if invalid_options.any?
         raise ArgumentError, "invalid option(s): #{invalid_options.join(', ')}"
@@ -222,7 +225,7 @@
       transport = Transport::Session.new(host, options)
       auth = Authentication::Session.new(transport, options)
 
-      user = options.fetch(:user, user)
+      user = options.fetch(:user, user) || Etc.getlogin
       if auth.authenticate("ssh-connection", user, options[:password])
         connection = Connection::Session.new(transport, options)
         if block_given?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2015-09-25 21:35:53.000000000 +0200
+++ new/metadata        2015-12-30 10:07:47.000000000 +0100
@@ -1,7 +1,7 @@
 --- !ruby/object:Gem::Specification
 name: net-ssh
 version: !ruby/object:Gem::Version
-  version: 3.0.1
+  version: 3.0.2
 platform: ruby
 authors:
 - Jamis Buck
@@ -14,24 +14,24 @@
   -----BEGIN CERTIFICATE-----
   MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRAwDgYDVQQDDAduZXQt
   c3NoMRkwFwYKCZImiZPyLGQBGRYJc29sdXRpb3VzMRMwEQYKCZImiZPyLGQBGRYD
-  Y29tMB4XDTE0MTIwMjE3MzkyMFoXDTE1MTIwMjE3MzkyMFowQjEQMA4GA1UEAwwH
+  Y29tMB4XDTE1MTIwNjIxMDYyNFoXDTE2MTIwNTIxMDYyNFowQjEQMA4GA1UEAwwH
   bmV0LXNzaDEZMBcGCgmSJomT8ixkARkWCXNvbHV0aW91czETMBEGCgmSJomT8ixk
-  ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ0qnw4JV5JN
-  MWelqu7pnW2z6GZJ7+zLFYJQNETJyF0U5zo7aCRK08OeUxnpu/TCCXK8iQVkNLfz
-  9pVIhF+X8pMEIruAkYGwBt1aWfuSNeyodyMk0vpZdxBHbOTJ4qBRUc6qOtNOeOzv
-  8ObYUX52P/EMMaeXTRU+e7MGkB9pb6FvPPNx5akxwIaoRvtcMsc/hJnQuP5r96w6
-  t06MgKbXhWAX6gev0RVlrQqzxXst6iuvsrgZGjFqzob5wbTiX9M0+bFAB0EI7tJC
-  sv5keEbtNRaU7p3ZbMm4wTHHJLOtD+BpUCSzwv4ToNj9mZtJBMYw2Eeo7z1DklEG
-  mr95zbe+zNMCAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQU1bTfpzmitXwv
-  LmTXi0IO5vd8NGYwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQA0Aps8
-  UPINGa8XUUtrZtzrgX0/iyXNkKY1ld85g1N3WKEAVLfQI7TlGr0Qv2Ekx6RqlxbR
-  Vyq08pytSnghW2otR3bIGMGQzqxAeRLb25cjEwH7YIJ32n7ZC1fpMnBZOBDmueWA
-  B9EonmoO3ne7AJSgIvBbZzBPhzM4HrQGRW8LsPFsuj+dcJI43HOQwkmv2TRz0+t6
-  mGZldmqLcK0abv4JepLfB9XTue3kuyA29NGBibqyvRwlKckLpvKfHZX6Jxad8xxm
-  MbvRpzgROzyfw1qYi4dnIyMwTtXFFcZ0a2jpxHPkcTYFK6TzvFgDLAP0Y/u9jqUQ
-  eZ7/3CdSi/isZHEw
+  ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMYnhNtn0f6p
+  nTylB8mE8lMdoMLJC8KwpMWsvk73Pe2WVDsH/OSwwwz6oUGk1i70cJyDjIEBNpwT
+  88GpVXJSumvqVsf9fCg3mWNeb5t0J+aeNm9MIvYVMTqj5tydoXQiwnILRDYHV9tZ
+  1c3o59/VlahSTpZ7YEgzVufpAkvEGkbJiG849exiipK7MN/ZIkMOxYVnyRXk43Xc
+  6GYlsHOfSgPwcXwW5g57DCwLQLWrjDsTka28dxDmO7B5Lv5EqzINxVxWsu43OgZG
+  21Io/jIyf5PNpeKPKNGDuAQJ8mvdMYBJoDhtCwgsUYbl0BZzA7g4ytl51HtIeP+j
+  Qp/eAvs/RrECAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUBfKiwO2eM4NE
+  iRrVG793qEPLYyMwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQCfZFdb
+  p4jzkfIzGDbiOxd0R8sdqJoC4nMLEgnQ7dLulawwA3IXe3sHAKgA5kmH3prsKc5H
+  zVmM5NlH2P1nRbegIkQTYiIod1hZQCNxdmVG/fprMqPq0ybpUOjjrP5pj0OtszE1
+  F2dQia1hOEstMR+n0nAtWII9HJAEyeZjVV0s2Cl7Pt85XJ3hxFcCKwzqsK5xRI7a
+  B3vwh3/JJYrFonIohQ//Lg9qTZASEkoKLlq1/hFeICoCGGIGLq45ZB7CzXLooCKi
+  s/ZUKye79ELwFYKJOhjW5g725OL3hy+llhEleytwKRwgXFQBPTC4f5UkdxZVVWGH
+  e2C9M1m/2odPZo8h
   -----END CERTIFICATE-----
-date: 2015-09-25 00:00:00.000000000 Z
+date: 2015-12-30 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: test-unit
@@ -195,14 +195,16 @@
 - test/integration/Vagrantfile
 - test/integration/common.rb
 - test/integration/playbook.yml
+- test/integration/test_forward.rb
 - test/integration/test_id_rsa_keys.rb
+- test/integration/test_proxy.rb
 - test/known_hosts/github
 - test/known_hosts/github_hash
-- test/manual/test_forward.rb
 - test/manual/test_pageant.rb
 - test/start/test_connection.rb
 - test/start/test_options.rb
 - test/start/test_transport.rb
+- test/start/test_user_nil.rb
 - test/test_all.rb
 - test/test_buffer.rb
 - test/test_buffered_io.rb
Files old/metadata.gz.sig and new/metadata.gz.sig differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/net-ssh-public_cert.pem new/net-ssh-public_cert.pem
--- old/net-ssh-public_cert.pem 2015-09-25 21:35:53.000000000 +0200
+++ new/net-ssh-public_cert.pem 2015-12-30 10:07:47.000000000 +0100
@@ -1,20 +1,20 @@
 -----BEGIN CERTIFICATE-----
 MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRAwDgYDVQQDDAduZXQt
 c3NoMRkwFwYKCZImiZPyLGQBGRYJc29sdXRpb3VzMRMwEQYKCZImiZPyLGQBGRYD
-Y29tMB4XDTE0MTIwMjE3MzkyMFoXDTE1MTIwMjE3MzkyMFowQjEQMA4GA1UEAwwH
+Y29tMB4XDTE1MTIwNjIxMDYyNFoXDTE2MTIwNTIxMDYyNFowQjEQMA4GA1UEAwwH
 bmV0LXNzaDEZMBcGCgmSJomT8ixkARkWCXNvbHV0aW91czETMBEGCgmSJomT8ixk
-ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ0qnw4JV5JN
-MWelqu7pnW2z6GZJ7+zLFYJQNETJyF0U5zo7aCRK08OeUxnpu/TCCXK8iQVkNLfz
-9pVIhF+X8pMEIruAkYGwBt1aWfuSNeyodyMk0vpZdxBHbOTJ4qBRUc6qOtNOeOzv
-8ObYUX52P/EMMaeXTRU+e7MGkB9pb6FvPPNx5akxwIaoRvtcMsc/hJnQuP5r96w6
-t06MgKbXhWAX6gev0RVlrQqzxXst6iuvsrgZGjFqzob5wbTiX9M0+bFAB0EI7tJC
-sv5keEbtNRaU7p3ZbMm4wTHHJLOtD+BpUCSzwv4ToNj9mZtJBMYw2Eeo7z1DklEG
-mr95zbe+zNMCAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQU1bTfpzmitXwv
-LmTXi0IO5vd8NGYwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQA0Aps8
-UPINGa8XUUtrZtzrgX0/iyXNkKY1ld85g1N3WKEAVLfQI7TlGr0Qv2Ekx6RqlxbR
-Vyq08pytSnghW2otR3bIGMGQzqxAeRLb25cjEwH7YIJ32n7ZC1fpMnBZOBDmueWA
-B9EonmoO3ne7AJSgIvBbZzBPhzM4HrQGRW8LsPFsuj+dcJI43HOQwkmv2TRz0+t6
-mGZldmqLcK0abv4JepLfB9XTue3kuyA29NGBibqyvRwlKckLpvKfHZX6Jxad8xxm
-MbvRpzgROzyfw1qYi4dnIyMwTtXFFcZ0a2jpxHPkcTYFK6TzvFgDLAP0Y/u9jqUQ
-eZ7/3CdSi/isZHEw
+ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMYnhNtn0f6p
+nTylB8mE8lMdoMLJC8KwpMWsvk73Pe2WVDsH/OSwwwz6oUGk1i70cJyDjIEBNpwT
+88GpVXJSumvqVsf9fCg3mWNeb5t0J+aeNm9MIvYVMTqj5tydoXQiwnILRDYHV9tZ
+1c3o59/VlahSTpZ7YEgzVufpAkvEGkbJiG849exiipK7MN/ZIkMOxYVnyRXk43Xc
+6GYlsHOfSgPwcXwW5g57DCwLQLWrjDsTka28dxDmO7B5Lv5EqzINxVxWsu43OgZG
+21Io/jIyf5PNpeKPKNGDuAQJ8mvdMYBJoDhtCwgsUYbl0BZzA7g4ytl51HtIeP+j
+Qp/eAvs/RrECAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUBfKiwO2eM4NE
+iRrVG793qEPLYyMwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQCfZFdb
+p4jzkfIzGDbiOxd0R8sdqJoC4nMLEgnQ7dLulawwA3IXe3sHAKgA5kmH3prsKc5H
+zVmM5NlH2P1nRbegIkQTYiIod1hZQCNxdmVG/fprMqPq0ybpUOjjrP5pj0OtszE1
+F2dQia1hOEstMR+n0nAtWII9HJAEyeZjVV0s2Cl7Pt85XJ3hxFcCKwzqsK5xRI7a
+B3vwh3/JJYrFonIohQ//Lg9qTZASEkoKLlq1/hFeICoCGGIGLq45ZB7CzXLooCKi
+s/ZUKye79ELwFYKJOhjW5g725OL3hy+llhEleytwKRwgXFQBPTC4f5UkdxZVVWGH
+e2C9M1m/2odPZo8h
 -----END CERTIFICATE-----
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/net-ssh.gemspec new/net-ssh.gemspec
--- old/net-ssh.gemspec 2015-09-25 21:35:53.000000000 +0200
+++ new/net-ssh.gemspec 2015-12-30 10:07:47.000000000 +0100
@@ -2,17 +2,17 @@
 # DO NOT EDIT THIS FILE DIRECTLY
 # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
 # -*- encoding: utf-8 -*-
-# stub: net-ssh 3.0.1 ruby lib
+# stub: net-ssh 3.0.2 ruby lib
 
 Gem::Specification.new do |s|
   s.name = "net-ssh"
-  s.version = "3.0.1"
+  s.version = "3.0.2"
 
   s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? 
:required_rubygems_version=
   s.require_paths = ["lib"]
   s.authors = ["Jamis Buck", "Delano Mandelbaum", "Mikl\u{f3}s Fazekas"]
   s.cert_chain = ["net-ssh-public_cert.pem"]
-  s.date = "2015-09-25"
+  s.date = "2015-12-30"
   s.description = "Net::SSH: a pure-Ruby implementation of the SSH2 client 
protocol. It allows you to write programs that invoke and interact with 
processes on remote servers, via SSH2."
   s.email = "[email protected]"
   s.extra_rdoc_files = [
@@ -144,14 +144,16 @@
     "test/integration/Vagrantfile",
     "test/integration/common.rb",
     "test/integration/playbook.yml",
+    "test/integration/test_forward.rb",
     "test/integration/test_id_rsa_keys.rb",
+    "test/integration/test_proxy.rb",
     "test/known_hosts/github",
     "test/known_hosts/github_hash",
-    "test/manual/test_forward.rb",
     "test/manual/test_pageant.rb",
     "test/start/test_connection.rb",
     "test/start/test_options.rb",
     "test/start/test_transport.rb",
+    "test/start/test_user_nil.rb",
     "test/test_all.rb",
     "test/test_buffer.rb",
     "test/test_buffered_io.rb",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/README.txt new/test/README.txt
--- old/test/README.txt 2015-09-25 21:35:53.000000000 +0200
+++ new/test/README.txt 2015-12-30 10:07:47.000000000 +0100
@@ -16,25 +16,3 @@
 
      brew install ansible ; ansible-galaxy install rvm_io.rvm1-ruby ; vagrant 
up ; vagrant ssh
      cd /net-ssh ; rake integration-test
-
-PORT FORWARDING TESTS
-
-     ruby -Ilib -Itest -rrubygems test/manual/test_forward.rb
-
-test_forward.rb must be run separately from the test suite because
-it requires authorizing your public SSH keys on you localhost.
-
-If you already have keys you can do this:
-
-     cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
-
-If you don't have keys see:
-
-     http://kimmo.suominen.com/docs/ssh/#ssh-keygen
-
-You should now be able to login to your localhost with out
-bring prompted for a password:
-
-     ssh localhost
-
--Delano
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/connection/test_channel.rb 
new/test/connection/test_channel.rb
--- old/test/connection/test_channel.rb 2015-09-25 21:35:53.000000000 +0200
+++ new/test/connection/test_channel.rb 2015-12-30 10:07:47.000000000 +0100
@@ -74,8 +74,11 @@
       assert !channel.closing?
 
       connection.expect { |t,packet| assert_equal CHANNEL_CLOSE, packet.type }
+      connection.expects(:cleanup_channel).with(channel)
       channel.close
 
+      channel.process
+
       assert channel.closing?
     end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/connection/test_session.rb 
new/test/connection/test_session.rb
--- old/test/connection/test_session.rb 2015-09-25 21:35:53.000000000 +0200
+++ new/test/connection/test_session.rb 2015-12-30 10:07:47.000000000 +0100
@@ -117,14 +117,14 @@
     end
 
     def test_process_should_exit_after_processing_if_block_is_true_then_false
-      session.channels[0] = stub("channel", :closing? => false)
+      session.channels[0] = stub("channel", :local_closed? => false)
       session.channels[0].expects(:process)
       IO.expects(:select).never
       process_times(2)
     end
 
     def test_process_should_not_process_channels_that_are_closing
-      session.channels[0] = stub("channel", :closing? => true)
+      session.channels[0] = stub("channel", :local_closed? => true)
       session.channels[0].expects(:process).never
       IO.expects(:select).never
       process_times(2)
@@ -299,8 +299,17 @@
     end
 
     def 
test_channel_close_packet_should_be_routed_to_corresponding_channel_and_channel_should_be_closed_and_removed
-      channel_at(14).expects(:do_close).with()
-      session.channels[14].expects(:close).with()
+      session.channels[14] = stub("channel") do
+          # this simulates the case where we closed the channel first, sent
+          # CHANNEL_CLOSE to server and are waiting for server's response.
+          expects(:local_closed?).returns(true)
+          expects(:do_close)
+          expects(:close).with()
+          expects(:remote_closed!).with()
+          expects(:remote_closed?).with().returns(true)
+          expects(:local_id).returns(14)
+      end
+
       transport.return(CHANNEL_CLOSE, :long, 14)
       process_times(2)
       assert session.channels.empty?
@@ -526,7 +535,7 @@
       end
 
       def channel_at(local_id)
-        session.channels[local_id] = stub("channel", :process => true, 
:closing? => false)
+        session.channels[local_id] = stub("channel", :process => true, 
:local_closed? => false)
       end
 
       def transport(options={})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/README.txt 
new/test/integration/README.txt
--- old/test/integration/README.txt     2015-09-25 21:35:53.000000000 +0200
+++ new/test/integration/README.txt     2015-12-30 10:07:47.000000000 +0100
@@ -8,10 +8,8 @@
 Setup:
 
     ansible-galaxy install rvm_io.rvm1-ruby
-    vagrant up
-    vagrant ssh
-    cd /net-ssh
-    rake integration-test
+    vagrant up ; vagrant ssh
+    rake test
 
 # TODO
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/common.rb 
new/test/integration/common.rb
--- old/test/integration/common.rb      2015-09-25 21:35:53.000000000 +0200
+++ new/test/integration/common.rb      2015-12-30 10:07:47.000000000 +0100
@@ -14,6 +14,12 @@
     raise "Command: #{command} failed:#{status.exitstatus}" unless res
   end
 
+  def tmpdir(&block)
+    Dir.mktmpdir do |dir|
+      yield(dir)
+    end
+  end
+
   def set_authorized_key(user,pubkey)
     authorized_key = "/home/#{user}/.ssh/authorized_keys"
     sh "sudo cp #{pubkey} #{authorized_key}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/playbook.yml 
new/test/integration/playbook.yml
--- old/test/integration/playbook.yml   2015-09-25 21:35:53.000000000 +0200
+++ new/test/integration/playbook.yml   2015-12-30 10:07:47.000000000 +0100
@@ -14,7 +14,7 @@
   roles:
     - { role: rvm_io.rvm1-ruby,
         tags: ruby, sudo: True,
-        rvm1_rubies: ["ruby-{{ruby_version}}"],
+        rvm1_rubies: ["ruby-{{ruby_version}}","ruby-2.3.0"],
         rvm1_install_path: "{{rvm1_install_path}}",
         rvm1_gpg_key_server: pool.sks-keyservers.net,
         when: "'{{current_ruby_version.stdout|default()}}' != 
'{{ruby_version}}'" }
@@ -34,6 +34,14 @@
     - name: sshd debug
       lineinfile: dest='/etc/ssh/sshd_config' line='LogLevel DEBUG' 
regexp=LogLevel
       notify: restart sshd
+    - name: put NET_SSH_RUN_INTEGRATION_TESTS=YES environment
+      lineinfile: dest='/etc/environment' 
line='NET_SSH_RUN_INTEGRATION_TESTS=YES'
+    - name: change dir in bashrc
+      lineinfile: dest=/home/vagrant/.bashrc owner=vagrant mode=0644
+        regexp='^cd ' line='cd /net-ssh'
+    - apt: name="{{item}}" state=present
+      with_items:
+        - pv
     - gem: name="{{item}}" state=present 
executable=/usr/local/rvm/rubies/ruby-{{ruby_version}}/bin/gem
       with_items:
         - byebug
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/test_forward.rb 
new/test/integration/test_forward.rb
--- old/test/integration/test_forward.rb        1970-01-01 01:00:00.000000000 
+0100
+++ new/test/integration/test_forward.rb        2015-12-30 10:07:47.000000000 
+0100
@@ -0,0 +1,435 @@
+#     $ 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_relative './common'
+require 'net/ssh/buffer'
+require 'net/ssh'
+require 'timeout'
+require 'tempfile'
+
+class TestForward < Test::Unit::TestCase
+  include IntegrationTestHelpers
+
+  def localhost
+    'localhost'
+  end
+
+  def user
+    'net_ssh_1'
+  end
+
+  def ssh_start_params
+    [localhost ,user , {:keys => @key_id_rsa, :verbose => :debug}]
+  end
+
+  def setup_ssh_env(&block)
+    tmpdir do |dir|
+      @key_id_rsa = "#{dir}/id_rsa"
+      sh "rm -rf #{@key_id_rsa} #{@key_id_rsa}.pub"
+      sh "ssh-keygen -f #{@key_id_rsa} -t rsa -N ''"
+      set_authorized_key(user,"#{@key_id_rsa}.pub")
+      yield
+    end
+  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|
+              client.puts "item#{i}"
+            end
+            client.close
+          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.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 
0].pack("ii"))
+            client.close
+          rescue
+            exceptions <<  $!
+            raise
+          end
+        end
+      end
+    end
+    return server
+  end
+
+  def test_in_file_no_password
+    setup_ssh_env do
+      ret = Net::SSH.start(*ssh_start_params) do |ssh|
+      #ret = Net::SSH.start("localhost", "net_ssh_1", {keys: @key_id_rsa}) do 
|ssh|
+        ssh.exec! 'echo "hello from:$USER"'
+      end
+      assert_equal "hello from:net_ssh_1\n", ret
+    end
+  end
+
+  def test_local_ephemeral_port_should_work_correctly
+    setup_ssh_env do
+      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
+  end
+
+  def test_remote_ephemeral_port_should_work_correctly
+    setup_ssh_env do
+      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
+  end
+
+  def test_remote_callback_should_fire
+    setup_ssh_env do
+      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
+  end
+
+  def test_remote_callback_should_fire_on_error_and_still_throw_exception
+    setup_ssh_env do
+      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
+  end
+
+  def 
test_remote_callback_should_fire_on_error_but_not_throw_exception_if_asked_not_to
+    setup_ssh_env do
+      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 got_port, :==, :error
+        assert_operator session.forward.active_remotes.length, :==, 0
+      end
+    end
+  end
+
+  def test_loop_should_not_abort_when_local_side_of_forward_is_closed
+    setup_ssh_env do
+      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)
+      client_done = Queue.new
+      Thread.start do
+        begin
+          client = TCPSocket.new(localhost, local_port)
+          client.recv(1024)
+          client.close
+          sleep(0.2)
+        ensure
+          client_done << true
+        end
+      end
+      session.loop(0.1) { client_done.empty? }
+      assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty?
+    end
+  end
+
+  def test_loop_should_not_abort_when_local_side_of_forward_is_reset
+    setup_ssh_env do
+      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)
+      client_done = Queue.new
+      Thread.start do
+        begin
+          client = TCPSocket.new(localhost, local_port)
+          client.recv(1024)
+          client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 
0].pack("ii"))
+          client.close
+          sleep(0.1)
+        ensure
+          client_done << true
+        end
+      end
+      session.loop(0.1) { client_done.empty? }
+      assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty?
+    end
+  end
+
+  def create_local_socket(&blk)
+    tempfile = Tempfile.new("net_ssh_forward_test")
+    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
+    setup_ssh_env do
+      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
+
+      create_local_socket do |local_socket|
+        session.forward.local(local_socket, localhost, remote_port)
+        client_done = Queue.new
+
+        Thread.start do
+          begin
+            client = UNIXSocket.new(local_socket.path)
+            client_data = client.recv(1024)
+            client.close
+            sleep(0.2)
+          ensure
+            client_done << true
+          end
+        end
+
+        session.loop(0.1) { client_done.empty? }
+      end
+
+      assert_not_nil(client_data, "client should have received data")
+      assert(client_data.match(/item\d/), 'client should have received the 
string item')
+    end
+  end if defined?(UNIXSocket)
+
+  def test_loop_should_not_abort_when_server_side_of_forward_is_closed
+    setup_ssh_env do
+      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|
+            client.puts "item#{i}"
+          end
+          client.close
+          sleep(0.1)
+        ensure
+          client_done << true
+        end
+      end
+      session.loop(0.1) { client_done.empty? }
+    end
+  end
+
+  def start_server
+    server = TCPServer.open(0)
+    Thread.start do
+      loop do
+        Thread.start(server.accept) do |client|
+          yield(client)
+        end
+      end
+    end
+    return server
+  end
+
+  def test_client_close_should_be_handled_remote
+    setup_ssh_env do
+      message = "This is a small message!"*1000
+      session = Net::SSH.start(*ssh_start_params)
+      server_done = Queue.new
+      server = start_server do |client|
+        begin
+          data = client.read message.size
+          server_done << data
+          client.close
+        rescue
+          server_done << $!
+        end
+      end
+      client_done = Queue.new
+      got_remote_port = Queue.new
+      local_port = server.addr[1]
+      session.forward.remote(0, localhost, local_port) do |actual_remote_port|
+        got_remote_port << actual_remote_port
+      end
+      session.loop(0.1) { got_remote_port.empty? }
+      remote_port = got_remote_port.pop
+      Thread.start do
+        begin
+          client = TCPSocket.new(localhost, remote_port)
+          client.write(message)
+          client.close
+          client_done << true
+        rescue
+          client_done << $!
+        end
+      end
+      timeout(5) do
+        session.loop(0.1) { server_done.empty? }
+        assert_equal message, server_done.pop
+      end
+    end
+  end
+
+  def test_client_close_should_be_handled
+    setup_ssh_env do
+      message = "This is a small message!"*1000
+      session = Net::SSH.start(*ssh_start_params)
+      server_done = Queue.new
+      server = start_server do |client|
+        begin
+          data = client.read message.size
+          server_done << data
+          client.close
+        rescue
+          server_done << $!
+        end
+      end
+      client_done = Queue.new
+      remote_port = server.addr[1]
+      local_port = session.forward.local(0, localhost, remote_port)
+      Thread.start do
+        begin
+          client = TCPSocket.new(localhost, local_port)
+          client.write(message)
+          client.close
+          client_done << true
+        rescue
+          client_done << $!
+        end
+      end
+      timeout(5) do
+        session.loop(0.1) { server_done.empty? }
+        assert_equal message, server_done.pop
+      end
+    end
+  end
+
+  def test_server_eof_should_be_handled_remote
+    setup_ssh_env do
+      message = "This is a small message!"
+      session = Net::SSH.start(*ssh_start_params)
+      server = start_server do |client|
+        client.write message
+        client.close
+      end
+      client_done = Queue.new
+      got_remote_port = Queue.new
+      local_port = server.addr[1]
+      session.forward.remote(0, localhost, local_port) do |actual_remote_port|
+        got_remote_port << actual_remote_port
+      end
+      session.loop(0.1) { got_remote_port.empty? }
+      remote_port = got_remote_port.pop
+      Thread.start do
+        begin
+          client = TCPSocket.new(localhost, remote_port)
+          data = client.read(4096)
+          client.close
+          client_done << data
+        rescue
+          client_done << $!
+        end
+      end
+      timeout(5) do
+        session.loop(0.1) { client_done.empty? }
+        assert_equal message, client_done.pop
+      end
+    end
+  end
+
+  def test_server_eof_should_be_handled
+    setup_ssh_env do
+      message = "This is a small message!"
+      session = Net::SSH.start(*ssh_start_params)
+      server = start_server do |client|
+        client.write message
+        client.close
+      end
+      client_done = Queue.new
+      remote_port = server.addr[1]
+      local_port = session.forward.local(0, localhost, remote_port)
+      Thread.start do
+        begin
+          client = TCPSocket.new(localhost, local_port)
+          data = client.read(4096)
+          client.close
+          client_done << data
+        rescue
+          client_done << $!
+        end
+      end
+      timeout(5) do
+        session.loop(0.1) { client_done.empty? }
+        assert_equal message, client_done.pop
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/test_id_rsa_keys.rb 
new/test/integration/test_id_rsa_keys.rb
--- old/test/integration/test_id_rsa_keys.rb    2015-09-25 21:35:53.000000000 
+0200
+++ new/test/integration/test_id_rsa_keys.rb    2015-12-30 10:07:47.000000000 
+0100
@@ -10,12 +10,6 @@
 class TestIDRSAPKeys < Test::Unit::TestCase
   include IntegrationTestHelpers
 
-  def tmpdir(&block)
-    Dir.mktmpdir do |dir|
-      yield(dir)
-    end
-  end
-
   def test_in_file_no_password
     tmpdir do |dir|
       sh "rm -rf #{dir}/id_rsa #{dir}/id_rsa.pub"
@@ -81,4 +75,22 @@
       assert_equal "hello from:net_ssh_1\n", ret
     end
   end
+
+  def test_asks_for_passwords_when_read_from_memory
+    tmpdir do |dir|
+      sh "rm -rf #{dir}/id_rsa #{dir}/id_rsa.pub"
+      sh "ssh-keygen -f #{dir}/id_rsa -t rsa -N 'pwd12'"
+      set_authorized_key('net_ssh_1',"#{dir}/id_rsa.pub")
+      private_key = File.read("#{dir}/id_rsa")
+
+      options = {keys: [], key_data: [private_key]}
+
+      key_manager = Net::SSH::Authentication::KeyManager.new(nil, options)
+
+      Net::SSH::KeyFactory.expects(:prompt).with('Enter passphrase for :', 
false).returns('pwd12')
+      Net::SSH.start("localhost", "net_ssh_1", options) do |ssh|
+        ssh.exec! 'whoami'
+      end
+    end
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/integration/test_proxy.rb 
new/test/integration/test_proxy.rb
--- old/test/integration/test_proxy.rb  1970-01-01 01:00:00.000000000 +0100
+++ new/test/integration/test_proxy.rb  2015-12-30 10:07:47.000000000 +0100
@@ -0,0 +1,93 @@
+require_relative './common'
+require 'net/ssh/buffer'
+require 'net/ssh'
+require 'timeout'
+require 'tempfile'
+require 'net/ssh/proxy/command'
+
+class TestProxy < Test::Unit::TestCase
+  include IntegrationTestHelpers
+
+  def localhost
+    'localhost'
+  end
+
+  def user
+    'net_ssh_1'
+  end
+
+  def ssh_start_params(options)
+    [localhost ,user , {:keys => @key_id_rsa, :verbose => 
:debug}.merge(options)]
+  end
+
+  def setup_ssh_env(&block)
+    tmpdir do |dir|
+      @key_id_rsa = "#{dir}/id_rsa"
+      sh "rm -rf #{@key_id_rsa} #{@key_id_rsa}.pub"
+      sh "ssh-keygen -f #{@key_id_rsa} -t rsa -N ''"
+      set_authorized_key(user,"#{@key_id_rsa}.pub")
+      yield
+    end
+  end
+
+  def test_smoke
+    setup_ssh_env do
+      proxy = Net::SSH::Proxy::Command.new("/bin/nc localhost 22")
+      msg = 'echo123'
+      ret = Net::SSH.start(*ssh_start_params(:proxy => proxy)) do |ssh|
+        ssh.exec! "echo \"$USER:#{msg}\""
+      end
+      assert_equal "net_ssh_1:#{msg}\n", ret
+    end
+  end
+
+  def with_spurious_write_wakeup_emulate(rate=99,&block)
+    orig_io_select = Net::SSH::Compat.method(:io_select)
+    count = 0
+    Net::SSH::Compat.singleton_class.send(:define_method,:io_select) do 
|*params|
+      count += 1
+      if (count % rate != 0)
+        if params && params[1] && !params[1].empty?
+          return [[],params[1],[]]
+        end
+        #if params && params[0] && !params[0].empty?
+        #return [params[0],[],[]]
+        #end
+      end
+      IO.select(*params)
+    end
+    begin
+      yield
+    ensure
+      
Net::SSH::Compat.singleton_class.send(:define_method,:io_select,&orig_io_select)
+    end
+  end
+
+  def test_with_rate_limit_and_spurious_wakeup
+    system("sudo sh -c 'echo 4096 > /proc/sys/fs/pipe-max-size'")
+    begin
+      setup_ssh_env do
+        proxy = Net::SSH::Proxy::Command.new("/usr/bin/pv --rate-limit 100k | 
/bin/nc localhost 22")
+        #proxy = Net::SSH::Proxy::Command.new("/bin/nc localhost 22")
+        begin
+          large_msg = 'echo123'*30000
+          ok = Net::SSH.start(*ssh_start_params(:proxy => proxy)) do |ssh|
+              with_spurious_write_wakeup_emulate do
+                ret = ssh.exec! "echo \"$USER:#{large_msg}\""
+                #assert_equal "net_ssh_1:#{large_msg}\n", ret
+                assert_equal "/bin/sh: Argument list too long\n", ret
+                hello_count = 1000
+                ret = ssh.exec! "ruby -e 'puts \"Hello\"*#{hello_count}'"
+                assert_equal "Hello"*hello_count+"\n", ret
+              end
+              :ok
+            end
+        end
+        assert_equal :ok, ok
+      end
+    ensure
+      system("sudo sh -c 'echo 1048576 > /proc/sys/fs/pipe-max-size'")
+    end
+  end
+
+end
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/manual/test_forward.rb 
new/test/manual/test_forward.rb
--- old/test/manual/test_forward.rb     2015-09-25 21:35:53.000000000 +0200
+++ new/test/manual/test_forward.rb     1970-01-01 01:00:00.000000000 +0100
@@ -1,285 +0,0 @@
-#     $ 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|
-              client.puts "item#{i}"
-            end
-            client.close
-          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.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 
0].pack("ii"))
-            client.close
-          rescue
-            exceptions <<  $!
-            raise
-          end
-        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)
-    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
-    Thread.start do
-      begin
-        client = TCPSocket.new(localhost, local_port)
-        client.recv(1024)
-        client.close
-        sleep(0.2)
-      ensure
-        client_done << true
-      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 = 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
-    Thread.start do
-      begin
-        client = TCPSocket.new(localhost, local_port)
-        client.recv(1024)
-        client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 
0].pack("ii"))
-        client.close
-        sleep(0.1)
-      ensure
-        client_done << true
-      end
-    end
-    session.loop(0.1) { client_done.empty? }
-    assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty?
-  end
-
-  def create_local_socket(&blk)
-    tempfile = Tempfile.new("net_ssh_forward_test")
-    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)
-    server_exc = Queue.new
-    server = start_server_sending_lot_of_data(server_exc)
-    remote_port = server.addr[1]
-    client_data = nil
-
-    create_local_socket do |local_socket|
-      session.forward.local(local_socket, localhost, remote_port)
-      client_done = Queue.new
-
-      Thread.start do
-        begin
-          client = UNIXSocket.new(local_socket.path)
-          client_data = client.recv(1024)
-          client.close
-          sleep(0.2)
-        ensure
-          client_done << true
-        end
-      end
-
-      session.loop(0.1) { client_done.empty? }
-    end
-
-    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)
-    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|
-          client.puts "item#{i}"
-        end
-        client.close
-        sleep(0.1)
-      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|
-          yield(client)
-        end
-      end
-    end
-    return server
-  end
-
-  def test_server_eof_should_be_handled
-    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
-    client_exception = Queue.new
-    client_data = Queue.new
-    remote_port = server.addr[1]
-    local_port = session.forward.local(0, localhost, remote_port)
-    Thread.start do
-      begin
-        client = TCPSocket.new(localhost, local_port)
-        data = client.read(4096)
-        client.close
-        client_done << data
-      rescue
-        client_done << $!
-      end
-    end
-    timeout(5) do
-      session.loop(0.1) { client_done.empty? }
-      assert_equal "This is a small message!", client_done.pop
-    end
-  end
-end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/start/test_user_nil.rb 
new/test/start/test_user_nil.rb
--- old/test/start/test_user_nil.rb     1970-01-01 01:00:00.000000000 +0100
+++ new/test/start/test_user_nil.rb     2015-12-30 10:07:47.000000000 +0100
@@ -0,0 +1,27 @@
+require 'common'
+require 'net/ssh'
+
+module NetSSH
+  class TestStartUserNil < Test::Unit::TestCase
+    def setup
+      @authentication_session = mock('authentication_session')
+      
Net::SSH::Authentication::Session.stubs(:new).returns(@authentication_session)
+      
Net::SSH::Transport::Session.stubs(:new).returns(mock('transport_session'))
+      
Net::SSH::Connection::Session.stubs(:new).returns(mock('connection_session'))
+    end
+
+    def test_start_should_accept_nil_user
+      @authentication_session.stubs(:authenticate).returns(true)
+      assert_nothing_raised do
+        Net::SSH.start('localhost')
+      end
+    end
+
+    def test_start_should_use_default_user_when_nil
+      @authentication_session.stubs(:authenticate).with() {|_next_service, 
user, _password| user == Etc.getlogin }.returns(true)
+      assert_nothing_raised do
+        Net::SSH.start('localhost')
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/test/test_all.rb new/test/test_all.rb
--- old/test/test_all.rb        2015-09-25 21:35:53.000000000 +0200
+++ new/test/test_all.rb        2015-12-30 10:07:47.000000000 +0100
@@ -4,7 +4,7 @@
 #     $ ruby -Ilib -Itest -rrubygems test/transport/test_server_version.rb
 Dir.chdir(File.dirname(__FILE__)) do
   test_files = Dir['**/test_*.rb']-['test_all.rb'] # prevent circular require
-  test_files -= Dir['integration/test_*.rb']
+  test_files -= Dir['integration/test_*.rb'] unless 
ENV['NET_SSH_RUN_INTEGRATION_TESTS']
   test_files = test_files.reject { |f| f =~ /^manual/ }
   test_files = test_files.select { |f| f =~ Regexp.new(ENV['ONLY']) } if 
ENV['ONLY']
   test_files = test_files.reject { |f| f =~ Regexp.new(ENV['EXCEPT']) } if 
ENV['EXCEPT']


Reply via email to