def test_auth_via_cert_missing_token_field(self): auth_via_cert_urlmatch = dict( netloc="localhost", path="/v1/service-types/ams/hosts/localhost:authx509", method='GET') # Mock response for successful token retrieval @urlmatch(**auth_via_cert_urlmatch) def auth_via_cert_missing_field(url, request): assert url.path == "/v1/service-types/ams/hosts/localhost:authx509" return response(200, '{"other_field": "success_token"}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(auth_via_cert_missing_field): try: ams = ArgoMessagingService(endpoint="localhost", project="TEST", cert="/path/cert", key="/path/key") ams.auth_via_cert("/path/cert", "/path/key") except AmsServiceException as e: self.assertEqual(e.code, 500) # py2 json.loads() builds dict with unicode encoded elements # while py3 version of it not if sys.version_info < (3, ): response_dict = "{u'other_field': u'success_token'}" else: response_dict = "{'other_field': 'success_token'}" self.assertEqual( e.msg, "While trying the [auth_x509]: Token was not found in the response. Response: " + response_dict)
def test_auth_via_cert_missing_token_field(self): auth_via_cert_urlmatch = dict( netloc="localhost", path="/v1/service-types/ams/hosts/localhost:authx509", method='GET') # Mock response for successful token retrieval @urlmatch(**auth_via_cert_urlmatch) def auth_via_cert_missing_field(url, request): assert url.path == "/v1/service-types/ams/hosts/localhost:authx509" return response(200, '{"other_field":"success_token"}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(auth_via_cert_missing_field): try: ams = ArgoMessagingService(endpoint="localhost", project="TEST", cert="/path/cert", key="/path/key") ams.auth_via_cert("/path/cert", "/path/key") except Exception as e: assert isinstance(e, AmsServiceException) self.assertEqual( e.message, { 'status_code': 500, 'error': "While trying the [auth_x509]: Token was not found in the response.Response: {u'other_field': u'success_token'}" })
def setUp(self): self.ams = ArgoMessagingService(endpoint="localhost", token="s3cr3t", project="TEST") self.msg = AmsMessage(attributes={'foo': 'bar'}, data='baz') self.submocks = SubMocks() self.topicmocks = TopicMocks()
def setUp(self): # Initialize ams in localhost with token s3cr3t and project TEST self.ams = ArgoMessagingService(endpoint="localhost", token="s3cr3t", project="TEST") self.submocks = SubMocks() self.topicmocks = TopicMocks()
def test_auth_via_cert_cert(self): try: ams = ArgoMessagingService(endpoint="localhost", token="s3cret", project="TEST") ams.auth_via_cert("", "") except AmsServiceException as e: self.assertEqual(e.code, 400) self.assertEqual( e.msg, 'While trying the [auth_x509]: No certificate provided.')
def setUp(self): # Initialize ams in localhost with token s3cr3t and project TEST self.ams = ArgoMessagingService(endpoint="localhost", token="s3cr3t", project="TEST") self.errormocks = ErrorMocks() self.topicmocks = TopicMocks() self.submocks = SubMocks() # set defaults for testing of retries retry = 0 retrysleep = 0.1 retrybackoff = None if sys.version_info < (3, ): self.ams._retry_make_request.im_func.func_defaults = (None, None, retry, retrysleep, retrybackoff) else: self.ams._retry_make_request.__func__.__defaults__ = (None, None, retry, retrysleep, retrybackoff)
def test_auth_via_cert_cert(self): try: ams = ArgoMessagingService(endpoint="localhost", token="s3cret", project="TEST") ams.auth_via_cert("", "") except Exception as e: assert isinstance(e, AmsServiceException) self.assertEqual( e.message, { 'status_code': 400, 'error': 'While trying the [auth_x509]: No certificate provided.' })
def test_auth_via_cert_success(self): auth_via_cert_urlmatch = dict( netloc="localhost", path="/v1/service-types/ams/hosts/localhost:authx509", method='GET') # Mock response for successful token retrieval @urlmatch(**auth_via_cert_urlmatch) def auth_via_cert_success(url, request): assert url.path == "/v1/service-types/ams/hosts/localhost:authx509" return response(200, '{"token":"success_token"}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(auth_via_cert_success): ams = ArgoMessagingService(endpoint="localhost", project="TEST", cert="/path/cert", key="/path/key") self.assertEqual(ams.token, "success_token")
def test_assign_token(self): ams = ArgoMessagingService(endpoint="localhost", token="some_token", project="TEST") self.assertEqual(ams.token, "some_token")
class TestErrorClient(unittest.TestCase): def setUp(self): # Initialize ams in localhost with token s3cr3t and project TEST self.ams = ArgoMessagingService(endpoint="localhost", token="s3cr3t", project="TEST") self.errormocks = ErrorMocks() self.topicmocks = TopicMocks() self.submocks = SubMocks() # Test create topic client request def testCreateTopics(self): # Execute ams client with mocked response with HTTMock(self.errormocks.create_topic_alreadyexist_mock): try: resp = self.ams.create_topic("topic1") except Exception as e: assert isinstance(e, AmsServiceException) self.assertEqual(e.status, 'ALREADY_EXIST') self.assertEqual(e.code, 409) def testCreateSubscription(self): # Execute ams client with mocked response with HTTMock(self.topicmocks.get_topic_mock, self.errormocks.create_subscription_alreadyexist_mock): try: resp = self.ams.create_sub("subscription1", "topic1", 10) except Exception as e: assert isinstance(e, AmsServiceException) self.assertEqual(e.status, 'ALREADY_EXIST') self.assertEqual(e.code, 409) # Test Publish client request def testFailedPublish(self): # Mock response for POST publish to topic @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1:publish", method="POST") def publish_mock(url, request): assert url.path == "/v1/projects/TEST/topics/topic1:publish" # Check request produced by ams client req_body = json.loads(request.body) assert req_body["messages"][0]["data"] == "Zm9vMQ==" assert req_body["messages"][0]["attributes"]["bar1"] == "baz1" return response(504, '<htmI><body><h1>504 Gateway Time-out</h1>\nThe server didn\'t respond in time.\n</body></html>\n', None, None, 5, request) # Execute ams client with mocked response with HTTMock(publish_mock): msg = AmsMessage(data='foo1', attributes={'bar1': 'baz1'}) try: resp = self.ams.publish("topic1", msg) except Exception as e: assert isinstance(e, AmsServiceException) self.assertEqual(e.code, 504) # Tests for plaintext or JSON encoded backend error messages def testErrorMsgBackend(self): @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1", method='GET') def error_plaintxt(url, request): assert url.path == "/v1/projects/TEST/topics/topic1" return response(500, "Cannot get topic", None, None, 5, request) with HTTMock(error_plaintxt): try: resp = self.ams.get_topic("topic1") except AmsServiceException as e: self.assertEqual(e.msg, "While trying the [topic_get]: Cannot get topic") @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1", method='GET') def error_json(url, request): assert url.path == "/v1/projects/TEST/topics/topic1" return response(500, json.loads('{"error": {"code": 500,\ "message": "Cannot get topic",\ "status": "INTERNAL_SERVER_ERROR"\ }}'), None, None, 5, request) with HTTMock(error_json): try: resp = self.ams.get_topic("topic1") except AmsServiceException as e: self.assertEqual(e.code, 500) self.assertEqual(e.msg, "While trying the [topic_get]: Cannot get topic") self.assertEqual(e.status, "INTERNAL_SERVER_ERROR")
class TestTopic(unittest.TestCase): def setUp(self): self.ams = ArgoMessagingService(endpoint="localhost", token="s3cr3t", project="TEST") self.msg = AmsMessage(attributes={'foo': 'bar'}, data='baz') self.submocks = SubMocks() self.topicmocks = TopicMocks() def testPublish(self): # Mock response for POST publish to topic @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1:publish", method="POST") def publish_mock(url, request): # Check request produced by ams client req_body = json.loads(request.body) self.assertEqual(req_body["messages"][0]["data"], 'YmF6') self.assertEqual(req_body["messages"][0]["attributes"]["foo"], "bar") return '{"msgIds":["1"]}' # Execute ams client with mocked response with HTTMock(self.topicmocks.has_topic_mock, publish_mock): topic = self.ams.topic('topic1') resp = topic.publish(self.msg.dict()) # Assert that ams client handled the json response correctly self.assertEqual(resp["msgIds"][0], "1") self.assertEqual(topic.name, 'topic1') self.assertEqual(topic.fullname, '/projects/TEST/topics/topic1') def testSubscription(self): # Execute ams client with mocked response with HTTMock(self.topicmocks.create_topic_mock, self.submocks.create_subscription_mock, self.topicmocks.get_topic_mock, self.submocks.has_subscription_mock): topic = self.ams.topic('topic1') sub = topic.subscription('subscription1') # Assert that ams client handled the json response correctly self.assertEqual(topic.name, 'topic1') self.assertEqual(topic.fullname, '/projects/TEST/topics/topic1') assert isinstance(sub, AmsSubscription) self.assertEqual(sub.topic, topic) self.assertEqual(sub.name, 'subscription1') self.assertEqual(sub.fullname, '/projects/TEST/subscriptions/subscription1') def testIterSubscriptions(self): # Mock response for GET Subscriptions request @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions", method="GET") def iter_subs_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions" # Return two topics in json format return response( 200, '{"subscriptions":[{"name": "/projects/TEST/subscriptions/subscription1",\ "topic": "/projects/TEST/topics/topic1","pushConfig": \ {"pushEndpoint": "","retryPolicy": {}},"ackDeadlineSeconds": 10},\ {"name": "/projects/TEST/subscriptions/subscription2", \ "topic": "/projects/TEST/topics/topic1", \ "pushConfig": {"pushEndpoint": "","retryPolicy": {}},\ "ackDeadlineSeconds": 10}]}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(iter_subs_mock, self.topicmocks.create_topic_mock, self.topicmocks.has_topic_mock): topic = self.ams.topic('topic1') resp = topic.iter_subs() obj1 = next(resp) obj2 = next(resp) assert isinstance(obj1, AmsSubscription) assert isinstance(obj2, AmsSubscription) if sys.version_info < (3, ): self.assertRaises(StopIteration, resp.next) else: self.assertRaises(StopIteration, resp.__next__) self.assertEqual(obj1.name, 'subscription1') self.assertEqual(obj2.name, 'subscription2') def testDelete(self): # Mock response for DELETE topic request @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1", method="DELETE") def delete_topic(url, request): return response(200, '{}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(delete_topic, self.topicmocks.create_topic_mock, self.topicmocks.has_topic_mock): topic = self.ams.topic('topic1') self.assertTrue(topic.delete()) def testAcl(self): # Mock response for GET topic request @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1:modifyAcl", method="POST") def modifyacl_topic_mock(url, request): self.assertEqual(url.path, "/v1/projects/TEST/topics/topic1:modifyAcl") self.assertEqual(request.body, '{"authorized_users": ["user1", "user2"]}') # Return the details of a topic in json format return response(200, '{}', None, None, 5, request) # Mock response for GET topic request @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1:acl", method="GET") def getacl_topic_mock(url, request): assert url.path == "/v1/projects/TEST/topics/topic1:acl" # Return the details of a topic in json format return response(200, '{"authorized_users": ["user1", "user2"]}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(getacl_topic_mock, self.topicmocks.get_topic_mock, modifyacl_topic_mock): topic = self.ams.topic('topic1') ret = topic.acl(['user1', 'user2']) self.assertTrue(ret) resp_users = topic.acl() self.assertEqual(resp_users['authorized_users'], ['user1', 'user2'])
class TestSubscription(unittest.TestCase): def setUp(self): self.ams = ArgoMessagingService(endpoint="localhost", token="s3cr3t", project="TEST") self.msg = AmsMessage(attributes={'foo': 'bar'}, data='baz') self.submocks = SubMocks() self.topicmocks = TopicMocks() def testPushConfig(self): # Mock response for POST pushconfig request @urlmatch( netloc="localhost", path= "/v1/projects/TEST/subscriptions/subscription1:modifyPushConfig", method="POST") def modify_pushconfig_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions/subscription1:modifyPushConfig" # Return two topics in json format return response( 200, '{"name": "/projects/TEST/subscriptions/subscription1",\ "topic":"/projects/TEST/topics/topic1",\ "pushConfig":{"pushEndpoint":"https://myproject.appspot.com/myhandler",\ "retryPolicy":{"type":"linear", "period":300 }},\ "ackDeadlineSeconds": 10}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(self.topicmocks.create_topic_mock, self.submocks.create_subscription_mock, self.topicmocks.get_topic_mock, modify_pushconfig_mock, self.submocks.get_sub_mock): topic = self.ams.topic('topic1') sub = topic.subscription('subscription1') self.assertEqual(topic.name, 'topic1') self.assertEqual(topic.fullname, '/projects/TEST/topics/topic1') assert isinstance(sub, AmsSubscription) self.assertEqual(sub.name, 'subscription1') self.assertEqual(sub.fullname, '/projects/TEST/subscriptions/subscription1') self.assertEqual(sub.push_endpoint, '') self.assertEqual(sub.retry_policy_type, '') self.assertEqual(sub.retry_policy_period, '') self.assertEqual(sub.ackdeadline, 10) resp = sub.pushconfig( push_endpoint='https://myproject.appspot.com/myhandler1') self.assertEqual(resp['pushConfig']['pushEndpoint'], "https://myproject.appspot.com/myhandler") self.assertEqual(resp['pushConfig']['retryPolicy']['type'], "linear") self.assertEqual(resp['pushConfig']['retryPolicy']['period'], 300) def testPull(self): # Mock response for POST pull from subscription @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription1:pull", method="POST") def pull_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions/subscription1:pull" # Check request produced by ams client req_body = json.loads(request.body) assert req_body["maxMessages"] == "1" return '{"receivedMessages":[{"ackId":"projects/TEST/subscriptions/subscription1:1221",\ "message":{"messageId":"1221","attributes":{"foo":"bar"},"data":"YmFzZTY0ZW5jb2RlZA==",\ "publishTime":"2016-02-24T11:55:09.786127994Z"}}]}' @urlmatch( netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription1:acknowledge", method="POST") def ack_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions/subscription1:acknowledge" # Error: library returns json in the form {"ackIds": 1221} assert request.body == '{"ackIds": ["1221"]}' # Check request produced by ams client return '{}' # Execute ams client with mocked response with HTTMock(pull_mock, ack_mock, self.submocks.get_sub_mock, self.topicmocks.create_topic_mock, self.topicmocks.get_topic_mock, self.submocks.create_subscription_mock): topic = self.ams.topic('topic1') sub = topic.subscription('subscription1') assert isinstance(sub, AmsSubscription) self.assertEqual(topic.name, 'topic1') self.assertEqual(topic.fullname, '/projects/TEST/topics/topic1') self.assertEqual(sub.name, 'subscription1') self.assertEqual(sub.fullname, '/projects/TEST/subscriptions/subscription1') resp_pull = sub.pull(1) ack_id, msg = resp_pull[0] self.assertEqual(ack_id, "projects/TEST/subscriptions/subscription1:1221") if sys.version_info < (3, ): self.assertEqual(msg.get_data(), "base64encoded") else: self.assertEqual(msg.get_data(), b"base64encoded") self.assertEqual(msg.get_msgid(), "1221") resp_ack = sub.ack(["1221"]) self.assertEqual(resp_ack, True) def testOffsets(self): # Mock response for GET subscriptions offsets @urlmatch( netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription2:modifyOffset", method="POST") def modifyoffset_sub2_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions/subscription2:modifyOffset" assert request.body == '{"offset": 79}' return '{}' @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription2:offsets", method="GET") def getoffsets_sub2_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions/subscription2:offsets" # Return the offsets for a subscription2 return response(200, '{"max": 79, "min": 0, "current": 79}', None, None, 5, request) # Mock response for GET subscription request @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription2", method="GET") def get_sub2_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions/subscription2" # Return the details of a subscription in json format return response( 200, '{"name":"/projects/TEST/subscriptions/subscription2",\ "topic":"/projects/TEST/topics/topic1",\ "pushConfig": {"pushEndpoint": "","retryPolicy": {}},\ "ackDeadlineSeconds": 10}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(self.submocks.getoffsets_sub_mock, self.submocks.timetooffset_sub_mock, self.submocks.get_sub_mock, self.topicmocks.create_topic_mock, self.topicmocks.get_topic_mock, getoffsets_sub2_mock, get_sub2_mock, modifyoffset_sub2_mock, self.submocks.modifyoffset_sub_mock, self.submocks.create_subscription_mock): topic = self.ams.topic('topic1') sub = topic.subscription('subscription1') assert isinstance(sub, AmsSubscription) self.assertEqual(topic.name, 'topic1') self.assertEqual(topic.fullname, '/projects/TEST/topics/topic1') self.assertEqual(sub.name, 'subscription1') self.assertEqual(sub.fullname, '/projects/TEST/subscriptions/subscription1') # should return a dict with all the offsets resp_all = sub.offsets() resp_dict_all = {"max": 79, "min": 0, "current": 78} # should return the max offset resp_max = sub.offsets("max") # should return the current offset resp_current = sub.offsets("current") # should return the min offset resp_min = sub.offsets("min") # time offset time_off = sub.time_to_offset( timestamp=datetime.datetime(2019, 9, 2, 13, 39, 11, 500000)) self.assertEqual(resp_all, resp_dict_all) self.assertEqual(resp_max, 79) self.assertEqual(resp_current, 78) self.assertEqual(resp_min, 0) self.assertEqual(time_off, 44) sub2 = topic.subscription('subscription2') move_offset_resp = sub2.offsets(move_to=79) self.assertEqual(move_offset_resp, { "max": 79, "current": 79, "min": 0 }) self.assertRaises(AmsException, sub2.offsets, offset='bogus', move_to=79) def testDelete(self): # Mock response for DELETE topic request @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription1", method="DELETE") def delete_subscription(url, request): return response(200, '{}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(delete_subscription, self.topicmocks.create_topic_mock, self.submocks.create_subscription_mock, self.topicmocks.get_topic_mock, self.submocks.get_sub_mock): topic = self.ams.topic('topic1') sub = topic.subscription('subscription1') self.assertTrue(sub.delete()) def testAcl(self): # Mock response for GET topic request @urlmatch( netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription1:modifyAcl", method="POST") def modifyacl_sub_mock(url, request): self.assertEqual( url.path, "/v1/projects/TEST/subscriptions/subscription1:modifyAcl") self.assertEqual(request.body, '{"authorized_users": ["user1", "user2"]}') # Return the details of a topic in json format return response(200, '{}', None, None, 5, request) # Mock response for GET topic request @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription1:acl", method="GET") def getacl_sub_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions/subscription1:acl" # Return the details of a topic in json format return response(200, '{"authorized_users": ["user1", "user2"]}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(self.topicmocks.create_topic_mock, self.topicmocks.get_topic_mock, getacl_sub_mock, self.submocks.get_sub_mock, modifyacl_sub_mock): topic = self.ams.topic('topic1') sub = topic.subscription('subscription1') ret = sub.acl(['user1', 'user2']) self.assertTrue(ret) resp_users = sub.acl() self.assertEqual(resp_users['authorized_users'], ['user1', 'user2'])
class TestErrorClient(unittest.TestCase): def setUp(self): # Initialize ams in localhost with token s3cr3t and project TEST self.ams = ArgoMessagingService(endpoint="localhost", token="s3cr3t", project="TEST") self.errormocks = ErrorMocks() self.topicmocks = TopicMocks() self.submocks = SubMocks() # set defaults for testing of retries retry = 0 retrysleep = 0.1 retrybackoff = None if sys.version_info < (3, ): self.ams._retry_make_request.im_func.func_defaults = (None, None, retry, retrysleep, retrybackoff) else: self.ams._retry_make_request.__func__.__defaults__ = (None, None, retry, retrysleep, retrybackoff) # Test create topic client request def testCreateTopics(self): # Execute ams client with mocked response with HTTMock(self.errormocks.create_topic_alreadyexist_mock): try: resp = self.ams.create_topic("topic1") except Exception as e: assert isinstance(e, AmsServiceException) self.assertEqual(e.status, 'ALREADY_EXIST') self.assertEqual(e.code, 409) # Test delete topic client request def testDeleteTopics(self): # Execute ams client with mocked response with HTTMock(self.errormocks.delete_topic_notfound_mock): try: resp = self.ams.delete_topic("topic1") except Exception as e: assert isinstance(e, AmsServiceException) self.assertEqual(e.status, 'NOT_FOUND') self.assertEqual(e.code, 404) def testCreateSubscription(self): # Execute ams client with mocked response with HTTMock(self.topicmocks.get_topic_mock, self.errormocks.create_subscription_alreadyexist_mock): try: resp = self.ams.create_sub("subscription1", "topic1", 10) except Exception as e: assert isinstance(e, AmsServiceException) self.assertEqual(e.status, 'ALREADY_EXIST') self.assertEqual(e.code, 409) # Test Publish client request def testFailedPublish(self): # Mock response for POST publish to topic @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1:publish", method="POST") def publish_mock(url, request): assert url.path == "/v1/projects/TEST/topics/topic1:publish" # Check request produced by ams client req_body = json.loads(request.body) assert req_body["messages"][0]["data"] == "Zm9vMQ==" assert req_body["messages"][0]["attributes"]["bar1"] == "baz1" return response(504, '<htmI><body><h1>504 Gateway Time-out</h1>\nThe server didn\'t respond in time.\n</body></html>\n', None, None, 5, request) # Execute ams client with mocked response with HTTMock(publish_mock): msg = AmsMessage(data='foo1', attributes={'bar1': 'baz1'}) try: resp = self.ams.publish("topic1", msg) except Exception as e: assert isinstance(e, AmsTimeoutException) self.assertEqual(e.code, 504) # Tests for plaintext or JSON encoded backend error messages def testErrorMsgBackend(self): @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1", method='GET') def error_plaintxt(url, request): assert url.path == "/v1/projects/TEST/topics/topic1" return response(500, "Cannot get topic", None, None, 5, request) with HTTMock(error_plaintxt): try: resp = self.ams.get_topic("topic1") except AmsServiceException as e: if sys.version_info < (3, 6 ): response_string = "Cannot get topic" else: response_string = "b'Cannot get topic'" self.assertEqual(e.msg, "While trying the [topic_get]: " + response_string) @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1", method='GET') def error_json(url, request): assert url.path == "/v1/projects/TEST/topics/topic1" return response(500, '{"error": {"code": 500,\ "message": "Cannot get topic",\ "status": "INTERNAL_SERVER_ERROR"\ }}', None, None, 5, request) with HTTMock(error_json): try: resp = self.ams.get_topic("topic1") except AmsServiceException as e: self.assertEqual(e.code, 500) self.assertEqual(e.msg, "While trying the [topic_get]: Cannot get topic") self.assertEqual(e.status, "INTERNAL_SERVER_ERROR") def testUnauthorized(self): @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1", method='GET') def error_unauth(url, request): assert url.path == "/v1/projects/TEST/topics/topic1" return response(401, '{"error": {"code": 401, \ "message": "Unauthorized", \ "status": "UNAUTHORIZED"}}') with HTTMock(error_unauth): try: resp = self.ams.get_topic("topic1") except AmsServiceException as e: self.assertEqual(e.code, 401) self.assertEqual(e.msg, 'While trying the [topic_get]: Unauthorized') self.assertEqual(e.status, 'UNAUTHORIZED') @mock.patch('pymod.ams.requests.get') def testRetryConnectionProblems(self, mock_requests_get): mock_requests_get.side_effect = [requests.exceptions.ConnectionError, requests.exceptions.ConnectionError, requests.exceptions.ConnectionError, requests.exceptions.ConnectionError] retry = 3 retrysleep = 0.1 if sys.version_info < (3, ): self.ams._retry_make_request.im_func.func_defaults = (None, None, retry, retrysleep, None) else: self.ams._retry_make_request.__func__.__defaults__ = (None, None, retry, retrysleep, None) self.assertRaises(AmsConnectionException, self.ams.list_topics) self.assertEqual(mock_requests_get.call_count, retry + 1) @mock.patch('pymod.ams.requests.get') def testBackoffRetryConnectionProblems(self, mock_requests_get): mock_requests_get.side_effect = [requests.exceptions.ConnectionError, requests.exceptions.ConnectionError, requests.exceptions.ConnectionError, requests.exceptions.ConnectionError] retry = 3 retrysleep = 0.1 retrybackoff = 0.1 if sys.version_info < (3, ): self.ams._retry_make_request.im_func.func_defaults = (None, None, retry, retrysleep, retrybackoff) else: self.ams._retry_make_request.__func__.__defaults__ = (None, None, retry, retrysleep, retrybackoff) self.assertRaises(AmsConnectionException, self.ams.list_topics) self.assertEqual(mock_requests_get.call_count, retry + 1) @mock.patch('pymod.ams.requests.post') def testRetryAmsBalancerTimeout408(self, mock_requests_post): retry = 4 retrysleep = 0.2 errmsg = "<html><body><h1>408 Request Time-out</h1>\nYour browser didn't send a complete request in time.\n</body></html>\n" mock_response = mock.create_autospec(requests.Response) mock_response.status_code = 408 mock_response.content = errmsg mock_requests_post.return_value = mock_response try: self.ams.pull_sub('subscription1', retry=retry, retrysleep=retrysleep) except Exception as e: assert isinstance(e, AmsTimeoutException) self.assertEqual(e.code, 408) self.assertEqual(e.msg, 'While trying the [sub_pull]: ' + errmsg) self.assertEqual(mock_requests_post.call_count, retry + 1) @mock.patch('pymod.ams.requests.post') def testRetryAmsBalancer502(self, mock_requests_post): retry = 4 retrysleep = 0.2 errmsg = "<html><body><h1>502 Bad Gateway</h1>\nThe server returned an invalid or incomplete response.\n</body></html>\n" mock_response = mock.create_autospec(requests.Response) mock_response.status_code = 502 mock_response.content = errmsg mock_requests_post.return_value = mock_response try: self.ams.pull_sub('subscription1', retry=retry, retrysleep=retrysleep) except Exception as e: assert isinstance(e, AmsBalancerException) self.assertEqual(e.code, 502) self.assertEqual(e.msg, 'While trying the [sub_pull]: ' + errmsg) self.assertEqual(mock_requests_post.call_count, retry + 1) @mock.patch('pymod.ams.requests.post') def testRetryAmsBalancer503(self, mock_requests_post): retry = 4 retrysleep = 0.2 errmsg = "<html><body><h1>503 Service Unavailable</h1>\nNo server is available to handle this request.\n</body></html>\n" mock_response = mock.create_autospec(requests.Response) mock_response.status_code = 503 mock_response.content = errmsg mock_requests_post.return_value = mock_response try: self.ams.pull_sub('subscription1', retry=retry, retrysleep=retrysleep) except Exception as e: assert isinstance(e, AmsBalancerException) self.assertEqual(e.code, 503) self.assertEqual(e.msg, 'While trying the [sub_pull]: ' + errmsg) self.assertEqual(mock_requests_post.call_count, retry + 1) @mock.patch('pymod.ams.requests.post') def testRetryAmsBalancerTimeout504(self, mock_requests_post): retry = 4 retrysleep = 0.2 errmsg = "<html><body><h1>504 Gateway Time-out</h1>\nThe server didn't respond in time.\n</body></html>\n" mock_response = mock.create_autospec(requests.Response) mock_response.status_code = 504 mock_response.content = errmsg mock_requests_post.return_value = mock_response try: self.ams.pull_sub('subscription1', retry=retry, retrysleep=retrysleep) except Exception as e: assert isinstance(e, AmsTimeoutException) self.assertEqual(e.code, 504) self.assertEqual(e.msg, 'While trying the [sub_pull]: ' + errmsg) self.assertEqual(mock_requests_post.call_count, retry + 1) @mock.patch('pymod.ams.requests.get') def testRetryAckDeadlineAmsTimeout(self, mock_requests_get): mock_response = mock.create_autospec(requests.Response) mock_response.status_code = 408 mock_response.content = '{"error": {"code": 408, \ "message": "Ams Timeout", \ "status": "TIMEOUT"}}' mock_requests_get.return_value = mock_response retry = 3 retrysleep = 0.1 if sys.version_info < (3, ): self.ams._retry_make_request.im_func.__defaults__ = (None, None, retry, retrysleep, None) else: self.ams._retry_make_request.__func__.__defaults__ = (None, None, retry, retrysleep, None) self.assertRaises(AmsTimeoutException, self.ams.list_topics) self.assertEqual(mock_requests_get.call_count, retry + 1)
class TestClient(unittest.TestCase): def setUp(self): # Initialize ams in localhost with token s3cr3t and project TEST self.ams = ArgoMessagingService(endpoint="localhost", token="s3cr3t", project="TEST") self.submocks = SubMocks() self.topicmocks = TopicMocks() # Test create topic client request def testCreateTopics(self): # Execute ams client with mocked response with HTTMock(self.topicmocks.create_topic_mock): resp = self.ams.create_topic("topic1") resp_obj = self.ams.create_topic("topic1", retobj=True) # Assert that ams client handled the json response correctly name = resp["name"] assert name == "/projects/TEST/topics/topic1" assert isinstance(resp_obj, AmsTopic) self.assertEqual(resp_obj.name, "topic1") # Test Pull client request def testPull(self): # Mock response for POST pull from subscription @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription1:pull", method="POST") def pull_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions/subscription1:pull" # Check request produced by ams client req_body = json.loads(request.body) assert req_body["maxMessages"] == "1" return '{"receivedMessages":[{"ackId":"projects/TEST/subscriptions/subscription1:1221",\ "message":{"messageId":"1221","attributes":{"foo":"bar"},"data":"YmFzZTY0ZW5jb2RlZA==",\ "publishTime":"2016-02-24T11:55:09.786127994Z"}}]}' # Execute ams client with mocked response with HTTMock(pull_mock, self.submocks.ack_mock, self.submocks.get_sub_mock): # msg = AmsMessage(data='foo1', attributes={'bar1': 'baz1'}).dict() resp_pull = self.ams.pull_sub("subscription1", 1) ack_id, msg = resp_pull[0] assert ack_id == "projects/TEST/subscriptions/subscription1:1221" assert msg.get_data() == "base64encoded" assert msg.get_msgid() == "1221" # Note: Maybe ack_sub should return a boolean resp_ack = self.ams.ack_sub("subscription1", ["1221"]) assert resp_ack == True # Test Create subscription client request def testCreateSubscription(self): # Execute ams client with mocked response with HTTMock(self.topicmocks.get_topic_mock, self.submocks.create_subscription_mock): resp = self.ams.create_sub("subscription1", "topic1", 10) # Assert that ams client handled the json response correctly name = resp["name"] assert name == "/projects/TEST/subscriptions/subscription1" # Test the Modify offset client request def testModifyOffset(self): # Execute ams client with mocked response with HTTMock(self.submocks.modifyoffset_sub_mock): resp = self.ams.modifyoffset_sub("subscription1", 79) self.assertEquals(resp, {}) # Test the Get offsets client request def testGetOffsets(self): # Execute ams client with mocked response with HTTMock(self.submocks.getoffsets_sub_mock): # should return a dict with all the offsets resp_all = self.ams.getoffsets_sub("subscription1") resp_dict_all = { "max": 79, "min": 0, "current": 78 } # should return the max offset resp_max = self.ams.getoffsets_sub("subscription1", "max") # should return the current offset resp_current = self.ams.getoffsets_sub("subscription1", "current") # should return the min offset resp_min = self.ams.getoffsets_sub("subscription1", "min") self.assertEquals(resp_all, resp_dict_all) self.assertEquals(resp_max, 79) self.assertEquals(resp_current, 78) self.assertEquals(resp_min, 0) # Test List topics client request def testListTopics(self): # Execute ams client with mocked response with HTTMock(self.topicmocks.list_topics_mock): resp = self.ams.list_topics() # Assert that ams client handled the json response correctly topics = resp["topics"] topic_objs = self.ams.topics.values() assert len(topics) == 2 assert topics[0]["name"] == "/projects/TEST/topics/topic1" assert topics[1]["name"] == "/projects/TEST/topics/topic2" assert isinstance(topic_objs[0], AmsTopic) assert isinstance(topic_objs[1], AmsTopic) self.assertEqual(topic_objs[0].fullname, "/projects/TEST/topics/topic1") self.assertEqual(topic_objs[1].fullname, "/projects/TEST/topics/topic2") # Test Iteration over AmsTopic objects def testIterTopics(self): # Mock response for GET topics request @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics", method="GET") def iter_topics_mock(url, request): assert url.path == "/v1/projects/TEST/topics" # Return two topics in json format return response(200, '{"topics":[{"name":"/projects/TEST/topics/topic1"},\ {"name":"/projects/TEST/topics/topic2"}]}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(iter_topics_mock): resp = self.ams.iter_topics() # Assert that ams client handled the json response correctly obj1 = resp.next() obj2 = resp.next() assert isinstance(obj1, AmsTopic) assert isinstance(obj2, AmsTopic) self.assertRaises(StopIteration, resp.next) self.assertEqual(obj1.name, 'topic1') self.assertEqual(obj2.name, 'topic2') # Test Get a subscription ACL client request def testGetAclSubscription(self): # Execute ams client with mocked response with HTTMock(self.submocks.getacl_subscription_mock, self.submocks.get_sub_mock): resp = self.ams.getacl_sub("subscription1") users = resp['authorized_users'] self.assertEqual(users, []) # Test Modify a topic ACL client request def testModifyAclSubscription(self): @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions/subscription1:acl", method="GET") def getacl_subscription_mock_filled(url, request): assert url.path == "/v1/projects/TEST/subscriptions/subscription1:acl" # Return the details of a topic in json format return response(200, '{"authorized_users": ["user1", "user2"]}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(self.submocks.modifyacl_subscription_mock, getacl_subscription_mock_filled, self.submocks.get_sub_mock): resp = self.ams.modifyacl_sub("subscription1", ["user1", "user2"]) self.assertTrue(resp) resp_users = self.ams.getacl_sub("subscription1") users = resp_users['authorized_users'] self.assertEqual(users, ["user1", "user2"]) # Test Get a topic ACL client request def testGetAclTopic(self): # Execute ams client with mocked response with HTTMock(self.topicmocks.getacl_topic_mock, self.topicmocks.get_topic_mock): resp = self.ams.getacl_topic("topic1") users = resp['authorized_users'] self.assertEqual(users, []) # Test Modify a topic ACL client request def testModifyAclTopic(self): @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1:acl", method="GET") def getacl_topic_mock_filled(url, request): assert url.path == "/v1/projects/TEST/topics/topic1:acl" # Return the details of a topic in json format return response(200, '{"authorized_users": ["user1", "user2"]}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(self.topicmocks.modifyacl_topic_mock, getacl_topic_mock_filled, self.topicmocks.get_topic_mock): resp = self.ams.modifyacl_topic("topic1", ["user1", "user2"]) self.assertTrue(resp) resp_users = self.ams.getacl_topic("topic1") users = resp_users['authorized_users'] self.assertEqual(users, ["user1", "user2"]) # Test Get a topic client request def testGetTopic(self): # Execute ams client with mocked response with HTTMock(self.topicmocks.get_topic_mock): resp = self.ams.get_topic("topic1") resp_obj = self.ams.get_topic("topic1", retobj=True) # Assert that ams client handled the json response correctly name = resp["name"] assert(name == "/projects/TEST/topics/topic1") assert isinstance(resp_obj, AmsTopic) self.assertEqual(resp_obj.name, 'topic1') # Test Publish client request def testPublish(self): # Mock response for POST publish to topic @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1:publish", method="POST") def publish_mock(url, request): assert url.path == "/v1/projects/TEST/topics/topic1:publish" # Check request produced by ams client req_body = json.loads(request.body) assert(req_body["messages"][0]["data"] == "Zm9vMQ==") assert (req_body["messages"][0]["attributes"]["bar1"] == "baz1") return '{"msgIds":["1"]}' # Execute ams client with mocked response with HTTMock(publish_mock): msg = AmsMessage(data='foo1', attributes={'bar1': 'baz1'}).dict() msg_bulk = [AmsMessage(data='foo1', attributes={'bar1': 'baz1'}), AmsMessage(data='foo2', attributes={'bar2': 'baz2'})] resp = self.ams.publish("topic1", msg) assert resp["msgIds"][0] == "1" resp_bulk = self.ams.publish("topic1", msg_bulk) assert resp["msgIds"][0] == "1" @urlmatch(netloc="localhost", path="/v1/projects/TEST/topics/topic1:publish", method="POST") def publish_bulk_mock(url, request): assert url.path == "/v1/projects/TEST/topics/topic1:publish" # Check request produced by ams client req_body = json.loads(request.body) self.assertEqual(req_body["messages"][0]["data"], "Zm9vMQ==") self.assertEqual(req_body["messages"][0]["attributes"]["bar1"], "baz1") self.assertEqual(req_body["messages"][1]["data"], "Zm9vMg==") self.assertEqual(req_body["messages"][1]["attributes"]["bar2"], "baz2") return '{"msgIds":["1", "2"]}' with HTTMock(publish_bulk_mock): msg_bulk = [AmsMessage(data='foo1', attributes={'bar1': 'baz1'}), AmsMessage(data='foo2', attributes={'bar2': 'baz2'})] resp_bulk = self.ams.publish("topic1", msg_bulk) self.assertEqual(len(resp_bulk["msgIds"]), 2) self.assertEqual(resp_bulk["msgIds"][0], "1") self.assertEqual(resp_bulk["msgIds"][1], "2") # Test List Subscriptions client request def testListSubscriptions(self): # Mock response for GET Subscriptions request @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions", method="GET") def list_subs_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions" # Return two topics in json format return response(200, '{"subscriptions":[{"name": "/projects/TEST/subscriptions/subscription1",\ "topic": "/projects/TEST/topics/topic1","pushConfig": \ {"pushEndpoint": "","retryPolicy": {}},"ackDeadlineSeconds": 10},\ {"name": "/projects/TEST/subscriptions/subscription2", \ "topic": "/projects/TEST/topics/topic1", \ "pushConfig": {"pushEndpoint": "","retryPolicy": {}},\ "ackDeadlineSeconds": 10}]}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(list_subs_mock): resp = self.ams.list_subs() subscriptions = resp["subscriptions"] subscription_objs = self.ams.subs.values() topic_objs = self.ams.topics.values() # Assert that ams client handled the json response correctly assert len(subscriptions) == 2 assert subscriptions[0]["name"] == "/projects/TEST/subscriptions/subscription1" assert subscriptions[1]["name"] == "/projects/TEST/subscriptions/subscription2" assert isinstance(subscription_objs[0], AmsSubscription) assert isinstance(subscription_objs[1], AmsSubscription) self.assertEqual(subscription_objs[0].fullname, "/projects/TEST/subscriptions/subscription1") self.assertEqual(subscription_objs[1].fullname, "/projects/TEST/subscriptions/subscription2") assert isinstance(topic_objs[0], AmsTopic) self.assertEqual(topic_objs[0].fullname, "/projects/TEST/topics/topic1") # Test Iteration over AmsSubscription objects def testIterSubscriptions(self): # Mock response for GET Subscriptions request @urlmatch(netloc="localhost", path="/v1/projects/TEST/subscriptions", method="GET") def iter_subs_mock(url, request): assert url.path == "/v1/projects/TEST/subscriptions" # Return two topics in json format return response(200, '{"subscriptions":[{"name": "/projects/TEST/subscriptions/subscription1",\ "topic": "/projects/TEST/topics/topic1","pushConfig": \ {"pushEndpoint": "","retryPolicy": {}},"ackDeadlineSeconds": 10},\ {"name": "/projects/TEST/subscriptions/subscription2", \ "topic": "/projects/TEST/topics/topic1", \ "pushConfig": {"pushEndpoint": "","retryPolicy": {}},\ "ackDeadlineSeconds": 10}]}', None, None, 5, request) # Execute ams client with mocked response with HTTMock(iter_subs_mock): resp = self.ams.iter_subs() obj1 = resp.next() obj2 = resp.next() assert isinstance(obj1, AmsSubscription) assert isinstance(obj2, AmsSubscription) self.assertRaises(StopIteration, resp.next) self.assertEqual(obj1.name, 'subscription1') self.assertEqual(obj2.name, 'subscription2') # Test Get a subscriptions client request def testGetSubscription(self): # Execute ams client with mocked response with HTTMock(self.submocks.get_sub_mock): resp = self.ams.get_sub("subscription1") resp_obj = self.ams.get_sub("subscription1", retobj=True) # Assert that ams client handled the json response correctly name = resp["name"] assert name == "/projects/TEST/subscriptions/subscription1" assert isinstance(resp_obj, AmsSubscription) self.assertEqual(resp_obj.name, 'subscription1') # Test has topic client def testHasTopic(self): with HTTMock(self.topicmocks.get_topic_mock): self.assertTrue(self.ams.has_topic('topic1')) # Test has subscription client def testHasSub(self): with HTTMock(self.submocks.get_sub_mock): self.assertTrue(self.ams.has_sub('subscription1'))