Repository: getmoto/moto
Pull request #7407 (2024-02-29 09:22:54)

S3: Adding tests of EventBridge notification `ObjectCreated:Copy`
- Adding a test of EventBridge notification for `ObjectCreated:Copy`.
- Some helper methods to set up AWS resources and retrieve sent event logs were added for reuse.
- `disable_notification` argument were added for `put_object` method to handle notification.


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getmoto/moto/pull/7407?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 95.77%. Comparing base [(`9aef694`)](https://app.codecov.io/gh/getmoto/moto/commit/9aef6944da6a6f1b84be99cefb34f1724e6ca58f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) to head [(`d02c780`)](https://app.codecov.io/gh/getmoto/moto/pull/7407?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).
> Report is 60 commits behind head on master.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #7407      +/-   ##
==========================================
- Coverage   95.88%   95.77%   -0.11%     
==========================================
  Files         843      843              
  Lines       82578    83072     +494     
==========================================
+ Hits        79178    79565     +387     
- Misses       3400     3507     +107     
```

| [Flag](https://app.codecov.io/gh/getmoto/moto/pull/7407/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Coverage Δ | |
|---|---|---|
| [servertests](https://app.codecov.io/gh/getmoto/moto/pull/7407/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `32.50% <100.00%> (-0.03%)` | :arrow_down: |
| [unittests](https://app.codecov.io/gh/getmoto/moto/pull/7407/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `95.74% <100.00%> (-0.11%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#carryforward-flags-in-the-pull-request-comment) to find out more.


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/getmoto/moto/pull/7407?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).


Patch:
diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md
index c51d2e8d7..7e83f4034 100644
--- a/IMPLEMENTATION_COVERAGE.md
+++ b/IMPLEMENTATION_COVERAGE.md
@@ -2684,7 +2684,7 @@
 - [X] get_lifecycle_policy
 - [ ] get_lifecycle_policy_preview
 - [X] get_registry_policy
-- [ ] get_registry_scanning_configuration
+- [X] get_registry_scanning_configuration
 - [X] get_repository_policy
 - [ ] initiate_layer_upload
 - [X] list_images
diff --git a/docs/docs/services/ecr.rst b/docs/docs/services/ecr.rst
index c03c6ac7f..6735bab0a 100644
--- a/docs/docs/services/ecr.rst
+++ b/docs/docs/services/ecr.rst
@@ -45,7 +45,7 @@ ecr
 - [X] get_lifecycle_policy
 - [ ] get_lifecycle_policy_preview
 - [X] get_registry_policy
-- [ ] get_registry_scanning_configuration
+- [X] get_registry_scanning_configuration
 - [X] get_repository_policy
 - [ ] initiate_layer_upload
 - [X] list_images
diff --git a/moto/ecr/models.py b/moto/ecr/models.py
index 046f96cc9..b049fbce6 100644
--- a/moto/ecr/models.py
+++ b/moto/ecr/models.py
@@ -1,6 +1,7 @@
 import hashlib
 import json
 import re
+import threading
 from collections import namedtuple
 from datetime import datetime, timezone
 from typing import Any, Dict, Iterable, List, Optional, Tuple
@@ -390,6 +391,11 @@ class ECRBackend(BaseBackend):
         self.registry_policy: Optional[str] = None
         self.replication_config: Dict[str, Any] = {"rules": []}
         self.repositories: Dict[str, Repository] = {}
+        self.registry_scanning_configuration: Dict[str, Any] = {
+            "scanType": "BASIC",
+            "rules": [],
+        }
+        self.registry_scanning_configuration_update_lock = threading.RLock()
         self.tagger = TaggingService(tag_name="tags")
 
     @staticmethod
@@ -495,6 +501,19 @@ class ECRBackend(BaseBackend):
         self.repositories[repository_name] = repository
         self.tagger.tag_resource(repository.arn, tags)
 
+        # check if any of the registry scanning policies applies to the repository
+        with self.registry_scanning_configuration_update_lock:
+            for rule in self.registry_scanning_configuration["rules"]:
+                for repo_filter in rule["repositoryFilters"]:
+                    if self._match_repository_filter(
+                        repo_filter["filter"], repository_name
+                    ):
+                        repository.scanning_config["scanFrequency"] = rule[
+                            "scanFrequency"
+                        ]
+                        # AWS testing seems to indicate that this is always overwritten
+                        repository.scanning_config["appliedScanFilters"] = [repo_filter]
+
         return repository
 
     def delete_repository(
@@ -1117,16 +1136,41 @@ class ECRBackend(BaseBackend):
 
         return {"replicationConfiguration": replication_config}
 
-    def put_registry_scanning_configuration(self, rules: List[Dict[str, Any]]) -> None:
-        for rule in rules:
-            for repo_filter in rule["repositoryFilters"]:
-                for repo in self.repositories.values():
-                    if repo_filter["filter"] == repo.name or re.match(
-                        repo_filter["filter"], repo.name
-                    ):
-                        repo.scanning_config["scanFrequency"] = rule["scanFrequency"]
-                        # AWS testing seems to indicate that this is always overwritten
-                        repo.scanning_config["appliedScanFilters"] = [repo_filter]
+    def _match_repository_filter(self, filter: str, repository_name: str) -> bool:
+        filter_regex = filter.replace("*", ".*")
+        return filter in repository_name or bool(
+            re.match(filter_regex, repository_name)
+        )
+
+    def get_registry_scanning_configuration(self) -> Dict[str, Any]:
+        return self.registry_scanning_configuration
+
+    def put_registry_scanning_configuration(
+        self, scan_type: str, rules: List[Dict[str, Any]]
+    ) -> None:
+        # locking here to avoid simultaneous updates which leads to inconsistent state
+        with self.registry_scanning_configuration_update_lock:
+            self.registry_scanning_configuration = {
+                "scanType": scan_type,
+                "rules": rules,
+            }
+
+            # reset all rules first
+            for repo in self.repositories.values():
+                repo.scanning_config["scanFrequency"] = "MANUAL"
+                repo.scanning_config["appliedScanFilters"] = []
+
+            for rule in rules:
+                for repo_filter in rule["repositoryFilters"]:
+                    for repo in self.repositories.values():
+                        if self._match_repository_filter(
+                            repo_filter["filter"], repo.name
+                        ):
+                            repo.scanning_config["scanFrequency"] = rule[
+                                "scanFrequency"
+                            ]
+                            # AWS testing seems to indicate that this is always overwritten
+                            repo.scanning_config["appliedScanFilters"] = [repo_filter]
 
     def describe_registry(self) -> Dict[str, Any]:
         return {
diff --git a/moto/ecr/responses.py b/moto/ecr/responses.py
index 903a4d00e..9ec4220ec 100644
--- a/moto/ecr/responses.py
+++ b/moto/ecr/responses.py
@@ -324,11 +324,24 @@ class ECRResponse(BaseResponse):
             )
         )
 
+    def get_registry_scanning_configuration(self) -> str:
+        registry_scanning_config = (
+            self.ecr_backend.get_registry_scanning_configuration()
+        )
+        return json.dumps(
+            {
+                "registryId": self.current_account,
+                "scanningConfiguration": registry_scanning_config,
+            }
+        )
+
     def put_registry_scanning_configuration(self) -> str:
         scan_type = self._get_param("scanType")
         rules = self._get_param("rules")
-        self.ecr_backend.put_registry_scanning_configuration(rules)
-        return json.dumps({"scanType": scan_type, "rules": rules})
+        self.ecr_backend.put_registry_scanning_configuration(scan_type, rules)
+        return json.dumps(
+            {"registryScanningConfiguration": {"scanType": scan_type, "rules": rules}}
+        )
 
     def describe_registry(self) -> str:
         return json.dumps(self.ecr_backend.describe_registry())
diff --git a/moto/s3/models.py b/moto/s3/models.py
index 99ca233ed..31df9c21d 100644
--- a/moto/s3/models.py
+++ b/moto/s3/models.py
@@ -2048,7 +2048,9 @@ class S3Backend(BaseBackend, CloudWatchMetricProvider):
         lock_legal_status: Optional[str] = None,
         lock_until: Optional[str] = None,
         checksum_value: Optional[str] = None,
+        # arguments to handle notification
         request_method: Optional[str] = "PUT",
+        disable_notification: Optional[bool] = False,
     ) -> FakeKey:
         if storage is not None and storage not in STORAGE_CLASS:
             raise InvalidStorageClass(storage=storage)
