58
58
raise NotImplementedError
60
def assertListRaises(self, excClass, func, *args, **kwargs):
61
"""Many transport functions can return generators this makes sure
62
to wrap them in a list() call to make sure the whole generator
63
is run, and that the proper exception is raised.
66
list(func(*args, **kwargs))
70
if hasattr(excClass,'__name__'): excName = excClass.__name__
71
else: excName = str(excClass)
72
raise self.failureException, "%s not raised" % excName
60
74
def test_has(self):
61
75
t = self.get_transport()
63
77
files = ['a', 'b', 'e', 'g', '%']
64
78
self.build_tree(files)
65
self.assertEqual(t.has('a'), True)
66
self.assertEqual(t.has('c'), False)
67
self.assertEqual(t.has(urlescape('%')), True)
79
self.assertEqual(True, t.has('a'))
80
self.assertEqual(False, t.has('c'))
81
self.assertEqual(True, t.has(urlescape('%')))
68
82
self.assertEqual(list(t.has_multi(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])),
69
83
[True, True, False, False, True, False, True, False])
70
self.assertEqual(t.has_any(['a', 'b', 'c']), True)
71
self.assertEqual(t.has_any(['c', 'd', 'f', urlescape('%%')]), False)
84
self.assertEqual(True, t.has_any(['a', 'b', 'c']))
85
self.assertEqual(False, t.has_any(['c', 'd', 'f', urlescape('%%')]))
72
86
self.assertEqual(list(t.has_multi(iter(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']))),
73
87
[True, True, False, False, True, False, True, False])
74
self.assertEqual(t.has_any(['c', 'c', 'c']), False)
75
self.assertEqual(t.has_any(['b', 'b', 'b']), True)
88
self.assertEqual(False, t.has_any(['c', 'c', 'c']))
89
self.assertEqual(True, t.has_any(['b', 'b', 'b']))
77
91
def test_get(self):
78
92
t = self.get_transport()
80
94
files = ['a', 'b', 'e', 'g']
81
95
self.build_tree(files)
82
self.assertEqual(t.get('a').read(), open('a', 'rb').read())
96
self.assertEqual(open('a', 'rb').read(), t.get('a').read())
83
97
content_f = t.get_multi(files)
84
98
for path,f in zip(files, content_f):
85
99
self.assertEqual(f.read(), open(path, 'rb').read())
89
103
self.assertEqual(f.read(), open(path, 'rb').read())
91
105
self.assertRaises(NoSuchFile, t.get, 'c')
93
files = list(t.get_multi(['a', 'b', 'c']))
97
self.fail('Failed to raise NoSuchFile for missing file in get_multi')
99
files = list(t.get_multi(iter(['a', 'b', 'c', 'e'])))
103
self.fail('Failed to raise NoSuchFile for missing file in get_multi')
106
self.assertListRaises(NoSuchFile, t.get_multi, ['a', 'b', 'c'])
107
self.assertListRaises(NoSuchFile, t.get_multi, iter(['a', 'b', 'c']))
105
109
def test_put(self):
106
110
t = self.get_transport()
376
378
'some\nmore\nfor\nb\n'
377
379
'from an iterator\n')
382
_append('c', 'some text\nfor a missing file\n')
383
_append('a', 'some text in a\n')
384
_append('d', 'missing file r\n')
386
t.append('c', 'some text\nfor a missing file\n')
387
t.append_multi([('a', 'some text in a\n'),
388
('d', 'missing file r\n')])
389
self.check_file_contents('a',
390
'diff\ncontents for\na\n'
391
'add\nsome\nmore\ncontents\n'
392
'and\nthen\nsome\nmore\n'
393
'a little bit more\n'
395
self.check_file_contents('c', 'some text\nfor a missing file\n')
396
self.check_file_contents('d', 'missing file r\n')
379
398
def test_append_file(self):
380
399
t = self.get_transport()
457
476
'some text for the\nthird file created\n'
458
477
'some garbage\nto put in three\n')
479
a5 = open('f2', 'rb')
480
a6 = open('f2', 'rb')
481
a7 = open('f3', 'rb')
483
_append('c', a5.read())
484
_append('a', a6.read())
485
_append('d', a7.read())
488
t.append_multi([('a', a6), ('d', a7)])
490
self.check_file_contents('c', open('f2', 'rb').read())
491
self.check_file_contents('d', open('f3', 'rb').read())
460
494
def test_delete(self):
461
495
# TODO: Test Transport.delete
462
496
t = self.get_transport()
498
# Not much to do with a readonly transport
502
open('a', 'wb').write('a little bit of text\n')
503
self.failUnless(t.has('a'))
504
self.failUnlessExists('a')
506
self.failIf(os.path.lexists('a'))
508
self.assertRaises(NoSuchFile, t.delete, 'a')
510
open('a', 'wb').write('a text\n')
511
open('b', 'wb').write('b text\n')
512
open('c', 'wb').write('c text\n')
513
self.assertEqual([True, True, True],
514
list(t.has_multi(['a', 'b', 'c'])))
515
t.delete_multi(['a', 'c'])
516
self.assertEqual([False, True, False],
517
list(t.has_multi(['a', 'b', 'c'])))
518
self.failIf(os.path.lexists('a'))
519
self.failUnlessExists('b')
520
self.failIf(os.path.lexists('c'))
522
self.assertRaises(NoSuchFile,
523
t.delete_multi, ['a', 'b', 'c'])
525
self.assertRaises(NoSuchFile,
526
t.delete_multi, iter(['a', 'b', 'c']))
528
open('a', 'wb').write('another a text\n')
529
open('c', 'wb').write('another c text\n')
530
t.delete_multi(iter(['a', 'b', 'c']))
532
# We should have deleted everything
533
# SftpServer creates control files in the
534
# working directory, so we can just do a
536
# self.assertEqual([], os.listdir('.'))
464
538
def test_move(self):
465
# TODO: Test Transport.move
466
539
t = self.get_transport()
544
# TODO: I would like to use os.listdir() to
545
# make sure there are no extra files, but SftpServer
546
# creates control files in the working directory
547
# perhaps all of this could be done in a subdirectory
549
open('a', 'wb').write('a first file\n')
550
self.assertEquals([True, False], list(t.has_multi(['a', 'b'])))
553
self.failUnlessExists('b')
554
self.failIf(os.path.lexists('a'))
556
self.check_file_contents('b', 'a first file\n')
557
self.assertEquals([False, True], list(t.has_multi(['a', 'b'])))
560
open('c', 'wb').write('c this file\n')
562
self.failIf(os.path.lexists('c'))
563
self.check_file_contents('b', 'c this file\n')
565
# TODO: Try to write a test for atomicity
566
# TODO: Test moving into a non-existant subdirectory
567
# TODO: Test Transport.move_multi
468
569
def test_copy(self):
469
# TODO: Test Transport.move
470
570
t = self.get_transport()
575
open('a', 'wb').write('a file\n')
577
self.check_file_contents('b', 'a file\n')
579
self.assertRaises(NoSuchFile, t.copy, 'c', 'd')
581
# What should the assert be if you try to copy a
582
# file over a directory?
583
#self.assertRaises(Something, t.copy, 'a', 'c')
584
open('d', 'wb').write('text in d\n')
586
self.check_file_contents('b', 'text in d\n')
588
# TODO: test copy_multi
472
590
def test_connection_error(self):
473
591
"""ConnectionError is raised when connection is impossible"""
474
592
if not hasattr(self, "get_bogus_transport"):
484
602
self.failIf(True, 'Did not get the expected exception.')
605
# TODO: Test stat, just try once, and if it throws, stop testing
606
from stat import S_ISDIR, S_ISREG
608
t = self.get_transport()
612
except TransportNotPossible, e:
613
# This transport cannot stat
616
paths = ['a', 'b/', 'b/c', 'b/d/', 'b/d/e']
617
self.build_tree(paths)
623
local_st = os.stat(p)
625
self.failUnless(S_ISDIR(st.st_mode))
627
self.failUnless(S_ISREG(st.st_mode))
628
self.assertEqual(local_st.st_size, st.st_size)
629
self.assertEqual(local_st.st_mode, st.st_mode)
630
local_stats.append(local_st)
632
remote_stats = list(t.stat_multi(paths))
633
remote_iter_stats = list(t.stat_multi(iter(paths)))
635
for local, remote, remote_iter in \
636
zip(local_stats, remote_stats, remote_iter_stats):
637
self.assertEqual(local.st_mode, remote.st_mode)
638
self.assertEqual(local.st_mode, remote_iter.st_mode)
640
self.assertEqual(local.st_size, remote.st_size)
641
self.assertEqual(local.st_size, remote_iter.st_size)
642
# Should we test UID/GID?
644
self.assertRaises(NoSuchFile, t.stat, 'q')
645
self.assertRaises(NoSuchFile, t.stat, 'b/a')
647
self.assertListRaises(NoSuchFile, t.stat_multi, ['a', 'c', 'd'])
648
self.assertListRaises(NoSuchFile, t.stat_multi, iter(['a', 'c', 'd']))
650
def test_list_dir(self):
651
# TODO: Test list_dir, just try once, and if it throws, stop testing
652
t = self.get_transport()
655
self.assertRaises(TransportNotPossible, t.list_dir, '.')
659
l = list(t.list_dir(d))
663
# SftpServer creates control files in the working directory
664
# so lets move down a directory to be safe
669
self.assertEqual([], sorted_list(u'.'))
670
self.build_tree(['a', 'b', 'c/', 'c/d', 'c/e'])
672
self.assertEqual([u'a', u'b', u'c'], sorted_list(u'.'))
673
self.assertEqual([u'd', u'e'], sorted_list(u'c'))
677
self.assertEqual([u'a', u'c'], sorted_list('.'))
678
self.assertEqual([u'e'], sorted_list(u'c'))
680
self.assertListRaises(NoSuchFile, t.list_dir, 'q')
681
self.assertListRaises(NoSuchFile, t.list_dir, 'c/f')
682
self.assertListRaises(NoSuchFile, t.list_dir, 'a')
684
def test_clone(self):
685
# TODO: Test that clone moves up and down the filesystem
686
t1 = self.get_transport()
688
self.build_tree(['a', 'b/', 'b/c'])
690
self.failUnless(t1.has('a'))
691
self.failUnless(t1.has('b/c'))
692
self.failIf(t1.has('c'))
695
self.failUnless(t2.has('c'))
696
self.failIf(t2.has('a'))
699
self.failUnless(t3.has('a'))
700
self.failIf(t3.has('c'))
702
self.failIf(t1.has('b/d'))
703
self.failIf(t2.has('d'))
704
self.failIf(t3.has('b/d'))
707
open('b/d', 'wb').write('newfile\n')
709
t2.put('d', 'newfile\n')
711
self.failUnless(t1.has('b/d'))
712
self.failUnless(t2.has('d'))
713
self.failUnless(t3.has('b/d'))
487
716
class LocalTransportTest(TestCaseInTempDir, TestTransportMixIn):
488
717
def get_transport(self):