from twisted.python import failure
from twisted.application import service
from allmydata import uri, dirnode
-from allmydata.interfaces import IURI, IMutableFileNode, IFileNode
+from allmydata.interfaces import IURI, IMutableFileNode, IFileNode, \
+ FileTooLargeError
from allmydata.encode import NotEnoughSharesError
from allmydata.util import log
class-level dictionary."""
implements(IMutableFileNode)
+ MUTABLE_SIZELIMIT = 10000
all_contents = {}
+
def __init__(self, client):
self.client = client
self.my_uri = make_mutable_file_uri()
self.storage_index = self.my_uri.storage_index
def create(self, initial_contents, key_generator=None):
+ if len(initial_contents) > self.MUTABLE_SIZELIMIT:
+ raise FileTooLargeError("SDMF is limited to one segment, and "
+ "%d > %d" % (len(initial_contents),
+ self.MUTABLE_SIZELIMIT))
self.all_contents[self.storage_index] = initial_contents
return defer.succeed(self)
def init_from_uri(self, myuri):
def download_best_version(self):
return defer.succeed(self.all_contents[self.storage_index])
def overwrite(self, new_contents):
+ if len(new_contents) > self.MUTABLE_SIZELIMIT:
+ raise FileTooLargeError("SDMF is limited to one segment, and "
+ "%d > %d" % (len(new_contents),
+ self.MUTABLE_SIZELIMIT))
assert not self.is_readonly()
self.all_contents[self.storage_index] = new_contents
return defer.succeed(None)
def modify(self, modifier):
+ # this does not implement FileTooLargeError, but the real one does
return defer.maybeDeferred(self._modify, modifier)
def _modify(self, modifier):
assert not self.is_readonly()
d.addCallback(lambda res: n)
return d
+ MUTABLE_SIZELIMIT = FakeMutableFileNode.MUTABLE_SIZELIMIT
def create_mutable_file(self, contents=""):
n = FakeMutableFileNode(self)
return n.create(contents)
res.trap(expected_failure)
if substring:
self.failUnless(substring in str(res),
- "substring '%s' not in '%s'"
- % (substring, str(res)))
+ "%s: substring '%s' not in '%s'"
+ % (which, substring, str(res)))
if response_substring:
self.failUnless(response_substring in res.value.response,
- "response substring '%s' not in '%s'"
- % (response_substring, res.value.response))
+ "%s: response substring '%s' not in '%s'"
+ % (which,
+ response_substring, res.value.response))
else:
self.fail("%s was supposed to raise %s, not get '%s'" %
(which, expected_failure, res))
self.NEWFILE_CONTENTS))
return d
+ def test_PUT_NEWFILEURL_mutable_toobig(self):
+ d = self.shouldFail2(error.Error, "test_PUT_NEWFILEURL_mutable_toobig",
+ "413 Request Entity Too Large",
+ "SDMF is limited to one segment, and 10001 > 10000",
+ self.PUT,
+ self.public_url + "/foo/new.txt?mutable=true",
+ "b" * (self.s.MUTABLE_SIZELIMIT+1))
+ return d
+
def test_PUT_NEWFILEURL_replace(self):
d = self.PUT(self.public_url + "/foo/bar.txt", self.NEWFILE_CONTENTS)
# TODO: we lose the response code, so we can't check this
d.addCallback(_check4)
return d
+ def test_POST_upload_no_link_mutable_toobig(self):
+ d = self.shouldFail2(error.Error,
+ "test_POST_upload_no_link_mutable_toobig",
+ "413 Request Entity Too Large",
+ "SDMF is limited to one segment, and 10001 > 10000",
+ self.POST,
+ "/uri", t="upload", mutable="true",
+ file=("new.txt",
+ "b" * (self.s.MUTABLE_SIZELIMIT+1)) )
+ return d
+
def test_POST_upload_mutable(self):
# this creates a mutable file
d = self.POST(self.public_url + "/foo", t="upload", mutable="true",
self.failUnlessEqual(headers["content-type"], ["text/plain"])
d.addCallback(_got_headers)
+ # make sure that size errors are displayed correctly for overwrite
+ d.addCallback(lambda res:
+ self.shouldFail2(error.Error,
+ "test_POST_upload_mutable-toobig",
+ "413 Request Entity Too Large",
+ "SDMF is limited to one segment, and 10001 > 10000",
+ self.POST,
+ self.public_url + "/foo", t="upload",
+ mutable="true",
+ file=("new.txt",
+ "b" * (self.s.MUTABLE_SIZELIMIT+1)),
+ ))
+
d.addErrback(self.dump_error)
return d
+ def test_POST_upload_mutable_toobig(self):
+ d = self.shouldFail2(error.Error,
+ "test_POST_upload_no_link_mutable_toobig",
+ "413 Request Entity Too Large",
+ "SDMF is limited to one segment, and 10001 > 10000",
+ self.POST,
+ self.public_url + "/foo",
+ t="upload", mutable="true",
+ file=("new.txt",
+ "b" * (self.s.MUTABLE_SIZELIMIT+1)) )
+ return d
+
def dump_error(self, f):
# if the web server returns an error code (like 400 Bad Request),
# web.client.getPage puts the HTTP response body into the .response