@@ -2097,21 +2099,22 @@ class S3Backend(BaseBackend, CloudWatchMetricProvider):
             keys = [new_key]
         bucket.keys.setlist(key_name, keys)
 
-        # Send event notification
-        if request_method == "POST":
-            notify_event_name = (
-                notifications.S3NotificationEvent.OBJECT_CREATED_POST_EVENT
-            )
-        else:  # PUT request
-            notify_event_name = (
-                notifications.S3NotificationEvent.OBJECT_CREATED_PUT_EVENT
+        if not disable_notification:
+            # Send event notification
+            if request_method == "POST":
+                notify_event_name = (
+                    notifications.S3NotificationEvent.OBJECT_CREATED_POST_EVENT
+                )
+            else:  # PUT request
+                notify_event_name = (
+                    notifications.S3NotificationEvent.OBJECT_CREATED_PUT_EVENT
+                )
+            notifications.send_event(
+                self.account_id,
+                notify_event_name,
+                bucket,
+                new_key,
             )
-        notifications.send_event(
-            self.account_id,
-            notify_event_name,
-            bucket,
-            new_key,
-        )
 
         return new_key
 
@@ -2706,6 +2709,7 @@ class S3Backend(BaseBackend, CloudWatchMetricProvider):
             lock_mode=lock_mode,
             lock_legal_status=lock_legal_status,
             lock_until=lock_until,
+            disable_notification=True,  # avoid sending PutObject events here
         )
         self.tagger.copy_tags(src_key.arn, new_key.arn)
         if mdirective != "REPLACE":
diff --git a/moto/sqs/models.py b/moto/sqs/models.py
index 3d9cd562c..d3f9705a6 100644
--- a/moto/sqs/models.py
+++ b/moto/sqs/models.py
@@ -792,6 +792,7 @@ class SQSBackend(BaseBackend):
         self,
         queue: Queue,
         message_body: str,
+        delay_seconds: int,
         deduplication_id: Optional[str] = None,
         group_id: Optional[str] = None,
     ) -> None:
@@ -814,6 +815,12 @@ class SQSBackend(BaseBackend):
                 )
                 raise InvalidParameterValue(msg)
 
+            if delay_seconds > 0:
+                raise InvalidParameterValue(
+                    f"Value {delay_seconds} for parameter DelaySeconds is invalid. Reason: "
+                    "The request include parameter that is not valid for this queue type."
+                )
+
         if len(message_body) > queue.maximum_message_size:  # type: ignore
             msg = f"One or more parameters are invalid. Reason: Message must be shorter than {queue.maximum_message_size} bytes."  # type: ignore
             raise InvalidParameterValue(msg)
@@ -843,13 +850,15 @@ class SQSBackend(BaseBackend):
     ) -> Message:
         queue = self.get_queue(queue_name)
 
-        self._validate_message(queue, message_body, deduplication_id, group_id)
-
         if delay_seconds is not None:
             delay_seconds = int(delay_seconds)
         else:
             delay_seconds = queue.delay_seconds  # type: ignore
 
+        self._validate_message(
+            queue, message_body, delay_seconds, deduplication_id, group_id
+        )
+
         message_id = str(random.uuid4())
         message = Message(message_id, message_body, system_attributes)
 
@@ -917,6 +926,7 @@ class SQSBackend(BaseBackend):
             self._validate_message(
                 queue,
                 entry["MessageBody"],
+                int(entry.get("DelaySeconds") or 0),
                 entry.get("MessageDeduplicationId"),
                 entry.get("MessageGroupId"),
             )


Test patch:
diff --git a/tests/test_ecr/test_ecr_scanning_config.py b/tests/test_ecr/test_ecr_scanning_config.py
index 5858ba9d0..5dad7197c 100644
--- a/tests/test_ecr/test_ecr_scanning_config.py
+++ b/tests/test_ecr/test_ecr_scanning_config.py
@@ -1,6 +1,10 @@
 import boto3
 
 from moto import mock_aws
+from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
+
+ECR_REGION = "us-east-1"
+ECR_REPO = "test-repo"
 
 
 @mock_aws
@@ -133,9 +137,120 @@ def test_put_registry_scanning_configuration():
             "repositoryArn": repo_arn,
             "repositoryName": repo_name,
             "scanOnPush": False,
-            "scanFrequency": "SCAN_ON_PUSH",
-            "appliedScanFilters": [
-                {"filter": f"{repo_name[:4]}*", "filterType": "WILDCARD"}
-            ],
+            "scanFrequency": "MANUAL",
+            "appliedScanFilters": [],
         }
     ]
+
+
+@mock_aws
+def test_registry_scanning_configuration_lifecycle():
+    client = boto3.client("ecr", region_name=ECR_REGION)
+    client.create_repository(repositoryName=ECR_REPO)
+
+    get_scanning_config_response = client.get_registry_scanning_configuration()
+    assert get_scanning_config_response["registryId"] == ACCOUNT_ID
+    assert get_scanning_config_response["scanningConfiguration"] == {
+        "rules": [],
+        "scanType": "BASIC",
+    }
+
+    put_scanning_config_response = client.put_registry_scanning_configuration(
+        scanType="BASIC",
+        rules=[
+            {
+                "repositoryFilters": [
+                    {
+                        "filter": "test-*",
+                        "filterType": "WILDCARD",
+                    }
+                ],
+                "scanFrequency": "SCAN_ON_PUSH",
+            }
+        ],
+    )
+
+    assert put_scanning_config_response["registryScanningConfiguration"] == {
+        "rules": [
+            {
+                "repositoryFilters": [{"filter": "test-*", "filterType": "WILDCARD"}],
+                "scanFrequency": "SCAN_ON_PUSH",
+            }
+        ],
+        "scanType": "BASIC",
+    }
+
+    # check if scanning config is returned in get operation
+    get_scanning_config_response = client.get_registry_scanning_configuration()
+    assert get_scanning_config_response["registryId"] == ACCOUNT_ID
+    assert get_scanning_config_response["scanningConfiguration"] == {
+        "rules": [
+            {
+                "repositoryFilters": [{"filter": "test-*", "filterType": "WILDCARD"}],
+                "scanFrequency": "SCAN_ON_PUSH",
+            }
+        ],
+        "scanType": "BASIC",
+    }
+
+    # check if the scanning config is returned in batch_get_repository_scanning_configuration
+    repo_scanning_config_result = client.batch_get_repository_scanning_configuration(
+        repositoryNames=[ECR_REPO]
+    )
+    assert repo_scanning_config_result["scanningConfigurations"][0] == {
+        "appliedScanFilters": [{"filter": "test-*", "filterType": "WILDCARD"}],
+        "repositoryArn": f"arn:aws:ecr:{ECR_REGION}:{ACCOUNT_ID}:repository/{ECR_REPO}",
+        "repositoryName": ECR_REPO,
+        "scanFrequency": "SCAN_ON_PUSH",
+        "scanOnPush": False,
+    }
+
+    # create new repository and check if scanning config is applied
+    client.create_repository(repositoryName="test-repo-2")
+    repo_scanning_config_result = client.batch_get_repository_scanning_configuration(
+        repositoryNames=["test-repo-2"]
+    )
+    assert repo_scanning_config_result["scanningConfigurations"][0] == {
+        "appliedScanFilters": [{"filter": "test-*", "filterType": "WILDCARD"}],
+        "repositoryArn": f"arn:aws:ecr:{ECR_REGION}:{ACCOUNT_ID}:repository/test-repo-2",
+        "repositoryName": "test-repo-2",
+        "scanFrequency": "SCAN_ON_PUSH",
+        "scanOnPush": False,
+    }
+
+    # revert scanning config and see if it is properly applied to all repositories
+    put_scanning_config_response = client.put_registry_scanning_configuration(
+        scanType="BASIC",
+        rules=[],
+    )
+    assert put_scanning_config_response["registryScanningConfiguration"] == {
+        "rules": [],
+        "scanType": "BASIC",
+    }
+
+    get_scanning_config_response = client.get_registry_scanning_configuration()
+    assert get_scanning_config_response["registryId"] == ACCOUNT_ID
+    assert get_scanning_config_response["scanningConfiguration"] == {
+        "rules": [],
+        "scanType": "BASIC",
+    }
+
+    repo_scanning_config_result = client.batch_get_repository_scanning_configuration(
+        repositoryNames=[ECR_REPO, "test-repo-2"]
+    )
+    assert repo_scanning_config_result["scanningConfigurations"] == [
+        {
+            "appliedScanFilters": [],
+            "repositoryArn": f"arn:aws:ecr:{ECR_REGION}:{ACCOUNT_ID}:repository/{ECR_REPO}",
+            "repositoryName": ECR_REPO,
+            "scanFrequency": "MANUAL",
+            "scanOnPush": False,
+        },
+        {
+            "appliedScanFilters": [],
+            "repositoryArn": f"arn:aws:ecr:{ECR_REGION}:{ACCOUNT_ID}:repository/test-repo-2",
+            "repositoryName": "test-repo-2",
+            "scanFrequency": "MANUAL",
+            "scanOnPush": False,
+        },
+    ]
diff --git a/tests/test_s3/test_s3_eventbridge_integration.py b/tests/test_s3/test_s3_eventbridge_integration.py
index 374631ff4..d84235020 100644
--- a/tests/test_s3/test_s3_eventbridge_integration.py
+++ b/tests/test_s3/test_s3_eventbridge_integration.py
@@ -1,5 +1,6 @@
 import json
 from io import BytesIO
