Merge "[Swift] Add base for Swift API Benchmarks: Patch-2"
This commit is contained in:
commit
87315aed09
@ -750,3 +750,60 @@
|
||||
users:
|
||||
tenants: 2
|
||||
users_per_tenant: 2
|
||||
|
||||
SwiftObjects.create_container_and_object_then_list_objects:
|
||||
-
|
||||
args:
|
||||
objects_per_container: 2
|
||||
object_size: 5120
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 2
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
roles:
|
||||
- "admin"
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
SwiftObjects.create_container_and_object_then_delete_all:
|
||||
-
|
||||
args:
|
||||
objects_per_container: 5
|
||||
object_size: 102400
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 4
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
roles:
|
||||
- "admin"
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
||||
SwiftObjects.create_container_and_object_then_download_object:
|
||||
-
|
||||
args:
|
||||
objects_per_container: 5
|
||||
object_size: 1024
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 6
|
||||
concurrency: 3
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
roles:
|
||||
- "admin"
|
||||
sla:
|
||||
failure_rate:
|
||||
max: 0
|
||||
|
@ -345,6 +345,53 @@ class DesignateServer(SynchronizedDeletion, base.ResourceManager):
|
||||
pass
|
||||
|
||||
|
||||
# SWIFT
|
||||
|
||||
_swift_order = get_order(1000)
|
||||
|
||||
|
||||
class SwiftMixin(SynchronizedDeletion, base.ResourceManager):
|
||||
|
||||
def _manager(self):
|
||||
client = self._admin_required and self.admin or self.user
|
||||
return getattr(client, self._service)()
|
||||
|
||||
def id(self):
|
||||
return self.raw_resource
|
||||
|
||||
def delete(self):
|
||||
delete_method = getattr(self._manager(), "delete_%s" % self._resource)
|
||||
# NOTE(weiwu): *self.raw_resource is required because for deleting
|
||||
# container we are passing only container name, to delete object we
|
||||
# should pass as first argument container and second is object name.
|
||||
delete_method(*self.raw_resource)
|
||||
|
||||
|
||||
@base.resource("swift", "object", order=next(_swift_order),
|
||||
tenant_resource=True)
|
||||
class SwiftObject(SwiftMixin):
|
||||
|
||||
def list(self):
|
||||
object_list = []
|
||||
containers = self._manager().get_account(full_listing=True)[1]
|
||||
for con in containers:
|
||||
objects = self._manager().get_container(con["name"],
|
||||
full_listing=True)[1]
|
||||
for obj in objects:
|
||||
raw_resource = [con["name"], obj["name"]]
|
||||
object_list.append(raw_resource)
|
||||
return object_list
|
||||
|
||||
|
||||
@base.resource("swift", "container", order=next(_swift_order),
|
||||
tenant_resource=True)
|
||||
class SwiftContainer(SwiftMixin):
|
||||
|
||||
def list(self):
|
||||
containers = self._manager().get_account(full_listing=True)[1]
|
||||
return [[con["name"]] for con in containers]
|
||||
|
||||
|
||||
# MISTRAL
|
||||
|
||||
@base.resource("mistral", "workbooks", order=1100, tenant_resource=True)
|
||||
|
0
rally/benchmark/scenarios/swift/__init__.py
Normal file
0
rally/benchmark/scenarios/swift/__init__.py
Normal file
124
rally/benchmark/scenarios/swift/objects.py
Normal file
124
rally/benchmark/scenarios/swift/objects.py
Normal file
@ -0,0 +1,124 @@
|
||||
# Copyright 2015: Cisco Systems, 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.
|
||||
|
||||
import tempfile
|
||||
|
||||
from rally.benchmark.scenarios import base
|
||||
from rally.benchmark.scenarios.swift import utils
|
||||
from rally.benchmark import validation
|
||||
from rally import consts
|
||||
|
||||
|
||||
class SwiftObjects(utils.SwiftScenario):
|
||||
"""Benchmark scenarios for Swift Objects."""
|
||||
|
||||
@validation.required_services(consts.Service.SWIFT)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario(context={"cleanup": ["swift"]})
|
||||
def create_container_and_object_then_list_objects(
|
||||
self, objects_per_container=1,
|
||||
object_size=1024, **kwargs):
|
||||
"""Create container and objects then list all objects.
|
||||
|
||||
:param objects_per_container: int, number of objects to upload
|
||||
:param object_size: int, temporary local object size
|
||||
:param kwargs: dict, optional parameters to create container
|
||||
"""
|
||||
key_suffix = "object"
|
||||
if objects_per_container > 1:
|
||||
key_suffix = "%i_objects" % objects_per_container
|
||||
|
||||
container_name = None
|
||||
with tempfile.TemporaryFile() as dummy_file:
|
||||
# set dummy file to specified object size
|
||||
dummy_file.truncate(object_size)
|
||||
container_name = self._create_container(**kwargs)
|
||||
with base.AtomicAction(self, "swift.create_%s" % key_suffix):
|
||||
for i in range(objects_per_container):
|
||||
dummy_file.seek(0)
|
||||
self._upload_object(container_name, dummy_file,
|
||||
atomic_action=False)
|
||||
self._list_objects(container_name)
|
||||
|
||||
@validation.required_services(consts.Service.SWIFT)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario(context={"cleanup": ["swift"]})
|
||||
def create_container_and_object_then_delete_all(
|
||||
self, objects_per_container=1,
|
||||
object_size=1024, **kwargs):
|
||||
"""Create container and objects then delete everything created.
|
||||
|
||||
:param objects_per_container: int, number of objects to upload
|
||||
:param object_size: int, temporary local object size
|
||||
:param kwargs: dict, optional parameters to create container
|
||||
"""
|
||||
key_suffix = "object"
|
||||
if objects_per_container > 1:
|
||||
key_suffix = "%i_objects" % objects_per_container
|
||||
|
||||
container_name = None
|
||||
objects_list = []
|
||||
with tempfile.TemporaryFile() as dummy_file:
|
||||
# set dummy file to specified object size
|
||||
dummy_file.truncate(object_size)
|
||||
container_name = self._create_container(**kwargs)
|
||||
with base.AtomicAction(self, "swift.create_%s" % key_suffix):
|
||||
for i in range(objects_per_container):
|
||||
dummy_file.seek(0)
|
||||
object_name = self._upload_object(container_name,
|
||||
dummy_file,
|
||||
atomic_action=False)[1]
|
||||
objects_list.append(object_name)
|
||||
|
||||
with base.AtomicAction(self, "swift.delete_%s" % key_suffix):
|
||||
for object_name in objects_list:
|
||||
self._delete_object(container_name, object_name,
|
||||
atomic_action=False)
|
||||
self._delete_container(container_name)
|
||||
|
||||
@validation.required_services(consts.Service.SWIFT)
|
||||
@validation.required_openstack(users=True)
|
||||
@base.scenario(context={"cleanup": ["swift"]})
|
||||
def create_container_and_object_then_download_object(
|
||||
self, objects_per_container=1,
|
||||
object_size=1024, **kwargs):
|
||||
"""Create container and objects then download all objects.
|
||||
|
||||
:param objects_per_container: int, number of objects to upload
|
||||
:param object_size: int, temporary local object size
|
||||
:param kwargs: dict, optional parameters to create container
|
||||
"""
|
||||
key_suffix = "object"
|
||||
if objects_per_container > 1:
|
||||
key_suffix = "%i_objects" % objects_per_container
|
||||
|
||||
container_name = None
|
||||
objects_list = []
|
||||
with tempfile.TemporaryFile() as dummy_file:
|
||||
# set dummy file to specified object size
|
||||
dummy_file.truncate(object_size)
|
||||
container_name = self._create_container(**kwargs)
|
||||
with base.AtomicAction(self, "swift.create_%s" % key_suffix):
|
||||
for i in range(objects_per_container):
|
||||
dummy_file.seek(0)
|
||||
object_name = self._upload_object(container_name,
|
||||
dummy_file,
|
||||
atomic_action=False)[1]
|
||||
objects_list.append(object_name)
|
||||
|
||||
with base.AtomicAction(self, "swift.download_%s" % key_suffix):
|
||||
for object_name in objects_list:
|
||||
self._download_object(container_name, object_name,
|
||||
atomic_action=False)
|
163
rally/benchmark/scenarios/swift/utils.py
Normal file
163
rally/benchmark/scenarios/swift/utils.py
Normal file
@ -0,0 +1,163 @@
|
||||
# Copyright 2015: Cisco Systems, 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 rally.benchmark.scenarios import base
|
||||
|
||||
|
||||
class SwiftScenario(base.Scenario):
|
||||
"""Base class for Swift scenarios with basic atomic actions."""
|
||||
|
||||
@base.atomic_action_timer("swift.list_containers")
|
||||
def _list_containers(self, full_listing=True, **kwargs):
|
||||
"""Return list of containers.
|
||||
|
||||
:param full_listing: bool, enable unlimit number of listing returned
|
||||
:param kwargs: dict, other optional parameters to get_account
|
||||
|
||||
:returns: tuple, (dict of response headers, a list of containers)
|
||||
"""
|
||||
return self.clients("swift").get_account(full_listing=full_listing,
|
||||
**kwargs)
|
||||
|
||||
def _create_container(self, container_name=None, public=False,
|
||||
atomic_action=True, **kwargs):
|
||||
"""Create a new container with given name.
|
||||
|
||||
:param container_name: str, name of the container to create
|
||||
:param public: bool, set container as public
|
||||
:param atomic_action: bool, enable create container to be tracked as an
|
||||
atomic action
|
||||
:param kwargs: dict, other optional parameters to put_container
|
||||
|
||||
:returns: container name
|
||||
"""
|
||||
if public:
|
||||
kwargs.setdefault("headers", {})
|
||||
kwargs["headers"].setdefault("X-Container-Read", ".r:*,.rlistings")
|
||||
|
||||
if container_name is None:
|
||||
container_name = self._generate_random_name(
|
||||
prefix="rally_container_")
|
||||
|
||||
if atomic_action:
|
||||
with base.AtomicAction(self, "swift.create_container"):
|
||||
self.clients("swift").put_container(container_name, **kwargs)
|
||||
else:
|
||||
self.clients("swift").put_container(container_name, **kwargs)
|
||||
return container_name
|
||||
|
||||
def _delete_container(self, container_name, atomic_action=True, **kwargs):
|
||||
"""Delete a container with given name.
|
||||
|
||||
:param container_name: str, name of the container to delete
|
||||
:param atomic_action: bool, enable delete container to be tracked as an
|
||||
atomic action
|
||||
:param kwargs: dict, other optional parameters to delete_container
|
||||
"""
|
||||
if atomic_action:
|
||||
with base.AtomicAction(self, "swift.delete_container"):
|
||||
self.clients("swift").delete_container(container_name,
|
||||
**kwargs)
|
||||
else:
|
||||
self.clients("swift").delete_container(container_name, **kwargs)
|
||||
|
||||
def _list_objects(self, container_name, full_listing=True,
|
||||
atomic_action=True, **kwargs):
|
||||
"""Return objects inside container.
|
||||
|
||||
:param container_name: str, name of the container to make the list
|
||||
objects operation against
|
||||
:param full_listing: bool, enable unlimit number of listing returned
|
||||
:param atomic_action: bool, enable list objects to be tracked as an
|
||||
atomic action
|
||||
:param kwargs: dict, other optional parameters to get_container
|
||||
|
||||
:returns: tuple, (dict of response headers, a list of objects)
|
||||
"""
|
||||
if atomic_action:
|
||||
with base.AtomicAction(self, "swift.list_objects"):
|
||||
return self.clients("swift").get_container(
|
||||
container_name, full_listing=full_listing,
|
||||
**kwargs)
|
||||
|
||||
return self.clients("swift").get_container(container_name,
|
||||
full_listing=full_listing,
|
||||
**kwargs)
|
||||
|
||||
def _upload_object(self, container_name, content, object_name=None,
|
||||
atomic_action=True, **kwargs):
|
||||
"""Upload content to a given container.
|
||||
|
||||
:param container_name: str, name of the container to upload object to
|
||||
:param content: file stream, content to upload
|
||||
:param object_name: str, name of the object to upload
|
||||
:param atomic_action: bool, enable upload object to be tracked as an
|
||||
atomic action
|
||||
:param kwargs: dict, other optional parameters to put_object
|
||||
|
||||
:returns: tuple, (etag and object name)
|
||||
"""
|
||||
if object_name is None:
|
||||
object_name = self._generate_random_name(prefix="rally_object_")
|
||||
|
||||
if atomic_action:
|
||||
with base.AtomicAction(self, "swift.upload_object"):
|
||||
return (self.clients("swift").put_object(container_name,
|
||||
object_name, content,
|
||||
**kwargs),
|
||||
object_name)
|
||||
|
||||
return (self.clients("swift").put_object(container_name, object_name,
|
||||
content, **kwargs),
|
||||
object_name)
|
||||
|
||||
def _download_object(self, container_name, object_name, atomic_action=True,
|
||||
**kwargs):
|
||||
"""Download object from container.
|
||||
|
||||
:param container_name: str, name of the container to download object
|
||||
from
|
||||
:param object_name: str, name of the object to download
|
||||
:param atomic_action: bool, enable download object to be tracked as an
|
||||
atomic action
|
||||
:param kwargs: dict, other optional parameters to get_object
|
||||
|
||||
:returns: tuple, (dict of response headers, the object's contents)
|
||||
"""
|
||||
if atomic_action:
|
||||
with base.AtomicAction(self, "swift.download_object"):
|
||||
return self.clients("swift").get_object(container_name,
|
||||
object_name, **kwargs)
|
||||
|
||||
return self.clients("swift").get_object(container_name, object_name,
|
||||
**kwargs)
|
||||
|
||||
def _delete_object(self, container_name, object_name, atomic_action=True,
|
||||
**kwargs):
|
||||
"""Delete object from container.
|
||||
|
||||
:param container_name: str, name of the container to delete object from
|
||||
:param object_name: str, name of the object to delete
|
||||
:param atomic_action: bool, enable delete object to be tracked as an
|
||||
atomic action
|
||||
:param kwargs: dict, other optional parameters to delete_object
|
||||
"""
|
||||
if atomic_action:
|
||||
with base.AtomicAction(self, "swift.delete_object"):
|
||||
self.clients("swift").delete_object(container_name,
|
||||
object_name, **kwargs)
|
||||
else:
|
||||
self.clients("swift").delete_object(container_name, object_name,
|
||||
**kwargs)
|
@ -134,12 +134,13 @@ class Clients(object):
|
||||
|
||||
def _get_auth_info(self, user_key="username",
|
||||
password_key="password",
|
||||
auth_url_key="auth_url",
|
||||
project_name_key="project_id"
|
||||
):
|
||||
kw = {
|
||||
user_key: self.endpoint.username,
|
||||
password_key: self.endpoint.password,
|
||||
"auth_url": self.endpoint.auth_url
|
||||
auth_url_key: self.endpoint.auth_url
|
||||
}
|
||||
if project_name_key:
|
||||
kw.update({project_name_key: self.endpoint.tenant_name})
|
||||
@ -389,6 +390,7 @@ class Clients(object):
|
||||
**self._get_auth_info(
|
||||
user_key="user",
|
||||
password_key="key",
|
||||
auth_url_key="authurl",
|
||||
project_name_key="tenant_name")
|
||||
)
|
||||
return client
|
||||
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"SwiftObjects.create_container_and_object_then_delete_all": [
|
||||
{
|
||||
"args": {
|
||||
"objects_per_container": 5,
|
||||
"object_size": 102400
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 4,
|
||||
"concurrency": 2
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 1,
|
||||
"users_per_tenant": 1
|
||||
},
|
||||
"roles": [
|
||||
"admin"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
---
|
||||
SwiftObjects.create_container_and_object_then_delete_all:
|
||||
-
|
||||
args:
|
||||
objects_per_container: 5
|
||||
object_size: 102400
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 4
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
roles:
|
||||
- "admin"
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"SwiftObjects.create_container_and_object_then_download_object": [
|
||||
{
|
||||
"args": {
|
||||
"objects_per_container": 5,
|
||||
"object_size": 1024
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 6,
|
||||
"concurrency": 3
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 1,
|
||||
"users_per_tenant": 1
|
||||
},
|
||||
"roles": [
|
||||
"admin"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
---
|
||||
SwiftObjects.create_container_and_object_then_download_object:
|
||||
-
|
||||
args:
|
||||
objects_per_container: 5
|
||||
object_size: 1024
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 6
|
||||
concurrency: 3
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
roles:
|
||||
- "admin"
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"SwiftObjects.create_container_and_object_then_list_objects": [
|
||||
{
|
||||
"args": {
|
||||
"objects_per_container": 2,
|
||||
"object_size": 5120
|
||||
},
|
||||
"runner": {
|
||||
"type": "constant",
|
||||
"times": 2,
|
||||
"concurrency": 2
|
||||
},
|
||||
"context": {
|
||||
"users": {
|
||||
"tenants": 1,
|
||||
"users_per_tenant": 1
|
||||
},
|
||||
"roles": [
|
||||
"admin"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
---
|
||||
SwiftObjects.create_container_and_object_then_list_objects:
|
||||
-
|
||||
args:
|
||||
objects_per_container: 2
|
||||
object_size: 5120
|
||||
runner:
|
||||
type: "constant"
|
||||
times: 2
|
||||
concurrency: 2
|
||||
context:
|
||||
users:
|
||||
tenants: 1
|
||||
users_per_tenant: 1
|
||||
roles:
|
||||
- "admin"
|
@ -342,3 +342,55 @@ class KeystoneMixinTestCase(test.TestCase):
|
||||
|
||||
self.assertSequenceEqual(result[:2], keystone_mixin.list())
|
||||
mock_wrap().list_some_resource2s.assert_called_once_with()
|
||||
|
||||
|
||||
class SwiftMixinTestCase(test.TestCase):
|
||||
|
||||
def get_swift_mixin(self):
|
||||
swift_mixin = resources.SwiftMixin()
|
||||
swift_mixin._service = "swift"
|
||||
return swift_mixin
|
||||
|
||||
def test_manager(self):
|
||||
swift_mixin = self.get_swift_mixin()
|
||||
swift_mixin.user = mock.MagicMock()
|
||||
self.assertEqual(swift_mixin.user.swift.return_value,
|
||||
swift_mixin._manager())
|
||||
|
||||
def test_id(self):
|
||||
swift_mixin = self.get_swift_mixin()
|
||||
swift_mixin.raw_resource = mock.MagicMock()
|
||||
self.assertEqual(swift_mixin.raw_resource, swift_mixin.id())
|
||||
|
||||
def test_delete(self):
|
||||
swift_mixin = self.get_swift_mixin()
|
||||
swift_mixin.user = mock.MagicMock()
|
||||
swift_mixin._resource = "some_resource"
|
||||
swift_mixin.raw_resource = mock.MagicMock()
|
||||
swift_mixin.delete()
|
||||
swift_mixin.user.swift().delete_some_resource.assert_called_once_with(
|
||||
*swift_mixin.raw_resource)
|
||||
|
||||
|
||||
class SwiftObjectTestCase(test.TestCase):
|
||||
|
||||
@mock.patch("%s.SwiftMixin._manager" % BASE)
|
||||
def test_list(self, mock_manager):
|
||||
containers = [mock.MagicMock(), mock.MagicMock()]
|
||||
objects = [mock.MagicMock(), mock.MagicMock(), mock.MagicMock()]
|
||||
mock_manager().get_account.return_value = ("header", containers)
|
||||
mock_manager().get_container.return_value = ("header", objects)
|
||||
self.assertEqual(len(containers),
|
||||
len(resources.SwiftContainer().list()))
|
||||
self.assertEqual(len(containers) * len(objects),
|
||||
len(resources.SwiftObject().list()))
|
||||
|
||||
|
||||
class SwiftContainerTestCase(test.TestCase):
|
||||
|
||||
@mock.patch("%s.SwiftMixin._manager" % BASE)
|
||||
def test_list(self, mock_manager):
|
||||
containers = [mock.MagicMock(), mock.MagicMock(), mock.MagicMock()]
|
||||
mock_manager().get_account.return_value = ("header", containers)
|
||||
self.assertEqual(len(containers),
|
||||
len(resources.SwiftContainer().list()))
|
||||
|
0
tests/unit/benchmark/scenarios/swift/__init__.py
Normal file
0
tests/unit/benchmark/scenarios/swift/__init__.py
Normal file
144
tests/unit/benchmark/scenarios/swift/test_objects.py
Normal file
144
tests/unit/benchmark/scenarios/swift/test_objects.py
Normal file
@ -0,0 +1,144 @@
|
||||
# Copyright 2015 Cisco Systems, 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.
|
||||
|
||||
import mock
|
||||
|
||||
from rally.benchmark.scenarios.swift import objects
|
||||
from tests.unit import fakes
|
||||
from tests.unit import test
|
||||
|
||||
|
||||
class SwiftObjectsTestCase(test.TestCase):
|
||||
|
||||
def test_create_container_and_object_then_list_objects(self):
|
||||
scenario = objects.SwiftObjects()
|
||||
scenario._create_container = mock.MagicMock(return_value="AA")
|
||||
scenario._upload_object = mock.MagicMock()
|
||||
scenario._list_objects = mock.MagicMock()
|
||||
|
||||
scenario.create_container_and_object_then_list_objects(
|
||||
objects_per_container=5,
|
||||
object_size=100)
|
||||
|
||||
self.assertEqual(1, scenario._create_container.call_count)
|
||||
self.assertEqual(5, scenario._upload_object.call_count)
|
||||
scenario._list_objects.assert_called_once_with("AA")
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.create_5_objects")
|
||||
|
||||
def test_create_container_and_object_then_delete_all(self):
|
||||
scenario = objects.SwiftObjects()
|
||||
scenario._create_container = mock.MagicMock(return_value="BB")
|
||||
scenario._upload_object = mock.MagicMock(
|
||||
side_effect=[("etaaag", "ooobj_%i" % i) for i in range(3)])
|
||||
scenario._delete_object = mock.MagicMock()
|
||||
scenario._delete_container = mock.MagicMock()
|
||||
|
||||
scenario.create_container_and_object_then_delete_all(
|
||||
objects_per_container=3,
|
||||
object_size=10)
|
||||
|
||||
self.assertEqual(1, scenario._create_container.call_count)
|
||||
self.assertEqual(3, scenario._upload_object.call_count)
|
||||
scenario._delete_object.assert_has_calls(
|
||||
[mock.call("BB", "ooobj_%i" % i,
|
||||
atomic_action=False) for i in range(3)])
|
||||
scenario._delete_container.assert_called_once_with("BB")
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.create_3_objects")
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.delete_3_objects")
|
||||
|
||||
def test_create_container_and_object_then_download_object(self):
|
||||
scenario = objects.SwiftObjects()
|
||||
scenario._create_container = mock.MagicMock(return_value="CC")
|
||||
scenario._upload_object = mock.MagicMock(
|
||||
side_effect=[("etaaaag", "obbbj_%i" % i) for i in range(2)])
|
||||
scenario._download_object = mock.MagicMock()
|
||||
|
||||
scenario.create_container_and_object_then_download_object(
|
||||
objects_per_container=2,
|
||||
object_size=50)
|
||||
|
||||
self.assertEqual(1, scenario._create_container.call_count)
|
||||
self.assertEqual(2, scenario._upload_object.call_count)
|
||||
scenario._download_object.assert_has_calls(
|
||||
[mock.call("CC", "obbbj_%i" % i,
|
||||
atomic_action=False) for i in range(2)])
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.create_2_objects")
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.download_2_objects")
|
||||
|
||||
def test_functional_create_container_and_object_then_list_objects(self):
|
||||
names_list = ["AA", "BB", "CC", "DD"]
|
||||
|
||||
scenario = objects.SwiftObjects(clients=fakes.FakeClients())
|
||||
scenario._generate_random_name = mock.MagicMock(side_effect=names_list)
|
||||
scenario._list_objects = mock.MagicMock()
|
||||
|
||||
scenario.create_container_and_object_then_list_objects(
|
||||
objects_per_container=3,
|
||||
object_size=100)
|
||||
|
||||
scenario._list_objects.assert_called_once_with("AA")
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.create_3_objects")
|
||||
|
||||
def test_functional_create_container_and_object_then_delete_all(self):
|
||||
names_list = ["111", "222", "333", "444", "555"]
|
||||
|
||||
scenario = objects.SwiftObjects(clients=fakes.FakeClients())
|
||||
scenario._generate_random_name = mock.MagicMock(side_effect=names_list)
|
||||
scenario._delete_object = mock.MagicMock()
|
||||
scenario._delete_container = mock.MagicMock()
|
||||
|
||||
scenario.create_container_and_object_then_delete_all(
|
||||
objects_per_container=4,
|
||||
object_size=240)
|
||||
|
||||
scenario._delete_object.assert_has_calls(
|
||||
[mock.call("111", name,
|
||||
atomic_action=False) for name in names_list[1:]])
|
||||
scenario._delete_container.assert_called_once_with("111")
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.create_4_objects")
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.delete_4_objects")
|
||||
|
||||
def test_functional_create_container_and_object_then_download_object(self):
|
||||
names_list = ["aaa", "bbb", "ccc", "ddd", "eee", "fff"]
|
||||
|
||||
scenario = objects.SwiftObjects(clients=fakes.FakeClients())
|
||||
scenario._generate_random_name = mock.MagicMock(side_effect=names_list)
|
||||
scenario._download_object = mock.MagicMock()
|
||||
|
||||
scenario.create_container_and_object_then_download_object(
|
||||
objects_per_container=5,
|
||||
object_size=750)
|
||||
|
||||
scenario._download_object.assert_has_calls(
|
||||
[mock.call("aaa", name,
|
||||
atomic_action=False) for name in names_list[1:]])
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.create_5_objects")
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.download_5_objects")
|
202
tests/unit/benchmark/scenarios/swift/test_utils.py
Normal file
202
tests/unit/benchmark/scenarios/swift/test_utils.py
Normal file
@ -0,0 +1,202 @@
|
||||
# Copyright 2015: Cisco Systems, 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.
|
||||
|
||||
import mock
|
||||
|
||||
from rally.benchmark.scenarios.swift import utils
|
||||
from tests.unit import test
|
||||
|
||||
SWIFT_UTILS = "rally.benchmark.scenarios.swift.utils"
|
||||
|
||||
|
||||
class SwiftScenarioTestCase(test.TestCase):
|
||||
|
||||
@mock.patch(SWIFT_UTILS + ".SwiftScenario.clients")
|
||||
def test__list_containers(self, mock_clients):
|
||||
headers_dict = mock.MagicMock()
|
||||
containers_list = mock.MagicMock()
|
||||
mock_clients("swift").get_account.return_value = (headers_dict,
|
||||
containers_list)
|
||||
scenario = utils.SwiftScenario()
|
||||
|
||||
self.assertEqual((headers_dict, containers_list),
|
||||
scenario._list_containers(fargs="f"))
|
||||
kw = {"full_listing": True, "fargs": "f"}
|
||||
mock_clients("swift").get_account.assert_called_once_with(**kw)
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.list_containers")
|
||||
|
||||
@mock.patch(SWIFT_UTILS + ".SwiftScenario.clients")
|
||||
def test__create_container(self, mock_clients):
|
||||
container_name = mock.MagicMock()
|
||||
scenario = utils.SwiftScenario()
|
||||
|
||||
# name + public=True + kw
|
||||
self.assertEqual(container_name,
|
||||
scenario._create_container(container_name,
|
||||
public=True, fargs="f"))
|
||||
kw = {"headers": {"X-Container-Read": ".r:*,.rlistings"}, "fargs": "f"}
|
||||
mock_clients("swift").put_container.assert_called_once_with(
|
||||
container_name,
|
||||
**kw)
|
||||
# name + public=True + additional header + kw
|
||||
mock_clients("swift").put_container.reset_mock()
|
||||
self.assertEqual(container_name,
|
||||
scenario._create_container(container_name,
|
||||
public=True,
|
||||
headers={"X-fake-name":
|
||||
"fake-value"},
|
||||
fargs="f"))
|
||||
kw = {"headers": {"X-Container-Read": ".r:*,.rlistings",
|
||||
"X-fake-name": "fake-value"}, "fargs": "f"}
|
||||
mock_clients("swift").put_container.assert_called_once_with(
|
||||
container_name,
|
||||
**kw)
|
||||
# name + public=False + additional header + kw
|
||||
mock_clients("swift").put_container.reset_mock()
|
||||
self.assertEqual(container_name,
|
||||
scenario._create_container(container_name,
|
||||
public=False,
|
||||
headers={"X-fake-name":
|
||||
"fake-value"},
|
||||
fargs="f"))
|
||||
kw = {"headers": {"X-fake-name": "fake-value"}, "fargs": "f"}
|
||||
mock_clients("swift").put_container.assert_called_once_with(
|
||||
container_name,
|
||||
**kw)
|
||||
# name + kw
|
||||
mock_clients("swift").put_container.reset_mock()
|
||||
self.assertEqual(container_name,
|
||||
scenario._create_container(container_name, fargs="f"))
|
||||
kw = {"fargs": "f"}
|
||||
mock_clients("swift").put_container.assert_called_once_with(
|
||||
container_name,
|
||||
**kw)
|
||||
# kw
|
||||
scenario._generate_random_name = mock.MagicMock(
|
||||
return_value=container_name)
|
||||
mock_clients("swift").put_container.reset_mock()
|
||||
self.assertEqual(container_name,
|
||||
scenario._create_container(fargs="f"))
|
||||
kw = {"fargs": "f"}
|
||||
mock_clients("swift").put_container.assert_called_once_with(
|
||||
container_name,
|
||||
**kw)
|
||||
self.assertEqual(1, scenario._generate_random_name.call_count)
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.create_container")
|
||||
|
||||
@mock.patch(SWIFT_UTILS + ".SwiftScenario.clients")
|
||||
def test__delete_container(self, mock_clients):
|
||||
container_name = mock.MagicMock()
|
||||
scenario = utils.SwiftScenario()
|
||||
scenario._delete_container(container_name, fargs="f")
|
||||
|
||||
kw = {"fargs": "f"}
|
||||
mock_clients("swift").delete_container.assert_called_once_with(
|
||||
container_name,
|
||||
**kw)
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.delete_container")
|
||||
|
||||
@mock.patch(SWIFT_UTILS + ".SwiftScenario.clients")
|
||||
def test__list_objects(self, mock_clients):
|
||||
container_name = mock.MagicMock()
|
||||
headers_dict = mock.MagicMock()
|
||||
objects_list = mock.MagicMock()
|
||||
mock_clients("swift").get_container.return_value = (headers_dict,
|
||||
objects_list)
|
||||
scenario = utils.SwiftScenario()
|
||||
|
||||
self.assertEqual((headers_dict, objects_list),
|
||||
scenario._list_objects(container_name, fargs="f"))
|
||||
kw = {"full_listing": True, "fargs": "f"}
|
||||
mock_clients("swift").get_container.assert_called_once_with(
|
||||
container_name,
|
||||
**kw)
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.list_objects")
|
||||
|
||||
@mock.patch(SWIFT_UTILS + ".SwiftScenario.clients")
|
||||
def test__upload_object(self, mock_clients):
|
||||
container_name = mock.MagicMock()
|
||||
object_name = mock.MagicMock()
|
||||
content = mock.MagicMock()
|
||||
etag = mock.MagicMock()
|
||||
mock_clients("swift").put_object.return_value = etag
|
||||
scenario = utils.SwiftScenario()
|
||||
|
||||
# container + content + name + kw
|
||||
self.assertEqual((etag, object_name),
|
||||
scenario._upload_object(container_name, content,
|
||||
object_name=object_name,
|
||||
fargs="f"))
|
||||
kw = {"fargs": "f"}
|
||||
mock_clients("swift").put_object.assert_called_once_with(
|
||||
container_name, object_name,
|
||||
content, **kw)
|
||||
# container + content + kw
|
||||
scenario._generate_random_name = mock.MagicMock(
|
||||
return_value=object_name)
|
||||
mock_clients("swift").put_object.reset_mock()
|
||||
self.assertEqual((etag, object_name),
|
||||
scenario._upload_object(container_name, content,
|
||||
fargs="f"))
|
||||
kw = {"fargs": "f"}
|
||||
mock_clients("swift").put_object.assert_called_once_with(
|
||||
container_name, object_name,
|
||||
content, **kw)
|
||||
self.assertEqual(1, scenario._generate_random_name.call_count)
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.upload_object")
|
||||
|
||||
@mock.patch(SWIFT_UTILS + ".SwiftScenario.clients")
|
||||
def test__download_object(self, mock_clients):
|
||||
container_name = mock.MagicMock()
|
||||
object_name = mock.MagicMock()
|
||||
headers_dict = mock.MagicMock()
|
||||
content = mock.MagicMock()
|
||||
mock_clients("swift").get_object.return_value = (headers_dict, content)
|
||||
scenario = utils.SwiftScenario()
|
||||
|
||||
self.assertEqual((headers_dict, content),
|
||||
scenario._download_object(container_name, object_name,
|
||||
fargs="f"))
|
||||
kw = {"fargs": "f"}
|
||||
mock_clients("swift").get_object.assert_called_once_with(
|
||||
container_name, object_name,
|
||||
**kw)
|
||||
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.download_object")
|
||||
|
||||
@mock.patch(SWIFT_UTILS + ".SwiftScenario.clients")
|
||||
def test__delete_object(self, mock_clients):
|
||||
container_name = mock.MagicMock()
|
||||
object_name = mock.MagicMock()
|
||||
scenario = utils.SwiftScenario()
|
||||
scenario._delete_object(container_name, object_name, fargs="f")
|
||||
|
||||
kw = {"fargs": "f"}
|
||||
mock_clients("swift").delete_object.assert_called_once_with(
|
||||
container_name, object_name,
|
||||
**kw)
|
||||
self._test_atomic_action_timer(scenario.atomic_actions(),
|
||||
"swift.delete_object")
|
@ -900,7 +900,7 @@ class FakeObjectManager(FakeManager):
|
||||
|
||||
def put_object(self, container_name, object_name, content, **kwargs):
|
||||
container = self.find(name=container_name)
|
||||
if container is None or object_name in container.items:
|
||||
if container is None:
|
||||
raise swift_exceptions.ClientException("Object PUT failed")
|
||||
container.items[object_name] = content
|
||||
return mock.MagicMock()
|
||||
|
@ -403,7 +403,7 @@ class OSClientsTestCase(test.TestCase):
|
||||
"user": self.endpoint.username,
|
||||
"key": self.endpoint.password,
|
||||
"tenant_name": self.endpoint.tenant_name,
|
||||
"auth_url": self.endpoint.auth_url
|
||||
"authurl": self.endpoint.auth_url
|
||||
}
|
||||
mock_swift.client.Connection.assert_called_once_with(**kw)
|
||||
self.assertEqual(self.clients.cache["swift"], fake_swift)
|
||||
|
Loading…
Reference in New Issue
Block a user