2008-01-10 03:25:50 +00:00
|
|
|
|
2008-01-17 08:18:10 +00:00
|
|
|
import os
|
2008-01-10 03:25:50 +00:00
|
|
|
from twisted.trial import unittest
|
|
|
|
from twisted.application import service
|
|
|
|
|
|
|
|
from foolscap import Tub, eventual
|
|
|
|
from foolscap.logging import log
|
|
|
|
|
|
|
|
from allmydata import upload, offloaded
|
2008-01-28 19:58:13 +00:00
|
|
|
from allmydata.util import hashutil, fileutil, idlib
|
|
|
|
from pycryptopp.cipher.aes import AES
|
2008-01-10 03:25:50 +00:00
|
|
|
|
2008-01-16 10:03:35 +00:00
|
|
|
MiB = 1024*1024
|
|
|
|
|
2008-01-11 11:53:37 +00:00
|
|
|
class CHKUploadHelper_fake(offloaded.CHKUploadHelper):
|
|
|
|
def start_encrypted(self, eu):
|
|
|
|
d = eu.get_size()
|
|
|
|
def _got_size(size):
|
2008-01-16 10:03:35 +00:00
|
|
|
d2 = eu.get_all_encoding_parameters()
|
|
|
|
def _got_parms(parms):
|
|
|
|
needed_shares, happy, total_shares, segsize = parms
|
|
|
|
return (hashutil.uri_extension_hash(""),
|
|
|
|
needed_shares, total_shares, size)
|
|
|
|
d2.addCallback(_got_parms)
|
|
|
|
return d2
|
2008-01-11 11:53:37 +00:00
|
|
|
d.addCallback(_got_size)
|
|
|
|
return d
|
2008-01-10 03:25:50 +00:00
|
|
|
|
2008-01-11 11:53:37 +00:00
|
|
|
class CHKUploadHelper_already_uploaded(offloaded.CHKUploadHelper):
|
|
|
|
def start(self):
|
|
|
|
res = {'uri_extension_hash': hashutil.uri_extension_hash("")}
|
|
|
|
return (res, None)
|
2008-01-10 03:25:50 +00:00
|
|
|
|
|
|
|
class FakeClient(service.MultiService):
|
2008-01-16 10:03:35 +00:00
|
|
|
DEFAULT_ENCODING_PARAMETERS = {"k":25,
|
|
|
|
"happy": 75,
|
|
|
|
"n": 100,
|
|
|
|
"max_segment_size": 1*MiB,
|
|
|
|
}
|
2008-01-15 04:16:58 +00:00
|
|
|
def log(self, *args, **kwargs):
|
|
|
|
return log.msg(*args, **kwargs)
|
2008-01-10 03:25:50 +00:00
|
|
|
def get_push_to_ourselves(self):
|
|
|
|
return True
|
|
|
|
def get_encoding_parameters(self):
|
2008-01-16 10:03:35 +00:00
|
|
|
return self.DEFAULT_ENCODING_PARAMETERS
|
2008-01-10 03:25:50 +00:00
|
|
|
|
|
|
|
def flush_but_dont_ignore(res):
|
|
|
|
d = eventual.flushEventualQueue()
|
|
|
|
def _done(ignored):
|
|
|
|
return res
|
|
|
|
d.addCallback(_done)
|
|
|
|
return d
|
|
|
|
|
|
|
|
class AssistedUpload(unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
|
|
self.s = FakeClient()
|
|
|
|
self.s.startService()
|
|
|
|
|
|
|
|
self.tub = t = Tub()
|
|
|
|
t.setServiceParent(self.s)
|
|
|
|
self.s.tub = t
|
|
|
|
# we never actually use this for network traffic, so it can use a
|
|
|
|
# bogus host/port
|
|
|
|
t.setLocation("bogus:1234")
|
|
|
|
|
2008-01-17 08:18:10 +00:00
|
|
|
def setUpHelper(self, basedir):
|
|
|
|
fileutil.make_dirs(basedir)
|
|
|
|
self.helper = h = offloaded.Helper(basedir)
|
2008-01-11 11:53:37 +00:00
|
|
|
h.chk_upload_helper_class = CHKUploadHelper_fake
|
2008-01-10 03:25:50 +00:00
|
|
|
h.setServiceParent(self.s)
|
2008-01-17 08:18:10 +00:00
|
|
|
self.helper_furl = self.tub.registerReference(h)
|
2008-01-10 03:25:50 +00:00
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
d = self.s.stopService()
|
|
|
|
d.addCallback(eventual.fireEventually)
|
|
|
|
d.addBoth(flush_but_dont_ignore)
|
|
|
|
return d
|
|
|
|
|
|
|
|
|
|
|
|
def test_one(self):
|
2008-01-17 08:18:10 +00:00
|
|
|
self.basedir = "helper/AssistedUpload/test_one"
|
|
|
|
self.setUpHelper(self.basedir)
|
2008-01-10 03:25:50 +00:00
|
|
|
u = upload.Uploader(self.helper_furl)
|
|
|
|
u.setServiceParent(self.s)
|
|
|
|
|
|
|
|
# wait a few turns
|
|
|
|
d = eventual.fireEventually()
|
|
|
|
d.addCallback(eventual.fireEventually)
|
|
|
|
d.addCallback(eventual.fireEventually)
|
|
|
|
|
|
|
|
def _ready(res):
|
|
|
|
assert u._helper
|
|
|
|
|
|
|
|
DATA = "I need help\n" * 1000
|
|
|
|
return u.upload_data(DATA)
|
|
|
|
d.addCallback(_ready)
|
|
|
|
def _uploaded(uri):
|
|
|
|
assert "CHK" in uri
|
|
|
|
d.addCallback(_uploaded)
|
|
|
|
|
2008-01-17 08:18:10 +00:00
|
|
|
def _check_empty(res):
|
|
|
|
files = os.listdir(os.path.join(self.basedir, "CHK_encoding"))
|
|
|
|
self.failUnlessEqual(files, [])
|
|
|
|
files = os.listdir(os.path.join(self.basedir, "CHK_incoming"))
|
|
|
|
self.failUnlessEqual(files, [])
|
|
|
|
d.addCallback(_check_empty)
|
|
|
|
|
2008-01-10 03:25:50 +00:00
|
|
|
return d
|
|
|
|
|
2008-01-28 19:58:13 +00:00
|
|
|
def test_previous_upload_failed(self):
|
|
|
|
self.basedir = "helper/AssistedUpload/test_previous_upload_failed"
|
|
|
|
self.setUpHelper(self.basedir)
|
|
|
|
DATA = "I need help\n" * 1000
|
|
|
|
|
|
|
|
# we want to make sure that an upload which fails (leaving the
|
|
|
|
# ciphertext in the CHK_encoding/ directory) does not prevent a later
|
|
|
|
# attempt to upload that file from working. We simulate this by
|
|
|
|
# populating the directory manually.
|
|
|
|
key = hashutil.key_hash(DATA)[:16]
|
|
|
|
encryptor = AES(key)
|
|
|
|
SI = hashutil.storage_index_chk_hash(key)
|
|
|
|
SI_s = idlib.b2a(SI)
|
|
|
|
encfile = os.path.join(self.basedir, "CHK_encoding", SI_s)
|
|
|
|
f = open(encfile, "wb")
|
|
|
|
f.write(encryptor.process(DATA))
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
u = upload.Uploader(self.helper_furl)
|
|
|
|
u.setServiceParent(self.s)
|
|
|
|
|
|
|
|
# wait a few turns
|
|
|
|
d = eventual.fireEventually()
|
|
|
|
d.addCallback(eventual.fireEventually)
|
|
|
|
d.addCallback(eventual.fireEventually)
|
|
|
|
|
|
|
|
def _ready(res):
|
|
|
|
assert u._helper
|
|
|
|
return u.upload_data(DATA)
|
|
|
|
d.addCallback(_ready)
|
|
|
|
def _uploaded(uri):
|
|
|
|
assert "CHK" in uri
|
|
|
|
d.addCallback(_uploaded)
|
|
|
|
|
|
|
|
def _check_empty(res):
|
|
|
|
files = os.listdir(os.path.join(self.basedir, "CHK_encoding"))
|
|
|
|
self.failUnlessEqual(files, [])
|
|
|
|
files = os.listdir(os.path.join(self.basedir, "CHK_incoming"))
|
|
|
|
self.failUnlessEqual(files, [])
|
|
|
|
d.addCallback(_check_empty)
|
|
|
|
|
|
|
|
return d
|
2008-01-11 11:53:37 +00:00
|
|
|
|
|
|
|
def test_already_uploaded(self):
|
2008-01-17 08:18:10 +00:00
|
|
|
self.basedir = "helper/AssistedUpload/test_already_uploaded"
|
|
|
|
self.setUpHelper(self.basedir)
|
2008-01-11 11:53:37 +00:00
|
|
|
self.helper.chk_upload_helper_class = CHKUploadHelper_already_uploaded
|
|
|
|
u = upload.Uploader(self.helper_furl)
|
|
|
|
u.setServiceParent(self.s)
|
|
|
|
|
|
|
|
# wait a few turns
|
|
|
|
d = eventual.fireEventually()
|
|
|
|
d.addCallback(eventual.fireEventually)
|
|
|
|
d.addCallback(eventual.fireEventually)
|
|
|
|
|
|
|
|
def _ready(res):
|
|
|
|
assert u._helper
|
|
|
|
|
|
|
|
DATA = "I need help\n" * 1000
|
|
|
|
return u.upload_data(DATA)
|
|
|
|
d.addCallback(_ready)
|
|
|
|
def _uploaded(uri):
|
|
|
|
assert "CHK" in uri
|
|
|
|
d.addCallback(_uploaded)
|
|
|
|
|
2008-01-17 08:18:10 +00:00
|
|
|
def _check_empty(res):
|
|
|
|
files = os.listdir(os.path.join(self.basedir, "CHK_encoding"))
|
|
|
|
self.failUnlessEqual(files, [])
|
|
|
|
files = os.listdir(os.path.join(self.basedir, "CHK_incoming"))
|
|
|
|
self.failUnlessEqual(files, [])
|
|
|
|
d.addCallback(_check_empty)
|
|
|
|
|
2008-01-11 11:53:37 +00:00
|
|
|
return d
|