From 2b8a312cb787922437ff75b88123e353d45f59ab Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Sat, 31 Mar 2012 11:36:20 -0700 Subject: [PATCH] Add test for bug #1689: repairing empty file hits no-privkey assertion --- src/allmydata/test/test_mutable.py | 47 ++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/allmydata/test/test_mutable.py b/src/allmydata/test/test_mutable.py index c8781178..1a3b7b17 100644 --- a/src/allmydata/test/test_mutable.py +++ b/src/allmydata/test/test_mutable.py @@ -39,6 +39,12 @@ from allmydata.test.test_download import PausingConsumer, \ PausingAndStoppingConsumer, StoppingConsumer, \ ImmediatelyStoppingConsumer +def eventuaaaaaly(res=None): + d = fireEventually(res) + d.addCallback(fireEventually) + d.addCallback(fireEventually) + return d + # this "FakeStorage" exists to put the share data in RAM and avoid using real # network connections, both to speed up the tests and to reduce the amount of @@ -69,7 +75,7 @@ class FakeStorage: def read(self, peerid, storage_index): shares = self._peers.get(peerid, {}) if self._sequence is None: - return defer.succeed(shares) + return eventuaaaaaly(shares) d = defer.Deferred() if not self._pending: self._pending_timer = reactor.callLater(1.0, self._fire_readers) @@ -233,11 +239,12 @@ def make_storagebroker(s=None, num_peers=10): storage_broker.test_add_rref(peerid, fss, ann) return storage_broker -def make_nodemaker(s=None, num_peers=10): +def make_nodemaker(s=None, num_peers=10, keysize=TEST_RSA_KEY_SIZE): storage_broker = make_storagebroker(s, num_peers) sh = client.SecretHolder("lease secret", "convergence secret") keygen = client.KeyGenerator() - keygen.set_default_keysize(TEST_RSA_KEY_SIZE) + if keysize: + keygen.set_default_keysize(keysize) nodemaker = NodeMaker(storage_broker, sh, None, None, None, {"k": 3, "n": 10}, SDMF_VERSION, keygen) @@ -957,6 +964,20 @@ class PublishMixin: d.addCallback(_created) return d + def publish_empty_sdmf(self): + self.CONTENTS = "" + self.uploadable = MutableData(self.CONTENTS) + self._storage = FakeStorage() + self._nodemaker = make_nodemaker(self._storage, keysize=None) + self._storage_broker = self._nodemaker.storage_broker + d = self._nodemaker.create_mutable_file(self.uploadable, + version=SDMF_VERSION) + def _created(node): + self._fn = node + self._fn2 = self._nodemaker.create_from_cap(node.get_uri()) + d.addCallback(_created) + return d + def publish_multiple(self, version=0): self.CONTENTS = ["Contents 0", @@ -2157,6 +2178,26 @@ class Repair(unittest.TestCase, PublishMixin, ShouldFailMixin): d.addCallback(_check_results) return d + def test_repair_empty(self): + # bug 1689: delete one share of an empty mutable file, then repair. + # In the buggy version, the check that preceeds the retrieve+publish + # cycle uses MODE_READ, instead of MODE_REPAIR, and fails to get the + # privkey that repair needs. + d = self.publish_empty_sdmf() + def _delete_one_share(ign): + shares = self._storage._peers + for peerid in shares: + for shnum in list(shares[peerid]): + if shnum == 0: + del shares[peerid][shnum] + d.addCallback(_delete_one_share) + d.addCallback(lambda ign: self._fn2.check(Monitor())) + d.addCallback(lambda check_results: self._fn2.repair(check_results)) + def _check(crr): + self.failUnlessEqual(crr.get_successful(), True) + d.addCallback(_check) + return d + class DevNullDictionary(dict): def __setitem__(self, key, value): return -- 2.37.2