# Path: microcosm_pubsub/backoff.py
# class ExponentialBackoffPolicy(BackoffPolicy):
#     """
#     Exponential backoff policy.
# 
#     Uses a timeout scaled between 1 and an exponential limit.
# 
#     """
#     def __init__(self, **kwargs):
#         pass
# 
#     def compute_backoff_timeout(self, message, message_timeout):
#         # exponential backoff means that on the Cth failure, timeout is maximized at N=2^C - 1
#         upper = 2**message.approximate_receive_count - 1
# 
#         # randomly select a timeout between 1..N; note that proper exponential backoff uses 0..N
#         scaling_factor = self.randint(1, upper)
# 
#         return min(scaling_factor, MAX_BACKOFF_TIMEOUT)
# 
#     def randint(self, lower, upper):
#         """
#         Test friendly randomization.
# 
#         """
#         return randint(lower, upper)
# 
# class NaiveBackoffPolicy(BackoffPolicy):
#     """
#     Naive backoff policy.
# 
#     Uses a fixed timeout from the message or system default.
# 
#     """
#     def __init__(self, message_retry_visibility_timeout_seconds, **kwargs):
#         self.message_retry_visibility_timeout_seconds = message_retry_visibility_timeout_seconds
# 
#     def compute_backoff_timeout(self, message, message_timeout):
#         backoff_timeout = message_timeout or self.message_retry_visibility_timeout_seconds
#         # we can only set integer timeouts
#         return int(backoff_timeout) if backoff_timeout is not None else backoff_timeout
# 
# Path: microcosm_pubsub/message.py
# class SQSMessage:
#     """
#     SQS message wrapper.
# 
#     """
#     def __init__(self,
#                  consumer,
#                  content,
#                  media_type,
#                  message_id,
#                  receipt_handle,
#                  topic_arn=None,
#                  approximate_receive_count=None,
#                  handler=None):
#         self.consumer = consumer
#         self.content = content
#         self.media_type = media_type
#         self.message_id = message_id
#         self.receipt_handle = receipt_handle
#         self.topic_arn = topic_arn
#         self.approximate_receive_count = approximate_receive_count
#         self.handler = handler
# 
#     def ack(self):
#         """
#         Acknowledge this message was processed successfully.
# 
#         """
#         self.consumer.ack(self)
# 
#     def nack(self, visibility_timeout_seconds=None):
#         """
#         Acknowledge this message was NOT processed successfully.
# 
#         """
#         self.consumer.nack(self, visibility_timeout_seconds)
# 
#     @property
#     def opaque_data(self):
#         if not self.content:
#             return dict()
#         return self.content.get("opaque_data", {})
# 
#     @property
#     def ttl(self):
#         if TTL_KEY not in self.opaque_data:
#             return None
#         return int(self.opaque_data[TTL_KEY])
# 
#     @property
#     def uri(self):
#         if not self.content:
#             return None
#         return self.content.get("uri")


from unittest.mock import patch
from hamcrest import assert_that, equal_to, is_
from microcosm_pubsub.backoff import ExponentialBackoffPolicy, NaiveBackoffPolicy
from microcosm_pubsub.message import SQSMessage
"""
Test backoff policies.

"""




def test_default_timeout():
    message = SQSMessage(
        None, None, None, None, None,
        approximate_receive_count=1,
    )
    backoff_policy = NaiveBackoffPolicy(42)

    assert_that(
        backoff_policy.compute_backoff_timeout(message, None),
        is_(equal_to(42)),
    )


def test_message_timeout():

# Path: microcosm_pubsub/backoff.py
# class ExponentialBackoffPolicy(BackoffPolicy):
#     """
#     Exponential backoff policy.
# 
#     Uses a timeout scaled between 1 and an exponential limit.
# 
#     """
#     def __init__(self, **kwargs):
#         pass
# 
#     def compute_backoff_timeout(self, message, message_timeout):
#         # exponential backoff means that on the Cth failure, timeout is maximized at N=2^C - 1
#         upper = 2**message.approximate_receive_count - 1
# 
#         # randomly select a timeout between 1..N; note that proper exponential backoff uses 0..N
#         scaling_factor = self.randint(1, upper)
# 
#         return min(scaling_factor, MAX_BACKOFF_TIMEOUT)
# 
#     def randint(self, lower, upper):
#         """
#         Test friendly randomization.
# 
#         """
#         return randint(lower, upper)
# 
# class NaiveBackoffPolicy(BackoffPolicy):
#     """
#     Naive backoff policy.
# 
#     Uses a fixed timeout from the message or system default.
# 
#     """
#     def __init__(self, message_retry_visibility_timeout_seconds, **kwargs):
#         self.message_retry_visibility_timeout_seconds = message_retry_visibility_timeout_seconds
# 
#     def compute_backoff_timeout(self, message, message_timeout):
#         backoff_timeout = message_timeout or self.message_retry_visibility_timeout_seconds
#         # we can only set integer timeouts
#         return int(backoff_timeout) if backoff_timeout is not None else backoff_timeout
# 
# Path: microcosm_pubsub/message.py
# class SQSMessage:
#     """
#     SQS message wrapper.
# 
#     """
#     def __init__(self,
#                  consumer,
#                  content,
#                  media_type,
#                  message_id,
#                  receipt_handle,
#                  topic_arn=None,
#                  approximate_receive_count=None,
#                  handler=None):
#         self.consumer = consumer
#         self.content = content
#         self.media_type = media_type
#         self.message_id = message_id
#         self.receipt_handle = receipt_handle
#         self.topic_arn = topic_arn
#         self.approximate_receive_count = approximate_receive_count
#         self.handler = handler
# 
#     def ack(self):
#         """
#         Acknowledge this message was processed successfully.
# 
#         """
#         self.consumer.ack(self)
# 
#     def nack(self, visibility_timeout_seconds=None):
#         """
#         Acknowledge this message was NOT processed successfully.
# 
#         """
#         self.consumer.nack(self, visibility_timeout_seconds)
# 
#     @property
#     def opaque_data(self):
#         if not self.content:
#             return dict()
#         return self.content.get("opaque_data", {})
# 
#     @property
#     def ttl(self):
#         if TTL_KEY not in self.opaque_data:
#             return None
#         return int(self.opaque_data[TTL_KEY])
# 
#     @property
#     def uri(self):
#         if not self.content:
#             return None
#         return self.content.get("uri")


# Path: microcosm_pubsub/tests/test_backoff.py
from unittest.mock import patch
from hamcrest import assert_that, equal_to, is_
from microcosm_pubsub.backoff import ExponentialBackoffPolicy, NaiveBackoffPolicy
from microcosm_pubsub.message import SQSMessage

"""
Test backoff policies.

"""




def test_default_timeout():
    message = SQSMessage(
        None, None, None, None, None,
        approximate_receive_count=1,
    )
    backoff_policy = NaiveBackoffPolicy(42)

    assert_that(
        backoff_policy.compute_backoff_timeout(message, None),
        is_(equal_to(42)),
    )


def test_message_timeout():

    message = SQSMessage(