75
57
raise NotImplementedError
77
def assertListRaises(self, excClass, func, *args, **kwargs):
78
"""Many transport functions can return generators this makes sure
79
to wrap them in a list() call to make sure the whole generator
80
is run, and that the proper exception is raised.
83
list(func(*args, **kwargs))
87
if hasattr(excClass,'__name__'): excName = excClass.__name__
88
else: excName = str(excClass)
89
raise self.failureException, "%s not raised" % excName
91
59
def test_has(self):
92
60
t = self.get_transport()
94
62
files = ['a', 'b', 'e', 'g', '%']
95
63
self.build_tree(files)
96
self.assertEqual(True, t.has('a'))
97
self.assertEqual(False, t.has('c'))
98
self.assertEqual(True, t.has(urlescape('%')))
64
self.assertEqual(t.has('a'), True)
65
self.assertEqual(t.has('c'), False)
66
self.assertEqual(t.has(urlescape('%')), True)
99
67
self.assertEqual(list(t.has_multi(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])),
100
68
[True, True, False, False, True, False, True, False])
101
self.assertEqual(True, t.has_any(['a', 'b', 'c']))
102
self.assertEqual(False, t.has_any(['c', 'd', 'f', urlescape('%%')]))
69
self.assertEqual(t.has_any(['a', 'b', 'c']), True)
70
self.assertEqual(t.has_any(['c', 'd', 'f', urlescape('%%')]), False)
103
71
self.assertEqual(list(t.has_multi(iter(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']))),
104
72
[True, True, False, False, True, False, True, False])
105
self.assertEqual(False, t.has_any(['c', 'c', 'c']))
106
self.assertEqual(True, t.has_any(['b', 'b', 'b']))
73
self.assertEqual(t.has_any(['c', 'c', 'c']), False)
74
self.assertEqual(t.has_any(['b', 'b', 'b']), True)
108
76
def test_get(self):
109
77
t = self.get_transport()
111
79
files = ['a', 'b', 'e', 'g']
112
80
self.build_tree(files)
113
self.assertEqual(open('a', 'rb').read(), t.get('a').read())
81
self.assertEqual(t.get('a').read(), open('a').read())
114
82
content_f = t.get_multi(files)
115
83
for path,f in zip(files, content_f):
116
self.assertEqual(f.read(), open(path, 'rb').read())
84
self.assertEqual(open(path).read(), f.read())
118
86
content_f = t.get_multi(iter(files))
119
87
for path,f in zip(files, content_f):
120
self.assertEqual(f.read(), open(path, 'rb').read())
88
self.assertEqual(open(path).read(), f.read())
122
90
self.assertRaises(NoSuchFile, t.get, 'c')
123
self.assertListRaises(NoSuchFile, t.get_multi, ['a', 'b', 'c'])
124
self.assertListRaises(NoSuchFile, t.get_multi, iter(['a', 'b', 'c']))
92
files = list(t.get_multi(['a', 'b', 'c']))
96
self.fail('Failed to raise NoSuchFile for missing file in get_multi')
98
files = list(t.get_multi(iter(['a', 'b', 'c', 'e'])))
102
self.fail('Failed to raise NoSuchFile for missing file in get_multi')
126
104
def test_put(self):
127
105
t = self.get_transport()
129
# TODO: jam 20051215 No need to do anything if the test is readonly
130
# origininally it was thought that it would give
131
# more of a workout to readonly tests. By now the
132
# suite is probably thorough enough without testing
133
# readonly protocols in write sections
134
# The only thing that needs to be tested is that the
135
# right error is raised
137
107
if self.readonly:
138
108
self.assertRaises(TransportNotPossible,
139
109
t.put, 'a', 'some text for a\n')
184
154
self.assertRaises(NoSuchFile,
185
155
t.put, 'path/doesnt/exist/c', 'contents')
187
if not self.readonly:
188
t.put('mode644', 'test text\n', mode=0644)
189
check_mode(self, 'mode644', 0644)
191
t.put('mode666', 'test text\n', mode=0666)
192
check_mode(self, 'mode666', 0666)
194
t.put('mode600', 'test text\n', mode=0600)
195
check_mode(self, 'mode600', 0600)
197
# Yes, you can put a file such that it becomes readonly
198
t.put('mode400', 'test text\n', mode=0400)
199
check_mode(self, 'mode400', 0400)
201
t.put_multi([('mmode644', 'text\n')], mode=0644)
202
check_mode(self, 'mmode644', 0644)
204
# TODO: jam 20051215 test put_multi with a mode. I didn't bother because
205
# it seems most people don't like the _multi functions
207
157
def test_put_file(self):
208
158
t = self.get_transport()
258
208
self.check_file_contents('f5', 'here is some text\nand a bit more\n')
259
209
self.check_file_contents('f6', 'some text for the\nthird file created\n')
261
if not self.readonly:
262
sio = StringIO('test text\n')
263
t.put('mode644', sio, mode=0644)
264
check_mode(self, 'mode644', 0644)
266
a = open('mode644', 'rb')
267
t.put('mode666', a, mode=0666)
268
check_mode(self, 'mode666', 0666)
270
a = open('mode644', 'rb')
271
t.put('mode600', a, mode=0600)
272
check_mode(self, 'mode600', 0600)
274
# Yes, you can put a file such that it becomes readonly
275
a = open('mode644', 'rb')
276
t.put('mode400', a, mode=0400)
277
check_mode(self, 'mode400', 0400)
279
213
def test_mkdir(self):
280
214
t = self.get_transport()
342
276
('dir_b/b', 'contents of dir_b/b')])
344
278
for f in ('dir_a/a', 'dir_b/b'):
345
self.assertEqual(t.get(f).read(), open(f, 'rb').read())
347
if not self.readonly:
348
# Test mkdir with a mode
349
t.mkdir('dmode755', mode=0755)
350
check_mode(self, 'dmode755', 0755)
352
t.mkdir('dmode555', mode=0555)
353
check_mode(self, 'dmode555', 0555)
355
t.mkdir('dmode777', mode=0777)
356
check_mode(self, 'dmode777', 0777)
358
t.mkdir('dmode700', mode=0700)
359
check_mode(self, 'dmode700', 0700)
361
# TODO: jam 20051215 test mkdir_multi with a mode
362
t.mkdir_multi(['mdmode755'], mode=0755)
363
check_mode(self, 'mdmode755', 0755)
279
self.assertEqual(t.get(f).read(), open(f).read())
366
281
def test_copy_to(self):
372
287
files = ['a', 'b', 'c', 'd']
373
288
self.build_tree(files)
375
def get_temp_local():
376
dtmp = tempfile.mkdtemp(dir=u'.', prefix='test-transport-')
377
dtmp_base = os.path.basename(dtmp)
378
return dtmp_base, LocalTransport(dtmp)
379
dtmp_base, local_t = get_temp_local()
290
dtmp = tempfile.mkdtemp(dir='.', prefix='test-transport-')
291
dtmp_base = os.path.basename(dtmp)
292
local_t = LocalTransport(dtmp)
381
294
t.copy_to(files, local_t)
383
self.assertEquals(open(f, 'rb').read(),
384
open(pathjoin(dtmp_base, f), 'rb').read())
296
self.assertEquals(open(f).read(),
297
open(os.path.join(dtmp_base, f)).read())
386
299
# Test that copying into a missing directory raises
389
302
open('e/f', 'wb').write('contents of e')
390
303
self.assertRaises(NoSuchFile, t.copy_to, ['e/f'], local_t)
392
os.mkdir(pathjoin(dtmp_base, 'e'))
305
os.mkdir(os.path.join(dtmp_base, 'e'))
393
306
t.copy_to(['e/f'], local_t)
395
del dtmp_base, local_t
308
del dtmp, dtmp_base, local_t
397
dtmp_base, local_t = get_temp_local()
310
dtmp = tempfile.mkdtemp(dir='.', prefix='test-transport-')
311
dtmp_base = os.path.basename(dtmp)
312
local_t = LocalTransport(dtmp)
399
314
files = ['a', 'b', 'c', 'd']
400
315
t.copy_to(iter(files), local_t)
402
self.assertEquals(open(f, 'rb').read(),
403
open(pathjoin(dtmp_base, f), 'rb').read())
405
del dtmp_base, local_t
407
for mode in (0666, 0644, 0600, 0400):
408
dtmp_base, local_t = get_temp_local()
409
t.copy_to(files, local_t, mode=mode)
411
check_mode(self, os.path.join(dtmp_base, f), mode)
317
self.assertEquals(open(f).read(),
318
open(os.path.join(dtmp_base, f)).read())
320
del dtmp, dtmp_base, local_t
413
322
def test_append(self):
414
323
t = self.get_transport()
466
375
'some\nmore\nfor\nb\n'
467
376
'from an iterator\n')
470
_append('c', 'some text\nfor a missing file\n')
471
_append('a', 'some text in a\n')
472
_append('d', 'missing file r\n')
474
t.append('c', 'some text\nfor a missing file\n')
475
t.append_multi([('a', 'some text in a\n'),
476
('d', 'missing file r\n')])
477
self.check_file_contents('a',
478
'diff\ncontents for\na\n'
479
'add\nsome\nmore\ncontents\n'
480
'and\nthen\nsome\nmore\n'
481
'a little bit more\n'
483
self.check_file_contents('c', 'some text\nfor a missing file\n')
484
self.check_file_contents('d', 'missing file r\n')
486
378
def test_append_file(self):
487
379
t = self.get_transport()
564
456
'some text for the\nthird file created\n'
565
457
'some garbage\nto put in three\n')
567
a5 = open('f2', 'rb')
568
a6 = open('f2', 'rb')
569
a7 = open('f3', 'rb')
571
_append('c', a5.read())
572
_append('a', a6.read())
573
_append('d', a7.read())
576
t.append_multi([('a', a6), ('d', a7)])
578
self.check_file_contents('c', open('f2', 'rb').read())
579
self.check_file_contents('d', open('f3', 'rb').read())
582
459
def test_delete(self):
583
460
# TODO: Test Transport.delete
584
t = self.get_transport()
586
# Not much to do with a readonly transport
590
open('a', 'wb').write('a little bit of text\n')
591
self.failUnless(t.has('a'))
592
self.failUnlessExists('a')
594
self.failIf(os.path.lexists('a'))
596
self.assertRaises(NoSuchFile, t.delete, 'a')
598
open('a', 'wb').write('a text\n')
599
open('b', 'wb').write('b text\n')
600
open('c', 'wb').write('c text\n')
601
self.assertEqual([True, True, True],
602
list(t.has_multi(['a', 'b', 'c'])))
603
t.delete_multi(['a', 'c'])
604
self.assertEqual([False, True, False],
605
list(t.has_multi(['a', 'b', 'c'])))
606
self.failIf(os.path.lexists('a'))
607
self.failUnlessExists('b')
608
self.failIf(os.path.lexists('c'))
610
self.assertRaises(NoSuchFile,
611
t.delete_multi, ['a', 'b', 'c'])
613
self.assertRaises(NoSuchFile,
614
t.delete_multi, iter(['a', 'b', 'c']))
616
open('a', 'wb').write('another a text\n')
617
open('c', 'wb').write('another c text\n')
618
t.delete_multi(iter(['a', 'b', 'c']))
620
# We should have deleted everything
621
# SftpServer creates control files in the
622
# working directory, so we can just do a
624
# self.assertEqual([], os.listdir('.'))
626
463
def test_move(self):
627
t = self.get_transport()
632
# TODO: I would like to use os.listdir() to
633
# make sure there are no extra files, but SftpServer
634
# creates control files in the working directory
635
# perhaps all of this could be done in a subdirectory
637
open('a', 'wb').write('a first file\n')
638
self.assertEquals([True, False], list(t.has_multi(['a', 'b'])))
641
self.failUnlessExists('b')
642
self.failIf(os.path.lexists('a'))
644
self.check_file_contents('b', 'a first file\n')
645
self.assertEquals([False, True], list(t.has_multi(['a', 'b'])))
648
open('c', 'wb').write('c this file\n')
650
self.failIf(os.path.lexists('c'))
651
self.check_file_contents('b', 'c this file\n')
653
# TODO: Try to write a test for atomicity
654
# TODO: Test moving into a non-existant subdirectory
655
# TODO: Test Transport.move_multi
658
t = self.get_transport()
663
open('a', 'wb').write('a file\n')
665
self.check_file_contents('b', 'a file\n')
667
self.assertRaises(NoSuchFile, t.copy, 'c', 'd')
669
# What should the assert be if you try to copy a
670
# file over a directory?
671
#self.assertRaises(Something, t.copy, 'a', 'c')
672
open('d', 'wb').write('text in d\n')
674
self.check_file_contents('b', 'text in d\n')
676
# TODO: test copy_multi
464
# TODO: Test Transport.move
678
467
def test_connection_error(self):
679
468
"""ConnectionError is raised when connection is impossible"""
690
479
self.failIf(True, 'Did not get the expected exception.')
693
# TODO: Test stat, just try once, and if it throws, stop testing
694
from stat import S_ISDIR, S_ISREG
696
t = self.get_transport()
700
except TransportNotPossible, e:
701
# This transport cannot stat
704
paths = ['a', 'b/', 'b/c', 'b/d/', 'b/d/e']
705
self.build_tree(paths)
711
local_st = os.stat(p)
713
self.failUnless(S_ISDIR(st.st_mode))
715
self.failUnless(S_ISREG(st.st_mode))
716
self.assertEqual(local_st.st_size, st.st_size)
717
self.assertEqual(local_st.st_mode, st.st_mode)
718
local_stats.append(local_st)
720
remote_stats = list(t.stat_multi(paths))
721
remote_iter_stats = list(t.stat_multi(iter(paths)))
723
for local, remote, remote_iter in \
724
zip(local_stats, remote_stats, remote_iter_stats):
725
self.assertEqual(local.st_mode, remote.st_mode)
726
self.assertEqual(local.st_mode, remote_iter.st_mode)
728
self.assertEqual(local.st_size, remote.st_size)
729
self.assertEqual(local.st_size, remote_iter.st_size)
730
# Should we test UID/GID?
732
self.assertRaises(NoSuchFile, t.stat, 'q')
733
self.assertRaises(NoSuchFile, t.stat, 'b/a')
735
self.assertListRaises(NoSuchFile, t.stat_multi, ['a', 'c', 'd'])
736
self.assertListRaises(NoSuchFile, t.stat_multi, iter(['a', 'c', 'd']))
738
def test_list_dir(self):
739
# TODO: Test list_dir, just try once, and if it throws, stop testing
740
t = self.get_transport()
743
self.assertRaises(TransportNotPossible, t.list_dir, '.')
747
l = list(t.list_dir(d))
751
# SftpServer creates control files in the working directory
752
# so lets move down a directory to be safe
757
self.assertEqual([], sorted_list(u'.'))
758
self.build_tree(['a', 'b', 'c/', 'c/d', 'c/e'])
760
self.assertEqual([u'a', u'b', u'c'], sorted_list(u'.'))
761
self.assertEqual([u'd', u'e'], sorted_list(u'c'))
765
self.assertEqual([u'a', u'c'], sorted_list('.'))
766
self.assertEqual([u'e'], sorted_list(u'c'))
768
self.assertListRaises(NoSuchFile, t.list_dir, 'q')
769
self.assertListRaises(NoSuchFile, t.list_dir, 'c/f')
770
self.assertListRaises(NoSuchFile, t.list_dir, 'a')
772
def test_clone(self):
773
# TODO: Test that clone moves up and down the filesystem
774
t1 = self.get_transport()
776
self.build_tree(['a', 'b/', 'b/c'])
778
self.failUnless(t1.has('a'))
779
self.failUnless(t1.has('b/c'))
780
self.failIf(t1.has('c'))
783
self.failUnless(t2.has('c'))
784
self.failIf(t2.has('a'))
787
self.failUnless(t3.has('a'))
788
self.failIf(t3.has('c'))
790
self.failIf(t1.has('b/d'))
791
self.failIf(t2.has('d'))
792
self.failIf(t3.has('b/d'))
795
open('b/d', 'wb').write('newfile\n')
797
t2.put('d', 'newfile\n')
799
self.failUnless(t1.has('b/d'))
800
self.failUnless(t2.has('d'))
801
self.failUnless(t3.has('b/d'))
804
482
class LocalTransportTest(TestCaseInTempDir, TestTransportMixIn):
805
483
def get_transport(self):
806
484
from bzrlib.transport.local import LocalTransport
807
return LocalTransport(u'.')
485
return LocalTransport('.')
810
488
class HttpTransportTest(TestCaseWithWebserver, TestTransportMixIn):