Repository: localstack/localstack

Issue:
SNS FIFO topic to SQS FIFO queue does not seem to work
### Is there an existing issue for this?

- [X] I have searched the existing issues

### Current Behavior

My SQS queue is not receiving notifications from SNS when they both have fifo enabled:

```
# Create SNS topic
docker exec -it localstack awslocal sns create-topic --name my-topic.fifo --attributes FifoTopic=true

# Create SQS queue
docker exec -it localstack awslocal sqs create-queue --queue-name my-queue.fifo --attributes FifoQueue=true

# Subscribe queue to topic
docker exec -it localstack awslocal sns subscribe --topic-arn arn:aws:sns:us-east-1:000000000000:my-topic.fifo --protocol sqs --notification-endpoint http://localhost:4566/000000000000/my-queue.fifo

# Send test notification
docker exec -it localstack awslocal sns publish-batch --topic-arn arn:aws:sns:us-east-1:000000000000:my-topic.fifo --publish-batch-request-entries Id=myId,Message=myMessage,MessageGroupId=myMessageGroupId,MessageDeduplicationId=myMessageDeduplicationId

# Receive messages
docker exec -it localstack awslocal sqs receive-message --queue-url http://localhost:4566/000000000000/my-queue.fifo --attribute-name All
```
Output:
```
{
    "TopicArn": "arn:aws:sns:us-east-1:000000000000:my-topic.fifo"
}
{
    "QueueUrl": "http://localhost:4566/000000000000/my-queue.fifo"
}
{
    "SubscriptionArn": "arn:aws:sns:us-east-1:000000000000:my-topic.fifo:46cd4bc8-c572-4a5b-ab69-cd0db1b160b4"
}
{
    "Successful": [
        {
            "Id": "myId",
            "MessageId": "c9b2c232-4a56-4875-9e11-21cb6b386221"
        }
    ],
    "Failed": []
}
```

No messages were received.


### Expected Behavior

If I do the above steps without fifo on SNS and SQS, then it works as it should:
```
docker exec -it localstack awslocal sns create-topic --name my-topic
docker exec -it localstack awslocal sqs create-queue --queue-name my-queue
docker exec -it localstack awslocal sns subscribe --topic-arn arn:aws:sns:us-east-1:000000000000:my-topic --protocol sqs --notification-endpoint http://localhost:4566/000000000000/my-queue
docker exec -it localstack awslocal sns publish-batch --topic-arn arn:aws:sns:us-east-1:000000000000:my-topic --publish-batch-request-entries Id=myId,Message=myMessage,MessageGroupId=myMessageGroupId,MessageDeduplicationId=myMessageDeduplicationId
docker exec -it localstack awslocal sqs receive-message --queue-url http://localhost:4566/000000000000/my-queue --attribute-name All
```
Outputs:
```
{
    "TopicArn": "arn:aws:sns:us-east-1:000000000000:my-topic"
}
{
    "QueueUrl": "http://localhost:4566/000000000000/my-queue"
}
{
    "SubscriptionArn": "arn:aws:sns:us-east-1:000000000000:my-topic:06b585e5-5ac3-434b-b817-489694fa891b"
}
{
    "Successful": [
        {
            "Id": "myId",
            "MessageId": "46bb7006-4e5e-4472-a1c0-29c902edff2c"
        }
    ],
    "Failed": []
}
{
    "Messages": [
        {
            "MessageId": "1a7d9db0-430b-424f-b23c-9f8f2f5f5c5f",
            "ReceiptHandle": "NjU0ZjJjMDYtN2I0Yy00OTgzLThmMzYtNWVjNTQ5ZjAwNWEzIGFybjphd3M6c3FzOnVzLWVhc3QtMTowMDAwMDAwMDAwMDA6bXktcXVldWUgMWE3ZDlkYjAtNDMwYi00MjRmLWIyM2MtOWY4ZjJmNWY1YzVmIDE2NjAyMzg2MzAuMzg4NzAyOQ==",
            "MD5OfBody": "f7ad57b0788283b7afaa4dba8ea1784b",
            "Body": "{\"Type\": \"Notification\", \"MessageId\": \"46bb7006-4e5e-4472-a1c0-29c902edff2c\", \"TopicArn\": \"arn:aws:sns:us-east-1:000000000000:my-topic\", \"Message\": \"myMessage\", \"Timestamp\": \"2022-08-11T17:23:49.814Z\", \"SignatureVersion\": \"1\", \"Signature\": \"EXAMPLEpH+..\", \"SigningCertURL\": \"https://sns.us-east-1.amazonaws.com/SimpleNotificationService-0000000000000000000000.pem\", \"UnsubscribeURL\": \"http://localhost:4566/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:000000000000:my-topic:06b585e5-5ac3-434b-b817-489694fa891b\"}",
            "Attributes": {
                "SenderId": "000000000000",
                "SentTimestamp": "1660238629853",
                "ApproximateReceiveCount": "1",
                "ApproximateFirstReceiveTimestamp": "1660238630388"
            }
        }
    ]
}
```

