From a01b763eb2a4efece5ff6af61dbc0c3f19b70b6f Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone <exarkun@twistedmatrix.com> Date: Fri, 5 Jul 2019 12:54:58 -0400 Subject: [PATCH] test for add_lease --- .../_storage_client.py | 14 +++ .../tests/test_storage_protocol.py | 115 +++++++++++++++--- 2 files changed, 111 insertions(+), 18 deletions(-) diff --git a/src/_secureaccesstokenauthorizer/_storage_client.py b/src/_secureaccesstokenauthorizer/_storage_client.py index 4560c06..f1df274 100644 --- a/src/_secureaccesstokenauthorizer/_storage_client.py +++ b/src/_secureaccesstokenauthorizer/_storage_client.py @@ -76,3 +76,17 @@ class SecureAccessTokenAuthorizerStorageClient(object): "get_buckets", storage_index, ) + + def add_lease( + self, + storage_index, + renew_secret, + cancel_secret, + ): + return self._rref.callRemote( + "add_lease", + self._get_tokens(), + storage_index, + renew_secret, + cancel_secret, + ) diff --git a/src/_secureaccesstokenauthorizer/tests/test_storage_protocol.py b/src/_secureaccesstokenauthorizer/tests/test_storage_protocol.py index e19d677..96369af 100644 --- a/src/_secureaccesstokenauthorizer/tests/test_storage_protocol.py +++ b/src/_secureaccesstokenauthorizer/tests/test_storage_protocol.py @@ -17,6 +17,10 @@ Tests for communication between the client and server components. """ import attr +from struct import ( + unpack, +) + from fixtures import ( Fixture, TempDir, @@ -26,6 +30,7 @@ from testtools import ( ) from testtools.matchers import ( Equals, + HasLength, ) from testtools.twistedsupport._deferred import ( # I'd rather use https://twistedmatrix.com/trac/ticket/8900 but efforts @@ -35,8 +40,15 @@ from testtools.twistedsupport._deferred import ( from hypothesis import ( given, + assume, +) +from hypothesis.strategies import ( + tuples, ) +from twisted.python.filepath import ( + FilePath, +) from twisted.internet.defer import ( execute, ) @@ -53,6 +65,7 @@ from .strategies import ( storage_indexes, lease_renew_secrets, lease_cancel_secrets, + sharenums, sharenum_sets, sizes, ) @@ -97,6 +110,23 @@ class ImmutableTests(TestCase): """ Tests for interaction with immutable shares. """ + def setUp(self): + super(ImmutableTests, self).setUp() + self.canary = LocalReferenceable(None) + self.anonymous_storage_server = self.useFixture(AnonymousStorageServer()).storage_server + + def get_tokens(): + return [u"x"] + + self.server = SecureAccessTokenAuthorizerStorageServer( + self.anonymous_storage_server, + ) + self.local_remote_server = LocalRemote(self.server) + self.client = SecureAccessTokenAuthorizerStorageClient( + get_rref=lambda: self.local_remote_server, + get_tokens=get_tokens, + ) + @given( storage_index=storage_indexes(), renew_secret=lease_renew_secrets(), @@ -110,28 +140,18 @@ class ImmutableTests(TestCase): resulting buckets can be read back using *get_buckets* and methods of those resulting buckets. """ - anonymous_storage_server = self.useFixture(AnonymousStorageServer()).storage_server - - def get_tokens(): - return [u"x"] - - server = SecureAccessTokenAuthorizerStorageServer( - anonymous_storage_server, - ) - local_remote_server = LocalRemote(server) - client = SecureAccessTokenAuthorizerStorageClient( - get_rref=lambda: local_remote_server, - get_tokens=get_tokens, - ) + # Hypothesis causes our storage server to be used many times. Clean + # up between iterations. + cleanup_storage_server(self.anonymous_storage_server) alreadygot, allocated = extract_result( - client.allocate_buckets( + self.client.allocate_buckets( storage_index, renew_secret, cancel_secret, sharenums, size, - canary=LocalReferenceable(None), + canary=self.canary, ), ) self.expectThat( @@ -146,12 +166,10 @@ class ImmutableTests(TestCase): ) for sharenum, bucket in allocated.items(): - # returns None, nothing to extract bucket.remote_write(0, bytes_for_share(sharenum, size)), - # returns None, nothing to extract bucket.remote_close() - readers = extract_result(client.get_buckets(storage_index)) + readers = extract_result(self.client.get_buckets(storage_index)) self.expectThat( set(readers.keys()), @@ -166,3 +184,64 @@ class ImmutableTests(TestCase): sharenum, ), ) + + @given( + storage_index=storage_indexes(), + renew_secrets=tuples(lease_renew_secrets(), lease_renew_secrets()), + cancel_secret=lease_cancel_secrets(), + sharenum=sharenums(), + size=sizes(), + ) + def test_add_lease(self, storage_index, renew_secrets, cancel_secret, sharenum, size): + """ + A lease can be added to an existing immutable share. + """ + # Hypothesis causes our storage server to be used many times. Clean + # up between iterations. + cleanup_storage_server(self.anonymous_storage_server) + + # Use a different secret so that it's a new lease and not an + # implicit renewal. + add_lease_secret, renew_lease_secret = renew_secrets + assume(add_lease_secret != renew_lease_secret) + + # Create a share we can toy with. + _, allocated = self.anonymous_storage_server.remote_allocate_buckets( + storage_index, + add_lease_secret, + cancel_secret, + {sharenum}, + size, + canary=self.canary, + ) + [(_, writer)] = allocated.items() + writer.remote_write(0, bytes_for_share(sharenum, size)) + writer.remote_close() + + extract_result( + self.client.add_lease( + storage_index, + renew_lease_secret, + cancel_secret, + ), + ) + + # It's hard to assert much about the lease without knowing about + # *some* implementation details of the storage server. I prefer to + # know Python API details rather than on-disk format details. + [(_, reader)] = self.server.remote_get_buckets(storage_index).items() + leases = list(reader._share_file.get_leases()) + self.assertThat(leases, HasLength(2)) + + +def cleanup_storage_server(storage_server): + """ + Delete all of the shares held by the given storage server. + + :param allmydata.storage.server.StorageServer storage_server: The storage + server with some on-disk shares to delete. + """ + start = FilePath(storage_server.sharedir) + for p in start.walk(): + if p is not start: + p.remove() -- GitLab