diff --git a/test/functional/__init__.py b/test/functional/__init__.py index 7992bf4add..4f3e1eeeb7 100644 --- a/test/functional/__init__.py +++ b/test/functional/__init__.py @@ -28,7 +28,7 @@ from swift.common import constraints from swiftclient import get_auth, http_connection from test import get_config -from test.functional.swift_test_client import Connection +from test.functional.swift_test_client import Connection, ResponseError config = {} @@ -47,24 +47,51 @@ skip, skip2, skip3 = False, False, False orig_collate = '' +cluster_info = {} + + +def get_cluster_info(): + # The fallback constraints used for testing will come from the current + # effective constraints. + eff_constraints = dict(constraints.EFFECTIVE_CONSTRAINTS) + + # We'll update those constraints based on what the /info API provides, if + # anything. + global cluster_info + try: + conn = Connection(config) + conn.authenticate() + cluster_info.update(conn.cluster_info()) + except (ResponseError, socket.error): + # Failed to get cluster_information via /info API, so fall back on + # test.conf data + pass + else: + eff_constraints.update(cluster_info['swift']) + + # Finally, we'll allow any constraint present in the swift-constraints + # section of test.conf to override everything. Note that only those + # constraints defined in the constraints module are converted to integers. + test_constraints = get_config('swift-constraints') + for k in constraints.DEFAULT_CONSTRAINTS: + try: + test_constraints[k] = int(test_constraints[k]) + except KeyError: + pass + except ValueError: + print >>sys.stderr, "Invalid constraint value: %s = %s" % ( + k, test_constraints[k]) + eff_constraints.update(test_constraints) + + # Just make it look like these constraints were loaded from a /info call, + # even if the /info call failed, or when they are overridden by values + # from the swift-constraints section of test.conf + cluster_info['swift'] = eff_constraints + def setup_package(): global config config.update(get_config('func_test')) - for k in constraints.DEFAULT_CONSTRAINTS: - if k in config: - # prefer what's in test.conf - config[k] = int(config[k]) - elif constraints.SWIFT_CONSTRAINTS_LOADED: - # swift.conf exists, so use what's defined there (or swift - # defaults) This normally happens when the test is running locally - # to the cluster as in a SAIO. - config[k] = constraints.EFFECTIVE_CONSTRAINTS[k] - else: - # .functests don't know what the constraints of the tested cluster - # are, so the tests can't reliably pass or fail. Therefore, skip - # those tests. - config[k] = '%s constraint is not defined' % k global web_front_end web_front_end = config.get('web_front_end', 'integral') @@ -160,6 +187,8 @@ def setup_package(): print >>sys.stderr, \ 'SKIPPING THIRD ACCOUNT FUNCTIONAL TESTS DUE TO NO CONFIG FOR THEM' + get_cluster_info() + def teardown_package(): global orig_collate @@ -249,21 +278,14 @@ def check_response(conn): def load_constraint(name): - global config - c = config[name] - if not isinstance(c, int): - raise SkipTest(c) - return c - - -cluster_info = {} - - -def get_cluster_info(): - conn = Connection(config) - conn.authenticate() global cluster_info - cluster_info = conn.cluster_info() + try: + c = cluster_info['swift'][name] + except KeyError: + raise SkipTest("Missing constraint: %s" % name) + if not isinstance(c, int): + raise SkipTest("Bad value, %r, for constraint: %s" % (c, name)) + return c def reset_acl(): @@ -280,10 +302,8 @@ def reset_acl(): def requires_acls(f): @functools.wraps(f) def wrapper(*args, **kwargs): - if skip: + if skip or not cluster_info: raise SkipTest - if not cluster_info: - get_cluster_info() # Determine whether this cluster has account ACLs; if not, skip test if not cluster_info.get('tempauth', {}).get('account_acls'): raise SkipTest diff --git a/test/functional/swift_test_client.py b/test/functional/swift_test_client.py index ce7508841c..142daae556 100644 --- a/test/functional/swift_test_client.py +++ b/test/functional/swift_test_client.py @@ -103,7 +103,8 @@ class Connection(object): def __init__(self, config): for key in 'auth_host auth_port auth_ssl username password'.split(): if key not in config: - raise SkipTest + raise SkipTest( + "Missing required configuration parameter: %s" % key) self.auth_host = config['auth_host'] self.auth_port = int(config['auth_port']) @@ -117,6 +118,7 @@ class Connection(object): self.storage_host = None self.storage_port = None + self.storage_url = None self.conn_class = None @@ -278,8 +280,6 @@ class Connection(object): (request, len(fail_messages), fail_messages)) def put_start(self, path, hdrs={}, parms={}, cfg={}, chunked=False): - self.http_connect() - path = self.make_path(path, cfg) headers = self.make_headers(hdrs, cfg=cfg) diff --git a/test/functional/test_object.py b/test/functional/test_object.py index 7252cd0058..39e32ce75a 100755 --- a/test/functional/test_object.py +++ b/test/functional/test_object.py @@ -894,14 +894,6 @@ class TestObject(unittest.TestCase): if tf.skip: raise SkipTest - def is_strict_mode(url, token, parsed, conn): - conn.request('GET', '/info') - resp = conn.getresponse() - if resp.status // 100 == 2: - info = json.loads(resp.read()) - return info.get('swift', {}).get('strict_cors_mode', False) - return False - def put_cors_cont(url, token, parsed, conn, orig): conn.request( 'PUT', '%s/%s' % (parsed.path, self.container), @@ -924,8 +916,6 @@ class TestObject(unittest.TestCase): '', headers) return conn.getresponse() - strict_cors = retry(is_strict_mode) - resp = retry(put_cors_cont, '*') resp.read() self.assertEquals(resp.status // 100, 2) @@ -977,6 +967,11 @@ class TestObject(unittest.TestCase): resp.read() self.assertEquals(resp.status, 401) + try: + strict_cors = tf.cluster_info['swift']['strict_cors_mode'] + except KeyError: + strict_cors = False + if strict_cors: resp = retry(check_cors, 'GET', 'cat', {'Origin': 'http://m.com'}) diff --git a/test/functional/tests.py b/test/functional/tests.py index 665b67aa76..959ceb7224 100644 --- a/test/functional/tests.py +++ b/test/functional/tests.py @@ -31,7 +31,7 @@ from nose import SkipTest from swift.common.utils import get_hub -from test.functional import normalized_urls, load_constraint +from test.functional import normalized_urls, load_constraint, cluster_info import test.functional as tf from test.functional.swift_test_client import Account, Connection, File, \ ResponseError @@ -1790,7 +1790,6 @@ class TestSloEnv(object): cls.conn.authenticate() if cls.slo_enabled is None: - cluster_info = cls.conn.cluster_info() cls.slo_enabled = 'slo' in cluster_info if not cls.slo_enabled: return @@ -2138,7 +2137,6 @@ class TestTempurlEnv(object): cls.conn.authenticate() if cls.tempurl_enabled is None: - cluster_info = cls.conn.cluster_info() cls.tempurl_enabled = 'tempurl' in cluster_info if not cls.tempurl_enabled: return @@ -2313,7 +2311,6 @@ class TestSloTempurlEnv(object): cls.conn.authenticate() if cls.enabled is None: - cluster_info = cls.conn.cluster_info() cls.enabled = 'tempurl' in cluster_info and 'slo' in cluster_info cls.tempurl_key = Utils.create_name() diff --git a/test/sample.conf b/test/sample.conf index 161a588aa2..bb6bf8b008 100644 --- a/test/sample.conf +++ b/test/sample.conf @@ -1,5 +1,5 @@ [func_test] -# sample config +# sample config for Swift with tempauth auth_host = 127.0.0.1 auth_port = 8080 auth_ssl = no @@ -25,11 +25,32 @@ password2 = testing2 username3 = tester3 password3 = testing3 -# If not defined here, the test runner will try to use the default constraint -# values as constructed by the constraints module, which will attempt to get -# them from /etc/swift/swift.conf, if possible. Then, if the swift.conf file -# isn't found, the test runner will skip tests that depend on those values. -# Note that the cluster must have "sane" values for the test suite to pass. +collate = C + +[unit_test] +fake_syslog = False + +[probe_test] +# check_server_timeout = 30 +# validate_rsync = false + +[swift-constraints] +# The functional test runner will try to use the constraint values provided in +# the swift-constraints section of test.conf. +# +# If a constraint value does not exist in that section, or because the +# swift-constraints section does not exist, the constraints values found in +# the /info API call (if successful) will be used. +# +# If a constraint value cannot be found in the /info results, either because +# the /info API call failed, or a value is not present, the constraint value +# used will fall back to those loaded by the constraints module at time of +# import (which will attempt to load /etc/swift/swift.conf, see the +# swift.common.constraints module for more information). +# +# Note that the cluster must have "sane" values for the test suite to pass +# (for some definition of sane). +# #max_file_size = 5368709122 #max_meta_name_length = 128 #max_meta_value_length = 256 @@ -42,11 +63,6 @@ password3 = testing3 #max_account_name_length = 256 #max_container_name_length = 256 -collate = C - -[unit_test] -fake_syslog = False - -[probe_test] -# check_server_timeout = 30 -# validate_rsync = false +# Newer swift versions default to strict cors mode, but older ones were the +# opposite. +#strict_cors_mode = true