mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-20 09:46:18 +00:00
mutable: improve NewDirectoryNode test coverage
This commit is contained in:
parent
d777283e9e
commit
f1c3ff62c1
@ -4,7 +4,8 @@ from zope.interface import implements
|
||||
from twisted.internet import defer
|
||||
import simplejson
|
||||
from allmydata.interfaces import IMutableFileNode, IDirectoryNode,\
|
||||
IMutableFileURI, INewDirectoryURI, IURI, IFileNode, NotMutableError
|
||||
IMutableFileURI, INewDirectoryURI, IURI, IFileNode, NotMutableError, \
|
||||
IVerifierURI
|
||||
from allmydata.util import hashutil
|
||||
from allmydata.util.hashutil import netstring
|
||||
from allmydata.dirnode import IntegrityCheckError, FileNode
|
||||
@ -55,7 +56,7 @@ class MutableFileNode:
|
||||
return cmp(self.uri, them.uri)
|
||||
|
||||
def get_verifier(self):
|
||||
return IMutableFileURI(self.uri).get_verifier()
|
||||
return IMutableFileURI(self._uri).get_verifier()
|
||||
|
||||
def check(self):
|
||||
verifier = self.get_verifier()
|
||||
@ -162,7 +163,7 @@ class NewDirectoryNode:
|
||||
return self._client.create_file_from_uri(u)
|
||||
if IMutableFileURI.providedBy(u):
|
||||
return self._client.create_mutable_file_from_uri(u)
|
||||
raise TypeError("cannot handle URI")
|
||||
raise TypeError("cannot handle '%s' URI" % (u.__class__,))
|
||||
|
||||
def _unpack_contents(self, data):
|
||||
# the directory is serialized as a list of netstrings, one per child.
|
||||
@ -216,6 +217,9 @@ class NewDirectoryNode:
|
||||
def get_uri(self):
|
||||
return self._uri.to_string()
|
||||
|
||||
def get_readonly(self):
|
||||
return self._uri.get_readonly().to_string()
|
||||
|
||||
def get_immutable_uri(self):
|
||||
return self._uri.get_readonly().to_string()
|
||||
|
||||
@ -242,7 +246,12 @@ class NewDirectoryNode:
|
||||
"""I return a Deferred that fires with a specific named child node,
|
||||
either an IFileNode or an IDirectoryNode."""
|
||||
d = self._read()
|
||||
d.addCallback(lambda children: children[name])
|
||||
d.addCallback(lambda children: children[name][0])
|
||||
return d
|
||||
|
||||
def get_metadata_for(self, name):
|
||||
d = self._read()
|
||||
d.addCallback(lambda children: children[name][1])
|
||||
return d
|
||||
|
||||
def get_child_at_path(self, path):
|
||||
@ -315,25 +324,34 @@ class NewDirectoryNode:
|
||||
|
||||
def delete(self, name):
|
||||
"""I remove the child at the specific name. I return a Deferred that
|
||||
fires when the operation finishes."""
|
||||
fires (with the node just removed) when the operation finishes."""
|
||||
if self.is_readonly():
|
||||
return defer.fail(NotMutableError())
|
||||
d = self._read()
|
||||
def _delete(children):
|
||||
old_child, metadata = children[name]
|
||||
del children[name]
|
||||
new_contents = self._pack_contents(children)
|
||||
return self._node.replace(new_contents)
|
||||
d = self._node.replace(new_contents)
|
||||
def _done(res):
|
||||
return old_child
|
||||
d.addCallback(_done)
|
||||
return d
|
||||
d.addCallback(_delete)
|
||||
d.addCallback(lambda res: None)
|
||||
return d
|
||||
|
||||
def create_empty_directory(self, name):
|
||||
"""I create and attach an empty directory at the given name. I return
|
||||
a Deferred that fires when the operation finishes."""
|
||||
a Deferred that fires (with the new directory node) when the
|
||||
operation finishes."""
|
||||
if self.is_readonly():
|
||||
return defer.fail(NotMutableError())
|
||||
d = self._client.create_empty_dirnode()
|
||||
d.addCallback(lambda child: self.set_node(name, child))
|
||||
def _created(child):
|
||||
d = self.set_node(name, child)
|
||||
d.addCallback(lambda res: child)
|
||||
return d
|
||||
d.addCallback(_created)
|
||||
return d
|
||||
|
||||
def move_child_to(self, current_child_name, new_parent,
|
||||
@ -368,7 +386,7 @@ class NewDirectoryNode:
|
||||
# They indicate this by returning None from their get_verifier
|
||||
# method. We need to remove any such Nones from our set. We also
|
||||
# want to convert all these caps into strings.
|
||||
return frozenset([cap.to_string()
|
||||
return frozenset([IVerifierURI(cap).to_string()
|
||||
for cap in manifest
|
||||
if cap is not None])
|
||||
d.addCallback(_done)
|
||||
@ -378,7 +396,7 @@ class NewDirectoryNode:
|
||||
d = node.list()
|
||||
def _got_list(res):
|
||||
dl = []
|
||||
for name, child in res.iteritems():
|
||||
for name, (child, metadata) in res.iteritems():
|
||||
verifier = child.get_verifier()
|
||||
if verifier not in manifest:
|
||||
manifest.add(verifier)
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
import itertools
|
||||
from twisted.trial import unittest
|
||||
from twisted.internet import defer
|
||||
|
||||
@ -38,18 +39,23 @@ class Netstring(unittest.TestCase):
|
||||
self.failUnlessEqual(bottom, ("hello", "world", "extra stuff"))
|
||||
|
||||
class FakeFilenode(mutable.MutableFileNode):
|
||||
counter = itertools.count(1)
|
||||
all_contents = {}
|
||||
|
||||
def init_from_uri(self, myuri):
|
||||
self._uri = myuri
|
||||
self.writekey = myuri.writekey
|
||||
return self
|
||||
def create(self, initial_contents):
|
||||
self.contents = initial_contents
|
||||
self.init_from_uri(uri.WriteableSSKFileURI("key", "fingerprint"))
|
||||
count = self.counter.next()
|
||||
self.init_from_uri(uri.WriteableSSKFileURI("key%d" % count,
|
||||
"fingerprint%d" % count))
|
||||
self.all_contents[self._uri] = initial_contents
|
||||
return defer.succeed(None)
|
||||
def download_to_data(self):
|
||||
return defer.succeed(self.contents)
|
||||
return defer.succeed(self.all_contents[self._uri])
|
||||
def replace(self, newdata):
|
||||
self.contents = newdata
|
||||
self.all_contents[self._uri] = newdata
|
||||
return defer.succeed(None)
|
||||
def is_readonly(self):
|
||||
return False
|
||||
@ -116,6 +122,8 @@ class Dirnode(unittest.TestCase):
|
||||
self.client = MyClient()
|
||||
|
||||
def test_create(self):
|
||||
self.expected_manifest = []
|
||||
|
||||
d = self.client.create_empty_dirnode()
|
||||
def _check(n):
|
||||
self.failUnless(n.is_mutable())
|
||||
@ -126,18 +134,60 @@ class Dirnode(unittest.TestCase):
|
||||
self.failUnless(u_ro.startswith("URI:DIR2-RO:"), u_ro)
|
||||
u_v = n.get_verifier()
|
||||
self.failUnless(u_v.startswith("URI:DIR2-Verifier:"), u_v)
|
||||
self.expected_manifest.append(u_v)
|
||||
|
||||
d = n.list()
|
||||
d.addCallback(lambda res: self.failUnlessEqual(res, {}))
|
||||
d.addCallback(lambda res: n.has_child("missing"))
|
||||
d.addCallback(lambda res: self.failIf(res))
|
||||
fake_file_uri = uri.WriteableSSKFileURI("a"*16,"b"*32)
|
||||
ffu_v = fake_file_uri.get_verifier().to_string()
|
||||
self.expected_manifest.append(ffu_v)
|
||||
d.addCallback(lambda res: n.set_uri("child", fake_file_uri))
|
||||
d.addCallback(lambda res: self.failUnlessEqual(res, None))
|
||||
|
||||
d.addCallback(lambda res: n.create_empty_directory("subdir"))
|
||||
def _created(subdir):
|
||||
self.failUnless(isinstance(subdir, FakeNewDirectoryNode))
|
||||
self.subdir = subdir
|
||||
new_v = subdir.get_verifier()
|
||||
self.expected_manifest.append(new_v)
|
||||
d.addCallback(_created)
|
||||
|
||||
d.addCallback(lambda res: n.list())
|
||||
def _check_list(children):
|
||||
self.failUnless("child" in children)
|
||||
d.addCallback(_check_list)
|
||||
d.addCallback(lambda children:
|
||||
self.failUnlessEqual(sorted(children.keys()),
|
||||
sorted(["child", "subdir"])))
|
||||
|
||||
d.addCallback(lambda res: n.build_manifest())
|
||||
def _check_manifest(manifest):
|
||||
self.failUnlessEqual(sorted(manifest),
|
||||
sorted(self.expected_manifest))
|
||||
d.addCallback(_check_manifest)
|
||||
|
||||
def _add_subsubdir(res):
|
||||
return self.subdir.create_empty_directory("subsubdir")
|
||||
d.addCallback(_add_subsubdir)
|
||||
d.addCallback(lambda res: n.get_child_at_path("subdir/subsubdir"))
|
||||
d.addCallback(lambda subsubdir:
|
||||
self.failUnless(isinstance(subsubdir,
|
||||
FakeNewDirectoryNode)))
|
||||
d.addCallback(lambda res: n.get_child_at_path(""))
|
||||
d.addCallback(lambda res: self.failUnlessEqual(res.get_uri(),
|
||||
n.get_uri()))
|
||||
|
||||
d.addCallback(lambda res: n.get_metadata_for("child"))
|
||||
d.addCallback(lambda metadata: self.failUnlessEqual(metadata, {}))
|
||||
|
||||
d.addCallback(lambda res: n.delete("subdir"))
|
||||
d.addCallback(lambda old_child:
|
||||
self.failUnlessEqual(old_child.get_uri(),
|
||||
self.subdir.get_uri()))
|
||||
|
||||
d.addCallback(lambda res: n.list())
|
||||
d.addCallback(lambda children:
|
||||
self.failUnlessEqual(sorted(children.keys()),
|
||||
sorted(["child"])))
|
||||
|
||||
return d
|
||||
|
||||
|
@ -4,7 +4,7 @@ from zope.interface import implements
|
||||
from twisted.python.components import registerAdapter
|
||||
from allmydata.util import idlib, hashutil
|
||||
from allmydata.interfaces import IURI, IDirnodeURI, IFileURI, IVerifierURI, \
|
||||
IMutableFileURI
|
||||
IMutableFileURI, INewDirectoryURI
|
||||
|
||||
# the URI shall be an ascii representation of the file. It shall contain
|
||||
# enough information to retrieve and validate the contents. It shall be
|
||||
@ -272,7 +272,7 @@ class SSKVerifierURI(_BaseURI):
|
||||
idlib.b2a(self.fingerprint))
|
||||
|
||||
class NewDirectoryURI(_BaseURI):
|
||||
implements(IURI, IDirnodeURI)
|
||||
implements(IURI, IDirnodeURI, INewDirectoryURI)
|
||||
|
||||
def __init__(self, filenode_uri=None):
|
||||
if filenode_uri:
|
||||
@ -293,6 +293,9 @@ class NewDirectoryURI(_BaseURI):
|
||||
(header_uri, header_ssk, bits) = fn_u.split(":", 2)
|
||||
return "URI:DIR2:" + bits
|
||||
|
||||
def get_filenode_uri(self):
|
||||
return self._filenode_uri
|
||||
|
||||
def is_readonly(self):
|
||||
return False
|
||||
def is_mutable(self):
|
||||
@ -324,6 +327,9 @@ class ReadonlyNewDirectoryURI(_BaseURI):
|
||||
(header_uri, header_ssk, bits) = fn_u.split(":", 2)
|
||||
return "URI:DIR2-RO:" + bits
|
||||
|
||||
def get_filenode_uri(self):
|
||||
return self._filenode_uri
|
||||
|
||||
def is_readonly(self):
|
||||
return True
|
||||
def is_mutable(self):
|
||||
@ -355,6 +361,9 @@ class NewDirectoryURIVerifier(_BaseURI):
|
||||
(header_uri, header_ssk, bits) = fn_u.split(":", 2)
|
||||
return "URI:DIR2-Verifier:" + bits
|
||||
|
||||
def get_filenode_uri(self):
|
||||
return self._filenode_uri
|
||||
|
||||
|
||||
|
||||
class DirnodeURI(_BaseURI):
|
||||
|
Loading…
x
Reference in New Issue
Block a user