cloudroast/cloudroast/objectstorage/regression/features/expiring_objects_test.py

243 lines
8.6 KiB
Python

"""
Copyright 2013 Rackspace
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 calendar import timegm
from time import gmtime, sleep
from cafe.drivers.unittest.decorators import (
DataDrivenFixture, data_driven_test)
from cloudcafe.objectstorage.objectstorage_api.common.constants import \
Constants
from cloudroast.objectstorage.fixtures import ObjectStorageFixture
from cloudroast.objectstorage.generators import ObjectDatasetList
CONTAINER_DESCRIPTOR = 'expiring_object_test'
STATUS_CODE_MSG = ('{method} expected status code {expected}'
' received status code {received}')
@DataDrivenFixture
class ExpiringObjectTest(ObjectStorageFixture):
@classmethod
def setUpClass(cls):
super(ExpiringObjectTest, cls).setUpClass()
cls.default_obj_name = Constants.VALID_OBJECT_NAME
cls.default_obj_data = Constants.VALID_OBJECT_DATA
@data_driven_test(ObjectDatasetList())
def ddtest_object_creation_with_x_delete_at(self, object_type,
generate_object):
container_name = self.create_temp_container(
descriptor=CONTAINER_DESCRIPTOR)
object_name = self.default_obj_name
start_time = timegm(gmtime())
future_time = str(int(start_time + 60))
object_headers = {'X-Delete-At': future_time}
generate_object(container_name, object_name, headers=object_headers)
response = self.client.get_object(container_name, object_name)
content_length = response.headers.get('content-length')
self.assertNotEqual(content_length, 0)
# Wait for object to expire using interval from config
sleep(self.objectstorage_api_config.object_deletion_wait_interval)
response = self.client.get_object(container_name, object_name)
self.assertEqual(response.status_code, 404)
@data_driven_test(ObjectDatasetList())
def ddtest_object_creation_with_x_delete_after(
self, object_type, generate_object):
container_name = self.create_temp_container(
descriptor=CONTAINER_DESCRIPTOR)
object_name = self.default_obj_name
object_headers = {'X-Delete-After': '60'}
generate_object(container_name, object_name, headers=object_headers)
response = self.client.get_object(container_name, object_name)
content_length = response.headers.get('content-length')
self.assertNotEqual(content_length, 0)
# wait for the object to expire - delete after 60 seconds + 10 seconds
sleep(70)
response = self.client.get_object(container_name, object_name)
self.assertEqual(response.status_code, 404)
@data_driven_test(ObjectDatasetList())
def ddtest_object_creation_with_x_delete_after_with_unicode_container_name(
self, object_type, generate_object):
"""
Scenario:
Create a container with a unicode name and then add
an expiring object to it using x_delete_after
Expected Results:
The object should be available until the expiration time,
then it should be deleted
"""
delete_after = 60
container_description = unicode(u'\u262D\u2622').encode('utf-8')
container_name = self.create_temp_container(
descriptor=container_description)
object_name = self.default_obj_name
object_headers = {'X-Delete-After': delete_after}
generate_object(container_name,
object_name,
headers=object_headers)
object_response = self.client.get_object(container_name, object_name)
method = 'Creating Expiring Object in Unicode Container'
expected = 200
received = object_response.status_code
self.assertEqual(
expected,
received,
msg=STATUS_CODE_MSG.format(
method=method,
expected=expected,
received=str(received)))
# Sleep for period set as X-Delete-After(object expiration)
sleep(delete_after)
object_response = self.client.get_object(container_name, object_name)
method = 'GET on expired object in Unicode Container'
expected = 404
received = object_response.status_code
self.assertEqual(
expected,
received,
msg=STATUS_CODE_MSG.format(
method=method,
expected=expected,
received=str(received)))
@data_driven_test(ObjectDatasetList())
def ddtest_object_creation_with_x_delete_at_with_unicode_container_name(
self, object_type, generate_object):
"""
Scenario:
Create a container with a unicode name and then add
an expiring object to it using x_delete_at.
Expected Results:
The object should be available until the expiration time,
then it should be deleted
"""
start_time = timegm(gmtime())
future_time = str(int(start_time + 60))
container_description = unicode(u'\u262D\u2622').encode('utf-8')
container_name = self.create_temp_container(
descriptor=container_description)
object_name = self.default_obj_name
object_headers = {'X-Delete-At': future_time}
generate_object(container_name,
object_name,
headers=object_headers)
object_response = self.client.get_object(container_name, object_name)
method = 'Creating Expiring Object in Unicode Container'
expected = 200
received = object_response.status_code
self.assertEqual(
expected,
received,
msg=STATUS_CODE_MSG.format(
method=method,
expected=expected,
received=str(received)))
# Wait for object to expire using interval from config
sleep(self.objectstorage_api_config.object_deletion_wait_interval)
object_response = self.client.get_object(container_name, object_name)
method = 'GET on expired object in Unicode Container'
expected = 404
received = object_response.status_code
self.assertEqual(
expected,
received,
msg=STATUS_CODE_MSG.format(
method=method,
expected=expected,
received=str(received)))
@data_driven_test(ObjectDatasetList())
def ddtest_object_deletion_with_x_delete_at(self, **kwargs):
"""
Scenario:
Create an object which has the X-Delete-At metadata.
Expected Results:
The object should be accessible before the 'delete at' time.
The object should not be accessible after the 'delete at' time.
The object should not be listed after the object expirer has had
time to run.
"""
container_name = self.behaviors.generate_unique_container_name(
self.base_container_name)
self.behaviors.create_container(container_name)
self.addCleanup(
self.behaviors.force_delete_containers,
[container_name])
delete_after = 60
delete_at = str(int(timegm(gmtime()) + delete_after))
headers = {'Content-Length': str(len(self.default_obj_data)),
'X-Delete-At': delete_at}
resp = self.client.create_object(
container_name, self.default_obj_name,
headers=headers, data=self.default_obj_data)
self.assertEqual(
201, resp.status_code,
'Object should be created with X-Delete-At header.')
resp = self.client.get_object(container_name, self.default_obj_name)
self.assertEqual(
200, resp.status_code,
'Object should exist before X-Delete-At.')
# wait for the object to be deleted.
sleep(self.objectstorage_api_config.object_deletion_wait_interval)
resp = self.client.get_object(container_name, self.default_obj_name)
self.assertEqual(
404, resp.status_code,
'Object should be deleted after X-Delete-At.')