From 5a3d6cd05e8f12aba2527b2d711cd0aa7a27f3e8 Mon Sep 17 00:00:00 2001 From: drebs Date: Tue, 19 Dec 2017 18:00:23 -0200 Subject: [feature] add ranges to blobs backend --- tests/blobs/test_fs_backend.py | 25 ++++++++++++----- tests/server/test_blobs_server.py | 52 ++++++++++++++++++++++++++++++++++++ tests/server/test_incoming_server.py | 6 ++--- 3 files changed, 73 insertions(+), 10 deletions(-) (limited to 'tests') diff --git a/tests/blobs/test_fs_backend.py b/tests/blobs/test_fs_backend.py index 5c086a51..2485ccd1 100644 --- a/tests/blobs/test_fs_backend.py +++ b/tests/blobs/test_fs_backend.py @@ -20,6 +20,7 @@ Tests for blobs backend on server side. from twisted.trial import unittest from twisted.internet import defer from twisted.web.client import FileBodyProducer +from twisted.web.test.requesthelper import DummyRequest from leap.common.files import mkdir_p from leap.soledad.server import _blobs from mock import Mock @@ -61,18 +62,18 @@ class FilesystemBackendTestCase(unittest.TestCase): self.assertEquals(10, size) @pytest.mark.usefixtures("method_tmpdir") - @mock.patch('leap.soledad.server._blobs.fs_backend.open') @mock.patch('leap.soledad.server._blobs.fs_backend' '.FilesystemBlobsBackend._get_path') @defer.inlineCallbacks - def test_read_blob(self, get_path, open): - get_path.return_value = 'path' - open.return_value = io.BytesIO('content') + def test_read_blob(self, get_path): + path = os.path.join(self.tempdir, 'blob') + with open(path, 'w') as f: + f.write('bl0b') + get_path.return_value = path backend = _blobs.FilesystemBlobsBackend(blobs_path=self.tempdir) - consumer = Mock() + consumer = DummyRequest(['']) yield backend.read_blob('user', 'blob_id', consumer) - consumer.write.assert_called_with('content') - get_path.assert_called_once_with('user', 'blob_id', '') + self.assertEqual(['bl0b'], consumer.written) @pytest.mark.usefixtures("method_tmpdir") @mock.patch.object(os.path, 'isfile') @@ -246,3 +247,13 @@ class FilesystemBackendTestCase(unittest.TestCase): count = yield backend.count('user', namespace='xfiles') self.assertEqual(2, count) + + @pytest.mark.usefixtures("method_tmpdir") + @defer.inlineCallbacks + def test_read_range(self): + backend = _blobs.FilesystemBlobsBackend(blobs_path=self.tempdir) + producer = FileBodyProducer(io.BytesIO("0123456789")) + yield backend.write_blob('user', 'blob-id', producer) + consumer = DummyRequest(['']) + yield backend.read_blob('user', 'blob-id', consumer, range=(1, 3)) + self.assertEqual(['12'], consumer.written) diff --git a/tests/server/test_blobs_server.py b/tests/server/test_blobs_server.py index bf929386..6fed6d65 100644 --- a/tests/server/test_blobs_server.py +++ b/tests/server/test_blobs_server.py @@ -19,6 +19,8 @@ Integration tests for blobs server """ import os import pytest +import re +import treq from urlparse import urljoin from uuid import uuid4 from io import BytesIO @@ -49,6 +51,11 @@ def sleep(x): return d +def _get(*args, **kwargs): + kwargs.update({'persistent': False}) + return treq.get(*args, **kwargs) + + class BlobServerTestCase(unittest.TestCase): def setUp(self): @@ -455,3 +462,48 @@ class BlobServerTestCase(unittest.TestCase): self.addCleanup(manager.close) with pytest.raises(SoledadError): yield manager.delete('missing_id') + + @defer.inlineCallbacks + @pytest.mark.usefixtures("method_tmpdir") + def test_get_range(self): + user_id = uuid4().hex + manager = BlobManager(self.tempdir, self.uri, self.secret, + self.secret, user_id) + self.addCleanup(manager.close) + blob_id, content = 'blob_id', '0123456789' + doc = BlobDoc(BytesIO(content), blob_id) + yield manager.put(doc, len(content)) + uri = urljoin(self.uri, '%s/%s' % (user_id, blob_id)) + res = yield _get(uri, headers={'Range': 'bytes=10-20'}) + text = yield res.text() + self.assertTrue(res.headers.hasHeader('content-range')) + content_range = res.headers.getRawHeaders('content-range').pop() + self.assertIsNotNone(re.match('^bytes 10-20/[0-9]+$', content_range)) + self.assertEqual(10, len(text)) + + @defer.inlineCallbacks + @pytest.mark.usefixtures("method_tmpdir") + def test_get_range_not_satisfiable(self): + # put a blob in place + user_id = uuid4().hex + manager = BlobManager(self.tempdir, self.uri, self.secret, + self.secret, user_id) + self.addCleanup(manager.close) + blob_id, content = uuid4().hex, 'content' + doc = BlobDoc(BytesIO(content), blob_id) + yield manager.put(doc, len(content)) + # and check possible parsing errors + uri = urljoin(self.uri, '%s/%s' % (user_id, blob_id)) + ranges = [ + 'bytes', + 'bytes=', + 'bytes=1', + 'bytes=blah-100', + 'potatoes=10-100' + 'blah' + ] + for range in ranges: + res = yield _get(uri, headers={'Range': range}) + self.assertEqual(416, res.code) + content_range = res.headers.getRawHeaders('content-range').pop() + self.assertIsNotNone(re.match('^bytes \*/[0-9]+$', content_range)) diff --git a/tests/server/test_incoming_server.py b/tests/server/test_incoming_server.py index 23c0aa90..16d5d5e6 100644 --- a/tests/server/test_incoming_server.py +++ b/tests/server/test_incoming_server.py @@ -18,13 +18,13 @@ Integration tests for incoming API """ import pytest -import mock import treq from io import BytesIO from uuid import uuid4 from twisted.web.server import Site from twisted.internet import reactor from twisted.internet import defer +from twisted.web.test.requesthelper import DummyRequest from leap.soledad.server._incoming import IncomingResource from leap.soledad.server._blobs import BlobsServerState @@ -83,10 +83,10 @@ class IncomingOnCouchServerTestCase(CouchDBTestCase): yield treq.put(incoming_endpoint, BytesIO(content), persistent=False) db = self.state.open_database(user_id) - consumer = mock.Mock() + consumer = DummyRequest(['']) yield db.read_blob(user_id, doc_id, consumer, namespace='MX') flags = yield db.get_flags(user_id, doc_id, namespace='MX') - data = consumer.write.call_args[0][0] + data = consumer.written.pop() expected_preamble = formatter.preamble(content, doc_id) expected_preamble = decode_preamble(expected_preamble, True) written_preamble, written_content = data.split() -- cgit v1.2.3