diff options
author | Dan Smith <dansmith@redhat.com> | 2020-08-20 08:10:41 -0700 |
---|---|---|
committer | Dan Smith <dansmith@redhat.com> | 2020-08-26 07:38:55 -0700 |
commit | 4dc622dc91cf161ebbb1f3ab3a8ffa3bcc7e1a43 (patch) | |
tree | 66df750aa737f128d5b2943b674512ffbb7125a6 | |
parent | 982313615a368e5caa2e12fce781ea528483512f (diff) | |
download | glance_store-4dc622dc91cf161ebbb1f3ab3a8ffa3bcc7e1a43.tar.gz |
Bring FakeData utility over from glance
This brings over the small-footprint FakeData generator from glance and
refactors the rbd resize tests to use it instead of a static string.
Change-Id: I842578ca933294e4340ba080be488999e7910727
-rw-r--r-- | glance_store/tests/unit/test_rbd_store.py | 4 | ||||
-rw-r--r-- | glance_store/tests/unit/test_test_utils.py | 38 | ||||
-rw-r--r-- | glance_store/tests/utils.py | 42 |
3 files changed, 82 insertions, 2 deletions
diff --git a/glance_store/tests/unit/test_rbd_store.py b/glance_store/tests/unit/test_rbd_store.py index 4f44bc2..fe6a2ac 100644 --- a/glance_store/tests/unit/test_rbd_store.py +++ b/glance_store/tests/unit/test_rbd_store.py @@ -24,6 +24,7 @@ from glance_store import exceptions from glance_store import location as g_location from glance_store.tests import base from glance_store.tests.unit import test_store_capabilities +from glance_store.tests import utils as test_utils class TestException(Exception): @@ -189,9 +190,8 @@ class TestReSize(base.StoreBaseTest, def test_add_w_image_size_zero_less_resizes(self): """Assert that correct size is returned even though 0 was provided.""" - # TODO(jokke): use the FakeData iterator once it exists. data_len = 57 * units.Mi - data_iter = six.BytesIO(b'*' * data_len) + data_iter = test_utils.FakeData(data_len) with mock.patch.object(rbd_store.rbd.Image, 'resize') as resize: with mock.patch.object(rbd_store.rbd.Image, 'write') as write: ret = self.store.add( diff --git a/glance_store/tests/unit/test_test_utils.py b/glance_store/tests/unit/test_test_utils.py new file mode 100644 index 0000000..81495a2 --- /dev/null +++ b/glance_store/tests/unit/test_test_utils.py @@ -0,0 +1,38 @@ +# Copyright 2020 Red Hat, Inc +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from glance_store.tests import base +from glance_store.tests import utils as test_utils + + +class TestFakeData(base.StoreBaseTest): + def test_via_read(self): + fd = test_utils.FakeData(1024) + data = [] + for i in range(0, 1025, 256): + chunk = fd.read(256) + data.append(chunk) + if not chunk: + break + + self.assertEqual(5, len(data)) + # Make sure we got a zero-length final read + self.assertEqual(b'', data[-1]) + # Make sure we only got 1024 bytes + self.assertEqual(1024, len(b''.join(data))) + + def test_via_iter(self): + data = b''.join(list(test_utils.FakeData(1024))) + self.assertEqual(1024, len(data)) diff --git a/glance_store/tests/utils.py b/glance_store/tests/utils.py index 2f3a90f..5180bdd 100644 --- a/glance_store/tests/utils.py +++ b/glance_store/tests/utils.py @@ -16,6 +16,7 @@ import six from six.moves import urllib +from oslo_utils import units import requests @@ -73,3 +74,44 @@ def fake_response(status_code=200, headers=None, content=None, **kwargs): r.headers = headers or {} r.raw = FakeHTTPResponse(status_code, headers, content, kwargs) return r + + +class FakeData(object): + """Generate a bunch of data without storing it in memory. + + This acts like a read-only file object which generates fake data + in chunks when read() is called or it is used as a generator. It + can generate an arbitrary amount of data without storing it in + memory. + + :param length: The number of bytes to generate + :param chunk_size: The chunk size to return in iteration mode, or when + read() is called unbounded + + """ + def __init__(self, length, chunk_size=64 * units.Ki): + self._max = length + self._chunk_size = chunk_size + self._len = 0 + + def read(self, length=None): + if length is None: + length = self._chunk_size + + length = min(length, self._max - self._len) + + self._len += length + if length == 0: + return b'' + else: + return b'0' * length + + def __iter__(self): + return self + + def __next__(self): + r = self.read() + if len(r) == 0: + raise StopIteration() + else: + return r |