Allow tests to pass with -OO by turning some AssertionErrors (the ones that

we actually exercise during tests) into more specific exceptions, so they
don't get optimized away. The best rule to follow is probably this: if an
exception is worth testing, then it's part of the API, and AssertionError
should never be part of the API. Closes #749.
This commit is contained in:
Brian Warner 2009-07-14 23:45:10 -07:00
parent 760bab7d2c
commit d8ba8c2eb5
9 changed files with 56 additions and 32 deletions

View File

@ -27,7 +27,8 @@ from allmydata.unknown import UnknownNode
from allmydata.stats import StatsProvider
from allmydata.history import History
from allmydata.interfaces import IURI, INewDirectoryURI, IStatsProducer, \
IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI, RIStubClient
IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI, RIStubClient, \
UnhandledCapTypeError
KiB=1024
MiB=1024*KiB
@ -429,9 +430,10 @@ class Client(node.Node, pollmixin.PollMixin):
node = LiteralFileNode(u, self) # LIT
else:
node = FileNode(u, self, self.download_cache_dirman) # CHK
else:
assert IMutableFileURI.providedBy(u), u
elif IMutableFileURI.providedBy(u):
node = MutableFileNode(self).init_from_uri(u)
else:
raise UnhandledCapTypeError("cap is recognized, but has no Node")
self._node_cache[u_s] = node # note: WeakValueDictionary
return self._node_cache[u_s]

View File

