diff --git a/s3tests/functional/test_s3.py b/s3tests/functional/test_s3.py index b8dc47f..46512d0 100644 --- a/s3tests/functional/test_s3.py +++ b/s3tests/functional/test_s3.py @@ -28,6 +28,7 @@ import re import xml.etree.ElementTree as ET +from collections import namedtuple from email.Utils import formatdate from httplib import HTTPConnection, HTTPSConnection from urlparse import urlparse @@ -7492,7 +7493,8 @@ def create_lifecycle(days = None, prefix = 'test/', rules = None): else: for rule in rules: expiration = boto.s3.lifecycle.Expiration(days=rule['days']) - rule = boto.s3.lifecycle.Rule(id=rule['id'], prefix=rule['prefix'], + _id = rule.get('id',None) + rule = boto.s3.lifecycle.Rule(id=_id, prefix=rule['prefix'], status=rule['status'], expiration=expiration) lifecycle.append(rule) return lifecycle @@ -7529,6 +7531,37 @@ def test_lifecycle_get(): eq(current[1].id, 'test2/') eq(current[1].prefix, 'test2/') + + +@attr(resource='bucket') +@attr(method='get') +@attr(operation='get lifecycle config no id') +@attr('lifecycle') +def test_lifecycle_get_no_id(): + Rule = namedtuple('Rule',['prefix','status','days']) + rules = {'rule1' : Rule('test1/','Enabled',31), + 'rule2' : Rule('test2/','Enabled',120)} + bucket = set_lifecycle(rules=[{'days': rules['rule1'].days , + 'prefix': rules['rule1'].prefix, + 'status': rules['rule1'].status}, + {'days': rules['rule2'].days, + 'prefix': rules['rule2'].prefix, + 'status': rules['rule2'].status}]) + current_lc = bucket.get_lifecycle_config() + # We can't guarantee the order of XML, since the id is random, let's walk + # through the rules and validate that both were present + for lc_rule in current_lc: + if lc_rule.expiration.days == rules['rule1'].days: + eq(lc_rule.prefix, rules['rule1'].prefix) + assert len(lc_rule.id) > 0 + elif lc_rule.expiration.days == rules['rule2'].days: + eq(lc_rule.prefix, rules['rule2'].prefix) + assert len(lc_rule.id) > 0 + else: + # neither of the rules we supplied, something wrong + assert False + + # The test harnass for lifecycle is configured to treat days as 2 second intervals. @attr(resource='bucket') @attr(method='put') @@ -7622,7 +7655,15 @@ def test_lifecycle_rules_conflicted(): def generate_lifecycle_body(rules): body = '' for rule in rules: - body += '%s%s%s' % (rule['ID'], rule['Prefix'], rule['Status']) + body += '%s%s' % (rule['ID'], rule['Status']) + if 'Prefix' in rule.keys(): + body += '%s' % rule['Prefix'] + if 'Filter' in rule.keys(): + prefix_str= '' # AWS supports empty filters + if 'Prefix' in rule['Filter'].keys(): + prefix_str = '%s' % rule['Filter']['Prefix'] + body += '%s' % prefix_str + if 'Expiration' in rule.keys(): if 'ExpiredObjectDeleteMarker' in rule['Expiration'].keys(): body += '%s' \ @@ -7774,6 +7815,44 @@ def test_lifecycle_set_deletemarker(): eq(res.status, 200) eq(res.reason, 'OK') +@attr(resource='bucket') +@attr(method='put') +@attr(operation='set lifecycle config with Filter') +@attr('lifecycle') +def test_lifecycle_set_filter(): + bucket = get_new_bucket() + rules = [ + {'ID': 'rule1', 'Filter': {'Prefix': 'foo'}, 'Status': 'Enabled', 'Expiration': {'ExpiredObjectDeleteMarker': 'true'}} + ] + body = generate_lifecycle_body(rules) + fp = StringIO(body) + md5 = boto.utils.compute_md5(fp) + headers = {'Content-MD5': md5[1], 'Content-Type': 'text/xml'} + res = bucket.connection.make_request('PUT', bucket.name, data=fp.getvalue(), query_args='lifecycle', + headers=headers) + eq(res.status, 200) + eq(res.reason, 'OK') + +@attr(resource='bucket') +@attr(method='put') +@attr(operation='set lifecycle config with empty Filter') +@attr('lifecycle') +def test_lifecycle_set_empty_filter(): + bucket = get_new_bucket() + rules = [ + {'ID': 'rule1', 'Filter': {}, 'Status': 'Enabled', 'Expiration': {'ExpiredObjectDeleteMarker': 'true'}} + ] + body = generate_lifecycle_body(rules) + fp = StringIO(body) + md5 = boto.utils.compute_md5(fp) + headers = {'Content-MD5': md5[1], 'Content-Type': 'text/xml'} + res = bucket.connection.make_request('PUT', bucket.name, data=fp.getvalue(), query_args='lifecycle', + headers=headers) + eq(res.status, 200) + eq(res.reason, 'OK') + + + # The test harnass for lifecycle is configured to treat days as 1 second intervals. @attr(resource='bucket')