Exemple #1
0
    def test_in_order_messages_are_handled_in_order(self):
        """Test that messages received in order are handled in order."""
        message_handling_order = []

        message_handler = OrderedMessageHandler(
            subscriber=MockSubscriber(),
            subscription=self.mock_subscription,
            message_handlers={
                "test": self._make_order_recording_message_handler(message_handling_order),
                "finish-test": lambda message: "This is the result.",
            },
        )

        with patch(
            "octue.cloud.pub_sub.service.OrderedMessageHandler._pull_message",
            new=MockMessagePuller(
                messages=[
                    {"type": "test", "message_number": 0},
                    {"type": "test", "message_number": 1},
                    {"type": "test", "message_number": 2},
                    {"type": "finish-test", "message_number": 3},
                ]
            ).pull,
        ):
            result = message_handler.handle_messages()

        self.assertEqual(result, "This is the result.")
        self.assertEqual(message_handling_order, [0, 1, 2])
Exemple #2
0
    def test_error_raised_if_delivery_acknowledgement_not_received_in_time(self):
        """Test that an error is raised if delivery acknowledgement isn't received before the given acknowledgement
        timeout.
        """
        message_handler = OrderedMessageHandler(subscriber=MockSubscriber(), subscription=self.mock_subscription)

        with patch("tests.cloud.pub_sub.mocks.MockSubscriber.pull", return_value=MockPullResponse()):
            with self.assertRaises(exceptions.QuestionNotDelivered):
                message_handler.handle_messages(delivery_acknowledgement_timeout=0)
Exemple #3
0
    def test_unknown_message_type_raises_warning(self):
        """Test that unknown message types result in a warning being logged."""
        message_handler = OrderedMessageHandler(
            subscriber=MockSubscriber(),
            subscription=self.mock_subscription,
            message_handlers={"finish-test": lambda message: message},
        )

        with patch("logging.StreamHandler.emit") as mock_emit:
            message_handler._handle_message({"type": "blah", "message_number": 0})

        self.assertIn("Received a message of unknown type", mock_emit.call_args_list[0][0][0].msg)
Exemple #4
0
    def test_is_push_subscription(self):
        """Test that `is_pull_subscription` is `False` and `is_push_subscription` is `True` for a pull subscription."""
        push_subscription = Subscription(
            name="world",
            topic=self.topic,
            namespace="hello",
            project_name=TEST_PROJECT_NAME,
            subscriber=MockSubscriber(),
            push_endpoint="https://example.com/endpoint",
        )

        self.assertTrue(push_subscription.is_push_subscription)
        self.assertFalse(push_subscription.is_pull_subscription)
Exemple #5
0
    def test_namespace_only_in_name_once(self):
        """Test that the subscription's namespace only appears in its name once, even if it is repeated."""
        self.assertEqual(self.subscription.name, "hello.world")

        subscription_with_repeated_namespace = Subscription(
            name="hello.world",
            topic=self.topic,
            namespace="hello",
            project_name=TEST_PROJECT_NAME,
            subscriber=MockSubscriber(),
        )

        self.assertEqual(subscription_with_repeated_namespace.name,
                         "hello.world")
Exemple #6
0
    def setUpClass(cls):
        """Set up the test class with a mock subscription.

        :return None:
        """
        service = MockService(backend=BACKEND)
        mock_topic = MockTopic(name="world", namespace="hello", service=service)
        cls.mock_subscription = MockSubscription(
            name="world",
            topic=mock_topic,
            namespace="hello",
            project_name=TEST_PROJECT_NAME,
            subscriber=MockSubscriber(),
        )
    def test_error_raised_if_attempting_to_wait_for_answer_from_push_subscription(
            self):
        """Test that an error is raised if attempting to wait for an answer from a push subscription."""
        service = Service(backend=BACKEND)

        mock_subscription = MockSubscription(
            name="world",
            topic=MockTopic(name="world", namespace="hello", service=service),
            namespace="hello",
            project_name=TEST_PROJECT_NAME,
            subscriber=MockSubscriber(),
            push_endpoint="https://example.com/endpoint",
        )

        with self.assertRaises(exceptions.PushSubscriptionCannotBePulled):
            service.wait_for_answer(subscription=mock_subscription)
