# Copyright 2016 Google Inc. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest2 try: # pylint: disable=unused-import import gcloud.pubsub._gax # pylint: enable=unused-import except ImportError: # pragma: NO COVER _HAVE_GAX = False else: _HAVE_GAX = True class _Base(object): PROJECT = 'PROJECT' PROJECT_PATH = 'projects/%s' % (PROJECT,) LIST_TOPICS_PATH = '%s/topics' % (PROJECT_PATH,) TOPIC_NAME = 'topic_name' TOPIC_PATH = 'projects/%s/topics/%s' % (PROJECT, TOPIC_NAME) LIST_TOPIC_SUBSCRIPTIONS_PATH = '%s/subscriptions' % (TOPIC_PATH,) SUB_NAME = 'sub_name' SUB_PATH = '%s/subscriptions/%s' % (TOPIC_PATH, SUB_NAME) def _makeOne(self, *args, **kw): return self._getTargetClass()(*args, **kw) @unittest2.skipUnless(_HAVE_GAX, 'No gax-python') class Test_PublisherAPI(_Base, unittest2.TestCase): def _getTargetClass(self): from gcloud.pubsub._gax import _PublisherAPI return _PublisherAPI def test_ctor(self): gax_api = _GAXPublisherAPI() api = self._makeOne(gax_api) self.assertTrue(api._gax_api is gax_api) def test_list_topics_no_paging(self): from google.gax import INITIAL_PAGE from gcloud._testing import _GAXPageIterator TOKEN = 'TOKEN' response = _GAXPageIterator([_TopicPB(self.TOPIC_PATH)], TOKEN) gax_api = _GAXPublisherAPI(_list_topics_response=response) api = self._makeOne(gax_api) topics, next_token = api.list_topics(self.PROJECT) self.assertEqual(len(topics), 1) topic = topics[0] self.assertIsInstance(topic, dict) self.assertEqual(topic['name'], self.TOPIC_PATH) self.assertEqual(next_token, TOKEN) name, page_size, options = gax_api._list_topics_called_with self.assertEqual(name, self.PROJECT_PATH) self.assertEqual(page_size, 0) self.assertTrue(options.page_token is INITIAL_PAGE) def test_list_topics_with_paging(self): from gcloud._testing import _GAXPageIterator SIZE = 23 TOKEN = 'TOKEN' NEW_TOKEN = 'NEW_TOKEN' response = _GAXPageIterator( [_TopicPB(self.TOPIC_PATH)], NEW_TOKEN) gax_api = _GAXPublisherAPI(_list_topics_response=response) api = self._makeOne(gax_api) topics, next_token = api.list_topics( self.PROJECT, page_size=SIZE, page_token=TOKEN) self.assertEqual(len(topics), 1) topic = topics[0] self.assertIsInstance(topic, dict) self.assertEqual(topic['name'], self.TOPIC_PATH) self.assertEqual(next_token, NEW_TOKEN) name, page_size, options = gax_api._list_topics_called_with self.assertEqual(name, self.PROJECT_PATH) self.assertEqual(page_size, SIZE) self.assertEqual(options.page_token, TOKEN) def test_topic_create(self): topic_pb = _TopicPB(self.TOPIC_PATH) gax_api = _GAXPublisherAPI(_create_topic_response=topic_pb) api = self._makeOne(gax_api) resource = api.topic_create(self.TOPIC_PATH) self.assertEqual(resource, {'name': self.TOPIC_PATH}) topic_path, options = gax_api._create_topic_called_with self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_topic_create_already_exists(self): from gcloud.exceptions import Conflict gax_api = _GAXPublisherAPI(_create_topic_conflict=True) api = self._makeOne(gax_api) with self.assertRaises(Conflict): api.topic_create(self.TOPIC_PATH) topic_path, options = gax_api._create_topic_called_with self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_topic_create_error(self): from google.gax.errors import GaxError gax_api = _GAXPublisherAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.topic_create(self.TOPIC_PATH) topic_path, options = gax_api._create_topic_called_with self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_topic_get_hit(self): topic_pb = _TopicPB(self.TOPIC_PATH) gax_api = _GAXPublisherAPI(_get_topic_response=topic_pb) api = self._makeOne(gax_api) resource = api.topic_get(self.TOPIC_PATH) self.assertEqual(resource, {'name': self.TOPIC_PATH}) topic_path, options = gax_api._get_topic_called_with self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_topic_get_miss(self): from gcloud.exceptions import NotFound gax_api = _GAXPublisherAPI() api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.topic_get(self.TOPIC_PATH) topic_path, options = gax_api._get_topic_called_with self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_topic_get_error(self): from google.gax.errors import GaxError gax_api = _GAXPublisherAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.topic_get(self.TOPIC_PATH) topic_path, options = gax_api._get_topic_called_with self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_topic_delete_hit(self): gax_api = _GAXPublisherAPI(_delete_topic_ok=True) api = self._makeOne(gax_api) api.topic_delete(self.TOPIC_PATH) topic_path, options = gax_api._delete_topic_called_with self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_topic_delete_miss(self): from gcloud.exceptions import NotFound gax_api = _GAXPublisherAPI(_delete_topic_ok=False) api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.topic_delete(self.TOPIC_PATH) topic_path, options = gax_api._delete_topic_called_with self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_topic_delete_error(self): from google.gax.errors import GaxError gax_api = _GAXPublisherAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.topic_delete(self.TOPIC_PATH) topic_path, options = gax_api._delete_topic_called_with self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_topic_publish_hit(self): import base64 PAYLOAD = b'This is the message text' B64 = base64.b64encode(PAYLOAD).decode('ascii') MSGID = 'DEADBEEF' MESSAGE = {'data': B64, 'attributes': {}} response = _PublishResponsePB([MSGID]) gax_api = _GAXPublisherAPI(_publish_response=response) api = self._makeOne(gax_api) resource = api.topic_publish(self.TOPIC_PATH, [MESSAGE]) self.assertEqual(resource, [MSGID]) topic_path, message_pbs, options = gax_api._publish_called_with self.assertEqual(topic_path, self.TOPIC_PATH) message_pb, = message_pbs self.assertEqual(message_pb.data, B64) self.assertEqual(message_pb.attributes, {}) self.assertEqual(options.is_bundling, False) def test_topic_publish_miss_w_attrs_w_bytes_payload(self): import base64 from gcloud.exceptions import NotFound PAYLOAD = u'This is the message text' B64 = base64.b64encode(PAYLOAD) MESSAGE = {'data': B64, 'attributes': {'foo': 'bar'}} gax_api = _GAXPublisherAPI() api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.topic_publish(self.TOPIC_PATH, [MESSAGE]) topic_path, message_pbs, options = gax_api._publish_called_with self.assertEqual(topic_path, self.TOPIC_PATH) message_pb, = message_pbs self.assertEqual(message_pb.data, B64) self.assertEqual(message_pb.attributes, {'foo': 'bar'}) self.assertEqual(options.is_bundling, False) def test_topic_publish_error(self): import base64 from google.gax.errors import GaxError PAYLOAD = b'This is the message text' B64 = base64.b64encode(PAYLOAD).decode('ascii') MESSAGE = {'data': B64, 'attributes': {}} gax_api = _GAXPublisherAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.topic_publish(self.TOPIC_PATH, [MESSAGE]) topic_path, message_pbs, options = gax_api._publish_called_with self.assertEqual(topic_path, self.TOPIC_PATH) message_pb, = message_pbs self.assertEqual(message_pb.data, B64) self.assertEqual(message_pb.attributes, {}) self.assertEqual(options.is_bundling, False) def test_topic_list_subscriptions_no_paging(self): from google.gax import INITIAL_PAGE from gcloud._testing import _GAXPageIterator response = _GAXPageIterator([ {'name': self.SUB_PATH, 'topic': self.TOPIC_PATH}], None) gax_api = _GAXPublisherAPI(_list_topic_subscriptions_response=response) api = self._makeOne(gax_api) subscriptions, next_token = api.topic_list_subscriptions( self.TOPIC_PATH) self.assertEqual(len(subscriptions), 1) subscription = subscriptions[0] self.assertIsInstance(subscription, dict) self.assertEqual(subscription['name'], self.SUB_PATH) self.assertEqual(subscription['topic'], self.TOPIC_PATH) self.assertEqual(next_token, None) topic_path, page_size, options = ( gax_api._list_topic_subscriptions_called_with) self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(page_size, 0) self.assertTrue(options.page_token is INITIAL_PAGE) def test_topic_list_subscriptions_with_paging(self): from gcloud._testing import _GAXPageIterator SIZE = 23 TOKEN = 'TOKEN' NEW_TOKEN = 'NEW_TOKEN' response = _GAXPageIterator([ {'name': self.SUB_PATH, 'topic': self.TOPIC_PATH}], NEW_TOKEN) gax_api = _GAXPublisherAPI(_list_topic_subscriptions_response=response) api = self._makeOne(gax_api) subscriptions, next_token = api.topic_list_subscriptions( self.TOPIC_PATH, page_size=SIZE, page_token=TOKEN) self.assertEqual(len(subscriptions), 1) subscription = subscriptions[0] self.assertIsInstance(subscription, dict) self.assertEqual(subscription['name'], self.SUB_PATH) self.assertEqual(subscription['topic'], self.TOPIC_PATH) self.assertEqual(next_token, NEW_TOKEN) name, page_size, options = ( gax_api._list_topic_subscriptions_called_with) self.assertEqual(name, self.TOPIC_PATH) self.assertEqual(page_size, SIZE) self.assertEqual(options.page_token, TOKEN) def test_topic_list_subscriptions_miss(self): from google.gax import INITIAL_PAGE from gcloud.exceptions import NotFound gax_api = _GAXPublisherAPI() api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.topic_list_subscriptions(self.TOPIC_PATH) topic_path, page_size, options = ( gax_api._list_topic_subscriptions_called_with) self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(page_size, 0) self.assertTrue(options.page_token is INITIAL_PAGE) def test_topic_list_subscriptions_error(self): from google.gax import INITIAL_PAGE from google.gax.errors import GaxError gax_api = _GAXPublisherAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.topic_list_subscriptions(self.TOPIC_PATH) topic_path, page_size, options = ( gax_api._list_topic_subscriptions_called_with) self.assertEqual(topic_path, self.TOPIC_PATH) self.assertEqual(page_size, 0) self.assertTrue(options.page_token is INITIAL_PAGE) @unittest2.skipUnless(_HAVE_GAX, 'No gax-python') class Test_SubscriberAPI(_Base, unittest2.TestCase): PUSH_ENDPOINT = 'https://api.example.com/push' def _getTargetClass(self): from gcloud.pubsub._gax import _SubscriberAPI return _SubscriberAPI def test_ctor(self): gax_api = _GAXSubscriberAPI() api = self._makeOne(gax_api) self.assertTrue(api._gax_api is gax_api) def test_list_subscriptions_no_paging(self): from google.gax import INITIAL_PAGE from gcloud._testing import _GAXPageIterator response = _GAXPageIterator([_SubscriptionPB( self.SUB_PATH, self.TOPIC_PATH, self.PUSH_ENDPOINT, 0)], None) gax_api = _GAXSubscriberAPI(_list_subscriptions_response=response) api = self._makeOne(gax_api) subscriptions, next_token = api.list_subscriptions(self.PROJECT) self.assertEqual(len(subscriptions), 1) subscription = subscriptions[0] self.assertIsInstance(subscription, dict) self.assertEqual(subscription['name'], self.SUB_PATH) self.assertEqual(subscription['topic'], self.TOPIC_PATH) self.assertEqual(subscription['pushConfig'], {'pushEndpoint': self.PUSH_ENDPOINT}) self.assertEqual(subscription['ackDeadlineSeconds'], 0) self.assertEqual(next_token, None) name, page_size, options = gax_api._list_subscriptions_called_with self.assertEqual(name, self.PROJECT_PATH) self.assertEqual(page_size, 0) self.assertTrue(options.page_token is INITIAL_PAGE) def test_list_subscriptions_with_paging(self): from gcloud._testing import _GAXPageIterator SIZE = 23 TOKEN = 'TOKEN' NEW_TOKEN = 'NEW_TOKEN' response = _GAXPageIterator([_SubscriptionPB( self.SUB_PATH, self.TOPIC_PATH, self.PUSH_ENDPOINT, 0)], NEW_TOKEN) gax_api = _GAXSubscriberAPI(_list_subscriptions_response=response) api = self._makeOne(gax_api) subscriptions, next_token = api.list_subscriptions( self.PROJECT, page_size=SIZE, page_token=TOKEN) self.assertEqual(len(subscriptions), 1) subscription = subscriptions[0] self.assertIsInstance(subscription, dict) self.assertEqual(subscription['name'], self.SUB_PATH) self.assertEqual(subscription['topic'], self.TOPIC_PATH) self.assertEqual(subscription['pushConfig'], {'pushEndpoint': self.PUSH_ENDPOINT}) self.assertEqual(subscription['ackDeadlineSeconds'], 0) self.assertEqual(next_token, NEW_TOKEN) name, page_size, options = gax_api._list_subscriptions_called_with self.assertEqual(name, self.PROJECT_PATH) self.assertEqual(page_size, 23) self.assertEqual(options.page_token, TOKEN) def test_subscription_create(self): sub_pb = _SubscriptionPB(self.SUB_PATH, self.TOPIC_PATH, '', 0) gax_api = _GAXSubscriberAPI(_create_subscription_response=sub_pb) api = self._makeOne(gax_api) resource = api.subscription_create(self.SUB_PATH, self.TOPIC_PATH) expected = { 'name': self.SUB_PATH, 'topic': self.TOPIC_PATH, 'ackDeadlineSeconds': 0, } self.assertEqual(resource, expected) name, topic, push_config, ack_deadline, options = ( gax_api._create_subscription_called_with) self.assertEqual(name, self.SUB_PATH) self.assertEqual(topic, self.TOPIC_PATH) self.assertEqual(push_config, None) self.assertEqual(ack_deadline, 0) self.assertEqual(options, None) def test_subscription_create_already_exists(self): from gcloud.exceptions import Conflict DEADLINE = 600 gax_api = _GAXSubscriberAPI(_create_subscription_conflict=True) api = self._makeOne(gax_api) with self.assertRaises(Conflict): api.subscription_create( self.SUB_PATH, self.TOPIC_PATH, DEADLINE, self.PUSH_ENDPOINT) name, topic, push_config, ack_deadline, options = ( gax_api._create_subscription_called_with) self.assertEqual(name, self.SUB_PATH) self.assertEqual(topic, self.TOPIC_PATH) self.assertEqual(push_config.push_endpoint, self.PUSH_ENDPOINT) self.assertEqual(ack_deadline, DEADLINE) self.assertEqual(options, None) def test_subscription_create_error(self): from google.gax.errors import GaxError gax_api = _GAXSubscriberAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.subscription_create(self.SUB_PATH, self.TOPIC_PATH) name, topic, push_config, ack_deadline, options = ( gax_api._create_subscription_called_with) self.assertEqual(name, self.SUB_PATH) self.assertEqual(topic, self.TOPIC_PATH) self.assertEqual(push_config, None) self.assertEqual(ack_deadline, 0) self.assertEqual(options, None) def test_subscription_get_hit(self): sub_pb = _SubscriptionPB( self.SUB_PATH, self.TOPIC_PATH, self.PUSH_ENDPOINT, 0) gax_api = _GAXSubscriberAPI(_get_subscription_response=sub_pb) api = self._makeOne(gax_api) resource = api.subscription_get(self.SUB_PATH) expected = { 'name': self.SUB_PATH, 'topic': self.TOPIC_PATH, 'ackDeadlineSeconds': 0, 'pushConfig': { 'pushEndpoint': self.PUSH_ENDPOINT, }, } self.assertEqual(resource, expected) sub_path, options = gax_api._get_subscription_called_with self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(options, None) def test_subscription_get_miss(self): from gcloud.exceptions import NotFound gax_api = _GAXSubscriberAPI() api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.subscription_get(self.SUB_PATH) sub_path, options = gax_api._get_subscription_called_with self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(options, None) def test_subscription_get_error(self): from google.gax.errors import GaxError gax_api = _GAXSubscriberAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.subscription_get(self.SUB_PATH) sub_path, options = gax_api._get_subscription_called_with self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(options, None) def test_subscription_delete_hit(self): gax_api = _GAXSubscriberAPI(_delete_subscription_ok=True) api = self._makeOne(gax_api) api.subscription_delete(self.TOPIC_PATH) sub_path, options = gax_api._delete_subscription_called_with self.assertEqual(sub_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_subscription_delete_miss(self): from gcloud.exceptions import NotFound gax_api = _GAXSubscriberAPI(_delete_subscription_ok=False) api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.subscription_delete(self.TOPIC_PATH) sub_path, options = gax_api._delete_subscription_called_with self.assertEqual(sub_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_subscription_delete_error(self): from google.gax.errors import GaxError gax_api = _GAXSubscriberAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.subscription_delete(self.TOPIC_PATH) sub_path, options = gax_api._delete_subscription_called_with self.assertEqual(sub_path, self.TOPIC_PATH) self.assertEqual(options, None) def test_subscription_modify_push_config_hit(self): gax_api = _GAXSubscriberAPI(_modify_push_config_ok=True) api = self._makeOne(gax_api) api.subscription_modify_push_config(self.SUB_PATH, self.PUSH_ENDPOINT) sub_path, config, options = gax_api._modify_push_config_called_with self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(config.push_endpoint, self.PUSH_ENDPOINT) self.assertEqual(options, None) def test_subscription_modify_push_config_miss(self): from gcloud.exceptions import NotFound gax_api = _GAXSubscriberAPI() api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.subscription_modify_push_config( self.SUB_PATH, self.PUSH_ENDPOINT) sub_path, config, options = gax_api._modify_push_config_called_with self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(config.push_endpoint, self.PUSH_ENDPOINT) self.assertEqual(options, None) def test_subscription_modify_push_config_error(self): from google.gax.errors import GaxError gax_api = _GAXSubscriberAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.subscription_modify_push_config( self.SUB_PATH, self.PUSH_ENDPOINT) sub_path, config, options = gax_api._modify_push_config_called_with self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(config.push_endpoint, self.PUSH_ENDPOINT) self.assertEqual(options, None) def test_subscription_pull_explicit(self): import base64 PAYLOAD = b'This is the message text' B64 = base64.b64encode(PAYLOAD).decode('ascii') ACK_ID = 'DEADBEEF' MSG_ID = 'BEADCAFE' MESSAGE = {'messageId': MSG_ID, 'data': B64, 'attributes': {'a': 'b'}} RECEIVED = [{'ackId': ACK_ID, 'message': MESSAGE}] message_pb = _PubsubMessagePB(MSG_ID, B64, {'a': 'b'}) response_pb = _PullResponsePB([_ReceivedMessagePB(ACK_ID, message_pb)]) gax_api = _GAXSubscriberAPI(_pull_response=response_pb) api = self._makeOne(gax_api) MAX_MESSAGES = 10 received = api.subscription_pull( self.SUB_PATH, return_immediately=True, max_messages=MAX_MESSAGES) self.assertEqual(received, RECEIVED) sub_path, max_messages, return_immediately, options = ( gax_api._pull_called_with) self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(max_messages, MAX_MESSAGES) self.assertTrue(return_immediately) self.assertEqual(options, None) def test_subscription_pull_defaults_miss(self): from gcloud.exceptions import NotFound gax_api = _GAXSubscriberAPI() api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.subscription_pull(self.SUB_PATH) sub_path, max_messages, return_immediately, options = ( gax_api._pull_called_with) self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(max_messages, 1) self.assertFalse(return_immediately) self.assertEqual(options, None) def test_subscription_pull_defaults_error(self): from google.gax.errors import GaxError gax_api = _GAXSubscriberAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.subscription_pull(self.SUB_PATH) sub_path, max_messages, return_immediately, options = ( gax_api._pull_called_with) self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(max_messages, 1) self.assertFalse(return_immediately) self.assertEqual(options, None) def test_subscription_acknowledge_hit(self): ACK_ID1 = 'DEADBEEF' ACK_ID2 = 'BEADCAFE' gax_api = _GAXSubscriberAPI(_acknowledge_ok=True) api = self._makeOne(gax_api) api.subscription_acknowledge(self.SUB_PATH, [ACK_ID1, ACK_ID2]) sub_path, ack_ids, options = gax_api._acknowledge_called_with self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(ack_ids, [ACK_ID1, ACK_ID2]) self.assertEqual(options, None) def test_subscription_acknowledge_miss(self): from gcloud.exceptions import NotFound ACK_ID1 = 'DEADBEEF' ACK_ID2 = 'BEADCAFE' gax_api = _GAXSubscriberAPI() api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.subscription_acknowledge(self.SUB_PATH, [ACK_ID1, ACK_ID2]) sub_path, ack_ids, options = gax_api._acknowledge_called_with self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(ack_ids, [ACK_ID1, ACK_ID2]) self.assertEqual(options, None) def test_subscription_acknowledge_error(self): from google.gax.errors import GaxError ACK_ID1 = 'DEADBEEF' ACK_ID2 = 'BEADCAFE' gax_api = _GAXSubscriberAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.subscription_acknowledge(self.SUB_PATH, [ACK_ID1, ACK_ID2]) sub_path, ack_ids, options = gax_api._acknowledge_called_with self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(ack_ids, [ACK_ID1, ACK_ID2]) self.assertEqual(options, None) def test_subscription_modify_ack_deadline_hit(self): ACK_ID1 = 'DEADBEEF' ACK_ID2 = 'BEADCAFE' NEW_DEADLINE = 90 gax_api = _GAXSubscriberAPI(_modify_ack_deadline_ok=True) api = self._makeOne(gax_api) api.subscription_modify_ack_deadline( self.SUB_PATH, [ACK_ID1, ACK_ID2], NEW_DEADLINE) sub_path, ack_ids, deadline, options = ( gax_api._modify_ack_deadline_called_with) self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(ack_ids, [ACK_ID1, ACK_ID2]) self.assertEqual(deadline, NEW_DEADLINE) self.assertEqual(options, None) def test_subscription_modify_ack_deadline_miss(self): from gcloud.exceptions import NotFound ACK_ID1 = 'DEADBEEF' ACK_ID2 = 'BEADCAFE' NEW_DEADLINE = 90 gax_api = _GAXSubscriberAPI() api = self._makeOne(gax_api) with self.assertRaises(NotFound): api.subscription_modify_ack_deadline( self.SUB_PATH, [ACK_ID1, ACK_ID2], NEW_DEADLINE) sub_path, ack_ids, deadline, options = ( gax_api._modify_ack_deadline_called_with) self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(ack_ids, [ACK_ID1, ACK_ID2]) self.assertEqual(deadline, NEW_DEADLINE) self.assertEqual(options, None) def test_subscription_modify_ack_deadline_error(self): from google.gax.errors import GaxError ACK_ID1 = 'DEADBEEF' ACK_ID2 = 'BEADCAFE' NEW_DEADLINE = 90 gax_api = _GAXSubscriberAPI(_random_gax_error=True) api = self._makeOne(gax_api) with self.assertRaises(GaxError): api.subscription_modify_ack_deadline( self.SUB_PATH, [ACK_ID1, ACK_ID2], NEW_DEADLINE) sub_path, ack_ids, deadline, options = ( gax_api._modify_ack_deadline_called_with) self.assertEqual(sub_path, self.SUB_PATH) self.assertEqual(ack_ids, [ACK_ID1, ACK_ID2]) self.assertEqual(deadline, NEW_DEADLINE) self.assertEqual(options, None) class _GaxAPIBase(object): _random_gax_error = False def __init__(self, **kw): self.__dict__.update(kw) def _make_grpc_error(self, status_code): from grpc.framework.interfaces.face.face import AbortionError class _DummyException(AbortionError): code = status_code def __init__(self): pass return _DummyException() def _make_grpc_not_found(self): from grpc.beta.interfaces import StatusCode return self._make_grpc_error(StatusCode.NOT_FOUND) def _make_grpc_failed_precondition(self): from grpc.beta.interfaces import StatusCode return self._make_grpc_error(StatusCode.FAILED_PRECONDITION) class _GAXPublisherAPI(_GaxAPIBase): _create_topic_conflict = False def list_topics(self, name, page_size, options): self._list_topics_called_with = name, page_size, options return self._list_topics_response def create_topic(self, name, options=None): from google.gax.errors import GaxError self._create_topic_called_with = name, options if self._random_gax_error: raise GaxError('error') if self._create_topic_conflict: raise GaxError('conflict', self._make_grpc_failed_precondition()) return self._create_topic_response def get_topic(self, name, options=None): from google.gax.errors import GaxError self._get_topic_called_with = name, options if self._random_gax_error: raise GaxError('error') try: return self._get_topic_response except AttributeError: raise GaxError('miss', self._make_grpc_not_found()) def delete_topic(self, name, options=None): from google.gax.errors import GaxError self._delete_topic_called_with = name, options if self._random_gax_error: raise GaxError('error') if not self._delete_topic_ok: raise GaxError('miss', self._make_grpc_not_found()) def publish(self, topic, messages, options=None): from google.gax.errors import GaxError self._publish_called_with = topic, messages, options if self._random_gax_error: raise GaxError('error') try: return self._publish_response except AttributeError: raise GaxError('miss', self._make_grpc_not_found()) def list_topic_subscriptions(self, topic, page_size, options=None): from google.gax.errors import GaxError self._list_topic_subscriptions_called_with = topic, page_size, options if self._random_gax_error: raise GaxError('error') try: return self._list_topic_subscriptions_response except AttributeError: raise GaxError('miss', self._make_grpc_not_found()) class _GAXSubscriberAPI(_GaxAPIBase): _create_subscription_conflict = False _modify_push_config_ok = False _acknowledge_ok = False _modify_ack_deadline_ok = False def list_subscriptions(self, project, page_size, options=None): self._list_subscriptions_called_with = (project, page_size, options) return self._list_subscriptions_response def create_subscription(self, name, topic, push_config, ack_deadline_seconds, options=None): from google.gax.errors import GaxError self._create_subscription_called_with = ( name, topic, push_config, ack_deadline_seconds, options) if self._random_gax_error: raise GaxError('error') if self._create_subscription_conflict: raise GaxError('conflict', self._make_grpc_failed_precondition()) return self._create_subscription_response def get_subscription(self, name, options=None): from google.gax.errors import GaxError self._get_subscription_called_with = name, options if self._random_gax_error: raise GaxError('error') try: return self._get_subscription_response except AttributeError: raise GaxError('miss', self._make_grpc_not_found()) def delete_subscription(self, name, options=None): from google.gax.errors import GaxError self._delete_subscription_called_with = name, options if self._random_gax_error: raise GaxError('error') if not self._delete_subscription_ok: raise GaxError('miss', self._make_grpc_not_found()) def modify_push_config(self, name, push_config, options=None): from google.gax.errors import GaxError self._modify_push_config_called_with = name, push_config, options if self._random_gax_error: raise GaxError('error') if not self._modify_push_config_ok: raise GaxError('miss', self._make_grpc_not_found()) def pull(self, name, max_messages, return_immediately, options=None): from google.gax.errors import GaxError self._pull_called_with = ( name, max_messages, return_immediately, options) if self._random_gax_error: raise GaxError('error') try: return self._pull_response except AttributeError: raise GaxError('miss', self._make_grpc_not_found()) def acknowledge(self, name, ack_ids, options=None): from google.gax.errors import GaxError self._acknowledge_called_with = name, ack_ids, options if self._random_gax_error: raise GaxError('error') if not self._acknowledge_ok: raise GaxError('miss', self._make_grpc_not_found()) def modify_ack_deadline(self, name, ack_ids, deadline, options=None): from google.gax.errors import GaxError self._modify_ack_deadline_called_with = ( name, ack_ids, deadline, options) if self._random_gax_error: raise GaxError('error') if not self._modify_ack_deadline_ok: raise GaxError('miss', self._make_grpc_not_found()) class _TopicPB(object): def __init__(self, name): self.name = name class _PublishResponsePB(object): def __init__(self, message_ids): self.message_ids = message_ids class _PushConfigPB(object): def __init__(self, push_endpoint): self.push_endpoint = push_endpoint class _PubsubMessagePB(object): def __init__(self, message_id, data, attributes): self.message_id = message_id self.data = data self.attributes = attributes class _ReceivedMessagePB(object): def __init__(self, ack_id, message): self.ack_id = ack_id self.message = message class _PullResponsePB(object): def __init__(self, received_messages): self.received_messages = received_messages class _SubscriptionPB(object): def __init__(self, name, topic, push_endpoint, ack_deadline_seconds): self.name = name self.topic = topic self.push_config = _PushConfigPB(push_endpoint) self.ack_deadline_seconds = ack_deadline_seconds