### How are you starting LocalStack?

With a docker-compose file

### Steps To Reproduce

#### How are you starting localstack (e.g., `bin/localstack` command, arguments, or `docker-compose.yml`)

    docker run localstack/localstack

#### Client commands (e.g., AWS SDK code snippet, or sequence of "awslocal" commands)

    awslocal s3 mb s3://mybucket


### Environment

```markdown
- OS: 5.4.0-1086-azure (Github Codespaces)
- LocalStack:latest

docker-compose.yml

localstack:
    image: localstack/localstack:latest
    container_name: localstack
    environment:
      - SERVICES=sqs,sns
      - AWS_DEFAULT_REGION=us-east-1
      - EDGE_PORT=4566
    ports:
      - '4566-4597:4566-4597'
    volumes:
      - "${TMPDIR:-/tmp/localstack}:/var/lib/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"
    networks:
      - app_network
```
```


### Anything else?

_No response_


Discussion:
Welcome to LocalStack! Thanks for reporting your first issue and our team will be working towards fixing the issue for you or reach out for more background information. We recommend joining our [Slack Community](https://localstack.cloud/contact/) for real-time help and drop a message to LocalStack Pro Support if you are a Pro user! If you are willing to contribute towards fixing this issue, please have a look at our [contributing guidelines](https://github.com/localstack/.github/blob/main/CONTRIBUTING.md) and our [developer guide](https://docs.localstack.cloud/developer-guide/).

Resolving patch:
diff --git a/localstack/services/sns/provider.py b/localstack/services/sns/provider.py
--- a/localstack/services/sns/provider.py
+++ b/localstack/services/sns/provider.py
@@ -243,9 +243,9 @@ def message_to_endpoint(target_arn, message, structure, endpoint_attributes, pla
         )
 
     if response is None:
-        LOG.warn("Platform not implemeted yet")
+        LOG.warning("Platform not implemented yet")
     elif response.status_code != 200:
-        LOG.warn(
+        LOG.warning(
             f"Platform {platform_name} returned response {response.status_code} with content {response.content}"
         )
 
@@ -481,7 +481,8 @@ def publish_batch(
             data["Subject"] = [entry.get("Subject")]
             if ".fifo" in topic_arn:
                 data["MessageGroupId"] = [entry.get("MessageGroupId")]
-            # TODO: add MessageDeduplication checks once ASF-SQS implementation becomes default
+                data["MessageDeduplicationId"] = [entry.get("MessageDeduplicationId")]
+            # TODO: implement SNS MessageDeduplicationId and ContentDeduplication checks
 
             message_attributes = entry.get("MessageAttributes", {})
             try:


Test patch:
diff --git a/tests/integration/test_sns.py b/tests/integration/test_sns.py
--- a/tests/integration/test_sns.py
+++ b/tests/integration/test_sns.py
@@ -1293,6 +1293,7 @@ def get_messages():
             "$..Successful..SequenceNumber",  # sequence number are not added
         ]
     )
+    @pytest.mark.parametrize("content_based_deduplication", [True, False])
     def test_publish_batch_messages_from_fifo_topic_to_fifo_queue(
         self,
         sns_client,
@@ -1301,16 +1302,19 @@ def test_publish_batch_messages_from_fifo_topic_to_fifo_queue(
         sqs_create_queue,
         sns_create_sqs_subscription,
         snapshot,
+        content_based_deduplication,
     ):
         topic_name = f"topic-{short_uid()}.fifo"
         queue_name = f"queue-{short_uid()}.fifo"
+        topic_attributes = {"FifoTopic": "true"}
+        queue_attributes = {"FifoQueue": "true"}
+        if content_based_deduplication:
+            topic_attributes["ContentBasedDeduplication"] = "true"
+            queue_attributes["ContentBasedDeduplication"] = "true"
 
         topic_arn = sns_create_topic(
             Name=topic_name,
-            Attributes={
-                "FifoTopic": "true",
-                "ContentBasedDeduplication": "true",
-            },
+            Attributes=topic_attributes,
         )["TopicArn"]
 
         response = sns_client.get_topic_attributes(TopicArn=topic_arn)
@@ -1318,10 +1322,7 @@ def test_publish_batch_messages_from_fifo_topic_to_fifo_queue(
 
         queue_url = sqs_create_queue(
             QueueName=queue_name,
-            Attributes={
-                "FifoQueue": "true",
-                "ContentBasedDeduplication": "true",
-            },
+            Attributes=queue_attributes,
         )
 
         subscription = sns_create_sqs_subscription(topic_arn=topic_arn, queue_url=queue_url)
@@ -1335,35 +1336,40 @@ def test_publish_batch_messages_from_fifo_topic_to_fifo_queue(
 
         response = sns_client.get_subscription_attributes(SubscriptionArn=subscription_arn)
         snapshot.match("sub-attrs-raw-true", response)
-
         message_group_id = "complexMessageGroupId"
+        publish_batch_request_entries = [
+            {
+                "Id": "1",
+                "MessageGroupId": message_group_id,
+                "Message": "Test Message with two attributes",
+                "Subject": "Subject",
+                "MessageAttributes": {
+                    "attr1": {"DataType": "Number", "StringValue": "99.12"},
+                    "attr2": {"DataType": "Number", "StringValue": "109.12"},
+                },
+            },
+            {
+                "Id": "2",
+                "MessageGroupId": message_group_id,
+                "Message": "Test Message with one attribute",
+                "Subject": "Subject",
+                "MessageAttributes": {"attr1": {"DataType": "Number", "StringValue": "19.12"}},
+            },
+            {
+                "Id": "3",
+                "MessageGroupId": message_group_id,
+                "Message": "Test Message without attribute",
+                "Subject": "Subject",
+            },
+        ]
+
+        if not content_based_deduplication:
+            for index, message in enumerate(publish_batch_request_entries):
+                message["MessageDeduplicationId"] = f"MessageDeduplicationId-{index}"
+
         publish_batch_response = sns_client.publish_batch(
             TopicArn=topic_arn,
-            PublishBatchRequestEntries=[
-                {
-                    "Id": "1",
-                    "MessageGroupId": message_group_id,
-                    "Message": "Test Message with two attributes",
-                    "Subject": "Subject",
-                    "MessageAttributes": {
-                        "attr1": {"DataType": "Number", "StringValue": "99.12"},
-                        "attr2": {"DataType": "Number", "StringValue": "109.12"},
-                    },
-                },
-                {
-                    "Id": "2",
-                    "MessageGroupId": message_group_id,
-                    "Message": "Test Message with one attribute",
-                    "Subject": "Subject",
-                    "MessageAttributes": {"attr1": {"DataType": "Number", "StringValue": "19.12"}},
-                },
-                {
-                    "Id": "3",
-                    "MessageGroupId": message_group_id,
-                    "Message": "Test Message without attribute",
-                    "Subject": "Subject",
-                },
-            ],
+            PublishBatchRequestEntries=publish_batch_request_entries,
         )
 
         snapshot.match("publish-batch-response-fifo", publish_batch_response)
@@ -1592,6 +1598,7 @@ def check_subscription_deleted():
             "$..Messages..Attributes.SequenceNumber",
         ]
     )
+    @pytest.mark.parametrize("content_based_deduplication", [True, False])
     def test_message_to_fifo_sqs(
         self,
         sns_client,
@@ -1600,39 +1607,48 @@ def test_message_to_fifo_sqs(
         sqs_create_queue,
         sns_create_sqs_subscription,
         snapshot,
+        content_based_deduplication,
     ):
-        # it is the md5 hash of the body containing a timestamp
-        snapshot.add_transformer(
-            snapshot.transform.key_value(
-                "MessageDeduplicationId",
-                value_replacement="<md5-hash>",
-                reference_replacement=False,
-            )
-        )
         topic_name = f"topic-{short_uid()}.fifo"
         queue_name = f"queue-{short_uid()}.fifo"
+        topic_attributes = {"FifoTopic": "true"}
+        queue_attributes = {"FifoQueue": "true"}
+        if content_based_deduplication:
+            topic_attributes["ContentBasedDeduplication"] = "true"
+            queue_attributes["ContentBasedDeduplication"] = "true"
 
         topic_arn = sns_create_topic(
             Name=topic_name,
-            Attributes={
-                "FifoTopic": "true",
-                "ContentBasedDeduplication": "true",  # todo: not enforced yet
-            },
+            Attributes=topic_attributes,
         )["TopicArn"]
         queue_url = sqs_create_queue(
             QueueName=queue_name,
-            Attributes={
-                "FifoQueue": "true",
-                "ContentBasedDeduplication": "true",
-            },
+            Attributes=queue_attributes,
         )
         # todo check both ContentBasedDeduplication and MessageDeduplicationId when implemented
         # https://docs.aws.amazon.com/sns/latest/dg/fifo-message-dedup.html
 
-        sns_create_sqs_subscription(topic_arn=topic_arn, queue_url=queue_url)
+        subscription = sns_create_sqs_subscription(topic_arn=topic_arn, queue_url=queue_url)
+
+        # this allows us to have a simplified body not containing timestamp, so we can check MessageDeduplicationId
+        sns_client.set_subscription_attributes(
+            SubscriptionArn=subscription["SubscriptionArn"],
+            AttributeName="RawMessageDelivery",
+            AttributeValue="true",
+        )
 
         message = "Test"
-        sns_client.publish(TopicArn=topic_arn, Message=message, MessageGroupId="message-group-id-1")
+        if content_based_deduplication:
+            sns_client.publish(
+                TopicArn=topic_arn, Message=message, MessageGroupId="message-group-id-1"
+            )
+        else:
+            sns_client.publish(
+                TopicArn=topic_arn,
+                Message=message,
+                MessageGroupId="message-group-id-1",
+                MessageDeduplicationId="message-deduplication-id-1",
+            )
 
         response = sqs_client.receive_message(
             QueueUrl=queue_url,
@@ -1642,9 +1658,6 @@ def test_message_to_fifo_sqs(
         )
         snapshot.match("messages", response)
 
-        msg_body = response["Messages"][0]["Body"]
-        assert json.loads(msg_body)["Message"] == message
-
     @pytest.mark.aws_validated
     def test_validations_for_fifo(
         self,
diff --git a/tests/integration/test_sns.snapshot.json b/tests/integration/test_sns.snapshot.json
--- a/tests/integration/test_sns.snapshot.json
+++ b/tests/integration/test_sns.snapshot.json
@@ -1167,177 +1167,6 @@
       }
     }
   },
-  "tests/integration/test_sns.py::TestSNSProvider::test_publish_batch_messages_from_fifo_topic_to_fifo_queue": {
-    "recorded-date": "09-08-2022, 11:35:46",
-    "recorded-content": {
-      "topic-attrs": {
-        "Attributes": {
-          "ContentBasedDeduplication": "true",
-          "DisplayName": "",
-          "EffectiveDeliveryPolicy": {
-            "http": {
-              "defaultHealthyRetryPolicy": {
-                "minDelayTarget": 20,
-                "maxDelayTarget": 20,
-                "numRetries": 3,
-                "numMaxDelayRetries": 0,
-                "numNoDelayRetries": 0,
-                "numMinDelayRetries": 0,
-                "backoffFunction": "linear"
-              },
-              "disableSubscriptionOverrides": false
-            }
-          },
-          "FifoTopic": "true",
-          "Owner": "111111111111",
-          "Policy": {
-            "Version": "2008-10-17",
-            "Id": "__default_policy_ID",
-            "Statement": [
-              {
-                "Sid": "__default_statement_ID",
-                "Effect": "Allow",
-                "Principal": {
-                  "AWS": "*"
-                },
-                "Action": [
-                  "SNS:GetTopicAttributes",
-                  "SNS:SetTopicAttributes",
-                  "SNS:AddPermission",
-                  "SNS:RemovePermission",
-                  "SNS:DeleteTopic",
-                  "SNS:Subscribe",
-                  "SNS:ListSubscriptionsByTopic",
-                  "SNS:Publish"
-                ],
-                "Resource": "arn:aws:sns:<region>:111111111111:<resource:1>",
-                "Condition": {
-                  "StringEquals": {
-                    "AWS:SourceOwner": "111111111111"
-                  }
-                }
-              }
-            ]
-          },
-          "SubscriptionsConfirmed": "0",
-          "SubscriptionsDeleted": "0",
-          "SubscriptionsPending": "0",
-          "TopicArn": "arn:aws:sns:<region>:111111111111:<resource:1>"
-        },
-        "ResponseMetadata": {
-          "HTTPHeaders": {},
-          "HTTPStatusCode": 200
-        }
-      },
-      "sub-attrs-raw-true": {
-        "Attributes": {
-          "ConfirmationWasAuthenticated": "true",
-          "Endpoint": "arn:aws:sqs:<region>:111111111111:<resource:2>",
-          "Owner": "111111111111",
-          "PendingConfirmation": "false",
-          "Protocol": "sqs",
-          "RawMessageDelivery": "true",
-          "SubscriptionArn": "arn:aws:sns:<region>:111111111111:<resource:1>:<resource:3>",
-          "TopicArn": "arn:aws:sns:<region>:111111111111:<resource:1>"
-        },
-        "ResponseMetadata": {
-          "HTTPHeaders": {},
-          "HTTPStatusCode": 200
-        }
-      },
-      "publish-batch-response-fifo": {
-        "Failed": [],
-        "ResponseMetadata": {
-          "HTTPHeaders": {},
-          "HTTPStatusCode": 200
-        },
-        "Successful": [
-          {
-            "Id": "1",
-            "MessageId": "<uuid:1>",
-            "SequenceNumber": "<sequence-number:1>"
-          },
-          {
-            "Id": "2",
-            "MessageId": "<uuid:2>",
-            "SequenceNumber": "<sequence-number:2>"
-          },
-          {
-            "Id": "3",
-            "MessageId": "<uuid:3>",
-            "SequenceNumber": "<sequence-number:3>"
-          }
-        ]
-      },
-      "messages": {
-        "Messages": [
-          {
-            "Attributes": {
-              "ApproximateFirstReceiveTimestamp": "timestamp",
-              "ApproximateReceiveCount": "1",
-              "MessageDeduplicationId": "47f6d7e2c477469ad670ae3bfee60ed3e79080bb0105fc01a2805a50f8b21358",
-              "MessageGroupId": "complexMessageGroupId",
-              "SenderId": "<sender-id>",
-              "SentTimestamp": "timestamp",
-              "SequenceNumber": "<sequence-number:4>"
-            },
-            "Body": "Test Message with two attributes",
-            "MD5OfBody": "<md5-hash>",
-            "MD5OfMessageAttributes": "9b720b3af309c1c4b0d395c53b08c502",
-            "MessageAttributes": {
-              "attr1": {
-                "DataType": "Number",
-                "StringValue": "99.12"
-              },
-              "attr2": {
-                "DataType": "Number",
-                "StringValue": "109.12"
-              }
-            },
-            "MessageId": "<uuid:4>",
-            "ReceiptHandle": "<receipt-handle:1>"
-          },
-          {
-            "Attributes": {
-              "ApproximateFirstReceiveTimestamp": "timestamp",
-              "ApproximateReceiveCount": "1",
-              "MessageDeduplicationId": "2186166772ec2fb49b7ba9efbda53c6eabf8e785cb00420db531c8eb9287d8e1",
-              "MessageGroupId": "complexMessageGroupId",
-              "SenderId": "<sender-id>",
-              "SentTimestamp": "timestamp",
-              "SequenceNumber": "<sequence-number:5>"
-            },
-            "Body": "Test Message with one attribute",
-            "MD5OfBody": "<md5-hash>",
-            "MD5OfMessageAttributes": "1f07082409022a373fa2a2601f82b3cb",
-            "MessageAttributes": {
-              "attr1": {
-                "DataType": "Number",
-                "StringValue": "19.12"
-              }
-            },
-            "MessageId": "<uuid:5>",
-            "ReceiptHandle": "<receipt-handle:2>"
-          },
-          {
-            "Attributes": {
-              "ApproximateFirstReceiveTimestamp": "timestamp",
-              "ApproximateReceiveCount": "1",
-              "MessageDeduplicationId": "a579d4ebff398c5ad4d5037534a1c1bfab36410100c80d8c7c1029b57c7898fe",
-              "MessageGroupId": "complexMessageGroupId",
-              "SenderId": "<sender-id>",
-              "SentTimestamp": "timestamp",
-              "SequenceNumber": "<sequence-number:6>"
-            },
-            "Body": "Test Message without attribute",
-            "MD5OfBody": "<md5-hash>",
-            "MessageId": "<uuid:6>",
-            "ReceiptHandle": "<receipt-handle:3>"
-          }
-        ]
-      }
-    }
-  },
   "tests/integration/test_sns.py::TestSNSProvider::test_publish_batch_exceptions": {
     "recorded-date": "09-08-2022, 11:35:46",
     "recorded-content": {
@@ -1467,42 +1296,6 @@
       }
     }
   },
-  "tests/integration/test_sns.py::TestSNSProvider::test_message_to_fifo_sqs": {
-    "recorded-date": "09-08-2022, 11:35:53",
-    "recorded-content": {
-      "messages": {
-        "Messages": [
-          {
-            "Attributes": {
-              "ApproximateFirstReceiveTimestamp": "timestamp",
-              "ApproximateReceiveCount": "1",
-              "MessageDeduplicationId": "<md5-hash>",
-              "MessageGroupId": "message-group-id-1",
-              "SenderId": "<sender-id>",
-              "SentTimestamp": "timestamp",
-              "SequenceNumber": "<sequence-number:1>"
-            },
-            "Body": {
-              "Type": "Notification",
-              "MessageId": "<uuid:1>",
-              "SequenceNumber": "<sequence-number:2>",
-              "TopicArn": "arn:aws:sns:<region>:111111111111:<resource:1>",
-              "Message": "Test",
-              "Timestamp": "date",
-              "UnsubscribeURL": "<unsubscribe-domain>/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:<region>:111111111111:<resource:1>:<resource:2>"
-            },
-            "MD5OfBody": "<md5-hash>",
-            "MessageId": "<uuid:2>",
-            "ReceiptHandle": "<receipt-handle:1>"
-          }
-        ],
-        "ResponseMetadata": {
-          "HTTPHeaders": {},
-          "HTTPStatusCode": 200
-        }
-      }
-    }
-  },
   "tests/integration/test_sns.py::TestSNSProvider::test_validations_for_fifo": {
     "recorded-date": "09-08-2022, 11:35:56",
     "recorded-content": {
@@ -1824,5 +1617,403 @@
         }
       }
     }
+  },
+  "tests/integration/test_sns.py::TestSNSProvider::test_publish_batch_messages_from_fifo_topic_to_fifo_queue[True]": {
+    "recorded-date": "12-08-2022, 13:43:57",
+    "recorded-content": {
+      "topic-attrs": {
+        "Attributes": {
+          "ContentBasedDeduplication": "true",
+          "DisplayName": "",
+          "EffectiveDeliveryPolicy": {
+            "http": {
+              "defaultHealthyRetryPolicy": {
+                "minDelayTarget": 20,
+                "maxDelayTarget": 20,
+                "numRetries": 3,
+                "numMaxDelayRetries": 0,
+                "numNoDelayRetries": 0,
+                "numMinDelayRetries": 0,
+                "backoffFunction": "linear"
+              },
+              "disableSubscriptionOverrides": false
+            }
+          },
+          "FifoTopic": "true",
+          "Owner": "111111111111",
+          "Policy": {
+            "Version": "2008-10-17",
+            "Id": "__default_policy_ID",
+            "Statement": [
+              {
+                "Sid": "__default_statement_ID",
+                "Effect": "Allow",
+                "Principal": {
+                  "AWS": "*"
+                },
+                "Action": [
+                  "SNS:GetTopicAttributes",
+                  "SNS:SetTopicAttributes",
+                  "SNS:AddPermission",
+                  "SNS:RemovePermission",
+                  "SNS:DeleteTopic",
+                  "SNS:Subscribe",
+                  "SNS:ListSubscriptionsByTopic",
+                  "SNS:Publish"
+                ],
+                "Resource": "arn:aws:sns:<region>:111111111111:<resource:1>",
+                "Condition": {
+                  "StringEquals": {
+                    "AWS:SourceOwner": "111111111111"
+                  }
+                }
+              }
+            ]
+          },
+          "SubscriptionsConfirmed": "0",
+          "SubscriptionsDeleted": "0",
+          "SubscriptionsPending": "0",
+          "TopicArn": "arn:aws:sns:<region>:111111111111:<resource:1>"
+        },
+        "ResponseMetadata": {
+          "HTTPHeaders": {},
+          "HTTPStatusCode": 200
+        }
+      },
+      "sub-attrs-raw-true": {
+        "Attributes": {
+          "ConfirmationWasAuthenticated": "true",
+          "Endpoint": "arn:aws:sqs:<region>:111111111111:<resource:2>",
+          "Owner": "111111111111",
+          "PendingConfirmation": "false",
+          "Protocol": "sqs",
+          "RawMessageDelivery": "true",
+          "SubscriptionArn": "arn:aws:sns:<region>:111111111111:<resource:1>:<resource:3>",
+          "TopicArn": "arn:aws:sns:<region>:111111111111:<resource:1>"
+        },
+        "ResponseMetadata": {
+          "HTTPHeaders": {},
+          "HTTPStatusCode": 200
+        }
+      },
+      "publish-batch-response-fifo": {
+        "Failed": [],
+        "ResponseMetadata": {
+          "HTTPHeaders": {},
+          "HTTPStatusCode": 200
+        },
+        "Successful": [
+          {
+            "Id": "1",
+            "MessageId": "<uuid:1>",
+            "SequenceNumber": "<sequence-number:1>"
+          },
+          {
+            "Id": "2",
+            "MessageId": "<uuid:2>",
+            "SequenceNumber": "<sequence-number:2>"
+          },
+          {
+            "Id": "3",
+            "MessageId": "<uuid:3>",
+            "SequenceNumber": "<sequence-number:3>"
+          }
+        ]
+      },
+      "messages": {
+        "Messages": [
+          {
+            "Attributes": {
+              "ApproximateFirstReceiveTimestamp": "timestamp",
+              "ApproximateReceiveCount": "1",
+              "MessageDeduplicationId": "47f6d7e2c477469ad670ae3bfee60ed3e79080bb0105fc01a2805a50f8b21358",
+              "MessageGroupId": "complexMessageGroupId",
+              "SenderId": "<sender-id>",
+              "SentTimestamp": "timestamp",
+              "SequenceNumber": "<sequence-number:4>"
+            },
+            "Body": "Test Message with two attributes",
+            "MD5OfBody": "<md5-hash>",
+            "MD5OfMessageAttributes": "9b720b3af309c1c4b0d395c53b08c502",
+            "MessageAttributes": {
+              "attr1": {
+                "DataType": "Number",
+                "StringValue": "99.12"
+              },
+              "attr2": {
+                "DataType": "Number",
+                "StringValue": "109.12"
+              }
+            },
+            "MessageId": "<uuid:4>",
+            "ReceiptHandle": "<receipt-handle:1>"
+          },
+          {
+            "Attributes": {
+              "ApproximateFirstReceiveTimestamp": "timestamp",
+              "ApproximateReceiveCount": "1",
+              "MessageDeduplicationId": "2186166772ec2fb49b7ba9efbda53c6eabf8e785cb00420db531c8eb9287d8e1",
+              "MessageGroupId": "complexMessageGroupId",
+              "SenderId": "<sender-id>",
+              "SentTimestamp": "timestamp",
+              "SequenceNumber": "<sequence-number:5>"
+            },
+            "Body": "Test Message with one attribute",
+            "MD5OfBody": "<md5-hash>",
+            "MD5OfMessageAttributes": "1f07082409022a373fa2a2601f82b3cb",
+            "MessageAttributes": {
+              "attr1": {
+                "DataType": "Number",
+                "StringValue": "19.12"
+              }
+            },
+            "MessageId": "<uuid:5>",
+            "ReceiptHandle": "<receipt-handle:2>"
+          },
+          {
+            "Attributes": {
+              "ApproximateFirstReceiveTimestamp": "timestamp",
+              "ApproximateReceiveCount": "1",
+              "MessageDeduplicationId": "a579d4ebff398c5ad4d5037534a1c1bfab36410100c80d8c7c1029b57c7898fe",
+              "MessageGroupId": "complexMessageGroupId",
+              "SenderId": "<sender-id>",
+              "SentTimestamp": "timestamp",
+              "SequenceNumber": "<sequence-number:6>"
+            },
+            "Body": "Test Message without attribute",
+            "MD5OfBody": "<md5-hash>",
+            "MessageId": "<uuid:6>",
+            "ReceiptHandle": "<receipt-handle:3>"
+          }
+        ]
+      }
+    }
+  },
+  "tests/integration/test_sns.py::TestSNSProvider::test_publish_batch_messages_from_fifo_topic_to_fifo_queue[False]": {
+    "recorded-date": "12-08-2022, 13:43:59",
+    "recorded-content": {
+      "topic-attrs": {
+        "Attributes": {
+          "ContentBasedDeduplication": "false",
+          "DisplayName": "",
+          "EffectiveDeliveryPolicy": {
+            "http": {
+              "defaultHealthyRetryPolicy": {
+                "minDelayTarget": 20,
+                "maxDelayTarget": 20,
+                "numRetries": 3,
+                "numMaxDelayRetries": 0,
+                "numNoDelayRetries": 0,
+                "numMinDelayRetries": 0,
+                "backoffFunction": "linear"
+              },
+              "disableSubscriptionOverrides": false
+            }
+          },
+          "FifoTopic": "true",
+          "Owner": "111111111111",
+          "Policy": {
+            "Version": "2008-10-17",
+            "Id": "__default_policy_ID",
+            "Statement": [
+              {
+                "Sid": "__default_statement_ID",
+                "Effect": "Allow",
+                "Principal": {
+                  "AWS": "*"
+                },
+                "Action": [
+                  "SNS:GetTopicAttributes",
+                  "SNS:SetTopicAttributes",
+                  "SNS:AddPermission",
+                  "SNS:RemovePermission",
+                  "SNS:DeleteTopic",
+                  "SNS:Subscribe",
+                  "SNS:ListSubscriptionsByTopic",
+                  "SNS:Publish"
+                ],
+                "Resource": "arn:aws:sns:<region>:111111111111:<resource:1>",
+                "Condition": {
+                  "StringEquals": {
+                    "AWS:SourceOwner": "111111111111"
+                  }
+                }
+              }
+            ]
+          },
+          "SubscriptionsConfirmed": "0",
+          "SubscriptionsDeleted": "0",
+          "SubscriptionsPending": "0",
+          "TopicArn": "arn:aws:sns:<region>:111111111111:<resource:1>"
+        },
+        "ResponseMetadata": {
+          "HTTPHeaders": {},
+          "HTTPStatusCode": 200
+        }
+      },
+      "sub-attrs-raw-true": {
+        "Attributes": {
+          "ConfirmationWasAuthenticated": "true",
+          "Endpoint": "arn:aws:sqs:<region>:111111111111:<resource:2>",
+          "Owner": "111111111111",
+          "PendingConfirmation": "false",
+          "Protocol": "sqs",
+          "RawMessageDelivery": "true",
+          "SubscriptionArn": "arn:aws:sns:<region>:111111111111:<resource:1>:<resource:3>",
+          "TopicArn": "arn:aws:sns:<region>:111111111111:<resource:1>"
+        },
+        "ResponseMetadata": {
+          "HTTPHeaders": {},
+          "HTTPStatusCode": 200
+        }
+      },
+      "publish-batch-response-fifo": {
+        "Failed": [],
+        "ResponseMetadata": {
+          "HTTPHeaders": {},
+          "HTTPStatusCode": 200
+        },
+        "Successful": [
+          {
+            "Id": "1",
+            "MessageId": "<uuid:1>",
+            "SequenceNumber": "<sequence-number:1>"
+          },
+          {
+            "Id": "2",
+            "MessageId": "<uuid:2>",
+            "SequenceNumber": "<sequence-number:2>"
+          },
+          {
+            "Id": "3",
+            "MessageId": "<uuid:3>",
+            "SequenceNumber": "<sequence-number:3>"
+          }
+        ]
+      },
+      "messages": {
+        "Messages": [
+          {
+            "Attributes": {
+              "ApproximateFirstReceiveTimestamp": "timestamp",
+              "ApproximateReceiveCount": "1",
+              "MessageDeduplicationId": "MessageDeduplicationId-0",
+              "MessageGroupId": "complexMessageGroupId",
+              "SenderId": "<sender-id>",
+              "SentTimestamp": "timestamp",
+              "SequenceNumber": "<sequence-number:4>"
+            },
+            "Body": "Test Message with two attributes",
+            "MD5OfBody": "<md5-hash>",
+            "MD5OfMessageAttributes": "9b720b3af309c1c4b0d395c53b08c502",
+            "MessageAttributes": {
+              "attr1": {
+                "DataType": "Number",
+                "StringValue": "99.12"
+              },
+              "attr2": {
+                "DataType": "Number",
+                "StringValue": "109.12"
+              }
+            },
+            "MessageId": "<uuid:4>",
+            "ReceiptHandle": "<receipt-handle:1>"
+          },
+          {
+            "Attributes": {
+              "ApproximateFirstReceiveTimestamp": "timestamp",
+              "ApproximateReceiveCount": "1",
+              "MessageDeduplicationId": "MessageDeduplicationId-1",
+              "MessageGroupId": "complexMessageGroupId",
+              "SenderId": "<sender-id>",
+              "SentTimestamp": "timestamp",
+              "SequenceNumber": "<sequence-number:5>"
+            },
+            "Body": "Test Message with one attribute",
+            "MD5OfBody": "<md5-hash>",
+            "MD5OfMessageAttributes": "1f07082409022a373fa2a2601f82b3cb",
+            "MessageAttributes": {
+              "attr1": {
+                "DataType": "Number",
+                "StringValue": "19.12"
+              }
+            },
+            "MessageId": "<uuid:5>",
+            "ReceiptHandle": "<receipt-handle:2>"
+          },
+          {
+            "Attributes": {
+              "ApproximateFirstReceiveTimestamp": "timestamp",
+              "ApproximateReceiveCount": "1",
+              "MessageDeduplicationId": "MessageDeduplicationId-2",
+              "MessageGroupId": "complexMessageGroupId",
+              "SenderId": "<sender-id>",
+              "SentTimestamp": "timestamp",
+              "SequenceNumber": "<sequence-number:6>"
+            },
+            "Body": "Test Message without attribute",
+            "MD5OfBody": "<md5-hash>",
+            "MessageId": "<uuid:6>",
+            "ReceiptHandle": "<receipt-handle:3>"
+          }
+        ]
+      }
+    }
+  },
+  "tests/integration/test_sns.py::TestSNSProvider::test_message_to_fifo_sqs[True]": {
+    "recorded-date": "12-08-2022, 13:52:38",
+    "recorded-content": {
+      "messages": {
+        "Messages": [
+          {
+            "Attributes": {
+              "ApproximateFirstReceiveTimestamp": "timestamp",
+              "ApproximateReceiveCount": "1",
+              "MessageDeduplicationId": "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25",
+              "MessageGroupId": "message-group-id-1",
+              "SenderId": "<sender-id>",
+              "SentTimestamp": "timestamp",
+              "SequenceNumber": "<sequence-number:1>"
+            },
+            "Body": "Test",
+            "MD5OfBody": "<md5-hash>",
+            "MessageId": "<uuid:1>",
+            "ReceiptHandle": "<receipt-handle:1>"
+          }
+        ],
+        "ResponseMetadata": {
+          "HTTPHeaders": {},
+          "HTTPStatusCode": 200
+        }
+      }
+    }
+  },
+  "tests/integration/test_sns.py::TestSNSProvider::test_message_to_fifo_sqs[False]": {
+    "recorded-date": "12-08-2022, 13:52:40",
+    "recorded-content": {
+      "messages": {
+        "Messages": [
+          {
+            "Attributes": {
+              "ApproximateFirstReceiveTimestamp": "timestamp",
+              "ApproximateReceiveCount": "1",
+              "MessageDeduplicationId": "message-deduplication-id-1",
+              "MessageGroupId": "message-group-id-1",
+              "SenderId": "<sender-id>",
+              "SentTimestamp": "timestamp",
+              "SequenceNumber": "<sequence-number:1>"
+            },
+            "Body": "Test",
+            "MD5OfBody": "<md5-hash>",
+            "MessageId": "<uuid:1>",
+            "ReceiptHandle": "<receipt-handle:1>"
+          }
+        ],
+        "ResponseMetadata": {
+          "HTTPHeaders": {},
+          "HTTPStatusCode": 200
+        }
+      }
+    }
   }
 }