diff options
author | Jeff Forcier <jeff@bitprophet.org> | 2016-11-30 20:02:20 -0800 |
---|---|---|
committer | Jeff Forcier <jeff@bitprophet.org> | 2016-11-30 20:02:20 -0800 |
commit | 9aec0c6300686e571fab5405c52876e6399f92e9 (patch) | |
tree | 8521aae70c6ebe889b92cbb9db69fd632f0fed08 /tests/test_client.py | |
parent | 2a568863bb462fbae50fdd4795bf4d3e05e101bb (diff) | |
parent | 7366f965546c015c3f9e9dd1ccb8f0b7b8758dae (diff) |
Merge branch 'master' into 398-int
Diffstat (limited to 'tests/test_client.py')
-rw-r--r-- | tests/test_client.py | 99 |
1 files changed, 62 insertions, 37 deletions
diff --git a/tests/test_client.py b/tests/test_client.py index 0022a4d9..32d9ac60 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -22,6 +22,8 @@ Some unit tests for SSHClient. from __future__ import with_statement +import gc +import platform import socket from tempfile import mkstemp import threading @@ -31,8 +33,9 @@ import warnings import os import time from tests.util import test_path + import paramiko -from paramiko.common import PY2, b +from paramiko.common import PY2 from paramiko.ssh_exception import SSHException @@ -75,7 +78,7 @@ class NullServer (paramiko.ServerInterface): return paramiko.OPEN_SUCCEEDED def check_channel_exec_request(self, channel, command): - if command != 'yes': + if command != b'yes': return False return True @@ -97,6 +100,12 @@ class SSHClientTest (unittest.TestCase): self.sockl.bind(('localhost', 0)) self.sockl.listen(1) self.addr, self.port = self.sockl.getsockname() + self.connect_kwargs = dict( + hostname=self.addr, + port=self.port, + username='slowdive', + look_for_keys=False, + ) self.event = threading.Event() def tearDown(self): @@ -134,11 +143,11 @@ class SSHClientTest (unittest.TestCase): self.tc.get_host_keys().add('[%s]:%d' % (self.addr, self.port), 'ssh-rsa', public_host_key) # Actual connection - self.tc.connect(self.addr, self.port, username='slowdive', **kwargs) + self.tc.connect(**dict(self.connect_kwargs, **kwargs)) # Authentication successful? self.event.wait(1.0) - self.assertTrue(self.event.isSet()) + self.assertTrue(self.event.is_set()) self.assertTrue(self.ts.is_active()) self.assertEqual('slowdive', self.ts.get_username()) self.assertEqual(True, self.ts.is_authenticated()) @@ -183,7 +192,7 @@ class SSHClientTest (unittest.TestCase): """ verify that SSHClient works with an ECDSA key. """ - self._test_connection(key_filename=test_path('test_ecdsa.key')) + self._test_connection(key_filename=test_path('test_ecdsa_256.key')) def test_3_multiple_key_files(self): """ @@ -200,15 +209,21 @@ class SSHClientTest (unittest.TestCase): for attempt, accept in ( (['rsa', 'dss'], ['dss']), # Original test #3 (['dss', 'rsa'], ['dss']), # Ordering matters sometimes, sadly - (['dss', 'rsa', 'ecdsa'], ['dss']), # Try ECDSA but fail - (['rsa', 'ecdsa'], ['ecdsa']), # ECDSA success + (['dss', 'rsa', 'ecdsa_256'], ['dss']), # Try ECDSA but fail + (['rsa', 'ecdsa_256'], ['ecdsa']), # ECDSA success ): - self._test_connection( - key_filename=[ - test_path('test_{0}.key'.format(x)) for x in attempt - ], - allowed_keys=[types_[x] for x in accept], - ) + try: + self._test_connection( + key_filename=[ + test_path('test_{0}.key'.format(x)) for x in attempt + ], + allowed_keys=[types_[x] for x in accept], + ) + finally: + # Clean up to avoid occasional gc-related deadlocks. + # TODO: use nose test generators after nose port + self.tearDown() + self.setUp() def test_multiple_key_files_failure(self): """ @@ -233,10 +248,10 @@ class SSHClientTest (unittest.TestCase): self.tc = paramiko.SSHClient() self.tc.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.assertEqual(0, len(self.tc.get_host_keys())) - self.tc.connect(self.addr, self.port, username='slowdive', password='pygmalion') + self.tc.connect(password='pygmalion', **self.connect_kwargs) self.event.wait(1.0) - self.assertTrue(self.event.isSet()) + self.assertTrue(self.event.is_set()) self.assertTrue(self.ts.is_active()) self.assertEqual('slowdive', self.ts.get_username()) self.assertEqual(True, self.ts.is_authenticated()) @@ -276,22 +291,21 @@ class SSHClientTest (unittest.TestCase): transport's packetizer) is closed. """ # Unclear why this is borked on Py3, but it is, and does not seem worth - # pursuing at the moment. + # pursuing at the moment. Skipped on PyPy because it fails on travis + # for unknown reasons, works fine locally. # XXX: It's the release of the references to e.g packetizer that fails # in py3... - if not PY2: + if not PY2 or platform.python_implementation() == "PyPy": return threading.Thread(target=self._run).start() - host_key = paramiko.RSAKey.from_private_key_file(test_path('test_rsa.key')) - public_host_key = paramiko.RSAKey(data=host_key.asbytes()) self.tc = paramiko.SSHClient() self.tc.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.assertEqual(0, len(self.tc.get_host_keys())) - self.tc.connect(self.addr, self.port, username='slowdive', password='pygmalion') + self.tc.connect(**dict(self.connect_kwargs, password='pygmalion')) self.event.wait(1.0) - self.assertTrue(self.event.isSet()) + self.assertTrue(self.event.is_set()) self.assertTrue(self.ts.is_active()) p = weakref.ref(self.tc._transport.packetizer) @@ -299,14 +313,10 @@ class SSHClientTest (unittest.TestCase): self.tc.close() del self.tc - # hrm, sometimes p isn't cleared right away. why is that? - #st = time.time() - #while (time.time() - st < 5.0) and (p() is not None): - # time.sleep(0.1) - - # instead of dumbly waiting for the GC to collect, force a collection - # to see whether the SSHClient object is deallocated correctly - import gc + # force a collection to see whether the SSHClient object is deallocated + # correctly. 2 GCs are needed to make sure it's really collected on + # PyPy + gc.collect() gc.collect() self.assertTrue(p() is None) @@ -316,17 +326,15 @@ class SSHClientTest (unittest.TestCase): verify that an SSHClient can be used a context manager """ threading.Thread(target=self._run).start() - host_key = paramiko.RSAKey.from_private_key_file(test_path('test_rsa.key')) - public_host_key = paramiko.RSAKey(data=host_key.asbytes()) with paramiko.SSHClient() as tc: self.tc = tc self.tc.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.assertEquals(0, len(self.tc.get_host_keys())) - self.tc.connect(self.addr, self.port, username='slowdive', password='pygmalion') + self.tc.connect(**dict(self.connect_kwargs, password='pygmalion')) self.event.wait(1.0) - self.assertTrue(self.event.isSet()) + self.assertTrue(self.event.is_set()) self.assertTrue(self.ts.is_active()) self.assertTrue(self.tc._transport is not None) @@ -345,15 +353,32 @@ class SSHClientTest (unittest.TestCase): self.tc = paramiko.SSHClient() self.tc.get_host_keys().add('[%s]:%d' % (self.addr, self.port), 'ssh-rsa', public_host_key) # Connect with a half second banner timeout. + kwargs = dict(self.connect_kwargs, banner_timeout=0.5) self.assertRaises( paramiko.SSHException, self.tc.connect, - self.addr, - self.port, - username='slowdive', + **kwargs + ) + + def test_8_auth_trickledown(self): + """ + Failed key auth doesn't prevent subsequent pw auth from succeeding + """ + # NOTE: re #387, re #394 + # If pkey module used within Client._auth isn't correctly handling auth + # errors (e.g. if it allows things like ValueError to bubble up as per + # midway thru #394) client.connect() will fail (at key load step) + # instead of succeeding (at password step) + kwargs = dict( + # Password-protected key whose passphrase is not 'pygmalion' (it's + # 'television' as per tests/test_pkey.py). NOTE: must use + # key_filename, loading the actual key here with PKey will except + # immediately; we're testing the try/except crap within Client. + key_filename=[test_path('test_rsa_password.key')], + # Actual password for default 'slowdive' user password='pygmalion', - banner_timeout=0.5 ) + self._test_connection(**kwargs) def test_update_environment(self): """ |