2006-12-01 09:54:28 +00:00
|
|
|
|
|
|
|
from twisted.trial import unittest
|
|
|
|
from twisted.internet import defer
|
2006-12-02 02:17:26 +00:00
|
|
|
from cStringIO import StringIO
|
2006-12-01 09:54:28 +00:00
|
|
|
|
2007-01-16 04:22:22 +00:00
|
|
|
from allmydata import upload, download
|
2007-01-17 04:29:59 +00:00
|
|
|
from allmydata.uri import unpack_uri
|
2006-12-01 09:54:28 +00:00
|
|
|
|
2006-12-02 02:17:26 +00:00
|
|
|
class StringBucketProxy:
|
|
|
|
# This is for unit tests: make a StringIO look like a RIBucketWriter.
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self.data = StringIO()
|
|
|
|
self.size = None
|
|
|
|
self.done = False
|
|
|
|
|
|
|
|
def callRemote(self, methname, **kwargs):
|
|
|
|
if methname == "write":
|
|
|
|
return defer.maybeDeferred(self.write, **kwargs)
|
|
|
|
elif methname == "close":
|
|
|
|
return defer.maybeDeferred(self.close, **kwargs)
|
|
|
|
else:
|
|
|
|
return defer.fail(NameError("no such method named %s" % methname))
|
|
|
|
|
|
|
|
def write(self, data):
|
|
|
|
self.data.write(data)
|
|
|
|
def close(self):
|
|
|
|
self.done = True
|
|
|
|
|
|
|
|
|
2006-12-01 09:54:28 +00:00
|
|
|
class FakePeer:
|
|
|
|
def __init__(self, peerid, response):
|
|
|
|
self.peerid = peerid
|
|
|
|
self.response = response
|
|
|
|
|
|
|
|
def callRemote(self, methname, *args, **kwargs):
|
|
|
|
assert not args
|
|
|
|
return defer.maybeDeferred(self._callRemote, methname, **kwargs)
|
|
|
|
|
|
|
|
def _callRemote(self, methname, **kwargs):
|
|
|
|
assert methname == "allocate_bucket"
|
|
|
|
assert kwargs["size"] == 100
|
|
|
|
assert kwargs["leaser"] == "fakeclient"
|
|
|
|
if self.response == "good":
|
|
|
|
return self
|
|
|
|
raise upload.TooFullError()
|
|
|
|
|
|
|
|
class FakeClient:
|
|
|
|
nodeid = "fakeclient"
|
|
|
|
def __init__(self, responses):
|
|
|
|
self.peers = []
|
|
|
|
for peerid,r in enumerate(responses):
|
|
|
|
if r == "disconnected":
|
|
|
|
self.peers.append(None)
|
|
|
|
else:
|
2006-12-03 03:31:02 +00:00
|
|
|
self.peers.append(FakePeer(str(peerid), r))
|
2006-12-01 09:54:28 +00:00
|
|
|
|
|
|
|
def permute_peerids(self, key, max_peers):
|
|
|
|
assert max_peers == None
|
2006-12-03 03:31:02 +00:00
|
|
|
return [str(i) for i in range(len(self.peers))]
|
|
|
|
|
2006-12-01 09:54:28 +00:00
|
|
|
def get_remote_service(self, peerid, name):
|
2006-12-03 03:31:02 +00:00
|
|
|
peer = self.peers[int(peerid)]
|
2006-12-01 09:54:28 +00:00
|
|
|
if not peer:
|
|
|
|
return defer.fail(IndexError("no connection to that peer"))
|
|
|
|
return defer.succeed(peer)
|
|
|
|
|
2007-01-16 04:22:22 +00:00
|
|
|
|
2006-12-03 01:27:18 +00:00
|
|
|
class NextPeerUploader(upload.FileUploader):
|
2007-01-16 04:22:22 +00:00
|
|
|
_size = 100
|
|
|
|
def _got_enough_peers(self, res):
|
2006-12-01 09:54:28 +00:00
|
|
|
return res
|
|
|
|
|
|
|
|
class NextPeer(unittest.TestCase):
|
|
|
|
responses = ["good", # 0
|
|
|
|
"full", # 1
|
|
|
|
"full", # 2
|
|
|
|
"disconnected", # 3
|
|
|
|
"good", # 4
|
|
|
|
]
|
|
|
|
|
2006-12-01 11:06:11 +00:00
|
|
|
def compare_landlords(self, u, c, expected):
|
2006-12-03 03:31:02 +00:00
|
|
|
exp = [(str(peerid), bucketnum, c.peers[peerid])
|
2006-12-01 11:06:11 +00:00
|
|
|
for peerid, bucketnum in expected]
|
2006-12-02 02:17:26 +00:00
|
|
|
self.failUnlessEqual(u.landlords, exp)
|
2006-12-01 11:06:11 +00:00
|
|
|
|
2007-01-16 04:22:22 +00:00
|
|
|
VERIFIERID = "\x00" * 20
|
2006-12-01 09:54:28 +00:00
|
|
|
def test_0(self):
|
|
|
|
c = FakeClient([])
|
|
|
|
u = NextPeerUploader(c)
|
2007-01-16 04:22:22 +00:00
|
|
|
u.set_verifierid(self.VERIFIERID)
|
|
|
|
u.set_params(2, 2, 2)
|
2006-12-01 09:54:28 +00:00
|
|
|
d = u.start()
|
|
|
|
def _check(f):
|
|
|
|
f.trap(upload.NotEnoughPeersError)
|
|
|
|
d.addCallbacks(lambda res: self.fail("this was supposed to fail"),
|
|
|
|
_check)
|
|
|
|
return d
|
|
|
|
|
|
|
|
def test_1(self):
|
|
|
|
c = FakeClient(self.responses)
|
|
|
|
u = NextPeerUploader(c)
|
2007-01-16 04:22:22 +00:00
|
|
|
u.set_verifierid(self.VERIFIERID)
|
|
|
|
u.set_params(2, 2, 2)
|
2006-12-01 09:54:28 +00:00
|
|
|
d = u.start()
|
|
|
|
def _check(res):
|
|
|
|
self.failUnlessEqual(u.goodness_points, 2)
|
2006-12-01 11:06:11 +00:00
|
|
|
self.compare_landlords(u, c, [(0, 0),
|
|
|
|
(4, 1),
|
|
|
|
])
|
2006-12-01 09:54:28 +00:00
|
|
|
d.addCallback(_check)
|
|
|
|
return d
|
|
|
|
|
|
|
|
def test_2(self):
|
|
|
|
c = FakeClient(self.responses)
|
|
|
|
u = NextPeerUploader(c)
|
2007-01-16 04:22:22 +00:00
|
|
|
u.set_verifierid(self.VERIFIERID)
|
|
|
|
u.set_params(3, 3, 3)
|
2006-12-01 09:54:28 +00:00
|
|
|
d = u.start()
|
|
|
|
def _check(res):
|
|
|
|
self.failUnlessEqual(u.goodness_points, 3)
|
2006-12-01 11:06:11 +00:00
|
|
|
self.compare_landlords(u, c, [(0, 0),
|
|
|
|
(4, 1),
|
|
|
|
(0, 2),
|
|
|
|
])
|
2006-12-01 09:54:28 +00:00
|
|
|
d.addCallback(_check)
|
|
|
|
return d
|
|
|
|
|
|
|
|
responses2 = ["good", # 0
|
|
|
|
"full", # 1
|
|
|
|
"full", # 2
|
|
|
|
"good", # 3
|
|
|
|
"full", # 4
|
|
|
|
]
|
|
|
|
|
|
|
|
def test_3(self):
|
|
|
|
c = FakeClient(self.responses2)
|
|
|
|
u = NextPeerUploader(c)
|
2007-01-16 04:22:22 +00:00
|
|
|
u.set_verifierid(self.VERIFIERID)
|
|
|
|
u.set_params(3, 3, 3)
|
2006-12-01 09:54:28 +00:00
|
|
|
d = u.start()
|
|
|
|
def _check(res):
|
|
|
|
self.failUnlessEqual(u.goodness_points, 3)
|
2006-12-01 11:06:11 +00:00
|
|
|
self.compare_landlords(u, c, [(0, 0),
|
|
|
|
(3, 1),
|
|
|
|
(0, 2),
|
|
|
|
])
|
2006-12-01 09:54:28 +00:00
|
|
|
d.addCallback(_check)
|
|
|
|
return d
|
2006-12-04 07:46:21 +00:00
|
|
|
|
|
|
|
responses3 = ["good", # 0
|
|
|
|
"good", # 1
|
|
|
|
"good", # 2
|
|
|
|
"good", # 3
|
|
|
|
"good", # 4
|
|
|
|
]
|
|
|
|
|
|
|
|
def test_4(self):
|
|
|
|
c = FakeClient(self.responses3)
|
|
|
|
u = NextPeerUploader(c)
|
2007-01-16 04:22:22 +00:00
|
|
|
u.set_verifierid(self.VERIFIERID)
|
|
|
|
u.set_params(4, 4, 4)
|
2006-12-04 07:46:21 +00:00
|
|
|
d = u.start()
|
|
|
|
def _check(res):
|
|
|
|
self.failUnlessEqual(u.goodness_points, 4)
|
|
|
|
self.compare_landlords(u, c, [(0, 0),
|
|
|
|
(1, 1),
|
|
|
|
(2, 2),
|
|
|
|
(3, 3),
|
|
|
|
])
|
|
|
|
d.addCallback(_check)
|
|
|
|
return d
|
2007-01-16 04:22:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
class FakePeer2:
|
|
|
|
def __init__(self, peerid):
|
|
|
|
self.peerid = peerid
|
|
|
|
self.data = ""
|
|
|
|
|
|
|
|
def callRemote(self, methname, *args, **kwargs):
|
|
|
|
if methname == "allocate_bucket":
|
|
|
|
return defer.maybeDeferred(self._allocate_bucket, *args, **kwargs)
|
|
|
|
if methname == "write":
|
|
|
|
return defer.maybeDeferred(self._write, *args, **kwargs)
|
|
|
|
if methname == "set_metadata":
|
|
|
|
return defer.maybeDeferred(self._set_metadata, *args, **kwargs)
|
|
|
|
if methname == "close":
|
|
|
|
return defer.maybeDeferred(self._close, *args, **kwargs)
|
|
|
|
return defer.maybeDeferred(self._bad_name, methname)
|
|
|
|
|
|
|
|
def _allocate_bucket(self, verifierid, bucket_num, size, leaser, canary):
|
|
|
|
self.allocated_size = size
|
|
|
|
return self
|
|
|
|
def _write(self, data):
|
|
|
|
self.data = self.data + data
|
|
|
|
def _set_metadata(self, metadata):
|
|
|
|
self.metadata = metadata
|
|
|
|
def _close(self):
|
|
|
|
pass
|
|
|
|
def _bad_name(self, methname):
|
|
|
|
raise NameError("FakePeer2 has no such method named '%s'" % methname)
|
|
|
|
|
|
|
|
class FakeClient2:
|
|
|
|
nodeid = "fakeclient"
|
|
|
|
def __init__(self, max_peers):
|
|
|
|
self.peers = []
|
|
|
|
for peerid in range(max_peers):
|
|
|
|
self.peers.append(FakePeer2(str(peerid)))
|
|
|
|
|
|
|
|
def permute_peerids(self, key, max_peers):
|
|
|
|
assert max_peers == None
|
|
|
|
return [str(i) for i in range(len(self.peers))]
|
|
|
|
|
|
|
|
def get_remote_service(self, peerid, name):
|
|
|
|
peer = self.peers[int(peerid)]
|
|
|
|
if not peer:
|
|
|
|
return defer.fail(IndexError("no connection to that peer"))
|
|
|
|
return defer.succeed(peer)
|
|
|
|
|
|
|
|
class Uploader(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
|
|
node = self.node = FakeClient2(10)
|
|
|
|
u = self.u = upload.Uploader()
|
|
|
|
u.running = 1
|
|
|
|
u.parent = node
|
|
|
|
|
|
|
|
def _check(self, uri):
|
|
|
|
self.failUnless(isinstance(uri, str))
|
|
|
|
self.failUnless(uri.startswith("URI:"))
|
2007-01-17 04:29:59 +00:00
|
|
|
codec_name, codec_params, verifierid = unpack_uri(uri)
|
2007-01-16 04:22:22 +00:00
|
|
|
self.failUnless(isinstance(verifierid, str))
|
|
|
|
self.failUnlessEqual(len(verifierid), 20)
|
2007-01-17 04:29:59 +00:00
|
|
|
self.failUnless(isinstance(codec_params, str))
|
2007-01-16 04:22:22 +00:00
|
|
|
peers = self.node.peers
|
|
|
|
self.failUnlessEqual(peers[0].allocated_size,
|
|
|
|
len(peers[0].data))
|
|
|
|
def testData(self):
|
|
|
|
data = "This is some data to upload"
|
|
|
|
d = self.u.upload_data(data)
|
|
|
|
d.addCallback(self._check)
|
|
|
|
return d
|
|
|
|
|
|
|
|
def testFileHandle(self):
|
|
|
|
data = "This is some data to upload"
|
|
|
|
d = self.u.upload_filehandle(StringIO(data))
|
|
|
|
d.addCallback(self._check)
|
|
|
|
return d
|
|
|
|
|
|
|
|
def testFilename(self):
|
|
|
|
fn = "Uploader-testFilename.data"
|
|
|
|
f = open(fn, "w")
|
|
|
|
data = "This is some data to upload"
|
|
|
|
f.write(data)
|
|
|
|
f.close()
|
|
|
|
d = self.u.upload_filename(fn)
|
|
|
|
d.addCallback(self._check)
|
|
|
|
return d
|