From a2bd4515eb75e670935e46d796584b6fe682b917 Mon Sep 17 00:00:00 2001 From: Brian Pandola Date: Sat, 10 Oct 2020 09:54:36 -0700 Subject: [PATCH] Add better support for SQS `MaximumMessageSize` attribute (#3374) Closes #3205 --- moto/sqs/exceptions.py | 10 ++++++++ moto/sqs/models.py | 17 ++++++++++++- tests/test_sqs/test_sqs.py | 51 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/moto/sqs/exceptions.py b/moto/sqs/exceptions.py index 46d2af400..872c25412 100644 --- a/moto/sqs/exceptions.py +++ b/moto/sqs/exceptions.py @@ -103,6 +103,16 @@ class InvalidAttributeName(RESTError): ) +class InvalidAttributeValue(RESTError): + code = 400 + + def __init__(self, attribute_name): + super(InvalidAttributeValue, self).__init__( + "InvalidAttributeValue", + "Invalid value for the parameter {}.".format(attribute_name), + ) + + class InvalidParameterValue(RESTError): code = 400 diff --git a/moto/sqs/models.py b/moto/sqs/models.py index 2784ee625..a837aacdc 100644 --- a/moto/sqs/models.py +++ b/moto/sqs/models.py @@ -35,6 +35,7 @@ from .exceptions import ( InvalidParameterValue, MissingParameter, OverLimit, + InvalidAttributeValue, ) from moto.core import ACCOUNT_ID as DEFAULT_ACCOUNT_ID @@ -43,6 +44,9 @@ DEFAULT_SENDER_ID = "AIDAIT2UOQQY3AUEKVGXU" MAXIMUM_MESSAGE_LENGTH = 262144 # 256 KiB +MAXIMUM_MESSAGE_SIZE_ATTR_LOWER_BOUND = 1024 +MAXIMUM_MESSAGE_SIZE_ATTR_UPPER_BOUND = MAXIMUM_MESSAGE_LENGTH + TRANSPORT_TYPE_ENCODINGS = { "String": b"\x01", "Binary": b"\x02", @@ -248,7 +252,7 @@ class Queue(CloudFormationModel): "FifoQueue": "false", "KmsDataKeyReusePeriodSeconds": 300, # five minutes "KmsMasterKeyId": None, - "MaximumMessageSize": int(64 << 12), + "MaximumMessageSize": MAXIMUM_MESSAGE_LENGTH, "MessageRetentionPeriod": 86400 * 4, # four days "Policy": None, "ReceiveMessageWaitTimeSeconds": 0, @@ -262,6 +266,11 @@ class Queue(CloudFormationModel): # Check some conditions if self.fifo_queue and not self.name.endswith(".fifo"): raise InvalidParameterValue("Queue name must end in .fifo for FIFO queues") + if ( + self.maximum_message_size < MAXIMUM_MESSAGE_SIZE_ATTR_LOWER_BOUND + or self.maximum_message_size > MAXIMUM_MESSAGE_SIZE_ATTR_UPPER_BOUND + ): + raise InvalidAttributeValue("MaximumMessageSize") @property def pending_messages(self): @@ -649,6 +658,12 @@ class SQSBackend(BaseBackend): queue = self.get_queue(queue_name) + if len(message_body) > queue.maximum_message_size: + msg = "One or more parameters are invalid. Reason: Message must be shorter than {} bytes.".format( + queue.maximum_message_size + ) + raise InvalidParameterValue(msg) + if delay_seconds: delay_seconds = int(delay_seconds) else: diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py index f98131db4..05f4bffab 100644 --- a/tests/test_sqs/test_sqs.py +++ b/tests/test_sqs/test_sqs.py @@ -22,6 +22,11 @@ from nose.tools import assert_raises from tests.helpers import requires_boto_gte from tests.test_awslambda.test_lambda import get_test_zip_file1, get_role_name from moto.core import ACCOUNT_ID +from moto.sqs.models import ( + MAXIMUM_MESSAGE_SIZE_ATTR_LOWER_BOUND, + MAXIMUM_MESSAGE_SIZE_ATTR_UPPER_BOUND, + MAXIMUM_MESSAGE_LENGTH, +) TEST_POLICY = """ { @@ -2157,3 +2162,49 @@ def test_invoke_function_from_sqs_exception(): time.sleep(1) assert False, "Test Failed" + + +@mock_sqs +def test_maximum_message_size_attribute_default(): + sqs = boto3.resource("sqs", region_name="eu-west-3") + queue = sqs.create_queue(QueueName="test-queue",) + int(queue.attributes["MaximumMessageSize"]).should.equal(MAXIMUM_MESSAGE_LENGTH) + with assert_raises(Exception) as e: + queue.send_message(MessageBody="a" * (MAXIMUM_MESSAGE_LENGTH + 1)) + ex = e.exception + ex.response["Error"]["Code"].should.equal("InvalidParameterValue") + + +@mock_sqs +def test_maximum_message_size_attribute_fails_for_invalid_values(): + sqs = boto3.resource("sqs", region_name="eu-west-3") + invalid_values = [ + MAXIMUM_MESSAGE_SIZE_ATTR_LOWER_BOUND - 1, + MAXIMUM_MESSAGE_SIZE_ATTR_UPPER_BOUND + 1, + ] + for message_size in invalid_values: + with assert_raises(ClientError) as e: + sqs.create_queue( + QueueName="test-queue", + Attributes={"MaximumMessageSize": str(message_size)}, + ) + ex = e.exception + ex.response["Error"]["Code"].should.equal("InvalidAttributeValue") + + +@mock_sqs +def test_send_message_fails_when_message_size_greater_than_max_message_size(): + sqs = boto3.resource("sqs", region_name="eu-west-3") + message_size_limit = 12345 + queue = sqs.create_queue( + QueueName="test-queue", + Attributes={"MaximumMessageSize": str(message_size_limit)}, + ) + int(queue.attributes["MaximumMessageSize"]).should.equal(message_size_limit) + with assert_raises(ClientError) as e: + queue.send_message(MessageBody="a" * (message_size_limit + 1)) + ex = e.exception + ex.response["Error"]["Code"].should.equal("InvalidParameterValue") + ex.response["Error"]["Message"].should.contain( + "{} bytes".format(message_size_limit) + )