+from typing import Any, Dict, List
 from unittest import SkipTest
 from uuid import uuid4
 
@@ -14,18 +15,31 @@ REGION_NAME = "us-east-1"
 REDUCED_PART_SIZE = 256
 
 
-@mock_aws
-def test_put_object_notification_ObjectCreated_PUT():
+def _seteup_bucket_notification_eventbridge(
+    bucket_name: str = str(uuid4()),
+    rule_name: str = "test-rule",
+    log_group_name: str = "/test-group",
+) -> Dict[str, str]:
+    """Setups S3, EventBridge and CloudWatchLogs"""
+    # Setup S3
     s3_res = boto3.resource("s3", region_name=REGION_NAME)
+    s3_res.create_bucket(Bucket=bucket_name)
+
+    # Put bucket notification event bridge
     s3_client = boto3.client("s3", region_name=REGION_NAME)
-    events_client = boto3.client("events", region_name=REGION_NAME)
-    logs_client = boto3.client("logs", region_name=REGION_NAME)
+    s3_client.put_bucket_notification_configuration(
+        Bucket=bucket_name,
+        NotificationConfiguration={"EventBridgeConfiguration": {}},
+    )
 
-    rule_name = "test-rule"
+    # Setup EventBridge Rule
+    events_client = boto3.client("events", region_name=REGION_NAME)
     events_client.put_rule(
         Name=rule_name, EventPattern=json.dumps({"account": [ACCOUNT_ID]})
     )
-    log_group_name = "/test-group"
+
+    # Create a log group and attach it to the events target.
+    logs_client = boto3.client("logs", region_name=REGION_NAME)
     logs_client.create_log_group(logGroupName=log_group_name)
     events_client.put_targets(
         Rule=rule_name,
@@ -37,23 +51,31 @@ def test_put_object_notification_ObjectCreated_PUT():
         ],
     )
 
-    # Create S3 bucket
-    bucket_name = str(uuid4())
-    s3_res.create_bucket(Bucket=bucket_name)
+    return {
+        "bucket_name": bucket_name,
+        "event_rule_name": rule_name,
+        "log_group_name": log_group_name,
+    }
 
-    # Put Notification
-    s3_client.put_bucket_notification_configuration(
-        Bucket=bucket_name,
-        NotificationConfiguration={"EventBridgeConfiguration": {}},
+
+def _get_send_events(log_group_name: str = "/test-group") -> List[Dict[str, Any]]:
+    logs_client = boto3.client("logs", region_name=REGION_NAME)
+    return sorted(
+        logs_client.filter_log_events(logGroupName=log_group_name)["events"],
+        key=lambda item: item["timestamp"],
     )
 
+
+@mock_aws
+def test_put_object_notification_ObjectCreated_PUT():
+    resource_names = _seteup_bucket_notification_eventbridge()
+    bucket_name = resource_names["bucket_name"]
+    s3_client = boto3.client("s3", region_name=REGION_NAME)
+
     # Put Object
     s3_client.put_object(Bucket=bucket_name, Key="keyname", Body="bodyofnewobject")
 
-    events = sorted(
-        logs_client.filter_log_events(logGroupName=log_group_name)["events"],
-        key=lambda item: item["eventId"],
-    )
+    events = _get_send_events()
     assert len(events) == 1
     event_message = json.loads(events[0]["message"])
     assert event_message["detail-type"] == "Object Created"
@@ -70,36 +92,8 @@ def test_put_object_notification_ObjectCreated_POST():
     if not settings.TEST_DECORATOR_MODE:
         raise SkipTest(("Doesn't quite work right with the Proxy or Server"))
 
-    s3_res = boto3.resource("s3", region_name=REGION_NAME)
-    s3_client = boto3.client("s3", region_name=REGION_NAME)
-    events_client = boto3.client("events", region_name=REGION_NAME)
-    logs_client = boto3.client("logs", region_name=REGION_NAME)
-
-    rule_name = "test-rule"
-    events_client.put_rule(
-        Name=rule_name, EventPattern=json.dumps({"account": [ACCOUNT_ID]})
-    )
-    log_group_name = "/test-group"
-    logs_client.create_log_group(logGroupName=log_group_name)
-    events_client.put_targets(
-        Rule=rule_name,
-        Targets=[
-            {
-                "Id": "test",
-                "Arn": f"arn:aws:logs:{REGION_NAME}:{ACCOUNT_ID}:log-group:{log_group_name}",
-            }
-        ],
-    )
-
-    # Create S3 bucket
-    bucket_name = str(uuid4())
-    s3_res.create_bucket(Bucket=bucket_name)
-
-    # Put bucket notification event bridge
-    s3_client.put_bucket_notification_configuration(
-        Bucket=bucket_name,
-        NotificationConfiguration={"EventBridgeConfiguration": {}},
-    )
+    resource_names = _seteup_bucket_notification_eventbridge()
+    bucket_name = resource_names["bucket_name"]
 
     ###
     # multipart/formdata POST request (this request is processed in S3Response._bucket_response_post)
@@ -113,10 +107,7 @@ def test_put_object_notification_ObjectCreated_POST():
         files={"file": ("tmp.txt", BytesIO(content))},
     )
 
-    events = sorted(
-        logs_client.filter_log_events(logGroupName=log_group_name)["events"],
-        key=lambda item: item["eventId"],
-    )
+    events = _get_send_events()
     assert len(events) == 1
     event_message = json.loads(events[0]["message"])
     assert event_message["detail-type"] == "Object Created"
