2007-01-05 04:52:51 +00:00
|
|
|
|
2007-02-02 00:13:01 +00:00
|
|
|
import os
|
2007-01-05 04:52:51 +00:00
|
|
|
from twisted.trial import unittest
|
2007-01-05 07:06:42 +00:00
|
|
|
from twisted.python import log
|
2007-02-01 23:07:00 +00:00
|
|
|
from allmydata.codec import ReplicatingEncoder, ReplicatingDecoder, CRSEncoder, CRSDecoder
|
2007-01-05 04:52:51 +00:00
|
|
|
import random
|
2007-02-01 23:07:00 +00:00
|
|
|
from allmydata.util import mathutil
|
2007-01-05 04:52:51 +00:00
|
|
|
|
|
|
|
class Tester:
|
2007-01-16 04:22:22 +00:00
|
|
|
def do_test(self, size, required_shares, max_shares, fewer_shares=None):
|
2007-02-01 23:07:00 +00:00
|
|
|
data0s = [os.urandom(mathutil.div_ceil(size, required_shares)) for i in range(required_shares)]
|
2007-01-05 04:52:51 +00:00
|
|
|
enc = self.enc_class()
|
2007-01-16 04:22:22 +00:00
|
|
|
enc.set_params(size, required_shares, max_shares)
|
2007-01-05 04:52:51 +00:00
|
|
|
serialized_params = enc.get_serialized_params()
|
2007-01-05 07:06:42 +00:00
|
|
|
log.msg("serialized_params: %s" % serialized_params)
|
2007-02-01 23:07:00 +00:00
|
|
|
d = enc.encode(data0s)
|
|
|
|
def _done_encoding_all((shares, shareids)):
|
2007-01-16 04:22:22 +00:00
|
|
|
self.failUnlessEqual(len(shares), max_shares)
|
2007-01-05 04:52:51 +00:00
|
|
|
self.shares = shares
|
2007-02-01 23:07:00 +00:00
|
|
|
self.shareids = shareids
|
2007-01-16 04:22:22 +00:00
|
|
|
d.addCallback(_done_encoding_all)
|
|
|
|
if fewer_shares is not None:
|
2007-02-01 23:07:00 +00:00
|
|
|
# also validate that the desired_shareids= parameter works
|
|
|
|
desired_shareids = random.sample(range(max_shares), fewer_shares)
|
|
|
|
d.addCallback(lambda res: enc.encode(data0s, desired_shareids))
|
|
|
|
def _check_fewer_shares((some_shares, their_shareids)):
|
|
|
|
self.failUnlessEqual(tuple(their_shareids), tuple(desired_shareids))
|
2007-01-16 04:22:22 +00:00
|
|
|
d.addCallback(_check_fewer_shares)
|
2007-01-05 04:52:51 +00:00
|
|
|
|
2007-02-01 23:07:00 +00:00
|
|
|
def _decode((shares, shareids)):
|
2007-01-05 04:52:51 +00:00
|
|
|
dec = self.dec_class()
|
|
|
|
dec.set_serialized_params(serialized_params)
|
2007-02-01 23:07:00 +00:00
|
|
|
d1 = dec.decode(shares, shareids)
|
2007-01-05 04:52:51 +00:00
|
|
|
return d1
|
|
|
|
|
2007-01-25 00:23:22 +00:00
|
|
|
def _check_data(decoded_shares):
|
2007-03-28 05:57:15 +00:00
|
|
|
self.failUnlessEqual(len(''.join(decoded_shares)), len(''.join(data0s)))
|
2007-02-01 23:07:00 +00:00
|
|
|
self.failUnlessEqual(len(decoded_shares), len(data0s))
|
2007-03-28 05:57:15 +00:00
|
|
|
for (i, (x, y)) in enumerate(zip(data0s, decoded_shares)):
|
|
|
|
self.failUnlessEqual(x, y, "%s: %r != %r.... first share was %r" % (str(i), x, y, data0s[0],))
|
|
|
|
self.failUnless(''.join(decoded_shares) == ''.join(data0s), "%s" % ("???",))
|
|
|
|
# 0data0sclipped = tuple(data0s)
|
|
|
|
# data0sclipped[-1] =
|
|
|
|
# self.failUnless(tuple(decoded_shares) == tuple(data0s))
|
2007-01-05 07:06:42 +00:00
|
|
|
|
2007-01-05 04:52:51 +00:00
|
|
|
def _decode_some(res):
|
2007-01-05 07:06:42 +00:00
|
|
|
log.msg("_decode_some")
|
2007-01-05 04:52:51 +00:00
|
|
|
# decode with a minimal subset of the shares
|
|
|
|
some_shares = self.shares[:required_shares]
|
2007-02-01 23:07:00 +00:00
|
|
|
some_shareids = self.shareids[:required_shares]
|
|
|
|
return _decode((some_shares, some_shareids))
|
2007-01-05 04:52:51 +00:00
|
|
|
d.addCallback(_decode_some)
|
|
|
|
d.addCallback(_check_data)
|
|
|
|
|
|
|
|
def _decode_some_random(res):
|
2007-01-05 07:06:42 +00:00
|
|
|
log.msg("_decode_some_random")
|
2007-01-05 04:52:51 +00:00
|
|
|
# use a randomly-selected minimal subset
|
2007-02-01 23:07:00 +00:00
|
|
|
l = random.sample(zip(self.shares, self.shareids), required_shares)
|
|
|
|
some_shares = [ x[0] for x in l ]
|
|
|
|
some_shareids = [ x[1] for x in l ]
|
|
|
|
return _decode((some_shares, some_shareids))
|
2007-01-05 04:52:51 +00:00
|
|
|
d.addCallback(_decode_some_random)
|
|
|
|
d.addCallback(_check_data)
|
|
|
|
|
|
|
|
def _decode_multiple(res):
|
2007-01-05 07:06:42 +00:00
|
|
|
log.msg("_decode_multiple")
|
2007-01-05 04:52:51 +00:00
|
|
|
# make sure we can re-use the decoder object
|
|
|
|
shares1 = random.sample(self.shares, required_shares)
|
2007-02-01 23:07:00 +00:00
|
|
|
sharesl1 = random.sample(zip(self.shares, self.shareids), required_shares)
|
|
|
|
shares1 = [ x[0] for x in sharesl1 ]
|
|
|
|
shareids1 = [ x[1] for x in sharesl1 ]
|
|
|
|
sharesl2 = random.sample(zip(self.shares, self.shareids), required_shares)
|
|
|
|
shares2 = [ x[0] for x in sharesl2 ]
|
|
|
|
shareids2 = [ x[1] for x in sharesl2 ]
|
2007-01-05 04:52:51 +00:00
|
|
|
dec = self.dec_class()
|
|
|
|
dec.set_serialized_params(serialized_params)
|
2007-02-01 23:07:00 +00:00
|
|
|
d1 = dec.decode(shares1, shareids1)
|
2007-01-05 04:52:51 +00:00
|
|
|
d1.addCallback(_check_data)
|
2007-02-01 23:07:00 +00:00
|
|
|
d1.addCallback(lambda res: dec.decode(shares2, shareids2))
|
2007-01-05 04:52:51 +00:00
|
|
|
d1.addCallback(_check_data)
|
|
|
|
return d1
|
|
|
|
d.addCallback(_decode_multiple)
|
|
|
|
|
|
|
|
return d
|
|
|
|
|
|
|
|
def test_encode(self):
|
|
|
|
return self.do_test(1000, 25, 100)
|
|
|
|
|
2007-01-05 06:50:21 +00:00
|
|
|
def test_encode1(self):
|
|
|
|
return self.do_test(8, 8, 16)
|
|
|
|
|
2007-01-05 07:06:42 +00:00
|
|
|
def test_encode2(self):
|
2007-03-28 05:57:15 +00:00
|
|
|
return self.do_test(125, 25, 100, 90)
|
2007-01-05 04:52:51 +00:00
|
|
|
|
|
|
|
class Replicating(unittest.TestCase, Tester):
|
|
|
|
enc_class = ReplicatingEncoder
|
|
|
|
dec_class = ReplicatingDecoder
|
2007-01-06 01:46:03 +00:00
|
|
|
|
2007-02-01 23:07:00 +00:00
|
|
|
class CRS(unittest.TestCase, Tester):
|
|
|
|
enc_class = CRSEncoder
|
|
|
|
dec_class = CRSDecoder
|
2007-01-06 01:46:03 +00:00
|
|
|
|