test/alternator: add more tests for TagResource

Issue #16904 discovered that Alternator refuses to allow an empty tag
value while it's useful (and DynamoDB allows it). This brought to my
attention that our test coverage of the TagResource operation was lacking.
So this patch adds more tests for some corner cases of TagResource which
we missed, including the allowed lengths of tag keys and values.

These tests reproduce #16904 (the case of empty tag value) and also #16908
(allowing and correctly counting unicode letters), and also add
regression testing to cases which we already handled correctly.

As usual, all the new tests also pass on DynamoDB.

Refs #16904
Refs #16908

Signed-off-by: Nadav Har'El <nyh@scylladb.com>
This commit is contained in:
Nadav Har'El
2024-01-21 20:16:12 +02:00
parent 08b26269d8
commit 830e52008d

View File

@@ -342,3 +342,106 @@ def test_concurrent_tag(dynamodb, test_table):
t2.start()
t1.join()
t2.join()
# An empty string is allowed as a tag's value
# Reproduces #16904.
def test_empty_tag_value(dynamodb, test_table):
client = dynamodb.meta.client
arn = client.describe_table(TableName=test_table.name)['Table']['TableArn']
tag = random_string()
client.tag_resource(ResourceArn=arn, Tags=[{'Key': tag, 'Value': ''}])
# Verify that the tag with the empty value was correctly saved:
tags = client.list_tags_of_resource(ResourceArn=arn)['Tags']
assert {'Key': tag, 'Value': ''} in tags
# Clean up the tag we just added
client.untag_resource(ResourceArn=arn, TagKeys=[tag])
# However, an empty string is NOT allowed as a tag's key
def test_empty_tag_key(dynamodb, test_table):
client = dynamodb.meta.client
arn = client.describe_table(TableName=test_table.name)['Table']['TableArn']
with pytest.raises(ClientError, match='ValidationException'):
client.tag_resource(ResourceArn=arn, Tags=[{'Key': '', 'Value': 'dog'}])
# Although an empty Value is allowed for a tag, a *missing* Value is not
# allowed:
def test_missing_tag_value(dynamodb, test_table):
client = dynamodb.meta.client
arn = client.describe_table(TableName=test_table.name)['Table']['TableArn']
with pytest.raises(ClientError, match='ValidationException'):
client.tag_resource(ResourceArn=arn, Tags=[{'Key': 'dog'}])
# According to the DynamoDB documentation, the maximum tag key length allowed
# is 128 characters. Actually, it's 128 *unicode* characters which are
# allowed, not 128 bytes.
# Reproduces #16908
@pytest.mark.parametrize("is_ascii", [
True,
pytest.param(False, marks=pytest.mark.xfail(reason="#16908"))])
def test_tag_key_length_128_allowed(dynamodb, test_table, is_ascii):
client = dynamodb.meta.client
arn = client.describe_table(TableName=test_table.name)['Table']['TableArn']
tag = ('x' if is_ascii else 'א') * 128
client.tag_resource(ResourceArn=arn, Tags=[{'Key': tag, 'Value': 'dog'}])
tags = client.list_tags_of_resource(ResourceArn=arn)['Tags']
assert {'Key': tag, 'Value': 'dog'} in tags
client.untag_resource(ResourceArn=arn, TagKeys=[tag])
def test_tag_key_length_129_forbidden(dynamodb, test_table):
client = dynamodb.meta.client
arn = client.describe_table(TableName=test_table.name)['Table']['TableArn']
tag = 'x'*129
with pytest.raises(ClientError, match='ValidationException'):
client.tag_resource(ResourceArn=arn, Tags=[{'Key': tag, 'Value': 'dog'}])
# According to the DynamoDB documentation, the maximum tag value length
# allowed is 256 characters. Actually, it's 256 *unicode* characters which
# are allowed, not 256 bytes.
# Reproduces #16908
@pytest.mark.parametrize("is_ascii", [
True,
pytest.param(False, marks=pytest.mark.xfail(reason="#16908"))])
def test_tag_value_length_256_allowed(dynamodb, test_table, is_ascii):
client = dynamodb.meta.client
arn = client.describe_table(TableName=test_table.name)['Table']['TableArn']
tag = random_string()
value = ('x' if is_ascii else 'א') * 256
client.tag_resource(ResourceArn=arn, Tags=[{'Key': tag, 'Value': value}])
tags = client.list_tags_of_resource(ResourceArn=arn)['Tags']
assert {'Key': tag, 'Value': value} in tags
client.untag_resource(ResourceArn=arn, TagKeys=[tag])
def test_tag_value_length_257_forbidden(dynamodb, test_table):
client = dynamodb.meta.client
arn = client.describe_table(TableName=test_table.name)['Table']['TableArn']
value = 'x'*257
with pytest.raises(ClientError, match='ValidationException'):
client.tag_resource(ResourceArn=arn, Tags=[{'Key': 'dog', 'Value': value}])
# According to the DynamoDB documentation, only letters, whitespace, numbers,
# and the characters [+-=._:/] are allowed in both tag keys or values.
# Let's check that other non-letter characters are not allowed in either
# key or value.
def test_tag_forbidden_chars(dynamodb, test_table):
client = dynamodb.meta.client
arn = client.describe_table(TableName=test_table.name)['Table']['TableArn']
for x in ['hi!', 'd%g', '"hello"']:
with pytest.raises(ClientError, match='ValidationException'):
client.tag_resource(ResourceArn=arn, Tags=[{'Key': x, 'Value': 'dog'}])
with pytest.raises(ClientError, match='ValidationException'):
client.tag_resource(ResourceArn=arn, Tags=[{'Key': 'dog', 'Value': x}])
# Check that's it's allowed to reassign a new value to an existing tag.
def test_tag_reassign(dynamodb, test_table):
client = dynamodb.meta.client
arn = client.describe_table(TableName=test_table.name)['Table']['TableArn']
tag = random_string()
value1 = random_string()
value2 = random_string()
client.tag_resource(ResourceArn=arn, Tags=[{'Key': tag, 'Value': value1}])
tags = client.list_tags_of_resource(ResourceArn=arn)['Tags']
assert {'Key': tag, 'Value': value1} in tags
client.tag_resource(ResourceArn=arn, Tags=[{'Key': tag, 'Value': value2}])
tags = client.list_tags_of_resource(ResourceArn=arn)['Tags']
assert {'Key': tag, 'Value': value2} in tags
client.untag_resource(ResourceArn=arn, TagKeys=[tag])