@@ -126,3 +117,28 @@ def test_put_object_notification_ObjectCreated_POST():
     assert event_message["detail"]["bucket"]["name"] == bucket_name
     assert event_message["detail"]["object"]["key"] == object_key
     assert event_message["detail"]["reason"] == "ObjectCreated"
+
+
+@mock_aws
+def test_copy_object_notification():
+    resource_names = _seteup_bucket_notification_eventbridge()
+    bucket_name = resource_names["bucket_name"]
+    s3_client = boto3.client("s3", region_name=REGION_NAME)
+
+    # Copy object (send two events; PutObject and CopyObject)
+    s3_client.put_object(Bucket=bucket_name, Key="keyname", Body="bodyofnewobject")
+    object_key = "key2"
+    s3_client.copy_object(
+        Bucket=bucket_name, CopySource=f"{bucket_name}/keyname", Key="key2"
+    )
+
+    events = _get_send_events()
+    assert len(events) == 2  # [PutObject event, CopyObject event]
+    event_message = json.loads(events[-1]["message"])
+    assert event_message["detail-type"] == "Object Created"
+    assert event_message["source"] == "aws.s3"
+    assert event_message["account"] == ACCOUNT_ID
+    assert event_message["region"] == REGION_NAME
+    assert event_message["detail"]["bucket"]["name"] == bucket_name
+    assert event_message["detail"]["object"]["key"] == object_key
+    assert event_message["detail"]["reason"] == "ObjectCreated"
diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py
index 6b8d4f67d..5ae192a63 100644
--- a/tests/test_sqs/test_sqs.py
+++ b/tests/test_sqs/test_sqs.py
@@ -43,11 +43,12 @@ TEST_POLICY = """
 """
 
 MOCK_DEDUPLICATION_TIME_IN_SECONDS = 5
+REGION = "us-east-1"
 
 
 @mock_aws
 def test_create_fifo_queue_fail():
-    sqs = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.client("sqs", region_name=REGION)
 
     try:
         sqs.create_queue(QueueName=str(uuid4())[0:6], Attributes={"FifoQueue": "true"})
@@ -59,7 +60,7 @@ def test_create_fifo_queue_fail():
 
 @mock_aws
 def test_create_queue_with_same_attributes():
