diff --git a/src/_zkapauthorizer/_storage_server.py b/src/_zkapauthorizer/_storage_server.py index e54f3780787bf500937188b512411cc3b027e074..da6c959cb4bc3bd22b7c48e1fb5fdbb3cf7a71cb 100644 --- a/src/_zkapauthorizer/_storage_server.py +++ b/src/_zkapauthorizer/_storage_server.py @@ -31,11 +31,10 @@ from os.path import join from struct import calcsize, unpack import attr -from allmydata.interfaces import RIStorageServer +from allmydata.interfaces import RIStorageServer, TestAndWriteVectorsForShares from allmydata.storage.common import storage_index_to_dir -from allmydata.storage.immutable import ShareFile from allmydata.storage.lease import LeaseInfo -from allmydata.storage.mutable import MutableShareFile +from allmydata.storage.server import StorageServer from allmydata.storage.shares import get_share_file from allmydata.util.base32 import b2a from attr.validators import instance_of, provides @@ -60,6 +59,11 @@ from .storage_common import ( slot_testv_and_readv_and_writev_message, ) +try: + from typing import Dict, List, Optional +except ImportError: + pass + # See allmydata/storage/mutable.py SLOT_HEADER_SIZE = 468 LEASE_TRAILER_SIZE = 4 @@ -755,7 +759,7 @@ def share_has_active_leases(storage_server, storage_index, sharenum, now): def get_writev_price(storage_server, pass_value, storage_index, tw_vectors, now): - # type: (StorageServer, int, bytes, TestWriteVectors, float) -> int + # type: (StorageServer, int, bytes, TestAndWriteVectorsForShares, float) -> int """ Determine the price to execute the given test/write vectors. """ diff --git a/src/_zkapauthorizer/lease_maintenance.py b/src/_zkapauthorizer/lease_maintenance.py index ad901881175186407b9d442318d6be2e051b2f6b..da19a99ab563202541467e88939c562b2f0cc9ec 100644 --- a/src/_zkapauthorizer/lease_maintenance.py +++ b/src/_zkapauthorizer/lease_maintenance.py @@ -36,8 +36,14 @@ from twisted.python.log import err from zope.interface import implementer from .controller import bracket +from .foolscap import ShareStat from .model import ILeaseMaintenanceObserver +try: + from typing import Iterable +except ImportError: + pass + SERVICE_NAME = u"lease maintenance service" diff --git a/src/_zkapauthorizer/tests/test_lease_maintenance.py b/src/_zkapauthorizer/tests/test_lease_maintenance.py index a5af5299757b943b8fe46161957d59b0972b51c9..49278eae88f42a190c3e5e9f85b8c389697fa286 100644 --- a/src/_zkapauthorizer/tests/test_lease_maintenance.py +++ b/src/_zkapauthorizer/tests/test_lease_maintenance.py @@ -37,7 +37,6 @@ from hypothesis.strategies import ( lists, randoms, sets, - tuples, ) from testtools import TestCase from testtools.matchers import ( @@ -51,7 +50,7 @@ from testtools.matchers import ( ) from testtools.twistedsupport import succeeded from twisted.application.service import IService -from twisted.internet.defer import maybeDeferred, succeed +from twisted.internet.defer import Deferred, maybeDeferred, succeed from twisted.internet.task import Clock from twisted.python.filepath import FilePath from zope.interface import implementer @@ -80,8 +79,30 @@ from .strategies import ( storage_indexes, ) +try: + from typing import Dict, List +except ImportError: + pass + + default_lease_maint_config = lease_maintenance_from_tahoe_config(empty_config) +def interval_means(): + return floats( + # It doesn't make sense to have a negative check interval mean. + min_value=0, + # We can't make this value too large or it isn't convertable to a + # timedelta. Also, even values as large as this one are of + # questionable value. + max_value=60 * 60 * 24 * 365, + ).map( + # By representing the result as a timedelta we avoid the cases where + # the lower precision of timedelta compared to float drops the whole + # value (anything between 0 and 1 microsecond). This is just one + # example of how working with timedeltas is nicer, in general. + lambda s: timedelta(seconds=s), + ) + def dummy_maintain_leases(): pass @@ -477,7 +498,6 @@ def lists_of_buckets(): min_size=count, max_size=count, ) - expiration_strategy = lists return builds( zip, si_strategy, diff --git a/src/_zkapauthorizer/tests/test_storage_protocol.py b/src/_zkapauthorizer/tests/test_storage_protocol.py index 6e3fd1222470ab0959d8f936177c1f1d78ba68d0..82b62acbdab9f855efc5cd83503252f07627627a 100644 --- a/src/_zkapauthorizer/tests/test_storage_protocol.py +++ b/src/_zkapauthorizer/tests/test_storage_protocol.py @@ -46,7 +46,6 @@ from twisted.internet.task import Clock from twisted.python.filepath import FilePath from twisted.python.runtime import platform -from .._storage_client import _encode_passes from ..api import ( MorePassesRequired, ZKAPAuthorizerStorageClient, @@ -57,7 +56,6 @@ from ..storage_common import ( allocate_buckets_message, get_implied_data_length, required_passes, - slot_testv_and_readv_and_writev_message, ) from .common import skipIf from .fixtures import AnonymousStorageServer diff --git a/src/_zkapauthorizer/tests/test_storage_server.py b/src/_zkapauthorizer/tests/test_storage_server.py index cdff293f8e7cd638f7b4cb3df1263196584061d5..cd0eb20d52e70db098875fa6a9ea48c4b26deb5c 100644 --- a/src/_zkapauthorizer/tests/test_storage_server.py +++ b/src/_zkapauthorizer/tests/test_storage_server.py @@ -383,26 +383,22 @@ class PassValidationTests(TestCase): ), ) - def _test_lease_operation_fails_without_passes( - self, - storage_index, - secrets, - sharenums, - allocated_size, - lease_operation, - lease_operation_message, + @given( + storage_index=storage_indexes(), + secrets=tuples( + lease_renew_secrets(), + lease_cancel_secrets(), + ), + sharenums=sharenum_sets(), + allocated_size=sizes(), + ) + def test_add_lease_fails_without_passes( + self, storage_index, secrets, sharenums, allocated_size ): """ - Assert that a lease-taking operation fails if it is not supplied with - enough passes to cover the cost of the lease. - - :param lease_operation: A two-argument callable. It is called with a - storage server and a list of passes. It should perform the - lease-taking operation. - - :param lease_operation_message: A one-argument callable. It is called - with a storage index. It should return the ZKAPAuthorizer binding - message for the lease-taking operation. + If ``remote_add_lease`` is invoked without supplying enough passes to + cover the storage for all shares on the given storage index, the + operation fails with ``MorePassesRequired``. """ renew_secret, cancel_secret = secrets @@ -433,11 +429,20 @@ class PassValidationTests(TestCase): # Attempt the lease operation with one fewer pass than is required. passes = make_passes( self.signing_key, - lease_operation_message(storage_index), + add_lease_message(storage_index), list(RandomToken.create() for i in range(required_count - 1)), ) try: - result = lease_operation(self.storage_server, passes) + result = self.storage_server.doRemoteCall( + "add_lease", + ( + passes, + storage_index, + renew_secret, + cancel_secret, + ), + {}, + ) except MorePassesRequired as e: self.assertThat( e, @@ -452,46 +457,6 @@ class PassValidationTests(TestCase): else: self.fail("Expected MorePassesRequired, got {}".format(result)) - @given( - storage_index=storage_indexes(), - secrets=tuples( - lease_renew_secrets(), - lease_cancel_secrets(), - ), - sharenums=sharenum_sets(), - allocated_size=sizes(), - ) - def test_add_lease_fails_without_passes( - self, storage_index, secrets, sharenums, allocated_size - ): - """ - If ``remote_add_lease`` is invoked without supplying enough passes to - cover the storage for all shares on the given storage index, the - operation fails with ``MorePassesRequired``. - """ - renew_secret, cancel_secret = secrets - - def add_lease(storage_server, passes): - return storage_server.doRemoteCall( - "add_lease", - ( - passes, - storage_index, - renew_secret, - cancel_secret, - ), - {}, - ) - - return self._test_lease_operation_fails_without_passes( - storage_index, - secrets, - sharenums, - allocated_size, - add_lease, - add_lease_message, - ) - @given( slot=storage_indexes(), secrets=tuples( diff --git a/tests.nix b/tests.nix index b8b5b39b0d656f43d07cd5c66938c7f52a28bdd2..7023c06a296dfd5be2cb3468c789d7038ac25add 100644 --- a/tests.nix +++ b/tests.nix @@ -49,7 +49,7 @@ in mkdir -p $out pushd ${zkapauthorizer.src} - ${python}/bin/pyflakes + ${python}/bin/pyflakes src ${lint-python}/bin/black --check src ${lint-python}/bin/isort --check src popd