mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-29 17:28:53 +00:00
86 lines
4.1 KiB
Python
86 lines
4.1 KiB
Python
from twisted.trial import unittest
|
|
from allmydata.monitor import Monitor
|
|
from allmydata.mutable.common import MODE_CHECK, MODE_READ
|
|
from .util import PublishMixin, CheckerMixin
|
|
|
|
|
|
class MultipleVersions(unittest.TestCase, PublishMixin, CheckerMixin):
|
|
|
|
def setUp(self):
|
|
return self.publish_multiple()
|
|
|
|
def test_multiple_versions(self):
|
|
# if we see a mix of versions in the grid, download_best_version
|
|
# should get the latest one
|
|
self._set_versions(dict([(i,2) for i in (0,2,4,6,8)]))
|
|
d = self._fn.download_best_version()
|
|
d.addCallback(lambda res: self.failUnlessEqual(res, self.CONTENTS[4]))
|
|
# and the checker should report problems
|
|
d.addCallback(lambda res: self._fn.check(Monitor()))
|
|
d.addCallback(self.check_bad, "test_multiple_versions")
|
|
|
|
# but if everything is at version 2, that's what we should download
|
|
d.addCallback(lambda res:
|
|
self._set_versions(dict([(i,2) for i in range(10)])))
|
|
d.addCallback(lambda res: self._fn.download_best_version())
|
|
d.addCallback(lambda res: self.failUnlessEqual(res, self.CONTENTS[2]))
|
|
# if exactly one share is at version 3, we should still get v2
|
|
d.addCallback(lambda res:
|
|
self._set_versions({0:3}))
|
|
d.addCallback(lambda res: self._fn.download_best_version())
|
|
d.addCallback(lambda res: self.failUnlessEqual(res, self.CONTENTS[2]))
|
|
# but the servermap should see the unrecoverable version. This
|
|
# depends upon the single newer share being queried early.
|
|
d.addCallback(lambda res: self._fn.get_servermap(MODE_READ))
|
|
def _check_smap(smap):
|
|
self.failUnlessEqual(len(smap.unrecoverable_versions()), 1)
|
|
newer = smap.unrecoverable_newer_versions()
|
|
self.failUnlessEqual(len(newer), 1)
|
|
verinfo, health = newer.items()[0]
|
|
self.failUnlessEqual(verinfo[0], 4)
|
|
self.failUnlessEqual(health, (1,3))
|
|
self.failIf(smap.needs_merge())
|
|
d.addCallback(_check_smap)
|
|
# if we have a mix of two parallel versions (s4a and s4b), we could
|
|
# recover either
|
|
d.addCallback(lambda res:
|
|
self._set_versions({0:3,2:3,4:3,6:3,8:3,
|
|
1:4,3:4,5:4,7:4,9:4}))
|
|
d.addCallback(lambda res: self._fn.get_servermap(MODE_READ))
|
|
def _check_smap_mixed(smap):
|
|
self.failUnlessEqual(len(smap.unrecoverable_versions()), 0)
|
|
newer = smap.unrecoverable_newer_versions()
|
|
self.failUnlessEqual(len(newer), 0)
|
|
self.failUnless(smap.needs_merge())
|
|
d.addCallback(_check_smap_mixed)
|
|
d.addCallback(lambda res: self._fn.download_best_version())
|
|
d.addCallback(lambda res: self.failUnless(res == self.CONTENTS[3] or
|
|
res == self.CONTENTS[4]))
|
|
return d
|
|
|
|
def test_replace(self):
|
|
# if we see a mix of versions in the grid, we should be able to
|
|
# replace them all with a newer version
|
|
|
|
# if exactly one share is at version 3, we should download (and
|
|
# replace) v2, and the result should be v4. Note that the index we
|
|
# give to _set_versions is different than the sequence number.
|
|
target = dict([(i,2) for i in range(10)]) # seqnum3
|
|
target[0] = 3 # seqnum4
|
|
self._set_versions(target)
|
|
|
|
def _modify(oldversion, servermap, first_time):
|
|
return oldversion + " modified"
|
|
d = self._fn.modify(_modify)
|
|
d.addCallback(lambda res: self._fn.download_best_version())
|
|
expected = self.CONTENTS[2] + " modified"
|
|
d.addCallback(lambda res: self.failUnlessEqual(res, expected))
|
|
# and the servermap should indicate that the outlier was replaced too
|
|
d.addCallback(lambda res: self._fn.get_servermap(MODE_CHECK))
|
|
def _check_smap(smap):
|
|
self.failUnlessEqual(smap.highest_seqnum(), 5)
|
|
self.failUnlessEqual(len(smap.unrecoverable_versions()), 0)
|
|
self.failUnlessEqual(len(smap.recoverable_versions()), 1)
|
|
d.addCallback(_check_smap)
|
|
return d
|