-    sqs = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.client("sqs", region_name=REGION)
 
     dlq_url = sqs.create_queue(QueueName=str(uuid4()))["QueueUrl"]
     dlq_arn = sqs.get_queue_attributes(QueueUrl=dlq_url, AttributeNames=["All"])[
@@ -85,7 +86,7 @@ def test_create_queue_with_same_attributes():
 
 @mock_aws
 def test_create_queue_with_different_attributes_fail():
-    sqs = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.client("sqs", region_name=REGION)
 
     q_name = str(uuid4())[0:6]
     sqs.create_queue(QueueName=q_name, Attributes={"VisibilityTimeout": "10"})
@@ -109,8 +110,7 @@ def test_create_queue_with_different_attributes_fail():
 @mock_aws
 def test_create_fifo_queue():
     # given
-    region_name = "us-east-1"
-    sqs = boto3.client("sqs", region_name=region_name)
+    sqs = boto3.client("sqs", region_name=REGION)
     queue_name = f"{str(uuid4())[0:6]}.fifo"
 
     # when
@@ -136,9 +136,7 @@ def test_create_fifo_queue():
     assert attributes["FifoThroughputLimit"] == "perQueue"
     assert attributes["MaximumMessageSize"] == "262144"
     assert attributes["MessageRetentionPeriod"] == "345600"
-    assert attributes["QueueArn"] == (
-        f"arn:aws:sqs:{region_name}:{ACCOUNT_ID}:{queue_name}"
-    )
+    assert attributes["QueueArn"] == (f"arn:aws:sqs:{REGION}:{ACCOUNT_ID}:{queue_name}")
     assert attributes["ReceiveMessageWaitTimeSeconds"] == "0"
     assert attributes["VisibilityTimeout"] == "30"
 
@@ -146,7 +144,7 @@ def test_create_fifo_queue():
 @mock_aws
 def test_create_fifo_queue_with_high_throughput():
     # given
-    sqs = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.client("sqs", region_name=REGION)
     queue_name = f"{str(uuid4())[0:6]}.fifo"
 
     # when
@@ -172,7 +170,7 @@ def test_create_fifo_queue_with_high_throughput():
 
 @mock_aws
 def test_create_queue():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
 
     q_name = str(uuid4())[0:6]
     new_queue = sqs.create_queue(QueueName=q_name)
@@ -180,13 +178,13 @@ def test_create_queue():
 
     queue = sqs.get_queue_by_name(QueueName=q_name)
     assert queue.attributes.get("QueueArn").split(":")[-1] == q_name
-    assert queue.attributes.get("QueueArn").split(":")[3] == "us-east-1"
+    assert queue.attributes.get("QueueArn").split(":")[3] == REGION
     assert queue.attributes.get("VisibilityTimeout") == "30"
 
 
 @mock_aws
 def test_create_queue_kms():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
 
     q_name = str(uuid4())[0:6]
     sqs.create_queue(
@@ -205,7 +203,7 @@ def test_create_queue_kms():
 
 @mock_aws
 def test_create_queue_with_tags():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     response = client.create_queue(
         QueueName=q_name, tags={"tag_key_1": "tag_value_1", "tag_key_2": ""}
@@ -220,7 +218,7 @@ def test_create_queue_with_tags():
 
 @mock_aws
 def test_create_queue_with_policy():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     response = client.create_queue(
         QueueName=q_name,
@@ -248,7 +246,7 @@ def test_create_queue_with_policy():
 
 @mock_aws
 def test_set_queue_attribute_empty_policy_removes_attr():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     response = client.create_queue(
         QueueName=q_name,
@@ -278,7 +276,7 @@ def test_is_empty_redrive_policy_returns_true_for_empty_and_falsy_values():
 
 
 def test_is_empty_redrive_policy_returns_false_for_valid_policy_format():
-    test_dlq_arn = "arn:aws:sqs:us-east-1:123456789012:test-dlr-queue"
+    test_dlq_arn = f"arn:aws:sqs:{REGION}:123456789012:test-dlr-queue"
     assert not Queue._is_empty_redrive_policy(
         json.dumps({"deadLetterTargetArn": test_dlq_arn, "maxReceiveCount": 5})
     )
@@ -287,7 +285,7 @@ def test_is_empty_redrive_policy_returns_false_for_valid_policy_format():
 
 @mock_aws
 def test_set_queue_attribute_empty_redrive_removes_attr():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     dlq_resp = client.create_queue(QueueName="test-dlr-queue")
     dlq_arn1 = client.get_queue_attributes(
@@ -314,7 +312,7 @@ def test_set_queue_attribute_empty_redrive_removes_attr():
 
 @mock_aws
 def test_get_queue_url():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     client.create_queue(QueueName=q_name)
 
@@ -326,7 +324,7 @@ def test_get_queue_url():
 @mock_aws
 def test_get_queue_url_error_not_exists():
     # given
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     # when
     with pytest.raises(ClientError) as e:
@@ -344,7 +342,7 @@ def test_get_queue_url_error_not_exists():
 
 @mock_aws
 def test_get_nonexistent_queue():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
 
     with pytest.raises(ClientError) as err:
         sqs.Queue("http://whatever-incorrect-queue-address").load()
@@ -358,7 +356,7 @@ def test_get_nonexistent_queue():
 
 @mock_aws
 def test_message_send_without_attributes():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
     msg = queue.send_message(MessageBody="derp")
     assert msg.get("MD5OfMessageBody") == "58fd9edd83341c29f1aebba81c31e257"
@@ -371,7 +369,7 @@ def test_message_send_without_attributes():
 
 @mock_aws
 def test_message_send_with_attributes():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
     msg = queue.send_message(
         MessageBody="derp",
@@ -392,7 +390,7 @@ def test_message_send_with_attributes():
 
 @mock_aws
 def test_message_retention_period():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"MessageRetentionPeriod": "3"}
     )
@@ -426,7 +424,7 @@ def test_message_retention_period():
 
 @mock_aws
 def test_queue_retention_period():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"MessageRetentionPeriod": "3"}
     )
@@ -449,7 +447,7 @@ def test_queue_retention_period():
 
 @mock_aws
 def test_message_with_invalid_attributes():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
     with pytest.raises(ClientError) as e:
         queue.send_message(
@@ -469,7 +467,7 @@ def test_message_with_invalid_attributes():
 
 @mock_aws
 def test_message_with_string_attributes():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
     msg = queue.send_message(
         MessageBody="derp",
@@ -495,7 +493,7 @@ def test_message_with_string_attributes():
 
 @mock_aws
 def test_message_with_binary_attribute():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
     msg = queue.send_message(
         MessageBody="derp",
@@ -522,7 +520,7 @@ def test_message_with_binary_attribute():
 
 @mock_aws
 def test_message_with_attributes_have_labels():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
     msg = queue.send_message(
         MessageBody="derp",
@@ -543,7 +541,7 @@ def test_message_with_attributes_have_labels():
 
 @mock_aws
 def test_message_with_attributes_invalid_datatype():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
 
     with pytest.raises(ClientError) as e:
@@ -567,7 +565,7 @@ def test_message_with_attributes_invalid_datatype():
 
 @mock_aws
 def test_send_message_with_message_group_id():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=f"{str(uuid4())[0:6]}.fifo", Attributes={"FifoQueue": "true"}
     )
@@ -592,7 +590,7 @@ def test_send_message_with_message_group_id():
 
 @mock_aws
 def test_send_message_with_message_group_id_standard_queue():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
 
     with pytest.raises(ClientError) as ex:
@@ -610,7 +608,7 @@ def test_send_message_with_message_group_id_standard_queue():
 def test_send_message_with_unicode_characters():
     body_one = "Héllo!😀"
 
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
     queue.send_message(MessageBody=body_one)
 
@@ -622,7 +620,7 @@ def test_send_message_with_unicode_characters():
 
 @mock_aws
 def test_set_queue_attributes():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
 
     assert queue.attributes["VisibilityTimeout"] == "30"
@@ -695,8 +693,8 @@ def test_get_queue_with_prefix():
 
 @mock_aws
 def test_delete_queue():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     q_resp = conn.create_queue(QueueName=q_name, Attributes={"VisibilityTimeout": "3"})
     queue = sqs.Queue(q_resp["QueueUrl"])
@@ -712,7 +710,7 @@ def test_delete_queue():
 
 @mock_aws
 def test_delete_queue_error_not_exists():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     with pytest.raises(ClientError) as e:
         client.delete_queue(
@@ -730,7 +728,7 @@ def test_delete_queue_error_not_exists():
 
 @mock_aws
 def test_get_queue_attributes():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     dlq_resp = client.create_queue(QueueName="test-dlr-queue")
     dlq_arn1 = client.get_queue_attributes(
@@ -759,7 +757,7 @@ def test_get_queue_attributes():
     assert response["Attributes"]["MaximumMessageSize"] == "262144"
     assert response["Attributes"]["MessageRetentionPeriod"] == "345600"
     assert response["Attributes"]["QueueArn"] == (
-        f"arn:aws:sqs:us-east-1:{ACCOUNT_ID}:{q_name}"
+        f"arn:aws:sqs:{REGION}:{ACCOUNT_ID}:{q_name}"
     )
     assert response["Attributes"]["ReceiveMessageWaitTimeSeconds"] == "0"
     assert response["Attributes"]["VisibilityTimeout"] == "30"
@@ -778,7 +776,7 @@ def test_get_queue_attributes():
     assert response["Attributes"] == {
         "ApproximateNumberOfMessages": "0",
         "MaximumMessageSize": "262144",
-        "QueueArn": f"arn:aws:sqs:us-east-1:{ACCOUNT_ID}:{q_name}",
+        "QueueArn": f"arn:aws:sqs:{REGION}:{ACCOUNT_ID}:{q_name}",
         "VisibilityTimeout": "30",
         "RedrivePolicy": json.dumps(
             {"deadLetterTargetArn": dlq_arn1, "maxReceiveCount": 2}
@@ -795,7 +793,7 @@ def test_get_queue_attributes():
 
 @mock_aws
 def test_get_queue_attributes_errors():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(QueueName=str(uuid4())[0:6])
     queue_url = response["QueueUrl"]
 
@@ -821,7 +819,7 @@ def test_get_queue_attributes_errors():
 @mock_aws
 def test_get_queue_attributes_error_not_exists():
     # given
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     # when
     with pytest.raises(ClientError) as e:
@@ -841,8 +839,8 @@ def test_get_queue_attributes_error_not_exists():
 
 @mock_aws
 def test_set_queue_attribute():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     q_resp = conn.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout": "3"}
     )
@@ -857,8 +855,8 @@ def test_set_queue_attribute():
 
 @mock_aws
 def test_send_receive_message_without_attributes():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     q_resp = conn.create_queue(QueueName=str(uuid4())[0:6])
     queue = sqs.Queue(q_resp["QueueUrl"])
 
@@ -887,8 +885,8 @@ def test_send_receive_message_without_attributes():
 
 @mock_aws
 def test_send_receive_message_with_attributes():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     q_resp = conn.create_queue(QueueName=str(uuid4())[0:6])
     queue = sqs.Queue(q_resp["QueueUrl"])
 
@@ -925,8 +923,8 @@ def test_send_receive_message_with_attributes():
 
 @mock_aws
 def test_send_receive_message_with_attributes_with_labels():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     q_resp = conn.create_queue(QueueName=str(uuid4())[0:6])
     queue = sqs.Queue(q_resp["QueueUrl"])
 
@@ -1006,8 +1004,8 @@ def test_change_message_visibility_than_permitted():
     if settings.TEST_SERVER_MODE:
         raise SkipTest("Cant manipulate time in server mode")
 
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
 
     with freeze_time("2015-01-01 12:00:00"):
         q_resp = conn.create_queue(QueueName="test-queue-visibility")
@@ -1038,8 +1036,8 @@ def test_change_message_visibility_than_permitted():
 
 @mock_aws
 def test_send_receive_message_timestamps():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     q_resp = conn.create_queue(QueueName=str(uuid4())[0:6])
     queue = sqs.Queue(q_resp["QueueUrl"])
 
@@ -1142,8 +1140,8 @@ def test_send_receive_message_timestamps():
     ],
 )
 def test_send_receive_message_with_attribute_name(attribute_name, expected):
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    client = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    client = boto3.client("sqs", region_name=REGION)
     q_resp = client.create_queue(QueueName=str(uuid4())[0:6])
     queue = sqs.Queue(q_resp["QueueUrl"])
 
@@ -1308,7 +1306,7 @@ def test_send_receive_message_with_attribute_name(attribute_name, expected):
     ],
 )
 def test_fifo_send_receive_message_with_attribute_name(attribute_name, expected):
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     queue_url = client.create_queue(
         QueueName=f"{str(uuid4())[0:6]}.fifo", Attributes={"FifoQueue": "true"}
     )["QueueUrl"]
@@ -1360,7 +1358,7 @@ def test_get_queue_attributes_no_param():
 
 @mock_aws
 def test_max_number_of_messages_invalid_param():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
 
     with pytest.raises(ClientError):
@@ -1375,7 +1373,7 @@ def test_max_number_of_messages_invalid_param():
 
 @mock_aws
 def test_wait_time_seconds_invalid_param():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
 
     with pytest.raises(ClientError):
@@ -1396,7 +1394,7 @@ def test_receive_messages_with_wait_seconds_timeout_of_zero():
     :return:
     """
 
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
 
     messages = queue.receive_messages(WaitTimeSeconds=0)
@@ -1405,8 +1403,8 @@ def test_receive_messages_with_wait_seconds_timeout_of_zero():
 
 @mock_aws
 def test_send_message_with_xml_characters():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    client = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    client = boto3.client("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
 
     body_one = "< & >"
@@ -1420,7 +1418,7 @@ def test_send_message_with_xml_characters():
 
 @mock_aws
 def test_send_message_with_delay():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
 
     body_one = "this is a test message"
@@ -1440,7 +1438,7 @@ def test_send_message_with_delay():
 
 @mock_aws
 def test_send_message_with_message_delay_overriding_queue_delay():
-    sqs = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.client("sqs", region_name=REGION)
     name = str(uuid4())[0:6]
     # By default, all messages on this queue are delayed
     resp = sqs.create_queue(QueueName=name, Attributes={"DelaySeconds": "10"})
@@ -1453,7 +1451,7 @@ def test_send_message_with_message_delay_overriding_queue_delay():
 
 @mock_aws
 def test_send_large_message_fails():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
 
     body = "test message" * 200000
@@ -1496,7 +1494,7 @@ def test_message_becomes_inflight_when_received():
 
 @mock_aws
 def test_receive_message_with_explicit_visibility_timeout():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout ": "1"}
     )
@@ -1518,7 +1516,7 @@ def test_receive_message_with_explicit_visibility_timeout():
 
 @mock_aws
 def test_change_message_visibility():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout ": "2"}
     )
@@ -1558,8 +1556,8 @@ def test_change_message_visibility():
 
 @mock_aws
 def test_change_message_visibility_on_unknown_receipt_handle():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout": "2"}
     )
@@ -1575,7 +1573,7 @@ def test_change_message_visibility_on_unknown_receipt_handle():
 
 @mock_aws
 def test_queue_length():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout ": "2"}
     )
@@ -1589,7 +1587,7 @@ def test_queue_length():
 
 @mock_aws
 def test_delete_batch_operation():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout ": "2"}
     )
@@ -1611,7 +1609,7 @@ def test_delete_batch_operation():
 
 @mock_aws
 def test_change_message_visibility_on_old_message():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout": "1"}
     )
@@ -1650,7 +1648,7 @@ def test_change_message_visibility_on_old_message():
 
 @mock_aws
 def test_change_message_visibility_on_visible_message():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout": "2"}
     )
@@ -1677,7 +1675,7 @@ def test_change_message_visibility_on_visible_message():
 
 @mock_aws
 def test_purge_queue_before_delete_message():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     create_resp = client.create_queue(
         QueueName=f"dlr-{str(uuid4())[0:6]}.fifo", Attributes={"FifoQueue": "true"}
@@ -1710,7 +1708,7 @@ def test_purge_queue_before_delete_message():
 @mock_aws
 def test_delete_message_after_visibility_timeout():
     VISIBILITY_TIMEOUT = 1
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6],
         Attributes={"VisibilityTimeout ": f"{VISIBILITY_TIMEOUT}"},
@@ -1733,7 +1731,7 @@ def test_delete_message_after_visibility_timeout():
 
 @mock_aws
 def test_delete_message_errors():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(QueueName=str(uuid4())[0:6])
     queue_url = response["QueueUrl"]
     client.send_message(QueueUrl=queue_url, MessageBody="body")
@@ -1758,7 +1756,7 @@ def test_delete_message_errors():
 
 @mock_aws
 def test_delete_message_twice_using_same_receipt_handle():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(QueueName=str(uuid4())[0:6])
     queue_url = response["QueueUrl"]
 
@@ -1772,7 +1770,7 @@ def test_delete_message_twice_using_same_receipt_handle():
 
 @mock_aws
 def test_delete_message_using_old_receipt_handle():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout": "0"}
     )
@@ -1801,7 +1799,7 @@ def test_delete_message_using_old_receipt_handle():
 
 @mock_aws
 def test_send_message_batch():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(
         QueueName=f"{str(uuid4())[0:6]}.fifo", Attributes={"FifoQueue": "true"}
     )
@@ -1869,7 +1867,7 @@ def test_send_message_batch():
 
 @mock_aws
 def test_delete_message_batch_with_duplicates():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(QueueName=str(uuid4())[0:6])
     queue_url = response["QueueUrl"]
     client.send_message(QueueUrl=queue_url, MessageBody="coucou")
@@ -1897,7 +1895,7 @@ def test_delete_message_batch_with_duplicates():
 
 @mock_aws
 def test_delete_message_batch_with_invalid_receipt_id():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(QueueName=str(uuid4())[0:6])
     queue_url = response["QueueUrl"]
     client.send_message(QueueUrl=queue_url, MessageBody="coucou")
@@ -1943,8 +1941,8 @@ def test_delete_message_batch_with_invalid_receipt_id():
 
 @mock_aws
 def test_message_attributes_in_receive_message():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     q_resp = conn.create_queue(QueueName=str(uuid4())[0:6])
     queue = sqs.Queue(q_resp["QueueUrl"])
 
@@ -2008,7 +2006,7 @@ def test_message_attributes_in_receive_message():
 
 @mock_aws
 def test_send_message_batch_errors():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     response = client.create_queue(QueueName="test-queue")
     queue_url = response["QueueUrl"]
@@ -2088,7 +2086,7 @@ def test_send_message_batch_errors():
 
 @mock_aws
 def test_send_message_batch_with_empty_list():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     response = client.create_queue(QueueName="test-queue")
     queue_url = response["QueueUrl"]
@@ -2106,7 +2104,7 @@ def test_batch_change_message_visibility():
         raise SkipTest("Cant manipulate time in server mode")
 
     with freeze_time("2015-01-01 12:00:00"):
-        sqs = boto3.client("sqs", region_name="us-east-1")
+        sqs = boto3.client("sqs", region_name=REGION)
         resp = sqs.create_queue(
             QueueName="test-dlr-queue.fifo",
             Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"},
@@ -2155,7 +2153,7 @@ def test_batch_change_message_visibility():
 
 @mock_aws
 def test_batch_change_message_visibility_on_old_message():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"VisibilityTimeout": "1"}
     )
@@ -2187,7 +2185,7 @@ def test_batch_change_message_visibility_on_old_message():
 
 @mock_aws
 def test_permissions():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     q_name = f"{str(uuid4())[0:6]}.fifo"
     resp = client.create_queue(QueueName=q_name, Attributes={"FifoQueue": "true"})
@@ -2212,7 +2210,7 @@ def test_permissions():
     policy = json.loads(response["Attributes"]["Policy"])
     assert policy["Version"] == "2012-10-17"
     assert policy["Id"] == (
-        f"arn:aws:sqs:us-east-1:123456789012:{q_name}/SQSDefaultPolicy"
+        f"arn:aws:sqs:{REGION}:123456789012:{q_name}/SQSDefaultPolicy"
     )
     assert sorted(policy["Statement"], key=lambda x: x["Sid"]) == [
         {
@@ -2220,14 +2218,14 @@ def test_permissions():
             "Effect": "Allow",
             "Principal": {"AWS": "arn:aws:iam::111111111111:root"},
             "Action": "SQS:*",
-            "Resource": f"arn:aws:sqs:us-east-1:123456789012:{q_name}",
+            "Resource": f"arn:aws:sqs:{REGION}:123456789012:{q_name}",
         },
         {
             "Sid": "account2",
             "Effect": "Allow",
             "Principal": {"AWS": "arn:aws:iam::222211111111:root"},
             "Action": "SQS:SendMessage",
-            "Resource": f"arn:aws:sqs:us-east-1:123456789012:{q_name}",
+            "Resource": f"arn:aws:sqs:{REGION}:123456789012:{q_name}",
         },
     ]
 
@@ -2238,14 +2236,14 @@ def test_permissions():
     )
     assert json.loads(response["Attributes"]["Policy"]) == {
         "Version": "2012-10-17",
-        "Id": f"arn:aws:sqs:us-east-1:123456789012:{q_name}/SQSDefaultPolicy",
+        "Id": f"arn:aws:sqs:{REGION}:123456789012:{q_name}/SQSDefaultPolicy",
         "Statement": [
             {
                 "Sid": "account1",
                 "Effect": "Allow",
                 "Principal": {"AWS": "arn:aws:iam::111111111111:root"},
                 "Action": "SQS:*",
-                "Resource": f"arn:aws:sqs:us-east-1:123456789012:{q_name}",
+                "Resource": f"arn:aws:sqs:{REGION}:123456789012:{q_name}",
             },
         ],
     }
@@ -2253,7 +2251,7 @@ def test_permissions():
 
 @mock_aws
 def test_get_queue_attributes_template_response_validation():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     resp = client.create_queue(
         QueueName=f"{str(uuid4())[0:6]}.fifo", Attributes={"FifoQueue": "true"}
@@ -2283,7 +2281,7 @@ def test_get_queue_attributes_template_response_validation():
 
 @mock_aws
 def test_add_permission_errors():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(QueueName=str(uuid4())[0:6])
     queue_url = response["QueueUrl"]
     client.add_permission(
@@ -2381,7 +2379,7 @@ def test_add_permission_errors():
 
 @mock_aws
 def test_remove_permission_errors():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(QueueName=str(uuid4())[0:6])
     queue_url = response["QueueUrl"]
 
@@ -2399,7 +2397,7 @@ def test_remove_permission_errors():
 
 @mock_aws
 def test_tags():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     resp = client.create_queue(
         QueueName="test-dlr-queue.fifo", Attributes={"FifoQueue": "true"}
@@ -2425,7 +2423,7 @@ def test_tags():
 
 @mock_aws
 def test_list_queue_tags_errors():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     response = client.create_queue(
         QueueName=str(uuid4())[0:6], tags={"tag_key_1": "tag_value_X"}
@@ -2441,7 +2439,7 @@ def test_list_queue_tags_errors():
 
 @mock_aws
 def test_tag_queue_errors():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     q_name = str(uuid4())[0:6]
     response = client.create_queue(QueueName=q_name, tags={"tag_key_1": "tag_value_X"})
@@ -2476,7 +2474,7 @@ def test_tag_queue_errors():
 
 @mock_aws
 def test_untag_queue_errors():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     response = client.create_queue(
         QueueName=str(uuid4())[0:6], tags={"tag_key_1": "tag_value_1"}
@@ -2498,7 +2496,7 @@ def test_untag_queue_errors():
 
 @mock_aws
 def test_create_fifo_queue_with_dlq():
-    sqs = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.client("sqs", region_name=REGION)
     resp = sqs.create_queue(
         QueueName=f"{str(uuid4())[0:6]}.fifo", Attributes={"FifoQueue": "true"}
     )
@@ -2543,7 +2541,7 @@ def test_queue_with_dlq():
     if settings.TEST_SERVER_MODE:
         raise SkipTest("Cant manipulate time in server mode")
 
-    sqs = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.client("sqs", region_name=REGION)
 
     with freeze_time("2015-01-01 12:00:00"):
         resp = sqs.create_queue(
@@ -2606,7 +2604,7 @@ def test_queue_with_dlq():
 
 @mock_aws
 def test_redrive_policy_available():
-    sqs = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.client("sqs", region_name=REGION)
 
     resp = sqs.create_queue(QueueName=str(uuid4())[0:6])
     queue_url1 = resp["QueueUrl"]
@@ -2640,9 +2638,9 @@ def test_redrive_policy_available():
 
 @mock_aws
 def test_redrive_policy_non_existent_queue():
-    sqs = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.client("sqs", region_name=REGION)
     redrive_policy = {
-        "deadLetterTargetArn": f"arn:aws:sqs:us-east-1:{ACCOUNT_ID}:no-queue",
+        "deadLetterTargetArn": f"arn:aws:sqs:{REGION}:{ACCOUNT_ID}:no-queue",
         "maxReceiveCount": 1,
     }
 
@@ -2655,7 +2653,7 @@ def test_redrive_policy_non_existent_queue():
 
 @mock_aws
 def test_redrive_policy_set_attributes():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
 
     q_name = str(uuid4())[0:6]
     queue = sqs.create_queue(QueueName=q_name)
@@ -2676,7 +2674,7 @@ def test_redrive_policy_set_attributes():
 
 @mock_aws
 def test_redrive_policy_set_attributes_with_string_value():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
 
     q_name = str(uuid4())[0:6]
     queue = sqs.create_queue(QueueName=q_name)
@@ -2704,7 +2702,7 @@ def test_redrive_policy_set_attributes_with_string_value():
 
 @mock_aws
 def test_receive_messages_with_message_group_id():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=f"{str(uuid4())[0:6]}.fifo",
         Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"},
@@ -2736,7 +2734,7 @@ def test_receive_messages_with_message_group_id():
 
 @mock_aws
 def test_receive_messages_with_message_group_id_on_requeue():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=f"{str(uuid4())[0:6]}.fifo",
         Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"},
@@ -2767,7 +2765,7 @@ def test_receive_messages_with_message_group_id_on_visibility_timeout():
         raise SkipTest("Cant manipulate time in server mode")
 
     with freeze_time("2015-01-01 12:00:00"):
-        sqs = boto3.resource("sqs", region_name="us-east-1")
+        sqs = boto3.resource("sqs", region_name=REGION)
         queue = sqs.create_queue(
             QueueName="test-queue.fifo",
             Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"},
@@ -2801,7 +2799,7 @@ def test_receive_messages_with_message_group_id_on_visibility_timeout():
 
 @mock_aws
 def test_receive_message_for_queue_with_receive_message_wait_time_seconds_set():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
 
     queue = sqs.create_queue(
         QueueName=str(uuid4())[0:6], Attributes={"ReceiveMessageWaitTimeSeconds": "2"}
@@ -2815,7 +2813,7 @@ def test_list_queues_limits_to_1000_queues():
     if settings.TEST_SERVER_MODE:
         # Re-visit once we have a NextToken-implementation for list_queues
         raise SkipTest("Too many queues for a persistent mode")
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
 
     prefix_name = str(uuid4())[0:6]
     queue_urls = []
@@ -2826,7 +2824,7 @@ def test_list_queues_limits_to_1000_queues():
     assert len(client.list_queues()["QueueUrls"]) == 1000
     assert len(client.list_queues(QueueNamePrefix=prefix_name)["QueueUrls"]) == 1000
 
-    resource = boto3.resource("sqs", region_name="us-east-1")
+    resource = boto3.resource("sqs", region_name=REGION)
 
     assert len(list(resource.queues.all())) == 1000
     assert len(list(resource.queues.filter(QueueNamePrefix=prefix_name))) == 1000
@@ -2853,7 +2851,7 @@ def test_send_message_to_fifo_without_message_group_id():
 
 @mock_aws
 def test_send_messages_to_fifo_without_message_group_id():
-    sqs = boto3.resource("sqs", region_name="eu-west-3")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName=f"{str(uuid4())[0:6]}.fifo",
         Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"},
@@ -2924,7 +2922,7 @@ def test_fifo_queue_deduplication_with_id(
     msg_1, msg_2, dedupid_1, dedupid_2, expected_count
 ):
 
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     msg_queue = sqs.create_queue(
         QueueName=(f"{q_name}-dlq.fifo"),
@@ -2947,7 +2945,7 @@ def test_fifo_queue_deduplication_with_id(
 )
 def test_fifo_queue_deduplication_withoutid(msg_1, msg_2, expected_count):
 
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     msg_queue = sqs.create_queue(
         QueueName=f"{q_name}-dlq.fifo",
@@ -2968,7 +2966,7 @@ def test_fifo_queue_send_duplicate_messages_after_deduplication_time_limit():
     if settings.TEST_SERVER_MODE:
         raise SkipTest("Cant patch env variables in server mode")
 
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     msg_queue = sqs.create_queue(
         QueueName="test-queue-dlq.fifo",
         Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"},
@@ -2984,7 +2982,7 @@ def test_fifo_queue_send_duplicate_messages_after_deduplication_time_limit():
 @mock_aws
 def test_fifo_queue_send_deduplicationid_same_as_sha256_of_old_message():
 
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     msg_queue = sqs.create_queue(
         QueueName=f"{q_name}-dlq.fifo",
@@ -3007,7 +3005,7 @@ def test_fifo_queue_send_deduplicationid_same_as_sha256_of_old_message():
 @mock_aws
 def test_fifo_send_message_when_same_group_id_is_in_dlq():
 
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     q_name = f"{str(uuid4())[0:6]}-dlq.fifo"
     dlq = sqs.create_queue(
         QueueName=q_name,
@@ -3048,8 +3046,8 @@ def test_fifo_send_message_when_same_group_id_is_in_dlq():
 
 @mock_aws
 def test_receive_message_using_name_should_return_name_as_url():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     name = str(uuid4())[0:6]
     q_response = conn.create_queue(QueueName=name)
     working_url = q_response["QueueUrl"]
@@ -3066,8 +3064,8 @@ def test_receive_message_using_name_should_return_name_as_url():
 
 @mock_aws
 def test_message_attributes_contains_trace_header():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     q_resp = conn.create_queue(QueueName=q_name)
     queue = sqs.Queue(q_resp["QueueUrl"])
@@ -3098,8 +3096,8 @@ def test_message_attributes_contains_trace_header():
 
 @mock_aws
 def test_receive_message_again_preserves_attributes():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
-    conn = boto3.client("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
+    conn = boto3.client("sqs", region_name=REGION)
     q_name = str(uuid4())[0:6]
     q_resp = conn.create_queue(QueueName=q_name)
     queue = sqs.Queue(q_resp["QueueUrl"])
@@ -3133,7 +3131,7 @@ def test_receive_message_again_preserves_attributes():
 
 @mock_aws
 def test_message_has_windows_return():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=f"{str(uuid4())[0:6]}")
 
     message = "content:\rmessage_with line"
@@ -3146,10 +3144,8 @@ def test_message_has_windows_return():
 
 @mock_aws
 def test_message_delay_is_more_than_15_minutes():
-    client = boto3.client("sqs", region_name="us-east-1")
-    response = client.create_queue(
-        QueueName=f"{str(uuid4())[0:6]}.fifo", Attributes={"FifoQueue": "true"}
-    )
+    client = boto3.client("sqs", region_name=REGION)
+    response = client.create_queue(QueueName=str(uuid4())[0:6])
     queue_url = response["QueueUrl"]
 
     response = client.send_message_batch(
@@ -3165,7 +3161,6 @@ def test_message_delay_is_more_than_15_minutes():
                         "DataType": "String",
                     }
                 },
-                "MessageGroupId": "message_group_id_1",
                 "MessageDeduplicationId": "message_deduplication_id_1",
             },
             {
@@ -3175,7 +3170,6 @@ def test_message_delay_is_more_than_15_minutes():
                 "MessageAttributes": {
                     "attribute_name_2": {"StringValue": "123", "DataType": "Number"}
                 },
-                "MessageGroupId": "message_group_id_2",
                 "MessageDeduplicationId": "message_deduplication_id_2",
             },
         ],
@@ -3199,9 +3193,6 @@ def test_message_delay_is_more_than_15_minutes():
     assert response["Messages"][0]["MessageAttributes"] == (
         {"attribute_name_1": {"StringValue": "attribute_value_1", "DataType": "String"}}
     )
-    assert (
-        response["Messages"][0]["Attributes"]["MessageGroupId"] == "message_group_id_1"
-    )
     assert response["Messages"][0]["Attributes"]["MessageDeduplicationId"] == (
         "message_deduplication_id_1"
     )
@@ -3209,7 +3200,7 @@ def test_message_delay_is_more_than_15_minutes():
 
 @mock_aws
 def test_receive_message_that_becomes_visible_while_long_polling():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(QueueName=str(uuid4())[0:6])
     msg_body = str(uuid4())
     queue.send_message(MessageBody=msg_body)
@@ -3226,7 +3217,7 @@ def test_receive_message_that_becomes_visible_while_long_polling():
 
 @mock_aws
 def test_dedupe_fifo():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName="my-queue.fifo",
         Attributes={
@@ -3245,7 +3236,7 @@ def test_dedupe_fifo():
 
 @mock_aws
 def test_fifo_dedupe_error_no_message_group_id():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName="my-queue.fifo",
         Attributes={"FifoQueue": "true"},
@@ -3264,7 +3255,7 @@ def test_fifo_dedupe_error_no_message_group_id():
 
 @mock_aws
 def test_fifo_dedupe_error_no_message_dedupe_id():
-    sqs = boto3.resource("sqs", region_name="us-east-1")
+    sqs = boto3.resource("sqs", region_name=REGION)
     queue = sqs.create_queue(
         QueueName="my-queue.fifo",
         Attributes={"FifoQueue": "true"},
@@ -3284,7 +3275,7 @@ def test_fifo_dedupe_error_no_message_dedupe_id():
 
 @mock_aws
 def test_fifo_dedupe_error_no_message_dedupe_id_batch():
-    client = boto3.client("sqs", region_name="us-east-1")
+    client = boto3.client("sqs", region_name=REGION)
     response = client.create_queue(
         QueueName=f"{str(uuid4())[0:6]}.fifo", Attributes={"FifoQueue": "true"}
     )
@@ -3314,3 +3305,48 @@ def test_fifo_dedupe_error_no_message_dedupe_id_batch():
         "The queue should either have ContentBasedDeduplication enabled "
         "or MessageDeduplicationId provided explicitly"
     )
+
+
+@mock_aws
+@pytest.mark.parametrize(
+    "queue_config", [{"FifoQueue": "true"}, {"FifoQueue": "true", "DelaySeconds": "10"}]
+)
+def test_send_message_delay_seconds_validation(queue_config):
+    # Setup
+    client = boto3.client("sqs", region_name=REGION)
+    q = "test.fifo"
+    client.create_queue(
+        QueueName=q,
+        Attributes=queue_config,
+    )
+
+    # Execute
+    with pytest.raises(ClientError) as err:
+        client.send_message(
+            QueueUrl=q,
+            MessageBody="test",
+            DelaySeconds=5,
+            MessageGroupId="test",
+            MessageDeduplicationId=str(uuid4()),
+        )
+
+    # this should succeed regardless of DelaySeconds configuration on the q
+    # https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html#API_SendMessage_RequestSyntax
+    client.send_message(
+        QueueUrl=q,
+        MessageBody="test",
+        DelaySeconds=0,
+        MessageGroupId="test",
+        MessageDeduplicationId=str(uuid4()),
+    )
+
+    # Verify
+    ex = err.value
+    assert ex.response["Error"]["Code"] == "InvalidParameterValue"
+    assert ex.response["Error"]["Message"] == (
+        "Value 5 for parameter DelaySeconds is invalid. Reason: "
+        "The request include parameter that is not valid for this queue type."
+    )
+
+    # clean up for servertests
+    client.delete_queue(QueueUrl=q)