4 from twisted.trial import unittest
6 from allmydata.frontends import ftpd
7 from allmydata.immutable import upload
8 from allmydata.mutable import publish
9 from allmydata.test.no_network import GridTestMixin
10 from allmydata.test.common_util import ReallyEqualMixin
12 class Handler(GridTestMixin, ReallyEqualMixin, unittest.TestCase):
14 This is a no-network unit test of ftpd.Handler and the abstractions
18 FALL_OF_BERLIN_WALL = 626644800
19 TURN_OF_MILLENIUM = 946684800
21 def _set_up(self, basedir, num_clients=1, num_servers=10):
22 self.basedir = "ftp/" + basedir
23 self.set_up_grid(num_clients=num_clients, num_servers=num_servers)
25 self.client = self.g.clients[0]
26 self.username = "alice"
29 d = self.client.create_dirnode()
30 def _created_root(node):
32 self.root_uri = node.get_uri()
33 self.handler = ftpd.Handler(self.client, self.root, self.username,
35 d.addCallback(_created_root)
38 def _set_metadata(self, name, metadata):
39 """Set metadata for `name', avoiding MetadataSetter's timestamp reset
41 def _modifier(old_contents, servermap, first_time):
42 children = self.root._unpack_contents(old_contents)
43 children[name] = (children[name][0], metadata)
44 return self.root._pack_contents(children)
46 return self.root._node.modify(_modifier)
48 def _set_up_tree(self):
49 # add immutable file at root
50 immutable = upload.Data("immutable file contents", None)
51 d = self.root.add_file(u"immutable", immutable)
53 # `mtime' and `linkmotime' both set
54 md_both = {'mtime': self.FALL_OF_BERLIN_WALL,
55 'tahoe': {'linkmotime': self.TURN_OF_MILLENIUM}}
56 d.addCallback(lambda _: self._set_metadata(u"immutable", md_both))
58 # add link to root from root
59 d.addCallback(lambda _: self.root.set_node(u"loop", self.root))
61 # `mtime' set, but no `linkmotime'
62 md_just_mtime = {'mtime': self.FALL_OF_BERLIN_WALL, 'tahoe': {}}
63 d.addCallback(lambda _: self._set_metadata(u"loop", md_just_mtime))
65 # add mutable file at root
66 mutable = publish.MutableData("mutable file contents")
67 d.addCallback(lambda _: self.client.create_mutable_file(mutable))
68 d.addCallback(lambda node: self.root.set_node(u"mutable", node))
70 # neither `mtime' nor `linkmotime' set
71 d.addCallback(lambda _: self._set_metadata(u"mutable", {}))
75 def _compareDirLists(self, actual, expected):
76 actual_list = sorted(actual)
77 expected_list = sorted(expected)
79 self.failUnlessReallyEqual(len(actual_list), len(expected_list),
80 "%r is wrong length, expecting %r" % (
81 actual_list, expected_list))
82 for (a, b) in zip(actual_list, expected_list):
84 (expected_name, expected_meta) = b
85 self.failUnlessReallyEqual(name, expected_name)
86 self.failUnlessReallyEqual(meta, expected_meta)
89 keys = ("size", "directory", "permissions", "hardlinks", "modified",
90 "owner", "group", "unexpected")
91 d = self._set_up("list")
93 d.addCallback(lambda _: self._set_up_tree())
94 d.addCallback(lambda _: self.handler.list("", keys=keys))
98 [0, True, 0600, 1, self.FALL_OF_BERLIN_WALL, 'alice', 'alice', '??']),
100 [23, False, 0600, 1, self.TURN_OF_MILLENIUM, 'alice', 'alice', '??']),
102 # timestamp should be 0 if no timestamp metadata is present
103 [0, False, 0600, 1, 0, 'alice', 'alice', '??'])]
105 d.addCallback(lambda root: self._compareDirLists(root, expected_root))