@ -482,6 +482,10 @@ class CannotPackUnknownNodeError(Exception):
"""UnknownNodes (using filecaps from the future that we don't understand)
cannot yet be copied safely, so I refuse to copy them."""
class UnhandledCapTypeError(Exception):
"""I recognize the cap/URI, but I cannot create an IFilesystemNode for
it."""
class IFilesystemNode(Interface):
def get_uri():
"""

View File

@ -53,7 +53,8 @@ class CorruptShareError(Exception):
self.shnum,
self.reason)
class UnknownVersionError(Exception):
"""The share we received was of a version we don't recognize."""
class ResponseCache:
"""I cache share data, to reduce the number of round trips used during

View File

@ -1,6 +1,6 @@
import struct
from common import NeedMoreDataError
from common import NeedMoreDataError, UnknownVersionError
PREFIX = ">BQ32s16s" # each version has a different prefix
SIGNED_PREFIX = ">BQ32s16s BBQQ" # this is covered by the signature
@ -34,7 +34,9 @@ def unpack_prefix_and_signature(data):
k, N, segsize, datalen,
o) = unpack_header(data)
assert version == 0
if version != 0:
raise UnknownVersionError("got mutable share version %d, but I only understand version 0" % version)
if len(data) < o['share_hash_chain']:
raise NeedMoreDataError(o['share_hash_chain'],
o['enc_privkey'], o['EOF']-o['enc_privkey'])
@ -60,7 +62,9 @@ def unpack_share(data):
o['enc_privkey'],
o['EOF']) = struct.unpack(HEADER, data[:HEADER_LENGTH])
assert version == 0
if version != 0:
raise UnknownVersionError("got mutable share version %d, but I only understand version 0" % version)
if len(data) < o['EOF']:
raise NeedMoreDataError(o['EOF'],
o['enc_privkey'], o['EOF']-o['enc_privkey'])
@ -132,7 +136,8 @@ def pack_checkstring(seqnum, root_hash, IV):
def unpack_checkstring(checkstring):
cs_len = struct.calcsize(PREFIX)
version, seqnum, root_hash, IV = struct.unpack(PREFIX, checkstring[:cs_len])
assert version == 0 # TODO: just ignore the share
if version != 0: # TODO: just ignore the share
raise UnknownVersionError("got mutable share version %d, but I only understand version 0" % version)
return (seqnum, root_hash, IV)
def pack_prefix(seqnum, root_hash, IV,

View File

@ -1030,7 +1030,7 @@ class Roundtrip(unittest.TestCase, testutil.ShouldFailMixin, PublishMixin):
# should be noted in the servermap's list of problems.
if substring:
allproblems = [str(f) for f in servermap.problems]
self.failUnless(substring in "".join(allproblems))
self.failUnlessIn(substring, "".join(allproblems))
return servermap
if should_succeed:
d1 = self._fn.download_version(servermap, ver)
@ -1049,9 +1049,9 @@ class Roundtrip(unittest.TestCase, testutil.ShouldFailMixin, PublishMixin):
return d
def test_corrupt_all_verbyte(self):
# when the version byte is not 0, we hit an assertion error in
# unpack_share().
d = self._test_corrupt_all(0, "AssertionError")
# when the version byte is not 0, we hit an UnknownVersionError error
# in unpack_share().
d = self._test_corrupt_all(0, "UnknownVersionError")
def _check_servermap(servermap):
# and the dump should mention the problems
s = StringIO()

View File

@ -186,10 +186,10 @@ class Constraint(unittest.TestCase):
def test_constraint(self):
good="http://127.0.0.1:3456/uri/URI%3ADIR2%3Agh3l5rbvnv2333mrfvalmjfr4i%3Alz6l7u3z3b7g37s4zkdmfpx5ly4ib4m6thrpbusi6ys62qtc6mma/"
uri.NewDirectoryURI.init_from_human_encoding(good)
self.failUnlessRaises(AssertionError, uri.NewDirectoryURI.init_from_string, good)
self.failUnlessRaises(uri.BadURIError, uri.NewDirectoryURI.init_from_string, good)
bad = good + '==='
self.failUnlessRaises(AssertionError, uri.NewDirectoryURI.init_from_human_encoding, bad)
self.failUnlessRaises(AssertionError, uri.NewDirectoryURI.init_from_string, bad)
self.failUnlessRaises(uri.BadURIError, uri.NewDirectoryURI.init_from_human_encoding, bad)
self.failUnlessRaises(uri.BadURIError, uri.NewDirectoryURI.init_from_string, bad)
fileURI = 'URI:CHK:gh3l5rbvnv2333mrfvalmjfr4i:lz6l7u3z3b7g37s4zkdmfpx5ly4ib4m6thrpbusi6ys62qtc6mma:3:10:345834'
uri.CHKFileURI.init_from_string(fileURI)

View File

@ -19,7 +19,8 @@ from allmydata.util.assertutil import precondition
from allmydata.test.common import FakeDirectoryNode, FakeCHKFileNode, \
FakeMutableFileNode, create_chk_filenode, WebErrorMixin, ShouldFailMixin
from allmydata.interfaces import IURI, INewDirectoryURI, \
IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI, IMutableFileNode
IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI, IMutableFileNode, \
UnhandledCapTypeError
from allmydata.mutable import servermap, publish, retrieve
import common_util as testutil
from allmydata.test.no_network import GridTestMixin
@ -74,8 +75,9 @@ class FakeClient(service.MultiService):
return FakeDirectoryNode(self).init_from_uri(u)
if IFileURI.providedBy(u):
return FakeCHKFileNode(u, self)
assert IMutableFileURI.providedBy(u), u
return FakeMutableFileNode(self).init_from_uri(u)
if IMutableFileURI.providedBy(u):
return FakeMutableFileNode(self).init_from_uri(u)
raise UnhandledCapTypeError("cap '%s' is recognized, but has no Node" % auri)
def create_empty_dirnode(self):
n = FakeDirectoryNode(self)

View File

@ -7,6 +7,9 @@ from allmydata.util import base32, hashutil
from allmydata.interfaces import IURI, IDirnodeURI, IFileURI, IImmutableFileURI, \
IVerifierURI, IMutableFileURI, INewDirectoryURI, IReadonlyNewDirectoryURI
class BadURIError(Exception):
pass
# the URI shall be an ascii representation of the file. It shall contain
# enough information to retrieve and validate the contents. It shall be
# expressed in a limited character set (namely [TODO]).
@ -60,21 +63,22 @@ class CHKFileURI(_BaseURI):
self.total_shares = total_shares
self.size = size
self.storage_index = hashutil.storage_index_hash(self.key)
assert len(self.storage_index) == 16
self.storage_index = hashutil.storage_index_hash(key)
assert len(self.storage_index) == 16 # sha256 hash truncated to 128
if not len(self.storage_index) == 16: # sha256 hash truncated to 128
raise BadURIError("storage index must be 16 bytes long")
@classmethod
def init_from_human_encoding(cls, uri):
mo = cls.HUMAN_RE.search(uri)
assert mo, uri
if not mo:
raise BadURIError("%s doesn't look like a cap" % (uri,))
return cls(base32.a2b(mo.group(1)), base32.a2b(mo.group(2)),
int(mo.group(3)), int(mo.group(4)), int(mo.group(5)))
@classmethod
def init_from_string(cls, uri):
mo = cls.STRING_RE.search(uri)
assert mo, uri
if not mo:
raise BadURIError("%s doesn't look like a cap" % (uri,))
return cls(base32.a2b(mo.group(1)), base32.a2b(mo.group(2)),
int(mo.group(3)), int(mo.group(4)), int(mo.group(5)))
@ -212,13 +216,15 @@ class WriteableSSKFileURI(_BaseURI):
@classmethod
def init_from_human_encoding(cls, uri):
mo = cls.HUMAN_RE.search(uri)
assert mo, uri
if not mo:
raise BadURIError("'%s' doesn't look like a cap" % (uri,))
return cls(base32.a2b(mo.group(1)), base32.a2b(mo.group(2)))
@classmethod
def init_from_string(cls, uri):
mo = cls.STRING_RE.search(uri)
assert mo, (uri, cls)
if not mo:
raise BadURIError("'%s' doesn't look like a %s cap" % (uri, cls))
return cls(base32.a2b(mo.group(1)), base32.a2b(mo.group(2)))
def to_string(self):
@ -260,13 +266,15 @@ class ReadonlySSKFileURI(_BaseURI):
@classmethod
def init_from_human_encoding(cls, uri):
mo = cls.HUMAN_RE.search(uri)
assert mo, uri
if not mo:
raise BadURIError("'%s' doesn't look like a cap" % (uri,))
return cls(base32.a2b(mo.group(1)), base32.a2b(mo.group(2)))
@classmethod
def init_from_string(cls, uri):
mo = cls.STRING_RE.search(uri)
assert mo, uri
if not mo:
raise BadURIError("'%s' doesn't look like a cap" % (uri,))
return cls(base32.a2b(mo.group(1)), base32.a2b(mo.group(2)))
def to_string(self):
@ -333,7 +341,8 @@ class _NewDirectoryBaseURI(_BaseURI):
@classmethod
def init_from_string(cls, uri):
mo = cls.BASE_STRING_RE.search(uri)
assert mo, (uri, cls)
if not mo:
raise BadURIError("'%s' doesn't look like a %s cap" % (uri, cls))
bits = uri[mo.end():]
fn = cls.INNER_URI_CLASS.init_from_string(
cls.INNER_URI_CLASS.BASE_STRING+bits)
@ -342,7 +351,8 @@ class _NewDirectoryBaseURI(_BaseURI):
@classmethod
def init_from_human_encoding(cls, uri):
mo = cls.BASE_HUMAN_RE.search(uri)
assert mo, (uri, cls)
if not mo:
raise BadURIError("'%s' doesn't look like a %s cap" % (uri, cls))
bits = uri[mo.end():]
while bits and bits[-1] == '/':
bits = bits[:-1]

View File

@ -12,7 +12,7 @@ import allmydata # to display import path
from allmydata import get_package_versions_string
from allmydata import provisioning
from allmydata.util import idlib, log
from allmydata.interfaces import IFileNode
from allmydata.interfaces import IFileNode, UnhandledCapTypeError
from allmydata.web import filenode, directory, unlinked, status, operations
from allmydata.web import reliability, storage
from allmydata.web.common import abbreviate_size, getxmlfile, WebError, \
@ -79,7 +79,7 @@ class URIHandler(RenderMixin, rend.Page):
try:
node = self.client.create_node_from_uri(name)
return directory.make_handler_for(node, self.client)
except (TypeError, AssertionError):
except (TypeError, UnhandledCapTypeError, AssertionError):
raise WebError("'%s' is not a valid file- or directory- cap"
% name)
@ -98,7 +98,7 @@ class FileHandler(rend.Page):
# 'name' must be a file URI
try:
node = self.client.create_node_from_uri(name)
except (TypeError, AssertionError):
except (TypeError, UnhandledCapTypeError, AssertionError):
raise WebError("'%s' is not a valid file- or directory- cap"
% name)
if not IFileNode.providedBy(node):