bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
1 |
# Copyright (C) 2005 Robey Pointer <robey@lag.net>, Canonical Ltd
|
2 |
||
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
||
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
||
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
16 |
||
17 |
import os |
|
18 |
import socket |
|
19 |
import threading |
|
20 |
||
|
1185.49.14
by John Arbash Meinel
[merge] bzr.dev |
21 |
from bzrlib.tests import TestCaseInTempDir, TestCase |
|
1185.31.25
by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py |
22 |
from bzrlib.tests.test_transport import TestTransportMixIn |
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
23 |
|
24 |
try: |
|
25 |
import paramiko |
|
26 |
from stub_sftp import StubServer, StubSFTPServer |
|
27 |
paramiko_loaded = True |
|
28 |
except ImportError: |
|
29 |
paramiko_loaded = False |
|
30 |
||
|
1185.48.4
by James Henstridge
Some test suite updates. The relative URI handling is pretty iffy ... |
31 |
# XXX: 20051124 jamesh
|
32 |
# The tests currently pop up a password prompt when an external ssh
|
|
33 |
# is used. This forces the use of the paramiko implementation.
|
|
|
1185.49.23
by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception. |
34 |
if paramiko_loaded: |
35 |
import bzrlib.transport.sftp |
|
36 |
bzrlib.transport.sftp._ssh_vendor = 'none' |
|
|
1185.48.4
by James Henstridge
Some test suite updates. The relative URI handling is pretty iffy ... |
37 |
|
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
38 |
|
39 |
STUB_SERVER_KEY = """ |
|
40 |
-----BEGIN RSA PRIVATE KEY-----
|
|
41 |
MIICWgIBAAKBgQDTj1bqB4WmayWNPB+8jVSYpZYk80Ujvj680pOTh2bORBjbIAyz
|
|
42 |
oWGW+GUjzKxTiiPvVmxFgx5wdsFvF03v34lEVVhMpouqPAYQ15N37K/ir5XY+9m/
|
|
43 |
d8ufMCkjeXsQkKqFbAlQcnWMCRnOoPHS3I4vi6hmnDDeeYTSRvfLbW0fhwIBIwKB
|
|
44 |
gBIiOqZYaoqbeD9OS9z2K9KR2atlTxGxOJPXiP4ESqP3NVScWNwyZ3NXHpyrJLa0
|
|
45 |
EbVtzsQhLn6rF+TzXnOlcipFvjsem3iYzCpuChfGQ6SovTcOjHV9z+hnpXvQ/fon
|
|
46 |
soVRZY65wKnF7IAoUwTmJS9opqgrN6kRgCd3DASAMd1bAkEA96SBVWFt/fJBNJ9H
|
|
47 |
tYnBKZGw0VeHOYmVYbvMSstssn8un+pQpUm9vlG/bp7Oxd/m+b9KWEh2xPfv6zqU
|
|
48 |
avNwHwJBANqzGZa/EpzF4J8pGti7oIAPUIDGMtfIcmqNXVMckrmzQ2vTfqtkEZsA
|
|
49 |
4rE1IERRyiJQx6EJsz21wJmGV9WJQ5kCQQDwkS0uXqVdFzgHO6S++tjmjYcxwr3g
|
|
50 |
H0CoFYSgbddOT6miqRskOQF3DZVkJT3kyuBgU2zKygz52ukQZMqxCb1fAkASvuTv
|
|
51 |
qfpH87Qq5kQhNKdbbwbmd2NxlNabazPijWuphGTdW0VfJdWfklyS2Kr+iqrs/5wV
|
|
52 |
HhathJt636Eg7oIjAkA8ht3MQ+XSl9yIJIS8gVpbPxSw5OMfw0PjVE7tBdQruiSc
|
|
53 |
nvuQES5C9BMHjF39LZiGH1iLQy7FgdHyoP+eodI7
|
|
54 |
-----END RSA PRIVATE KEY-----
|
|
55 |
"""
|
|
56 |
||
57 |
||
58 |
class SingleListener (threading.Thread): |
|
59 |
def __init__(self, callback): |
|
60 |
threading.Thread.__init__(self) |
|
61 |
self._callback = callback |
|
62 |
self._socket = socket.socket() |
|
|
1185.40.10
by Robey Pointer
set REUSEADDR on the listen socket in sftp transport tests, and delay opening the listening socket until we know the test is really going to run (some tests are currently stubs) |
63 |
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
|
1185.40.8
by Robey Pointer
modification of a patch by alexey shamrin to make more of the transport tests pass on windows |
64 |
self._socket.bind(('localhost', 0)) |
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
65 |
self._socket.listen(1) |
66 |
self.port = self._socket.getsockname()[1] |
|
67 |
self.stop_event = threading.Event() |
|
68 |
||
69 |
def run(self): |
|
70 |
s, _ = self._socket.accept() |
|
71 |
# now close the listen socket
|
|
72 |
self._socket.close() |
|
73 |
self._callback(s, self.stop_event) |
|
74 |
||
75 |
def stop(self): |
|
76 |
self.stop_event.set() |
|
|
1185.49.10
by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp). |
77 |
# We should consider waiting for the other thread
|
78 |
# to stop, because otherwise we get spurious
|
|
79 |
# bzr: ERROR: Socket exception: Connection reset by peer (54)
|
|
80 |
# because the test suite finishes before the thread has a chance
|
|
81 |
# to close. (Especially when only running a few tests)
|
|
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
82 |
|
83 |
||
84 |
class TestCaseWithSFTPServer (TestCaseInTempDir): |
|
85 |
""" |
|
86 |
Execute a test case with a stub SFTP server, serving files from the local
|
|
87 |
filesystem over the loopback network.
|
|
88 |
"""
|
|
89 |
||
90 |
def _run_server(self, s, stop_event): |
|
91 |
ssh_server = paramiko.Transport(s) |
|
92 |
key_file = os.path.join(self._root, 'test_rsa.key') |
|
93 |
file(key_file, 'w').write(STUB_SERVER_KEY) |
|
94 |
host_key = paramiko.RSAKey.from_private_key_file(key_file) |
|
95 |
ssh_server.add_server_key(host_key) |
|
|
1185.49.10
by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp). |
96 |
server = StubServer(self) |
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
97 |
ssh_server.set_subsystem_handler('sftp', paramiko.SFTPServer, StubSFTPServer, root=self._root) |
98 |
event = threading.Event() |
|
99 |
ssh_server.start_server(event, server) |
|
100 |
event.wait(5.0) |
|
101 |
stop_event.wait(30.0) |
|
102 |
||
103 |
def setUp(self): |
|
104 |
TestCaseInTempDir.setUp(self) |
|
105 |
self._root = self.test_dir |
|
|
1185.49.14
by John Arbash Meinel
[merge] bzr.dev |
106 |
self._is_setup = False |
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
107 |
|
|
1185.40.10
by Robey Pointer
set REUSEADDR on the listen socket in sftp transport tests, and delay opening the listening socket until we know the test is really going to run (some tests are currently stubs) |
108 |
def delayed_setup(self): |
109 |
# some tests are just stubs that call setUp and then immediately call
|
|
110 |
# tearDwon. so don't create the port listener until get_transport is
|
|
111 |
# called and we know we're in an actual test.
|
|
|
1185.49.14
by John Arbash Meinel
[merge] bzr.dev |
112 |
if self._is_setup: |
113 |
return
|
|
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
114 |
self._listener = SingleListener(self._run_server) |
115 |
self._listener.setDaemon(True) |
|
116 |
self._listener.start() |
|
117 |
self._sftp_url = 'sftp://foo:bar@localhost:%d/' % (self._listener.port,) |
|
|
1185.49.14
by John Arbash Meinel
[merge] bzr.dev |
118 |
self._is_setup = True |
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
119 |
|
120 |
def tearDown(self): |
|
|
1185.40.10
by Robey Pointer
set REUSEADDR on the listen socket in sftp transport tests, and delay opening the listening socket until we know the test is really going to run (some tests are currently stubs) |
121 |
try: |
122 |
self._listener.stop() |
|
123 |
except AttributeError: |
|
124 |
pass
|
|
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
125 |
TestCaseInTempDir.tearDown(self) |
126 |
||
127 |
||
128 |
class SFTPTransportTest (TestCaseWithSFTPServer, TestTransportMixIn): |
|
129 |
readonly = False |
|
130 |
||
|
1185.49.10
by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp). |
131 |
def setUp(self): |
132 |
TestCaseWithSFTPServer.setUp(self) |
|
133 |
self.sftplogs = [] |
|
134 |
||
135 |
def log(self, *args): |
|
136 |
"""Override the default log to grab sftp server messages""" |
|
137 |
TestCaseWithSFTPServer.log(self, *args) |
|
138 |
if args and args[0].startswith('sftpserver'): |
|
139 |
self.sftplogs.append(args[0]) |
|
140 |
||
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
141 |
def get_transport(self): |
|
1185.49.14
by John Arbash Meinel
[merge] bzr.dev |
142 |
self.delayed_setup() |
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
143 |
from bzrlib.transport.sftp import SFTPTransport |
144 |
url = self._sftp_url |
|
145 |
return SFTPTransport(url) |
|
146 |
||
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
147 |
def test_sftp_locks(self): |
148 |
from bzrlib.errors import LockError |
|
149 |
t = self.get_transport() |
|
150 |
||
151 |
l = t.lock_write('bogus') |
|
152 |
self.failUnlessExists('bogus.write-lock') |
|
153 |
||
154 |
# Don't wait for the lock, locking an already locked
|
|
155 |
# file should raise an assert
|
|
156 |
self.assertRaises(LockError, t.lock_write, 'bogus') |
|
157 |
||
158 |
l.unlock() |
|
159 |
self.failIf(os.path.lexists('bogus.write-lock')) |
|
160 |
||
161 |
open('something.write-lock', 'wb').write('fake lock\n') |
|
162 |
self.assertRaises(LockError, t.lock_write, 'something') |
|
163 |
os.remove('something.write-lock') |
|
164 |
||
165 |
l = t.lock_write('something') |
|
166 |
||
167 |
l2 = t.lock_write('bogus') |
|
168 |
||
169 |
l.unlock() |
|
170 |
l2.unlock() |
|
171 |
||
|
1185.49.10
by John Arbash Meinel
Use a weakref dictionary to enable re-use of a connection (for sftp). |
172 |
def test_multiple_connections(self): |
173 |
t = self.get_transport() |
|
174 |
self.assertEquals(self.sftplogs, |
|
175 |
['sftpserver - authorizing: foo' |
|
176 |
, 'sftpserver - channel request: session, 1']) |
|
177 |
self.sftplogs = [] |
|
178 |
# The second request should reuse the first connection
|
|
179 |
# SingleListener only allows for a single connection,
|
|
180 |
# So the next line fails unless the connection is reused
|
|
181 |
t2 = self.get_transport() |
|
182 |
self.assertEquals(self.sftplogs, []) |
|
183 |
||
|
1185.40.4
by Robey Pointer
fix sftp urls to support the ietf draft url spec wrt relative vs absolute sftp urls (this will break existing branch urls); fix username/password parsing in sftp urls; add unit tests to make sure sftp url parsing is working |
184 |
|
185 |
class FakeSFTPTransport (object): |
|
186 |
_sftp = object() |
|
187 |
fake = FakeSFTPTransport() |
|
188 |
||
189 |
||
|
1185.49.14
by John Arbash Meinel
[merge] bzr.dev |
190 |
class SFTPNonServerTest(TestCase): |
|
1185.40.4
by Robey Pointer
fix sftp urls to support the ietf draft url spec wrt relative vs absolute sftp urls (this will break existing branch urls); fix username/password parsing in sftp urls; add unit tests to make sure sftp url parsing is working |
191 |
def test_parse_url(self): |
192 |
from bzrlib.transport.sftp import SFTPTransport |
|
193 |
s = SFTPTransport('sftp://simple.example.com/%2fhome/source', clone_from=fake) |
|
194 |
self.assertEquals(s._host, 'simple.example.com') |
|
|
1185.49.23
by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception. |
195 |
self.assertEquals(s._port, None) |
|
1185.48.5
by James Henstridge
Change SFTP url parsing back to treat the path in sftp://host/path as |
196 |
self.assertEquals(s._path, '/home/source') |
|
1185.49.19
by John Arbash Meinel
Testing that sftp.base gets properly sanitized |
197 |
self.failUnless(s._password is None) |
198 |
||
199 |
self.assertEquals(s.base, 'sftp://simple.example.com/%2Fhome/source') |
|
|
1185.40.4
by Robey Pointer
fix sftp urls to support the ietf draft url spec wrt relative vs absolute sftp urls (this will break existing branch urls); fix username/password parsing in sftp urls; add unit tests to make sure sftp url parsing is working |
200 |
|
201 |
s = SFTPTransport('sftp://ro%62ey:h%40t@example.com:2222/relative', clone_from=fake) |
|
202 |
self.assertEquals(s._host, 'example.com') |
|
203 |
self.assertEquals(s._port, 2222) |
|
204 |
self.assertEquals(s._username, 'robey') |
|
205 |
self.assertEquals(s._password, 'h@t') |
|
|
1185.48.5
by James Henstridge
Change SFTP url parsing back to treat the path in sftp://host/path as |
206 |
self.assertEquals(s._path, 'relative') |
|
1185.33.58
by Martin Pool
[patch] Better error when sftp urls are given with invalid port numbers (Matthieu Moy) |
207 |
|
|
1185.49.19
by John Arbash Meinel
Testing that sftp.base gets properly sanitized |
208 |
# Base should not keep track of the password
|
209 |
self.assertEquals(s.base, 'sftp://robey@example.com:2222/relative') |
|
210 |
||
211 |
# Double slash should be accepted instead of using %2F
|
|
212 |
s = SFTPTransport('sftp://user@example.com:22//absolute/path', clone_from=fake) |
|
213 |
self.assertEquals(s._host, 'example.com') |
|
214 |
self.assertEquals(s._port, 22) |
|
215 |
self.assertEquals(s._username, 'user') |
|
216 |
self.assertEquals(s._password, None) |
|
217 |
self.assertEquals(s._path, '/absolute/path') |
|
218 |
||
219 |
# Also, don't show the port if it is the default 22
|
|
|
1185.49.23
by John Arbash Meinel
bugreport from Matthieu Moy: relpath was failing, but throwing an unhelpful exception. |
220 |
self.assertEquals(s.base, 'sftp://user@example.com:22/%2Fabsolute/path') |
221 |
||
222 |
def test_relpath(self): |
|
223 |
from bzrlib.transport.sftp import SFTPTransport |
|
224 |
from bzrlib.errors import NonRelativePath |
|
225 |
||
226 |
s = SFTPTransport('sftp://user@host.com//abs/path', clone_from=fake) |
|
227 |
self.assertEquals(s.relpath('sftp://user@host.com//abs/path/sub'), 'sub') |
|
228 |
# Can't test this one, because we actually get an AssertionError
|
|
229 |
# TODO: Consider raising an exception rather than an assert
|
|
230 |
#self.assertRaises(NonRelativePath, s.relpath, 'http://user@host.com//abs/path/sub')
|
|
231 |
self.assertRaises(NonRelativePath, s.relpath, 'sftp://user2@host.com//abs/path/sub') |
|
232 |
self.assertRaises(NonRelativePath, s.relpath, 'sftp://user@otherhost.com//abs/path/sub') |
|
233 |
self.assertRaises(NonRelativePath, s.relpath, 'sftp://user@host.com:33//abs/path/sub') |
|
234 |
self.assertRaises(NonRelativePath, s.relpath, 'sftp://user@host.com/abs/path/sub') |
|
|
1185.49.19
by John Arbash Meinel
Testing that sftp.base gets properly sanitized |
235 |
|
|
1185.49.25
by John Arbash Meinel
Added a couple more test cases, just in case. |
236 |
# Make sure it works when we don't supply a username
|
237 |
s = SFTPTransport('sftp://host.com//abs/path', clone_from=fake) |
|
238 |
self.assertEquals(s.relpath('sftp://host.com//abs/path/sub'), 'sub') |
|
239 |
||
240 |
# Make sure it works when parts of the path will be url encoded
|
|
241 |
# TODO: These may be incorrect, we might need to urllib.urlencode() before
|
|
242 |
# we pass the paths into the SFTPTransport constructor
|
|
243 |
s = SFTPTransport('sftp://host.com/dev/,path', clone_from=fake) |
|
244 |
self.assertEquals(s.relpath('sftp://host.com/dev/,path/sub'), 'sub') |
|
245 |
s = SFTPTransport('sftp://host.com/dev/%path', clone_from=fake) |
|
246 |
self.assertEquals(s.relpath('sftp://host.com/dev/%path/sub'), 'sub') |
|
247 |
||
|
1185.33.58
by Martin Pool
[patch] Better error when sftp urls are given with invalid port numbers (Matthieu Moy) |
248 |
def test_parse_invalid_url(self): |
249 |
from bzrlib.transport.sftp import SFTPTransport, SFTPTransportError |
|
250 |
try: |
|
251 |
s = SFTPTransport('sftp://lilypond.org:~janneke/public_html/bzr/gub', |
|
252 |
clone_from=fake) |
|
253 |
self.fail('expected exception not raised') |
|
254 |
except SFTPTransportError, e: |
|
255 |
self.assertEquals(str(e), |
|
256 |
'~janneke: invalid port number') |
|
257 |
||
|
1185.40.4
by Robey Pointer
fix sftp urls to support the ietf draft url spec wrt relative vs absolute sftp urls (this will break existing branch urls); fix username/password parsing in sftp urls; add unit tests to make sure sftp url parsing is working |
258 |
|
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
259 |
class SFTPBranchTest(TestCaseWithSFTPServer): |
260 |
"""Test some stuff when accessing a bzr Branch over sftp""" |
|
261 |
||
262 |
def test_lock_file(self): |
|
263 |
"""Make sure that a Branch accessed over sftp tries to lock itself.""" |
|
264 |
from bzrlib.branch import Branch |
|
265 |
||
|
1185.40.19
by Robey Pointer
fix the new sftp selftest (it was failing as written) |
266 |
self.delayed_setup() |
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
267 |
b = Branch.initialize(self._sftp_url) |
268 |
self.failUnlessExists('.bzr/') |
|
269 |
self.failUnlessExists('.bzr/branch-format') |
|
270 |
self.failUnlessExists('.bzr/branch-lock') |
|
271 |
||
272 |
self.failIf(os.path.lexists('.bzr/branch-lock.write-lock')) |
|
273 |
b.lock_write() |
|
274 |
self.failUnlessExists('.bzr/branch-lock.write-lock') |
|
275 |
b.unlock() |
|
276 |
self.failIf(os.path.lexists('.bzr/branch-lock.write-lock')) |
|
277 |
||
278 |
||
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
279 |
if not paramiko_loaded: |
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
280 |
# TODO: Skip these
|
|
1185.16.127
by Martin Pool
[patch] paramiko sftp tests (robey) |
281 |
del SFTPTransportTest |
|
1185.40.4
by Robey Pointer
fix sftp urls to support the ietf draft url spec wrt relative vs absolute sftp urls (this will break existing branch urls); fix username/password parsing in sftp urls; add unit tests to make sure sftp url parsing is working |
282 |
del SFTPNonServerTest |
|
1185.49.3
by John Arbash Meinel
Added a form of locking to sftp branches. Refactored _sftp_open_exclusive to take a relative path |
283 |
del SFTPBranchTest |