Exemple #8
0
    def test_timeout(self):
        """Test that a TimeoutError is raised if message handling takes longer than the given timeout."""
        message_handler = OrderedMessageHandler(
            subscriber=MockSubscriber(),
            subscription=self.mock_subscription,
            message_handlers={
                "test": self._make_order_recording_message_handler([]),
                "finish-test": lambda message: message,
            },
        )

        with patch(
            "octue.cloud.pub_sub.service.OrderedMessageHandler._pull_message",
            new=MockMessagePuller(messages=[{"type": "test", "message_number": 0}]).pull,
        ):
            with self.assertRaises(TimeoutError):
                message_handler.handle_messages(timeout=0)
    def test_timeout_error_raised_if_no_messages_received_when_waiting(self):
        """Test that a TimeoutError is raised if no messages are received while waiting."""
        service = Service(backend=BACKEND)
        mock_topic = MockTopic(name="world",
                               namespace="hello",
                               service=service)

        mock_subscription = MockSubscription(
            name="world",
            topic=mock_topic,
            namespace="hello",
            project_name=TEST_PROJECT_NAME,
            subscriber=MockSubscriber(),
        )

        with patch(
                "octue.cloud.pub_sub.service.pubsub_v1.SubscriberClient.pull",
                return_value=MockPullResponse()):
            with self.assertRaises(TimeoutError):
                service.wait_for_answer(subscription=mock_subscription,
                                        timeout=0.01)
Exemple #10
0
    def test_delivery_acknowledgement(self):
        """Test that a delivery acknowledgement message is handled correctly."""
        message_handler = OrderedMessageHandler(subscriber=MockSubscriber(), subscription=self.mock_subscription)
        self.assertFalse(message_handler.received_delivery_acknowledgement)

        with patch(
            "octue.cloud.pub_sub.service.OrderedMessageHandler._pull_message",
            new=MockMessagePuller(
                [
                    {
                        "type": "delivery_acknowledgement",
                        "delivery_time": "2021-11-17 17:33:59.717428",
                        "message_number": 0,
                    },
                    {"type": "result", "output_values": None, "output_manifest": None, "message_number": 1},
                ]
            ).pull,
        ):
            result = message_handler.handle_messages()

        self.assertTrue(message_handler.received_delivery_acknowledgement)
        self.assertEqual(result, {"output_values": None, "output_manifest": None})
