2 from twisted.trial import unittest
4 from allmydata.frontends import ftpd
5 from allmydata.immutable import upload
6 from allmydata.mutable import publish
7 from allmydata.test.no_network import GridTestMixin
8 from allmydata.test.common_util import ReallyEqualMixin
10 class Handler(GridTestMixin, ReallyEqualMixin, unittest.TestCase):
12 This is a no-network unit test of ftpd.Handler and the abstractions
16 FALL_OF_BERLIN_WALL = 626644800
17 TURN_OF_MILLENIUM = 946684800
19 def _set_up(self, basedir, num_clients=1, num_servers=10):
20 self.basedir = "ftp/" + basedir
21 self.set_up_grid(num_clients=num_clients, num_servers=num_servers)
23 self.client = self.g.clients[0]
24 self.username = "alice"
27 d = self.client.create_dirnode()
28 def _created_root(node):
30 self.root_uri = node.get_uri()
31 self.handler = ftpd.Handler(self.client, self.root, self.username,
33 d.addCallback(_created_root)
36 def _set_metadata(self, name, metadata):
37 """Set metadata for `name', avoiding MetadataSetter's timestamp reset
39 def _modifier(old_contents, servermap, first_time):
40 children = self.root._unpack_contents(old_contents)
41 children[name] = (children[name][0], metadata)
42 return self.root._pack_contents(children)
44 return self.root._node.modify(_modifier)
46 def _set_up_tree(self):
47 # add immutable file at root
48 immutable = upload.Data("immutable file contents", None)
49 d = self.root.add_file(u"immutable", immutable)
51 # `mtime' and `linkmotime' both set
52 md_both = {'mtime': self.FALL_OF_BERLIN_WALL,
53 'tahoe': {'linkmotime': self.TURN_OF_MILLENIUM}}
54 d.addCallback(lambda _: self._set_metadata(u"immutable", md_both))
56 # add link to root from root
57 d.addCallback(lambda _: self.root.set_node(u"loop", self.root))
59 # `mtime' set, but no `linkmotime'
60 md_just_mtime = {'mtime': self.FALL_OF_BERLIN_WALL, 'tahoe': {}}
61 d.addCallback(lambda _: self._set_metadata(u"loop", md_just_mtime))
63 # add mutable file at root
64 mutable = publish.MutableData("mutable file contents")
65 d.addCallback(lambda _: self.client.create_mutable_file(mutable))
66 d.addCallback(lambda node: self.root.set_node(u"mutable", node))
68 # neither `mtime' nor `linkmotime' set
69 d.addCallback(lambda _: self._set_metadata(u"mutable", {}))
73 def _compareDirLists(self, actual, expected):
74 actual_list = sorted(actual)
75 expected_list = sorted(expected)
77 self.failUnlessReallyEqual(len(actual_list), len(expected_list),
78 "%r is wrong length, expecting %r" % (
79 actual_list, expected_list))
80 for (a, b) in zip(actual_list, expected_list):
82 (expected_name, expected_meta) = b
83 self.failUnlessReallyEqual(name, expected_name)
84 self.failUnlessReallyEqual(meta, expected_meta)
87 keys = ("size", "directory", "permissions", "hardlinks", "modified",
88 "owner", "group", "unexpected")
89 d = self._set_up("list")
91 d.addCallback(lambda _: self._set_up_tree())
92 d.addCallback(lambda _: self.handler.list("", keys=keys))
96 [0, True, ftpd.IntishPermissions(0600), 1, self.FALL_OF_BERLIN_WALL, 'alice', 'alice', '??']),
98 [23, False, ftpd.IntishPermissions(0600), 1, self.TURN_OF_MILLENIUM, 'alice', 'alice', '??']),
100 # timestamp should be 0 if no timestamp metadata is present
101 [0, False, ftpd.IntishPermissions(0600), 1, 0, 'alice', 'alice', '??'])]
103 d.addCallback(lambda root: self._compareDirLists(root, expected_root))