commit
4213f88c6b
@ -110,7 +110,7 @@ It gets even better! Moto isn't just for Python code and it isn't just for S3. L
|
|||||||
|------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------------|
|
||||||
| SES | @mock_ses | core endpoints done |
|
| SES | @mock_ses | core endpoints done |
|
||||||
|------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------------|
|
||||||
| SNS | @mock_sns | core endpoints done |
|
| SNS | @mock_sns | all endpoints done |
|
||||||
|------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------------|
|
||||||
| SQS | @mock_sqs | core endpoints done |
|
| SQS | @mock_sqs | core endpoints done |
|
||||||
|------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------------|
|
||||||
|
@ -77,6 +77,7 @@ class Subscription(BaseModel):
|
|||||||
self.protocol = protocol
|
self.protocol = protocol
|
||||||
self.arn = make_arn_for_subscription(self.topic.arn)
|
self.arn = make_arn_for_subscription(self.topic.arn)
|
||||||
self.attributes = {}
|
self.attributes = {}
|
||||||
|
self.confirmed = False
|
||||||
|
|
||||||
def publish(self, message, message_id):
|
def publish(self, message, message_id):
|
||||||
if self.protocol == 'sqs':
|
if self.protocol == 'sqs':
|
||||||
@ -172,12 +173,18 @@ class SNSBackend(BaseBackend):
|
|||||||
self.applications = {}
|
self.applications = {}
|
||||||
self.platform_endpoints = {}
|
self.platform_endpoints = {}
|
||||||
self.region_name = region_name
|
self.region_name = region_name
|
||||||
|
self.sms_attributes = {}
|
||||||
|
self.opt_out_numbers = ['+447420500600', '+447420505401', '+447632960543', '+447632960028', '+447700900149', '+447700900550', '+447700900545', '+447700900907']
|
||||||
|
self.permissions = {}
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
region_name = self.region_name
|
region_name = self.region_name
|
||||||
self.__dict__ = {}
|
self.__dict__ = {}
|
||||||
self.__init__(region_name)
|
self.__init__(region_name)
|
||||||
|
|
||||||
|
def update_sms_attributes(self, attrs):
|
||||||
|
self.sms_attributes.update(attrs)
|
||||||
|
|
||||||
def create_topic(self, name):
|
def create_topic(self, name):
|
||||||
topic = Topic(name, self)
|
topic = Topic(name, self)
|
||||||
self.topics[topic.arn] = topic
|
self.topics[topic.arn] = topic
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from moto.core.utils import camelcase_to_underscores
|
from moto.core.utils import camelcase_to_underscores
|
||||||
@ -7,11 +9,17 @@ from .models import sns_backends
|
|||||||
|
|
||||||
|
|
||||||
class SNSResponse(BaseResponse):
|
class SNSResponse(BaseResponse):
|
||||||
|
SMS_ATTR_REGEX = re.compile(r'^attributes\.entry\.(?P<index>\d+)\.(?P<type>key|value)$')
|
||||||
|
OPT_OUT_PHONE_NUMBER_REGEX = re.compile(r'^\+?\d+$')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def backend(self):
|
def backend(self):
|
||||||
return sns_backends[self.region]
|
return sns_backends[self.region]
|
||||||
|
|
||||||
|
def _error(self, code, message, sender='Sender'):
|
||||||
|
template = self.response_template(ERROR_RESPONSE)
|
||||||
|
return template.render(code=code, message=message, sender=sender)
|
||||||
|
|
||||||
def _get_attributes(self):
|
def _get_attributes(self):
|
||||||
attributes = self._get_list_prefix('Attributes.entry')
|
attributes = self._get_list_prefix('Attributes.entry')
|
||||||
return dict(
|
return dict(
|
||||||
@ -459,6 +467,131 @@ class SNSResponse(BaseResponse):
|
|||||||
template = self.response_template(SET_SUBSCRIPTION_ATTRIBUTES_TEMPLATE)
|
template = self.response_template(SET_SUBSCRIPTION_ATTRIBUTES_TEMPLATE)
|
||||||
return template.render()
|
return template.render()
|
||||||
|
|
||||||
|
def set_sms_attributes(self):
|
||||||
|
# attributes.entry.1.key
|
||||||
|
# attributes.entry.1.value
|
||||||
|
# to
|
||||||
|
# 1: {key:X, value:Y}
|
||||||
|
temp_dict = defaultdict(dict)
|
||||||
|
for key, value in self.querystring.items():
|
||||||
|
match = self.SMS_ATTR_REGEX.match(key)
|
||||||
|
if match is not None:
|
||||||
|
temp_dict[match.group('index')][match.group('type')] = value[0]
|
||||||
|
|
||||||
|
# 1: {key:X, value:Y}
|
||||||
|
# to
|
||||||
|
# X: Y
|
||||||
|
# All of this, just to take into account when people provide invalid stuff.
|
||||||
|
result = {}
|
||||||
|
for item in temp_dict.values():
|
||||||
|
if 'key' in item and 'value' in item:
|
||||||
|
result[item['key']] = item['value']
|
||||||
|
|
||||||
|
self.backend.update_sms_attributes(result)
|
||||||
|
|
||||||
|
template = self.response_template(SET_SMS_ATTRIBUTES_TEMPLATE)
|
||||||
|
return template.render()
|
||||||
|
|
||||||
|
def get_sms_attributes(self):
|
||||||
|
filter_list = set()
|
||||||
|
for key, value in self.querystring.items():
|
||||||
|
if key.startswith('attributes.member.1'):
|
||||||
|
filter_list.add(value[0])
|
||||||
|
|
||||||
|
if len(filter_list) > 0:
|
||||||
|
result = {k: v for k, v in self.backend.sms_attributes.items() if k in filter_list}
|
||||||
|
else:
|
||||||
|
result = self.backend.sms_attributes
|
||||||
|
|
||||||
|
template = self.response_template(GET_SMS_ATTRIBUTES_TEMPLATE)
|
||||||
|
return template.render(attributes=result)
|
||||||
|
|
||||||
|
def check_if_phone_number_is_opted_out(self):
|
||||||
|
number = self._get_param('phoneNumber')
|
||||||
|
if self.OPT_OUT_PHONE_NUMBER_REGEX.match(number) is None:
|
||||||
|
error_response = self._error(
|
||||||
|
code='InvalidParameter',
|
||||||
|
message='Invalid parameter: PhoneNumber Reason: input incorrectly formatted'
|
||||||
|
)
|
||||||
|
return error_response, dict(status=400)
|
||||||
|
|
||||||
|
# There should be a nicer way to set if a nubmer has opted out
|
||||||
|
template = self.response_template(CHECK_IF_OPTED_OUT_TEMPLATE)
|
||||||
|
return template.render(opt_out=str(number.endswith('99')).lower())
|
||||||
|
|
||||||
|
def list_phone_numbers_opted_out(self):
|
||||||
|
template = self.response_template(LIST_OPTOUT_TEMPLATE)
|
||||||
|
return template.render(opt_outs=self.backend.opt_out_numbers)
|
||||||
|
|
||||||
|
def opt_in_phone_number(self):
|
||||||
|
number = self._get_param('phoneNumber')
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.backend.opt_out_numbers.remove(number)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
template = self.response_template(OPT_IN_NUMBER_TEMPLATE)
|
||||||
|
return template.render()
|
||||||
|
|
||||||
|
def add_permission(self):
|
||||||
|
arn = self._get_param('TopicArn')
|
||||||
|
label = self._get_param('Label')
|
||||||
|
accounts = self._get_multi_param('AWSAccountId.member.')
|
||||||
|
action = self._get_multi_param('ActionName.member.')
|
||||||
|
|
||||||
|
if arn not in self.backend.topics:
|
||||||
|
error_response = self._error('NotFound', 'Topic does not exist')
|
||||||
|
return error_response, dict(status=404)
|
||||||
|
|
||||||
|
key = (arn, label)
|
||||||
|
self.backend.permissions[key] = {'accounts': accounts, 'action': action}
|
||||||
|
|
||||||
|
template = self.response_template(ADD_PERMISSION_TEMPLATE)
|
||||||
|
return template.render()
|
||||||
|
|
||||||
|
def remove_permission(self):
|
||||||
|
arn = self._get_param('TopicArn')
|
||||||
|
label = self._get_param('Label')
|
||||||
|
|
||||||
|
if arn not in self.backend.topics:
|
||||||
|
error_response = self._error('NotFound', 'Topic does not exist')
|
||||||
|
return error_response, dict(status=404)
|
||||||
|
|
||||||
|
try:
|
||||||
|
key = (arn, label)
|
||||||
|
del self.backend.permissions[key]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
template = self.response_template(DEL_PERMISSION_TEMPLATE)
|
||||||
|
return template.render()
|
||||||
|
|
||||||
|
def confirm_subscription(self):
|
||||||
|
arn = self._get_param('TopicArn')
|
||||||
|
|
||||||
|
if arn not in self.backend.topics:
|
||||||
|
error_response = self._error('NotFound', 'Topic does not exist')
|
||||||
|
return error_response, dict(status=404)
|
||||||
|
|
||||||
|
# Once Tokens are stored by the `subscribe` endpoint and distributed
|
||||||
|
# to the client somehow, then we can check validity of tokens
|
||||||
|
# presented to this method. The following code works, all thats
|
||||||
|
# needed is to perform a token check and assign that value to the
|
||||||
|
# `already_subscribed` variable.
|
||||||
|
#
|
||||||
|
# token = self._get_param('Token')
|
||||||
|
# auth = self._get_param('AuthenticateOnUnsubscribe')
|
||||||
|
# if already_subscribed:
|
||||||
|
# error_response = self._error(
|
||||||
|
# code='AuthorizationError',
|
||||||
|
# message='Subscription already confirmed'
|
||||||
|
# )
|
||||||
|
# return error_response, dict(status=400)
|
||||||
|
|
||||||
|
template = self.response_template(CONFIRM_SUBSCRIPTION_TEMPLATE)
|
||||||
|
return template.render(sub_arn='{0}:68762e72-e9b1-410a-8b3b-903da69ee1d5'.format(arn))
|
||||||
|
|
||||||
|
|
||||||
CREATE_TOPIC_TEMPLATE = """<CreateTopicResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
CREATE_TOPIC_TEMPLATE = """<CreateTopicResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
<CreateTopicResult>
|
<CreateTopicResult>
|
||||||
@ -758,3 +891,85 @@ SET_SUBSCRIPTION_ATTRIBUTES_TEMPLATE = """<SetSubscriptionAttributesResponse xml
|
|||||||
<RequestId>a8763b99-33a7-11df-a9b7-05d48da6f042</RequestId>
|
<RequestId>a8763b99-33a7-11df-a9b7-05d48da6f042</RequestId>
|
||||||
</ResponseMetadata>
|
</ResponseMetadata>
|
||||||
</SetSubscriptionAttributesResponse>"""
|
</SetSubscriptionAttributesResponse>"""
|
||||||
|
|
||||||
|
SET_SMS_ATTRIBUTES_TEMPLATE = """<SetSMSAttributesResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
|
<SetSMSAttributesResult/>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>26332069-c04a-5428-b829-72524b56a364</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</SetSMSAttributesResponse>"""
|
||||||
|
|
||||||
|
GET_SMS_ATTRIBUTES_TEMPLATE = """<GetSMSAttributesResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
|
<GetSMSAttributesResult>
|
||||||
|
<attributes>
|
||||||
|
{% for name, value in attributes.items() %}
|
||||||
|
<entry>
|
||||||
|
<key>{{ name }}</key>
|
||||||
|
<value>{{ value }}</value>
|
||||||
|
</entry>
|
||||||
|
{% endfor %}
|
||||||
|
</attributes>
|
||||||
|
</GetSMSAttributesResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>287f9554-8db3-5e66-8abc-c76f0186db7e</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</GetSMSAttributesResponse>"""
|
||||||
|
|
||||||
|
CHECK_IF_OPTED_OUT_TEMPLATE = """<CheckIfPhoneNumberIsOptedOutResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
|
<CheckIfPhoneNumberIsOptedOutResult>
|
||||||
|
<isOptedOut>{{ opt_out }}</isOptedOut>
|
||||||
|
</CheckIfPhoneNumberIsOptedOutResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>287f9554-8db3-5e66-8abc-c76f0186db7e</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</CheckIfPhoneNumberIsOptedOutResponse>"""
|
||||||
|
|
||||||
|
ERROR_RESPONSE = """<ErrorResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
|
<Error>
|
||||||
|
<Type>{{ sender }}</Type>
|
||||||
|
<Code>{{ code }}</Code>
|
||||||
|
<Message>{{ message }}</Message>
|
||||||
|
</Error>
|
||||||
|
<RequestId>9dd01905-5012-5f99-8663-4b3ecd0dfaef</RequestId>
|
||||||
|
</ErrorResponse>"""
|
||||||
|
|
||||||
|
LIST_OPTOUT_TEMPLATE = """<ListPhoneNumbersOptedOutResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
|
<ListPhoneNumbersOptedOutResult>
|
||||||
|
<phoneNumbers>
|
||||||
|
{% for item in opt_outs %}
|
||||||
|
<member>{{ item }}</member>
|
||||||
|
{% endfor %}
|
||||||
|
</phoneNumbers>
|
||||||
|
</ListPhoneNumbersOptedOutResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>985e196d-a237-51b6-b33a-4b5601276b38</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</ListPhoneNumbersOptedOutResponse>"""
|
||||||
|
|
||||||
|
OPT_IN_NUMBER_TEMPLATE = """<OptInPhoneNumberResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
|
<OptInPhoneNumberResult/>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>4c61842c-0796-50ef-95ac-d610c0bc8cf8</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</OptInPhoneNumberResponse>"""
|
||||||
|
|
||||||
|
ADD_PERMISSION_TEMPLATE = """<AddPermissionResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>c046e713-c5ff-5888-a7bc-b52f0e4f1299</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</AddPermissionResponse>"""
|
||||||
|
|
||||||
|
DEL_PERMISSION_TEMPLATE = """<RemovePermissionResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>e767cc9f-314b-5e1b-b283-9ea3fd4e38a3</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</RemovePermissionResponse>"""
|
||||||
|
|
||||||
|
CONFIRM_SUBSCRIPTION_TEMPLATE = """<ConfirmSubscriptionResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
|
||||||
|
<ConfirmSubscriptionResult>
|
||||||
|
<SubscriptionArn>{{ sub_arn }}</SubscriptionArn>
|
||||||
|
</ConfirmSubscriptionResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>16eb4dde-7b3c-5b3e-a22a-1fe2a92d3293</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</ConfirmSubscriptionResponse>"""
|
||||||
|
@ -321,3 +321,30 @@ def test_publish_to_disabled_platform_endpoint():
|
|||||||
MessageStructure="json",
|
MessageStructure="json",
|
||||||
TargetArn=endpoint_arn,
|
TargetArn=endpoint_arn,
|
||||||
).should.throw(ClientError)
|
).should.throw(ClientError)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sns
|
||||||
|
def test_set_sms_attributes():
|
||||||
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
|
|
||||||
|
conn.set_sms_attributes(attributes={'DefaultSMSType': 'Transactional', 'test': 'test'})
|
||||||
|
|
||||||
|
response = conn.get_sms_attributes()
|
||||||
|
response.should.contain('attributes')
|
||||||
|
response['attributes'].should.contain('DefaultSMSType')
|
||||||
|
response['attributes'].should.contain('test')
|
||||||
|
response['attributes']['DefaultSMSType'].should.equal('Transactional')
|
||||||
|
response['attributes']['test'].should.equal('test')
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sns
|
||||||
|
def test_get_sms_attributes_filtered():
|
||||||
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
|
|
||||||
|
conn.set_sms_attributes(attributes={'DefaultSMSType': 'Transactional', 'test': 'test'})
|
||||||
|
|
||||||
|
response = conn.get_sms_attributes(attributes=['DefaultSMSType'])
|
||||||
|
response.should.contain('attributes')
|
||||||
|
response['attributes'].should.contain('DefaultSMSType')
|
||||||
|
response['attributes'].should_not.contain('test')
|
||||||
|
response['attributes']['DefaultSMSType'].should.equal('Transactional')
|
||||||
|
@ -34,6 +34,7 @@ def test_creating_subscription():
|
|||||||
"ListSubscriptionsResult"]["Subscriptions"]
|
"ListSubscriptionsResult"]["Subscriptions"]
|
||||||
subscriptions.should.have.length_of(0)
|
subscriptions.should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
@mock_sns_deprecated
|
@mock_sns_deprecated
|
||||||
def test_deleting_subscriptions_by_deleting_topic():
|
def test_deleting_subscriptions_by_deleting_topic():
|
||||||
conn = boto.connect_sns()
|
conn = boto.connect_sns()
|
||||||
@ -66,6 +67,7 @@ def test_deleting_subscriptions_by_deleting_topic():
|
|||||||
"ListSubscriptionsResult"]["Subscriptions"]
|
"ListSubscriptionsResult"]["Subscriptions"]
|
||||||
subscriptions.should.have.length_of(0)
|
subscriptions.should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
@mock_sns_deprecated
|
@mock_sns_deprecated
|
||||||
def test_getting_subscriptions_by_topic():
|
def test_getting_subscriptions_by_topic():
|
||||||
conn = boto.connect_sns()
|
conn = boto.connect_sns()
|
||||||
|
@ -37,6 +37,7 @@ def test_creating_subscription():
|
|||||||
subscriptions = conn.list_subscriptions()["Subscriptions"]
|
subscriptions = conn.list_subscriptions()["Subscriptions"]
|
||||||
subscriptions.should.have.length_of(0)
|
subscriptions.should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
@mock_sns
|
@mock_sns
|
||||||
def test_deleting_subscriptions_by_deleting_topic():
|
def test_deleting_subscriptions_by_deleting_topic():
|
||||||
conn = boto3.client('sns', region_name='us-east-1')
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
@ -68,6 +69,7 @@ def test_deleting_subscriptions_by_deleting_topic():
|
|||||||
subscriptions = conn.list_subscriptions()["Subscriptions"]
|
subscriptions = conn.list_subscriptions()["Subscriptions"]
|
||||||
subscriptions.should.have.length_of(0)
|
subscriptions.should.have.length_of(0)
|
||||||
|
|
||||||
|
|
||||||
@mock_sns
|
@mock_sns
|
||||||
def test_getting_subscriptions_by_topic():
|
def test_getting_subscriptions_by_topic():
|
||||||
conn = boto3.client('sns', region_name='us-east-1')
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
@ -197,3 +199,67 @@ def test_set_subscription_attributes():
|
|||||||
AttributeName='InvalidName',
|
AttributeName='InvalidName',
|
||||||
AttributeValue='true'
|
AttributeValue='true'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sns
|
||||||
|
def test_check_not_opted_out():
|
||||||
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
|
response = conn.check_if_phone_number_is_opted_out(phoneNumber='+447428545375')
|
||||||
|
|
||||||
|
response.should.contain('isOptedOut')
|
||||||
|
response['isOptedOut'].should.be(False)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sns
|
||||||
|
def test_check_opted_out():
|
||||||
|
# Phone number ends in 99 so is hardcoded in the endpoint to return opted
|
||||||
|
# out status
|
||||||
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
|
response = conn.check_if_phone_number_is_opted_out(phoneNumber='+447428545399')
|
||||||
|
|
||||||
|
response.should.contain('isOptedOut')
|
||||||
|
response['isOptedOut'].should.be(True)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sns
|
||||||
|
def test_check_opted_out_invalid():
|
||||||
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
|
|
||||||
|
# Invalid phone number
|
||||||
|
with assert_raises(ClientError):
|
||||||
|
conn.check_if_phone_number_is_opted_out(phoneNumber='+44742LALALA')
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sns
|
||||||
|
def test_list_opted_out():
|
||||||
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
|
response = conn.list_phone_numbers_opted_out()
|
||||||
|
|
||||||
|
response.should.contain('phoneNumbers')
|
||||||
|
len(response['phoneNumbers']).should.be.greater_than(0)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sns
|
||||||
|
def test_opt_in():
|
||||||
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
|
response = conn.list_phone_numbers_opted_out()
|
||||||
|
current_len = len(response['phoneNumbers'])
|
||||||
|
assert current_len > 0
|
||||||
|
|
||||||
|
conn.opt_in_phone_number(phoneNumber=response['phoneNumbers'][0])
|
||||||
|
|
||||||
|
response = conn.list_phone_numbers_opted_out()
|
||||||
|
len(response['phoneNumbers']).should.be.greater_than(0)
|
||||||
|
len(response['phoneNumbers']).should.be.lower_than(current_len)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sns
|
||||||
|
def test_confirm_subscription():
|
||||||
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
|
response = conn.create_topic(Name='testconfirm')
|
||||||
|
|
||||||
|
conn.confirm_subscription(
|
||||||
|
TopicArn=response['TopicArn'],
|
||||||
|
Token='2336412f37fb687f5d51e6e241d59b68c4e583a5cee0be6f95bbf97ab8d2441cf47b99e848408adaadf4c197e65f03473d53c4ba398f6abbf38ce2e8ebf7b4ceceb2cd817959bcde1357e58a2861b05288c535822eb88cac3db04f592285249971efc6484194fc4a4586147f16916692',
|
||||||
|
AuthenticateOnUnsubscribe='true'
|
||||||
|
)
|
||||||
|
@ -129,3 +129,20 @@ def test_topic_paging():
|
|||||||
response.shouldnt.have("NextToken")
|
response.shouldnt.have("NextToken")
|
||||||
|
|
||||||
topics_list.should.have.length_of(int(DEFAULT_PAGE_SIZE / 2))
|
topics_list.should.have.length_of(int(DEFAULT_PAGE_SIZE / 2))
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sns
|
||||||
|
def test_add_remove_permissions():
|
||||||
|
conn = boto3.client('sns', region_name='us-east-1')
|
||||||
|
response = conn.create_topic(Name='testpermissions')
|
||||||
|
|
||||||
|
conn.add_permission(
|
||||||
|
TopicArn=response['TopicArn'],
|
||||||
|
Label='Test1234',
|
||||||
|
AWSAccountId=['999999999999'],
|
||||||
|
ActionName=['AddPermission']
|
||||||
|
)
|
||||||
|
conn.remove_permission(
|
||||||
|
TopicArn=response['TopicArn'],
|
||||||
|
Label='Test1234'
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user