Exemple #11
0
class TestSubscription(BaseTestCase):

    service = Service(backend=GCPPubSubBackend(project_name="my-project"))
    topic = Topic(name="world", namespace="hello", service=service)
    subscription = Subscription(name="world",
                                topic=topic,
                                namespace="hello",
                                project_name=TEST_PROJECT_NAME,
                                subscriber=MockSubscriber())

    def test_namespace_only_in_name_once(self):
        """Test that the subscription's namespace only appears in its name once, even if it is repeated."""
        self.assertEqual(self.subscription.name, "hello.world")

        subscription_with_repeated_namespace = Subscription(
            name="hello.world",
            topic=self.topic,
            namespace="hello",
            project_name=TEST_PROJECT_NAME,
            subscriber=MockSubscriber(),
        )

        self.assertEqual(subscription_with_repeated_namespace.name,
                         "hello.world")

    def test_repr(self):
        """Test that Subscriptions are represented correctly."""
        self.assertEqual(repr(self.subscription),
                         "<Subscription(hello.world)>")

    def test_error_raised_when_creating_without_allowing_existing_when_subscription_already_exists(
            self):
        """Test that an error is raised when trying to create a subscription that already exists and `allow_existing` is
        `False`.
        """
        with patch(
                "tests.cloud.pub_sub.mocks.MockSubscriber.create_subscription",
                side_effect=google.api_core.exceptions.AlreadyExists(""),
        ):
            with self.assertRaises(google.api_core.exceptions.AlreadyExists):
                self.subscription.create(allow_existing=False)

    def test_create_with_allow_existing_when_already_exists(self):
        """Test that trying to create a subscription that already exists when `allow_existing` is `True` results in no
        error.
        """
        with patch(
                "tests.cloud.pub_sub.mocks.MockSubscriber.create_subscription",
                side_effect=google.api_core.exceptions.AlreadyExists(""),
        ):
            self.subscription.create(allow_existing=True)

    def test_create_pull_subscription(self):
        """Test that creating a pull subscription works properly."""
        project_name = os.environ["TEST_PROJECT_NAME"]
        service = Service(backend=GCPPubSubBackend(project_name=project_name))
        topic = Topic(name="my-topic", namespace="tests", service=service)

        subscription = Subscription(
            name="world",
            topic=topic,
            namespace="hello",
            project_name=project_name,
            subscriber=SubscriberClient(credentials=service.credentials),
        )

        with patch("google.pubsub_v1.SubscriberClient.create_subscription",
                   new=MockSubscriptionCreationResponse):
            response = subscription.create(allow_existing=True)

        self.assertEqual(response._pb.ack_deadline_seconds, 600)
        self.assertEqual(response._pb.expiration_policy.ttl.seconds,
                         THIRTY_ONE_DAYS)
        self.assertEqual(response._pb.message_retention_duration.seconds, 600)
        self.assertEqual(response._pb.retry_policy.minimum_backoff.seconds, 10)
        self.assertEqual(response._pb.retry_policy.maximum_backoff.seconds,
                         600)

    def test_create_push_subscription(self):
        """Test that creating a push subscription works properly."""
        project_name = os.environ["TEST_PROJECT_NAME"]
        service = Service(backend=GCPPubSubBackend(project_name=project_name))
        topic = Topic(name="my-topic", namespace="tests", service=service)

        subscription = Subscription(
            name="world",
            topic=topic,
            namespace="hello",
            project_name=project_name,
            subscriber=SubscriberClient(credentials=service.credentials),
            push_endpoint="https://example.com/endpoint",
        )

        with patch("google.pubsub_v1.SubscriberClient.create_subscription",
                   new=MockSubscriptionCreationResponse):
            response = subscription.create(allow_existing=True)

        self.assertEqual(response._pb.ack_deadline_seconds, 600)
        self.assertEqual(response._pb.expiration_policy.ttl.seconds,
                         THIRTY_ONE_DAYS)
        self.assertEqual(response._pb.message_retention_duration.seconds, 600)
        self.assertEqual(response._pb.retry_policy.minimum_backoff.seconds, 10)
        self.assertEqual(response._pb.retry_policy.maximum_backoff.seconds,
                         600)
        self.assertEqual(response._pb.push_config.push_endpoint,
                         "https://example.com/endpoint")

    def test_is_pull_subscription(self):
        """Test that `is_pull_subscription` is `True` and `is_push_subscription` is `False` for a pull subscription."""
        self.assertTrue(self.subscription.is_pull_subscription)
        self.assertFalse(self.subscription.is_push_subscription)

    def test_is_push_subscription(self):
        """Test that `is_pull_subscription` is `False` and `is_push_subscription` is `True` for a pull subscription."""
        push_subscription = Subscription(
            name="world",
            topic=self.topic,
            namespace="hello",
            project_name=TEST_PROJECT_NAME,
            subscriber=MockSubscriber(),
            push_endpoint="https://example.com/endpoint",
        )

        self.assertTrue(push_subscription.is_push_subscription)
        self.assertFalse(push_subscription.is_pull_subscription)