diff options
author | Luis Pabon <lpabon@redhat.com> | 2013-06-21 16:41:50 -0400 |
---|---|---|
committer | Peter Portante <pportant@redhat.com> | 2013-06-28 13:17:50 -0700 |
commit | 5cef798f8dcdee0d0512e47b67ac67d5f8d6c14c (patch) | |
tree | 73dce36cbfc970b5a363bd0dbd33ade5ff291ac8 /test/functional | |
parent | 92fdc68d6b90f4f7327bdffe542c5e8807a3e6c5 (diff) |
OpenStack Swift Functional Tests for G4S
This commit has the following changes:
* G4S no longer accepts URLs that end in /. A HTTP code
of 400 is returned when a / at the end of the object
is detected.
* Directories can be created as objects setting the
content-type to application/directory and content-length
to 0.
* Functional tests have been adjusted to work with
G4S constraints
Change-Id: I31038a59699a8e3eeaba902db322218c6400093e
Signed-off-by: Luis Pabon <lpabon@redhat.com>
Reviewed-on: http://review.gluster.org/5246
Reviewed-by: Peter Portante <pportant@redhat.com>
Tested-by: Peter Portante <pportant@redhat.com>
Diffstat (limited to 'test/functional')
-rw-r--r-- | test/functional/gluster_swift_tests.py | 151 | ||||
-rw-r--r-- | test/functional/tests.py | 32 |
2 files changed, 182 insertions, 1 deletions
diff --git a/test/functional/gluster_swift_tests.py b/test/functional/gluster_swift_tests.py new file mode 100644 index 0000000..442c315 --- /dev/null +++ b/test/functional/gluster_swift_tests.py @@ -0,0 +1,151 @@ +# Copyright (c) 2013 Red Hat, Inc. +# +# 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. + +""" OpenStack Swift based functional tests for Gluster for Swift""" + +from test.functional.tests import config, locale, Base, Utils +from test.functional.swift_test_client import Account, Connection, File, \ + ResponseError + + +class TestGlusterContainerPathsEnv: + @classmethod + def setUp(cls): + cls.conn = Connection(config) + cls.conn.authenticate() + cls.account = Account(cls.conn, config.get('account', + config['username'])) + cls.account.delete_containers() + + cls.file_size = 8 + + cls.container = cls.account.container(Utils.create_name()) + if not cls.container.create(): + raise ResponseError(cls.conn.response) + + cls.dirs = [ + 'dir1', + 'dir2', + 'dir1/subdir1', + 'dir1/subdir2', + 'dir1/subdir1/subsubdir1', + 'dir1/subdir1/subsubdir2', + 'dir1/subdir with spaces', + 'dir1/subdir+with{whatever', + ] + + cls.files = [ + 'file1', + 'file A', + 'dir1/file2', + 'dir1/subdir1/file2', + 'dir1/subdir1/file3', + 'dir1/subdir1/file4', + 'dir1/subdir1/subsubdir1/file5', + 'dir1/subdir1/subsubdir1/file6', + 'dir1/subdir1/subsubdir1/file7', + 'dir1/subdir1/subsubdir1/file8', + 'dir1/subdir1/subsubdir2/file9', + 'dir1/subdir1/subsubdir2/file0', + 'dir1/subdir with spaces/file B', + 'dir1/subdir+with{whatever/file D', + ] + + stored_files = set() + for d in cls.dirs: + file = cls.container.file(d) + file.write(hdrs={'Content-Type': 'application/directory'}) + for f in cls.files: + file = cls.container.file(f) + file.write_random(cls.file_size, hdrs={'Content-Type': + 'application/octet-stream'}) + stored_files.add(f) + cls.stored_files = sorted(stored_files) + cls.sorted_objects = sorted(set(cls.dirs + cls.files)) + + +class TestGlusterContainerPaths(Base): + env = TestGlusterContainerPathsEnv + set_up = False + + def testTraverseContainer(self): + found_files = [] + found_dirs = [] + + def recurse_path(path, count=0): + if count > 10: + raise ValueError('too deep recursion') + + for file in self.env.container.files(parms={'path': path}): + self.assert_(file.startswith(path)) + if file in self.env.dirs: + recurse_path(file, count + 1) + found_dirs.append(file) + else: + found_files.append(file) + + recurse_path('') + for file in self.env.stored_files: + self.assert_(file in found_files) + self.assert_(file not in found_dirs) + + + def testContainerListing(self): + for format in (None, 'json', 'xml'): + files = self.env.container.files(parms={'format': format}) + self.assertFalse(len(files) == 0) + + if isinstance(files[0], dict): + files = [str(x['name']) for x in files] + + self.assertEquals(files, self.env.sorted_objects) + + for format in ('json', 'xml'): + for file in self.env.container.files(parms={'format': format}): + self.assert_(int(file['bytes']) >= 0) + self.assert_('last_modified' in file) + if file['name'] in self.env.dirs: + self.assertEquals(file['content_type'], + 'application/directory') + else: + self.assertEquals(file['content_type'], + 'application/octet-stream') + + def testStructure(self): + def assert_listing(path, list): + files = self.env.container.files(parms={'path': path}) + self.assertEquals(sorted(list, cmp=locale.strcoll), files) + + assert_listing('', ['file1', 'dir1', 'dir2', 'file A']) + assert_listing('dir1', ['dir1/file2', 'dir1/subdir1', + 'dir1/subdir2', 'dir1/subdir with spaces', + 'dir1/subdir+with{whatever']) + assert_listing('dir1/subdir1', + ['dir1/subdir1/file4', 'dir1/subdir1/subsubdir2', + 'dir1/subdir1/file2', 'dir1/subdir1/file3', + 'dir1/subdir1/subsubdir1']) + assert_listing('dir1/subdir1/subsubdir1', + ['dir1/subdir1/subsubdir1/file7', + 'dir1/subdir1/subsubdir1/file5', + 'dir1/subdir1/subsubdir1/file8', + 'dir1/subdir1/subsubdir1/file6']) + assert_listing('dir1/subdir1/subsubdir1', + ['dir1/subdir1/subsubdir1/file7', + 'dir1/subdir1/subsubdir1/file5', + 'dir1/subdir1/subsubdir1/file8', + 'dir1/subdir1/subsubdir1/file6']) + assert_listing('dir1/subdir with spaces', + ['dir1/subdir with spaces/file B']) + diff --git a/test/functional/tests.py b/test/functional/tests.py index d6f8d70..da45cde 100644 --- a/test/functional/tests.py +++ b/test/functional/tests.py @@ -15,6 +15,7 @@ # limitations under the License. from datetime import datetime +import os import locale import random import StringIO @@ -32,6 +33,8 @@ from swift.common.constraints import MAX_FILE_SIZE, MAX_META_NAME_LENGTH, \ MAX_META_VALUE_LENGTH, MAX_META_COUNT, MAX_META_OVERALL_SIZE, \ MAX_OBJECT_NAME_LENGTH, CONTAINER_LISTING_LIMIT, ACCOUNT_LISTING_LIMIT, \ MAX_ACCOUNT_NAME_LENGTH, MAX_CONTAINER_NAME_LENGTH +from gluster.swift.common.constraints import \ + set_object_name_component_length, get_object_name_component_length default_constraints = dict(( ('max_file_size', MAX_FILE_SIZE), @@ -69,6 +72,7 @@ for k in default_constraints: web_front_end = config.get('web_front_end', 'integral') normalized_urls = config.get('normalized_urls', False) +set_object_name_component_length() def load_constraint(name): c = config[name] @@ -79,6 +83,31 @@ def load_constraint(name): locale.setlocale(locale.LC_COLLATE, config.get('collate', 'C')) +def create_limit_filename(name_limit): + """ + Convert a split a large object name with + slashes so as to conform the GlusterFS file name + constraints. + Example: Take a object name: 'a'*1024, and + convert it to a*255/a*255/... + """ + # Get the file name limit from the configuration file + filename_limit = get_object_name_component_length() + + # Convert string to a list: "abc" -> ['a', 'b', 'c'] + filename_list = list('a' * name_limit) + + # Replace chars at filename limits to '/' + for index in range(filename_limit, name_limit, filename_limit): + filename_list[index] = os.path.sep + + # Cannot end in a '/' + if os.path.sep == filename_list[-1]: + return "".join(filename_list[:-1]) + else: + return "".join(filename_list) + + def chunks(s, length=3): i, j = 0, length while i < len(s): @@ -675,6 +704,7 @@ class TestContainerUTF8(Base2, TestContainer): class TestContainerPathsEnv: @classmethod def setUp(cls): + raise SkipTest('Objects ending in / are not supported') cls.conn = Connection(config) cls.conn.authenticate() cls.account = Account(cls.conn, config.get('account', @@ -1034,7 +1064,7 @@ class TestFile(Base): limit = load_constraint('max_object_name_length') for l in (1, 10, limit / 2, limit - 1, limit, limit + 1, limit * 2): - file = self.env.container.file('a' * l) + file = self.env.container.file(create_limit_filename(l)) if l <= limit: self.assert_(file.write()) |