From 47d6d7a10c0162590ccf8003b81b687d2e359862 Mon Sep 17 00:00:00 2001 From: gholt Date: Mon, 16 Aug 2010 19:11:19 -0700 Subject: [PATCH] Argh. Forgot the tests themselves! --- test/functionalnosetests/__init__.py | 0 test/functionalnosetests/swift_testing.py | 94 +++++++ test/functionalnosetests/test_account.py | 136 ++++++++++ test/functionalnosetests/test_container.py | 302 +++++++++++++++++++++ 4 files changed, 532 insertions(+) create mode 100644 test/functionalnosetests/__init__.py create mode 100644 test/functionalnosetests/swift_testing.py create mode 100755 test/functionalnosetests/test_account.py create mode 100755 test/functionalnosetests/test_container.py diff --git a/test/functionalnosetests/__init__.py b/test/functionalnosetests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/functionalnosetests/swift_testing.py b/test/functionalnosetests/swift_testing.py new file mode 100644 index 0000000000..1c805f854d --- /dev/null +++ b/test/functionalnosetests/swift_testing.py @@ -0,0 +1,94 @@ +import errno +import os +import socket +import sys +from ConfigParser import ConfigParser +from httplib import HTTPException +from time import sleep + +from swift.common.client import get_auth, http_connection + + +swift_test_auth = os.environ.get('SWIFT_TEST_AUTH') +swift_test_user = os.environ.get('SWIFT_TEST_USER') +swift_test_key = os.environ.get('SWIFT_TEST_KEY') + +# If no environment set, fall back to old school conf file +if not all([swift_test_auth, swift_test_user, swift_test_key]): + conf = ConfigParser() + class Sectionizer(object): + def __init__(self, fp): + self.sent_section = False + self.fp = fp + def readline(self): + if self.sent_section: + return self.fp.readline() + self.sent_section = True + return '[func_test]\n' + try: + conf.readfp(Sectionizer(open('/etc/swift/func_test.conf'))) + conf = dict(conf.items('func_test')) + swift_test_auth = 'http' + if conf.get('auth_ssl', 'no').lower() in ('yes', 'true', 'on', '1'): + swift_test_auth = 'https' + swift_test_auth += '://%(auth_host)s:%(auth_port)s/v1.0' % conf + swift_test_user = '%(account)s:%(username)s' % conf + swift_test_key = conf['password'] + except IOError, err: + if err.errno != errno.ENOENT: + raise + +skip = not all([swift_test_auth, swift_test_user, swift_test_key]) +if skip: + print >>sys.stderr, 'SKIPPING FUNCTIONAL TESTS DUE TO NO CONFIG' + + +class AuthError(Exception): + pass + + +class InternalServerError(Exception): + pass + + +url = token = parsed = conn = None + +def retry(func, *args, **kwargs): + global url, token, parsed, conn + retries = kwargs.get('retries', 5) + attempts = 0 + backoff = 1 + while attempts <= retries: + attempts += 1 + try: + if not url or not token: + url, token = \ + get_auth(swift_test_auth, swift_test_user, swift_test_key) + parsed = conn = None + if not parsed or not conn: + parsed, conn = http_connection(url) + return func(url, token, parsed, conn, *args, **kwargs) + except (socket.error, HTTPException): + if attempts > retries: + raise + parsed = conn = None + except AuthError, err: + url = token = None + continue + except InternalServerError, err: + pass + if attempts <= retries: + sleep(backoff) + backoff *= 2 + raise Exception('No result after %s retries.' % retries) + + +def check_response(conn): + resp = conn.getresponse() + if resp.status == 401: + resp.read() + raise AuthError() + elif resp.status // 100 == 5: + resp.read() + raise InternalServerError() + return resp diff --git a/test/functionalnosetests/test_account.py b/test/functionalnosetests/test_account.py new file mode 100755 index 0000000000..dea19380ac --- /dev/null +++ b/test/functionalnosetests/test_account.py @@ -0,0 +1,136 @@ +#!/usr/bin/python + +import unittest + +from swift.common.constraints import MAX_META_COUNT, MAX_META_NAME_LENGTH, \ + MAX_META_OVERALL_SIZE, MAX_META_VALUE_LENGTH + +from swift_testing import check_response, retry, skip + + +class TestAccount(unittest.TestCase): + + def test_metadata(self): + if skip: + return + def post(url, token, parsed, conn, value): + conn.request('POST', parsed.path, '', + {'X-Auth-Token': token, 'X-Account-Meta-Test': value}) + return check_response(conn) + def head(url, token, parsed, conn): + conn.request('HEAD', parsed.path, '', {'X-Auth-Token': token}) + return check_response(conn) + def get(url, token, parsed, conn): + conn.request('GET', parsed.path, '', {'X-Auth-Token': token}) + return check_response(conn) + resp = retry(post, '') + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(head) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-account-meta-test'), None) + resp = retry(get) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-account-meta-test'), None) + resp = retry(post, 'Value') + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(head) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-account-meta-test'), 'Value') + resp = retry(get) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-account-meta-test'), 'Value') + + def test_multi_metadata(self): + if skip: + return + def post(url, token, parsed, conn, name, value): + conn.request('POST', parsed.path, '', + {'X-Auth-Token': token, name: value}) + return check_response(conn) + def head(url, token, parsed, conn): + conn.request('HEAD', parsed.path, '', {'X-Auth-Token': token}) + return check_response(conn) + resp = retry(post, 'X-Account-Meta-One', '1') + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(head) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-account-meta-one'), '1') + resp = retry(post, 'X-Account-Meta-Two', '2') + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(head) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-account-meta-one'), '1') + self.assertEquals(resp.getheader('x-account-meta-two'), '2') + + def test_bad_metadata(self): + if skip: + return + def post(url, token, parsed, conn, extra_headers): + headers = {'X-Auth-Token': token} + headers.update(extra_headers) + conn.request('POST', parsed.path, '', headers) + return check_response(conn) + resp = retry(post, + {'X-Account-Meta-' + ('k' * MAX_META_NAME_LENGTH): 'v'}) + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(post, + {'X-Account-Meta-' + ('k' * (MAX_META_NAME_LENGTH + 1)): 'v'}) + resp.read() + self.assertEquals(resp.status, 400) + + resp = retry(post, + {'X-Account-Meta-Too-Long': 'k' * MAX_META_VALUE_LENGTH}) + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(post, + {'X-Account-Meta-Too-Long': 'k' * (MAX_META_VALUE_LENGTH + 1)}) + resp.read() + self.assertEquals(resp.status, 400) + + headers = {} + for x in xrange(MAX_META_COUNT): + headers['X-Account-Meta-%d' % x] = 'v' + resp = retry(post, headers) + resp.read() + self.assertEquals(resp.status, 204) + headers = {} + for x in xrange(MAX_META_COUNT + 1): + headers['X-Account-Meta-%d' % x] = 'v' + resp = retry(post, headers) + resp.read() + self.assertEquals(resp.status, 400) + + headers = {} + header_value = 'k' * MAX_META_VALUE_LENGTH + size = 0 + x = 0 + while size < MAX_META_OVERALL_SIZE - 4 - MAX_META_VALUE_LENGTH: + size += 4 + MAX_META_VALUE_LENGTH + headers['X-Account-Meta-%04d' % x] = header_value + x += 1 + if MAX_META_OVERALL_SIZE - size > 1: + headers['X-Account-Meta-k'] = \ + 'v' * (MAX_META_OVERALL_SIZE - size - 1) + resp = retry(post, headers) + resp.read() + self.assertEquals(resp.status, 204) + headers['X-Account-Meta-k'] = \ + 'v' * (MAX_META_OVERALL_SIZE - size) + resp = retry(post, headers) + resp.read() + self.assertEquals(resp.status, 400) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/functionalnosetests/test_container.py b/test/functionalnosetests/test_container.py new file mode 100755 index 0000000000..9c36b460b8 --- /dev/null +++ b/test/functionalnosetests/test_container.py @@ -0,0 +1,302 @@ +#!/usr/bin/python + +import unittest +from uuid import uuid4 + +from swift.common.constraints import MAX_META_COUNT, MAX_META_NAME_LENGTH, \ + MAX_META_OVERALL_SIZE, MAX_META_VALUE_LENGTH + +from swift_testing import check_response, retry, skip + + +class TestContainer(unittest.TestCase): + + def setUp(self): + if skip: + return + self.name = uuid4().hex + def put(url, token, parsed, conn): + conn.request('PUT', parsed.path + '/' + self.name, '', + {'X-Auth-Token': token}) + return check_response(conn) + resp = retry(put) + resp.read() + self.assertEquals(resp.status, 201) + + def tearDown(self): + if skip: + return + def delete(url, token, parsed, conn): + conn.request('DELETE', parsed.path + '/' + self.name, '', + {'X-Auth-Token': token}) + return check_response(conn) + resp = retry(delete) + resp.read() + self.assertEquals(resp.status, 204) + + def test_multi_metadata(self): + if skip: + return + def post(url, token, parsed, conn, name, value): + conn.request('POST', parsed.path + '/' + self.name, '', + {'X-Auth-Token': token, name: value}) + return check_response(conn) + def head(url, token, parsed, conn): + conn.request('HEAD', parsed.path + '/' + self.name, '', + {'X-Auth-Token': token}) + return check_response(conn) + resp = retry(post, 'X-Container-Meta-One', '1') + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(head) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-one'), '1') + resp = retry(post, 'X-Container-Meta-Two', '2') + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(head) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-one'), '1') + self.assertEquals(resp.getheader('x-container-meta-two'), '2') + + def test_PUT_metadata(self): + if skip: + return + def put(url, token, parsed, conn, name, value): + conn.request('PUT', parsed.path + '/' + name, '', + {'X-Auth-Token': token, 'X-Container-Meta-Test': value}) + return check_response(conn) + def head(url, token, parsed, conn, name): + conn.request('HEAD', parsed.path + '/' + name, '', + {'X-Auth-Token': token}) + return check_response(conn) + def get(url, token, parsed, conn, name): + conn.request('GET', parsed.path + '/' + name, '', + {'X-Auth-Token': token}) + return check_response(conn) + def delete(url, token, parsed, conn, name): + conn.request('DELETE', parsed.path + '/' + name, '', + {'X-Auth-Token': token}) + return check_response(conn) + name = uuid4().hex + resp = retry(put, name, 'Value') + resp.read() + self.assertEquals(resp.status, 201) + resp = retry(head, name) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-test'), 'Value') + resp = retry(get, name) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-test'), 'Value') + name = uuid4().hex + resp = retry(put, name, '') + resp.read() + self.assertEquals(resp.status, 201) + resp = retry(head, name) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-test'), None) + resp = retry(get, name) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-test'), None) + resp = retry(delete, name) + resp.read() + self.assertEquals(resp.status, 204) + + def test_POST_metadata(self): + if skip: + return + def post(url, token, parsed, conn, value): + conn.request('POST', parsed.path + '/' + self.name, '', + {'X-Auth-Token': token, 'X-Container-Meta-Test': value}) + return check_response(conn) + def head(url, token, parsed, conn): + conn.request('HEAD', parsed.path + '/' + self.name, '', + {'X-Auth-Token': token}) + return check_response(conn) + def get(url, token, parsed, conn): + conn.request('GET', parsed.path + '/' + self.name, '', + {'X-Auth-Token': token}) + return check_response(conn) + resp = retry(head) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-test'), None) + resp = retry(get) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-test'), None) + resp = retry(post, 'Value') + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(head) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-test'), 'Value') + resp = retry(get) + resp.read() + self.assert_(resp.status in (200, 204), resp.status) + self.assertEquals(resp.getheader('x-container-meta-test'), 'Value') + + def test_PUT_bad_metadata(self): + if skip: + return + def put(url, token, parsed, conn, name, extra_headers): + headers = {'X-Auth-Token': token} + headers.update(extra_headers) + conn.request('PUT', parsed.path + '/' + name, '', headers) + return check_response(conn) + def delete(url, token, parsed, conn, name): + conn.request('DELETE', parsed.path + '/' + name, '', + {'X-Auth-Token': token}) + return check_response(conn) + name = uuid4().hex + resp = retry(put, name, + {'X-Container-Meta-' + ('k' * MAX_META_NAME_LENGTH): 'v'}) + resp.read() + self.assertEquals(resp.status, 201) + resp = retry(delete, name) + resp.read() + self.assertEquals(resp.status, 204) + name = uuid4().hex + resp = retry(put, name, + {'X-Container-Meta-' + ('k' * (MAX_META_NAME_LENGTH + 1)): 'v'}) + resp.read() + self.assertEquals(resp.status, 400) + resp = retry(delete, name) + resp.read() + self.assertEquals(resp.status, 404) + + name = uuid4().hex + resp = retry(put, name, + {'X-Container-Meta-Too-Long': 'k' * MAX_META_VALUE_LENGTH}) + resp.read() + self.assertEquals(resp.status, 201) + resp = retry(delete, name) + resp.read() + self.assertEquals(resp.status, 204) + name = uuid4().hex + resp = retry(put, name, + {'X-Container-Meta-Too-Long': 'k' * (MAX_META_VALUE_LENGTH + 1)}) + resp.read() + self.assertEquals(resp.status, 400) + resp = retry(delete, name) + resp.read() + self.assertEquals(resp.status, 404) + + name = uuid4().hex + headers = {} + for x in xrange(MAX_META_COUNT): + headers['X-Container-Meta-%d' % x] = 'v' + resp = retry(put, name, headers) + resp.read() + self.assertEquals(resp.status, 201) + resp = retry(delete, name) + resp.read() + self.assertEquals(resp.status, 204) + name = uuid4().hex + headers = {} + for x in xrange(MAX_META_COUNT + 1): + headers['X-Container-Meta-%d' % x] = 'v' + resp = retry(put, name, headers) + resp.read() + self.assertEquals(resp.status, 400) + resp = retry(delete, name) + resp.read() + self.assertEquals(resp.status, 404) + + name = uuid4().hex + headers = {} + header_value = 'k' * MAX_META_VALUE_LENGTH + size = 0 + x = 0 + while size < MAX_META_OVERALL_SIZE - 4 - MAX_META_VALUE_LENGTH: + size += 4 + MAX_META_VALUE_LENGTH + headers['X-Container-Meta-%04d' % x] = header_value + x += 1 + if MAX_META_OVERALL_SIZE - size > 1: + headers['X-Container-Meta-k'] = \ + 'v' * (MAX_META_OVERALL_SIZE - size - 1) + resp = retry(put, name, headers) + resp.read() + self.assertEquals(resp.status, 201) + resp = retry(delete, name) + resp.read() + self.assertEquals(resp.status, 204) + name = uuid4().hex + headers['X-Container-Meta-k'] = \ + 'v' * (MAX_META_OVERALL_SIZE - size) + resp = retry(put, name, headers) + resp.read() + self.assertEquals(resp.status, 400) + resp = retry(delete, name) + resp.read() + self.assertEquals(resp.status, 404) + + def test_POST_bad_metadata(self): + if skip: + return + def post(url, token, parsed, conn, extra_headers): + headers = {'X-Auth-Token': token} + headers.update(extra_headers) + conn.request('POST', parsed.path + '/' + self.name, '', headers) + return check_response(conn) + resp = retry(post, + {'X-Container-Meta-' + ('k' * MAX_META_NAME_LENGTH): 'v'}) + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(post, + {'X-Container-Meta-' + ('k' * (MAX_META_NAME_LENGTH + 1)): 'v'}) + resp.read() + self.assertEquals(resp.status, 400) + + resp = retry(post, + {'X-Container-Meta-Too-Long': 'k' * MAX_META_VALUE_LENGTH}) + resp.read() + self.assertEquals(resp.status, 204) + resp = retry(post, + {'X-Container-Meta-Too-Long': 'k' * (MAX_META_VALUE_LENGTH + 1)}) + resp.read() + self.assertEquals(resp.status, 400) + + headers = {} + for x in xrange(MAX_META_COUNT): + headers['X-Container-Meta-%d' % x] = 'v' + resp = retry(post, headers) + resp.read() + self.assertEquals(resp.status, 204) + headers = {} + for x in xrange(MAX_META_COUNT + 1): + headers['X-Container-Meta-%d' % x] = 'v' + resp = retry(post, headers) + resp.read() + self.assertEquals(resp.status, 400) + + headers = {} + header_value = 'k' * MAX_META_VALUE_LENGTH + size = 0 + x = 0 + while size < MAX_META_OVERALL_SIZE - 4 - MAX_META_VALUE_LENGTH: + size += 4 + MAX_META_VALUE_LENGTH + headers['X-Container-Meta-%04d' % x] = header_value + x += 1 + if MAX_META_OVERALL_SIZE - size > 1: + headers['X-Container-Meta-k'] = \ + 'v' * (MAX_META_OVERALL_SIZE - size - 1) + resp = retry(post, headers) + resp.read() + self.assertEquals(resp.status, 204) + headers['X-Container-Meta-k'] = \ + 'v' * (MAX_META_OVERALL_SIZE - size) + resp = retry(post, headers) + resp.read() + self.assertEquals(resp.status, 400) + + +if __name__ == '__main__': + unittest.main()