88
103
stop_event.wait(30.0)
106
if not paramiko_loaded:
107
raise TestSkipped('you must have paramiko to run this test')
91
108
TestCaseInTempDir.setUp(self)
92
109
self._root = self.test_dir
110
self._is_setup = False
112
def delayed_setup(self):
113
# some tests are just stubs that call setUp and then immediately call
114
# tearDwon. so don't create the port listener until get_transport is
115
# called and we know we're in an actual test.
94
118
self._listener = SingleListener(self._run_server)
95
119
self._listener.setDaemon(True)
96
120
self._listener.start()
97
121
self._sftp_url = 'sftp://foo:bar@localhost:%d/' % (self._listener.port,)
122
self._is_setup = True
99
124
def tearDown(self):
100
self._listener.stop()
126
self._listener.stop()
127
except AttributeError:
101
129
TestCaseInTempDir.tearDown(self)
104
132
class SFTPTransportTest (TestCaseWithSFTPServer, TestTransportMixIn):
136
TestCaseWithSFTPServer.setUp(self)
139
def log(self, *args):
140
"""Override the default log to grab sftp server messages"""
141
TestCaseWithSFTPServer.log(self, *args)
142
if args and args[0].startswith('sftpserver'):
143
self.sftplogs.append(args[0])
107
145
def get_transport(self):
108
147
from bzrlib.transport.sftp import SFTPTransport
109
148
url = self._sftp_url
110
149
return SFTPTransport(url)
112
if not paramiko_loaded:
113
del SFTPTransportTest
151
def test_sftp_locks(self):
152
from bzrlib.errors import LockError
153
t = self.get_transport()
155
l = t.lock_write('bogus')
156
self.failUnlessExists('bogus.write-lock')
158
# Don't wait for the lock, locking an already locked
159
# file should raise an assert
160
self.assertRaises(LockError, t.lock_write, 'bogus')
163
self.failIf(lexists('bogus.write-lock'))
165
open('something.write-lock', 'wb').write('fake lock\n')
166
self.assertRaises(LockError, t.lock_write, 'something')
167
os.remove('something.write-lock')
169
l = t.lock_write('something')
171
l2 = t.lock_write('bogus')
176
def test_multiple_connections(self):
177
t = self.get_transport()
178
self.assertEquals(self.sftplogs,
179
['sftpserver - authorizing: foo'
180
, 'sftpserver - channel request: session, 1'])
182
# The second request should reuse the first connection
183
# SingleListener only allows for a single connection,
184
# So the next line fails unless the connection is reused
185
t2 = self.get_transport()
186
self.assertEquals(self.sftplogs, [])
189
class FakeSFTPTransport (object):
191
fake = FakeSFTPTransport()
194
class SFTPNonServerTest(TestCase):
197
if not paramiko_loaded:
198
raise TestSkipped('you must have paramiko to run this test')
200
def test_parse_url(self):
201
from bzrlib.transport.sftp import SFTPTransport
202
s = SFTPTransport('sftp://simple.example.com/%2fhome/source', clone_from=fake)
203
self.assertEquals(s._host, 'simple.example.com')
204
self.assertEquals(s._port, None)
205
self.assertEquals(s._path, '/home/source')
206
self.failUnless(s._password is None)
208
self.assertEquals(s.base, 'sftp://simple.example.com/%2Fhome/source')
210
s = SFTPTransport('sftp://ro%62ey:h%40t@example.com:2222/relative', clone_from=fake)
211
self.assertEquals(s._host, 'example.com')
212
self.assertEquals(s._port, 2222)
213
self.assertEquals(s._username, 'robey')
214
self.assertEquals(s._password, 'h@t')
215
self.assertEquals(s._path, 'relative')
217
# Base should not keep track of the password
218
self.assertEquals(s.base, 'sftp://robey@example.com:2222/relative')
220
# Double slash should be accepted instead of using %2F
221
s = SFTPTransport('sftp://user@example.com:22//absolute/path', clone_from=fake)
222
self.assertEquals(s._host, 'example.com')
223
self.assertEquals(s._port, 22)
224
self.assertEquals(s._username, 'user')
225
self.assertEquals(s._password, None)
226
self.assertEquals(s._path, '/absolute/path')
228
# Also, don't show the port if it is the default 22
229
self.assertEquals(s.base, 'sftp://user@example.com:22/%2Fabsolute/path')
231
def test_relpath(self):
232
from bzrlib.transport.sftp import SFTPTransport
233
from bzrlib.errors import PathNotChild
235
s = SFTPTransport('sftp://user@host.com//abs/path', clone_from=fake)
236
self.assertEquals(s.relpath('sftp://user@host.com//abs/path/sub'), 'sub')
237
# Can't test this one, because we actually get an AssertionError
238
# TODO: Consider raising an exception rather than an assert
239
#self.assertRaises(PathNotChild, s.relpath, 'http://user@host.com//abs/path/sub')
240
self.assertRaises(PathNotChild, s.relpath, 'sftp://user2@host.com//abs/path/sub')
241
self.assertRaises(PathNotChild, s.relpath, 'sftp://user@otherhost.com//abs/path/sub')
242
self.assertRaises(PathNotChild, s.relpath, 'sftp://user@host.com:33//abs/path/sub')
243
self.assertRaises(PathNotChild, s.relpath, 'sftp://user@host.com/abs/path/sub')
245
# Make sure it works when we don't supply a username
246
s = SFTPTransport('sftp://host.com//abs/path', clone_from=fake)
247
self.assertEquals(s.relpath('sftp://host.com//abs/path/sub'), 'sub')
249
# Make sure it works when parts of the path will be url encoded
250
# TODO: These may be incorrect, we might need to urllib.urlencode() before
251
# we pass the paths into the SFTPTransport constructor
252
s = SFTPTransport('sftp://host.com/dev/,path', clone_from=fake)
253
self.assertEquals(s.relpath('sftp://host.com/dev/,path/sub'), 'sub')
254
s = SFTPTransport('sftp://host.com/dev/%path', clone_from=fake)
255
self.assertEquals(s.relpath('sftp://host.com/dev/%path/sub'), 'sub')
257
def test_parse_invalid_url(self):
258
from bzrlib.transport.sftp import SFTPTransport, TransportError
260
s = SFTPTransport('sftp://lilypond.org:~janneke/public_html/bzr/gub',
262
self.fail('expected exception not raised')
263
except TransportError, e:
264
self.assertEquals(str(e),
265
'~janneke: invalid port number')
268
class SFTPBranchTest(TestCaseWithSFTPServer):
269
"""Test some stuff when accessing a bzr Branch over sftp"""
271
def test_lock_file(self):
272
"""Make sure that a Branch accessed over sftp tries to lock itself."""
273
from bzrlib.branch import Branch
276
b = Branch.initialize(self._sftp_url)
277
self.failUnlessExists('.bzr/')
278
self.failUnlessExists('.bzr/branch-format')
279
self.failUnlessExists('.bzr/branch-lock')
281
self.failIf(lexists('.bzr/branch-lock.write-lock'))
283
self.failUnlessExists('.bzr/branch-lock.write-lock')
285
self.failIf(lexists('.bzr/branch-lock.write-lock'))
287
def test_no_working_tree(self):
288
from bzrlib.branch import Branch
290
b = Branch.initialize(self._sftp_url)
291
self.assertRaises(errors.NoWorkingTree, b.working_tree)
293
def test_push_support(self):
294
from bzrlib.branch import Branch
297
self.build_tree(['a/', 'a/foo'])
298
b = Branch.initialize('a')
301
t.commit('foo', rev_id='a1')
304
b2 = Branch.initialize(self._sftp_url + 'b')
307
self.assertEquals(b2.revision_history(), ['a1'])
309
open('a/foo', 'wt').write('something new in foo\n')
310
t.commit('new', rev_id='a2')
313
self.assertEquals(b2.revision_history(), ['a1', 'a2'])