mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-24 07:06:41 +00:00
Merge pull request #797 from tahoe-lafs/3396.storage-tests-python-3
Make allmydata.test.test_storage run (but not pass!) on Python 3 Fixes ticket:3396
This commit is contained in:
commit
e237b37069
0
newsfragments/3396.minor
Normal file
0
newsfragments/3396.minor
Normal file
@ -2,7 +2,10 @@ import os, stat, time, weakref
|
|||||||
from base64 import urlsafe_b64encode
|
from base64 import urlsafe_b64encode
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from errno import ENOENT, EPERM
|
from errno import ENOENT, EPERM
|
||||||
from ConfigParser import NoSectionError
|
try:
|
||||||
|
from ConfigParser import NoSectionError
|
||||||
|
except ImportError:
|
||||||
|
from configparser import NoSectionError
|
||||||
|
|
||||||
from foolscap.furl import (
|
from foolscap.furl import (
|
||||||
decode_furl,
|
decode_furl,
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
"""Directory Node implementation."""
|
"""Directory Node implementation."""
|
||||||
|
from past.builtins import unicode
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from zope.interface import implementer
|
from zope.interface import implementer
|
||||||
@ -227,7 +229,7 @@ def pack_children(childrenx, writekey, deep_immutable=False):
|
|||||||
return _pack_normalized_children(children, writekey=writekey, deep_immutable=deep_immutable)
|
return _pack_normalized_children(children, writekey=writekey, deep_immutable=deep_immutable)
|
||||||
|
|
||||||
|
|
||||||
ZERO_LEN_NETSTR=netstring('')
|
ZERO_LEN_NETSTR=netstring(b'')
|
||||||
def _pack_normalized_children(children, writekey, deep_immutable=False):
|
def _pack_normalized_children(children, writekey, deep_immutable=False):
|
||||||
"""Take a dict that maps:
|
"""Take a dict that maps:
|
||||||
children[unicode_nfc_name] = (IFileSystemNode, metadata_dict)
|
children[unicode_nfc_name] = (IFileSystemNode, metadata_dict)
|
||||||
|
@ -4,7 +4,7 @@ from foolscap.api import eventually
|
|||||||
from allmydata.interfaces import NotEnoughSharesError, NoSharesError
|
from allmydata.interfaces import NotEnoughSharesError, NoSharesError
|
||||||
from allmydata.util import log
|
from allmydata.util import log
|
||||||
from allmydata.util.dictutil import DictOfSets
|
from allmydata.util.dictutil import DictOfSets
|
||||||
from common import OVERDUE, COMPLETE, CORRUPT, DEAD, BADSEGNUM, \
|
from .common import OVERDUE, COMPLETE, CORRUPT, DEAD, BADSEGNUM, \
|
||||||
BadSegmentNumberError
|
BadSegmentNumberError
|
||||||
|
|
||||||
class SegmentFetcher(object):
|
class SegmentFetcher(object):
|
||||||
|
@ -5,7 +5,7 @@ from foolscap.api import eventually
|
|||||||
from allmydata.util import base32, log
|
from allmydata.util import base32, log
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
|
|
||||||
from share import Share, CommonShare
|
from .share import Share, CommonShare
|
||||||
|
|
||||||
def incidentally(res, f, *args, **kwargs):
|
def incidentally(res, f, *args, **kwargs):
|
||||||
"""Add me to a Deferred chain like this:
|
"""Add me to a Deferred chain like this:
|
||||||
|
@ -13,10 +13,10 @@ from allmydata.hashtree import IncompleteHashTree, BadHashError, \
|
|||||||
NotEnoughHashesError
|
NotEnoughHashesError
|
||||||
|
|
||||||
# local imports
|
# local imports
|
||||||
from finder import ShareFinder
|
from .finder import ShareFinder
|
||||||
from fetcher import SegmentFetcher
|
from .fetcher import SegmentFetcher
|
||||||
from segmentation import Segmentation
|
from .segmentation import Segmentation
|
||||||
from common import BadCiphertextHashError
|
from .common import BadCiphertextHashError
|
||||||
|
|
||||||
class IDownloadStatusHandlingConsumer(Interface):
|
class IDownloadStatusHandlingConsumer(Interface):
|
||||||
def set_download_status_read_event(read_ev):
|
def set_download_status_read_event(read_ev):
|
||||||
|
@ -9,7 +9,7 @@ from allmydata.util import log
|
|||||||
from allmydata.util.spans import overlap
|
from allmydata.util.spans import overlap
|
||||||
from allmydata.interfaces import DownloadStopped
|
from allmydata.interfaces import DownloadStopped
|
||||||
|
|
||||||
from common import BadSegmentNumberError, WrongSegmentError
|
from .common import BadSegmentNumberError, WrongSegmentError
|
||||||
|
|
||||||
@implementer(IPushProducer)
|
@implementer(IPushProducer)
|
||||||
class Segmentation(object):
|
class Segmentation(object):
|
||||||
|
@ -13,7 +13,7 @@ from allmydata.hashtree import IncompleteHashTree, BadHashError, \
|
|||||||
|
|
||||||
from allmydata.immutable.layout import make_write_bucket_proxy
|
from allmydata.immutable.layout import make_write_bucket_proxy
|
||||||
from allmydata.util.observer import EventStreamObserver
|
from allmydata.util.observer import EventStreamObserver
|
||||||
from common import COMPLETE, CORRUPT, DEAD, BADSEGNUM
|
from .common import COMPLETE, CORRUPT, DEAD, BADSEGNUM
|
||||||
|
|
||||||
|
|
||||||
class LayoutInvalid(Exception):
|
class LayoutInvalid(Exception):
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from past.builtins import long
|
||||||
|
|
||||||
import os, time, weakref, itertools
|
import os, time, weakref, itertools
|
||||||
from zope.interface import implementer
|
from zope.interface import implementer
|
||||||
from twisted.python import failure
|
from twisted.python import failure
|
||||||
@ -26,7 +28,7 @@ from allmydata.interfaces import IUploadable, IUploader, IUploadResults, \
|
|||||||
from allmydata.immutable import layout
|
from allmydata.immutable import layout
|
||||||
|
|
||||||
from six.moves import cStringIO as StringIO
|
from six.moves import cStringIO as StringIO
|
||||||
from happiness_upload import share_placement, calculate_happiness
|
from .happiness_upload import share_placement, calculate_happiness
|
||||||
|
|
||||||
from ..util.eliotutil import (
|
from ..util.eliotutil import (
|
||||||
log_call_deferred,
|
log_call_deferred,
|
||||||
|
@ -2,12 +2,17 @@
|
|||||||
This module contains classes and functions to implement and manage
|
This module contains classes and functions to implement and manage
|
||||||
a node for Tahoe-LAFS.
|
a node for Tahoe-LAFS.
|
||||||
"""
|
"""
|
||||||
|
from past.builtins import unicode
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
import types
|
import types
|
||||||
import errno
|
import errno
|
||||||
import ConfigParser
|
try:
|
||||||
|
import ConfigParser
|
||||||
|
except ImportError:
|
||||||
|
import configparser as ConfigParser
|
||||||
import tempfile
|
import tempfile
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from base64 import b32decode, b32encode
|
from base64 import b32decode, b32encode
|
||||||
@ -67,7 +72,7 @@ def _common_valid_config():
|
|||||||
|
|
||||||
# Add our application versions to the data that Foolscap's LogPublisher
|
# Add our application versions to the data that Foolscap's LogPublisher
|
||||||
# reports.
|
# reports.
|
||||||
for thing, things_version in get_package_versions().iteritems():
|
for thing, things_version in get_package_versions().items():
|
||||||
app_versions.add_version(thing, str(things_version))
|
app_versions.add_version(thing, str(things_version))
|
||||||
|
|
||||||
# group 1 will be addr (dotted quad string), group 3 if any will be portnum (string)
|
# group 1 will be addr (dotted quad string), group 3 if any will be portnum (string)
|
||||||
@ -272,7 +277,10 @@ class _Config(object):
|
|||||||
self.config = configparser
|
self.config = configparser
|
||||||
|
|
||||||
nickname_utf8 = self.get_config("node", "nickname", "<unspecified>")
|
nickname_utf8 = self.get_config("node", "nickname", "<unspecified>")
|
||||||
self.nickname = nickname_utf8.decode("utf-8")
|
if isinstance(nickname_utf8, bytes): # Python 2
|
||||||
|
self.nickname = nickname_utf8.decode("utf-8")
|
||||||
|
else:
|
||||||
|
self.nickname = nickname_utf8
|
||||||
assert type(self.nickname) is unicode
|
assert type(self.nickname) is unicode
|
||||||
|
|
||||||
def validate(self, valid_config_sections):
|
def validate(self, valid_config_sections):
|
||||||
|
@ -30,9 +30,12 @@ the foolscap-based server implemented in src/allmydata/storage/*.py .
|
|||||||
|
|
||||||
|
|
||||||
import re, time, hashlib
|
import re, time, hashlib
|
||||||
from ConfigParser import (
|
try:
|
||||||
NoSectionError,
|
from ConfigParser import (
|
||||||
)
|
NoSectionError,
|
||||||
|
)
|
||||||
|
except ImportError:
|
||||||
|
from configparser import NoSectionError
|
||||||
import attr
|
import attr
|
||||||
from zope.interface import (
|
from zope.interface import (
|
||||||
Attribute,
|
Attribute,
|
||||||
@ -534,11 +537,11 @@ class _NullStorage(object):
|
|||||||
which we can't communicate.
|
which we can't communicate.
|
||||||
"""
|
"""
|
||||||
nickname = ""
|
nickname = ""
|
||||||
permutation_seed = hashlib.sha256("").digest()
|
permutation_seed = hashlib.sha256(b"").digest()
|
||||||
tubid = hashlib.sha256("").digest()
|
tubid = hashlib.sha256(b"").digest()
|
||||||
storage_server = None
|
storage_server = None
|
||||||
|
|
||||||
lease_seed = hashlib.sha256("").digest()
|
lease_seed = hashlib.sha256(b"").digest()
|
||||||
|
|
||||||
name = "<unsupported>"
|
name = "<unsupported>"
|
||||||
longname = "<storage with unsupported protocol>"
|
longname = "<storage with unsupported protocol>"
|
||||||
|
@ -52,7 +52,6 @@ from twisted.internet.defer import inlineCallbacks, returnValue
|
|||||||
from twisted.internet.interfaces import IPullProducer
|
from twisted.internet.interfaces import IPullProducer
|
||||||
from twisted.python import failure
|
from twisted.python import failure
|
||||||
from twisted.python.filepath import FilePath
|
from twisted.python.filepath import FilePath
|
||||||
from twisted.application import service
|
|
||||||
from twisted.web.error import Error as WebError
|
from twisted.web.error import Error as WebError
|
||||||
from twisted.internet.interfaces import (
|
from twisted.internet.interfaces import (
|
||||||
IStreamServerEndpointStringParser,
|
IStreamServerEndpointStringParser,
|
||||||
@ -88,6 +87,8 @@ from ..crypto import (
|
|||||||
from .eliotutil import (
|
from .eliotutil import (
|
||||||
EliotLoggedRunTest,
|
EliotLoggedRunTest,
|
||||||
)
|
)
|
||||||
|
# Backwards compatibility imports:
|
||||||
|
from .common_py3 import LoggingServiceParent, ShouldFailMixin # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
TEST_RSA_KEY_SIZE = 522
|
TEST_RSA_KEY_SIZE = 522
|
||||||
@ -780,53 +781,8 @@ def create_mutable_filenode(contents, mdmf=False, all_contents=None):
|
|||||||
return filenode
|
return filenode
|
||||||
|
|
||||||
|
|
||||||
class LoggingServiceParent(service.MultiService):
|
|
||||||
def log(self, *args, **kwargs):
|
|
||||||
return log.msg(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
TEST_DATA="\x02"*(Uploader.URI_LIT_SIZE_THRESHOLD+1)
|
TEST_DATA="\x02"*(Uploader.URI_LIT_SIZE_THRESHOLD+1)
|
||||||
|
|
||||||
class ShouldFailMixin(object):
|
|
||||||
def shouldFail(self, expected_failure, which, substring,
|
|
||||||
callable, *args, **kwargs):
|
|
||||||
"""Assert that a function call raises some exception. This is a
|
|
||||||
Deferred-friendly version of TestCase.assertRaises() .
|
|
||||||
|
|
||||||
Suppose you want to verify the following function:
|
|
||||||
|
|
||||||
def broken(a, b, c):
|
|
||||||
if a < 0:
|
|
||||||
raise TypeError('a must not be negative')
|
|
||||||
return defer.succeed(b+c)
|
|
||||||
|
|
||||||
You can use:
|
|
||||||
d = self.shouldFail(TypeError, 'test name',
|
|
||||||
'a must not be negative',
|
|
||||||
broken, -4, 5, c=12)
|
|
||||||
in your test method. The 'test name' string will be included in the
|
|
||||||
error message, if any, because Deferred chains frequently make it
|
|
||||||
difficult to tell which assertion was tripped.
|
|
||||||
|
|
||||||
The substring= argument, if not None, must appear in the 'repr'
|
|
||||||
of the message wrapped by this Failure, or the test will fail.
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert substring is None or isinstance(substring, str)
|
|
||||||
d = defer.maybeDeferred(callable, *args, **kwargs)
|
|
||||||
def done(res):
|
|
||||||
if isinstance(res, failure.Failure):
|
|
||||||
res.trap(expected_failure)
|
|
||||||
if substring:
|
|
||||||
message = repr(res.value.args[0])
|
|
||||||
self.failUnless(substring in message,
|
|
||||||
"%s: substring '%s' not in '%s'"
|
|
||||||
% (which, substring, message))
|
|
||||||
else:
|
|
||||||
self.fail("%s was supposed to raise %s, not get '%s'" %
|
|
||||||
(which, expected_failure, res))
|
|
||||||
d.addBoth(done)
|
|
||||||
return d
|
|
||||||
|
|
||||||
class WebErrorMixin(object):
|
class WebErrorMixin(object):
|
||||||
def explain_web_error(self, f):
|
def explain_web_error(self, f):
|
||||||
|
@ -19,11 +19,13 @@ import time
|
|||||||
import signal
|
import signal
|
||||||
|
|
||||||
from twisted.internet import defer, reactor
|
from twisted.internet import defer, reactor
|
||||||
|
from twisted.application import service
|
||||||
from twisted.python import failure
|
from twisted.python import failure
|
||||||
from twisted.trial import unittest
|
from twisted.trial import unittest
|
||||||
|
|
||||||
from ..util.assertutil import precondition
|
from ..util.assertutil import precondition
|
||||||
from ..util.encodingutil import unicode_platform, get_filesystem_encoding
|
from ..util.encodingutil import unicode_platform, get_filesystem_encoding
|
||||||
|
from ..util import log
|
||||||
|
|
||||||
|
|
||||||
class TimezoneMixin(object):
|
class TimezoneMixin(object):
|
||||||
@ -77,6 +79,28 @@ class ShouldFailMixin(object):
|
|||||||
|
|
||||||
def shouldFail(self, expected_failure, which, substring,
|
def shouldFail(self, expected_failure, which, substring,
|
||||||
callable, *args, **kwargs):
|
callable, *args, **kwargs):
|
||||||
|
"""Assert that a function call raises some exception. This is a
|
||||||
|
Deferred-friendly version of TestCase.assertRaises() .
|
||||||
|
|
||||||
|
Suppose you want to verify the following function:
|
||||||
|
|
||||||
|
def broken(a, b, c):
|
||||||
|
if a < 0:
|
||||||
|
raise TypeError('a must not be negative')
|
||||||
|
return defer.succeed(b+c)
|
||||||
|
|
||||||
|
You can use:
|
||||||
|
d = self.shouldFail(TypeError, 'test name',
|
||||||
|
'a must not be negative',
|
||||||
|
broken, -4, 5, c=12)
|
||||||
|
in your test method. The 'test name' string will be included in the
|
||||||
|
error message, if any, because Deferred chains frequently make it
|
||||||
|
difficult to tell which assertion was tripped.
|
||||||
|
|
||||||
|
The substring= argument, if not None, must appear in the 'repr'
|
||||||
|
of the message wrapped by this Failure, or the test will fail.
|
||||||
|
"""
|
||||||
|
|
||||||
assert substring is None or isinstance(substring, (bytes, unicode))
|
assert substring is None or isinstance(substring, (bytes, unicode))
|
||||||
d = defer.maybeDeferred(callable, *args, **kwargs)
|
d = defer.maybeDeferred(callable, *args, **kwargs)
|
||||||
def done(res):
|
def done(res):
|
||||||
@ -135,3 +159,9 @@ class FakeCanary(object):
|
|||||||
if self.ignore:
|
if self.ignore:
|
||||||
return
|
return
|
||||||
del self.disconnectors[marker]
|
del self.disconnectors[marker]
|
||||||
|
|
||||||
|
|
||||||
|
class LoggingServiceParent(service.MultiService):
|
||||||
|
def log(self, *args, **kwargs):
|
||||||
|
return log.msg(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
Tools aimed at the interaction between tests and Eliot.
|
Tools aimed at the interaction between tests and Eliot.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from past.builtins import unicode
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"RUN_TEST",
|
"RUN_TEST",
|
||||||
"EliotLoggedRunTest",
|
"EliotLoggedRunTest",
|
||||||
|
@ -30,12 +30,11 @@ from allmydata.mutable.layout import MDMFSlotWriteProxy, MDMFSlotReadProxy, \
|
|||||||
VERIFICATION_KEY_SIZE, \
|
VERIFICATION_KEY_SIZE, \
|
||||||
SHARE_HASH_CHAIN_SIZE
|
SHARE_HASH_CHAIN_SIZE
|
||||||
from allmydata.interfaces import BadWriteEnablerError
|
from allmydata.interfaces import BadWriteEnablerError
|
||||||
from allmydata.test.common import LoggingServiceParent, ShouldFailMixin
|
|
||||||
from allmydata.test.no_network import NoNetworkServer
|
from allmydata.test.no_network import NoNetworkServer
|
||||||
from allmydata.storage_client import (
|
from allmydata.storage_client import (
|
||||||
_StorageServer,
|
_StorageServer,
|
||||||
)
|
)
|
||||||
from .common_py3 import FakeCanary
|
from .common_py3 import FakeCanary, LoggingServiceParent, ShouldFailMixin
|
||||||
|
|
||||||
|
|
||||||
class FakeStatsProvider(object):
|
class FakeStatsProvider(object):
|
||||||
|
@ -980,6 +980,8 @@ class CountingDataUploadable(upload.Data):
|
|||||||
|
|
||||||
class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
|
class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
|
||||||
|
|
||||||
|
timeout = 180
|
||||||
|
|
||||||
def test_connections(self):
|
def test_connections(self):
|
||||||
self.basedir = "system/SystemTest/test_connections"
|
self.basedir = "system/SystemTest/test_connections"
|
||||||
d = self.set_up_nodes()
|
d = self.set_up_nodes()
|
||||||
|
Loading…
Reference in New Issue
Block a user