def test_simple_call_notify(monkeypatch): service = RemoteService(DUMMY_SERVICE_URL) monkeypatch.setattr(urllib.request, 'urlopen', dummy_urlopen) result = service.notify("test", []) assert result is None
def test_client_async_as_completed(microservice_url): client = RemoteService(microservice_url) for ready_result in as_completed( *[client.call_method_async("sum", [i, i + 1]) for i in range(10)]): print(ready_result) assert ready_result.finished()
def test_client_connection(self): client = RemoteService(self.service_url) self.assertEqual(client.name, "test.service.client.1") self.assertCountEqual(client.get_available_methods(), [ "get_service_specs", "method1", "method2", "method3", "method4", "method5", "sleep", "sleep_with_error" ])
def test_simple_call(monkeypatch): service = RemoteService(DUMMY_SERVICE_URL) monkeypatch.setattr(urllib.request, 'urlopen', dummy_urlopen) result = service.call_method("test", []) assert isinstance(result, Result) assert result.id == result.method_call.id
def test_client_async_call(microservice_url): client = RemoteService(microservice_url) async_call = client.call_method_async("sum", [1, 2]) assert isinstance(async_call, AsyncMethodCall) async_call.result(wait=True) assert async_call.finished() assert async_call.result().result == 3
def test_client_async_first_completed(microservice_url): client = RemoteService(microservice_url) res = first_completed(*[client.call_method_async("sum", [i, i + 1]) for i in range(10)]) assert isinstance(res, Result) assert res.error is None assert isinstance(res.result, int) assert 1 <= res.result <= 19
def test_client_simple_method_call(microservice_url): client = RemoteService(microservice_url) result = client.call_method("sum", params=[1, 2]) assert isinstance(result, Result) assert result.result == 3 result = client.call_method("sum", params={"a": 1, "b": 2}) assert isinstance(result, Result) assert result.result == 3
def test_async_call(monkeypatch): service = RemoteService(DUMMY_SERVICE_URL) monkeypatch.setattr(urllib.request, 'urlopen', dummy_urlopen) result = service.call_method_async("test", []) assert isinstance(result, AsyncMethodCall) result = result.result(wait=True) assert isinstance(result, Result) assert result.id == result.method_call.id
def test_as_completed(monkeypatch): service = RemoteService(DUMMY_SERVICE_URL) monkeypatch.setattr(urllib.request, 'urlopen', dummy_urlopen) items = [service.call_method_async("test", []) for _ in range(10)] data = as_completed(*items) assert inspect.isgenerator(data) results = list(data) assert len(results) == 10
def test_client_simple_method_call_with_objects(microservice_url): client = RemoteService(microservice_url) req = MethodCall("sum", [1, 2]) result = client.call_method(req) assert isinstance(result, Result) assert result.result == 3 req = MethodCall("sum", {"a": 1, "b": 2}) result = client.call_method(req) assert isinstance(result, Result) assert result.result == 3
def test_remote_service_make_request_obj(): service = RemoteService(DUMMY_SERVICE_URL) body = {"test": "ok"} req_obj = service.build_http_request_obj(body) assert isinstance(req_obj, urllib.request.Request) assert req_obj.get_full_url() == DUMMY_SERVICE_URL assert req_obj.method == "POST" assert req_obj.get_header( "Content-Type".capitalize()) == 'application/json' assert req_obj.data == b'{"test": "ok"}'
def test_method_call_with_complex_result(self): client = RemoteService(self.service_url) result = client.methods.method4(arg1="test", arg2="success") self.assertEqual(result, {"arg1": "test", "arg2": "success"}) result = client.methods.method4("test", "success") self.assertEqual(result, {"arg1": "test", "arg2": "success"})
def test_method_call_wrong_params(self): client = RemoteService(self.service_url) with self.assertRaises(CalledServiceError): result = client.methods.method1(param="should_not_be_here") with self.assertRaises(CalledServiceError): result = client.methods.method1(1, 2, 3)
def get_service(self, name): """ Locates a remote service by name. The name can be a glob-like pattern (``"project.worker.*"``). If multiple services match the given name, a random instance will be chosen. There might be multiple services that match a given name if there are multiple services with the same name running, or when the pattern matches multiple different services. .. todo:: Make this use self.io_loop to resolve the request. The current implementation is blocking and slow :param name: a pattern for the searched service. :return: a :py:class:`gemstone.RemoteService` instance :raises ValueError: when the service can not be located :raises ServiceConfigurationError: when there is no configured service registry """ if not self.registries: raise ServiceConfigurationError("No service registry available") for service_reg in self.registries: endpoints = service_reg.methods.locate_service(name) if not endpoints: continue random.shuffle(endpoints) for url in endpoints: try: return RemoteService(url) except ConnectionError: continue # could not establish connection, try next raise ValueError("Service could not be located")
def test_method_call_private_token_incorrect(self): client = RemoteService(self.service_url, options={ "auth_type": "header", "auth_token": "wrong-token" }) with self.assertRaises(CalledServiceError): result = client.methods.method5("test")
def test_method_call_private_token_ok(self): client = RemoteService(self.service_url, options={ "auth_type": "header", "auth_token": "test-token" }) result = client.methods.method5("test") self.assertEqual(result, "private test")
def test_simple_batch_call(monkeypatch): service = RemoteService(DUMMY_SERVICE_URL) monkeypatch.setattr(urllib.request, 'urlopen', dummy_urlopen_batch) calls = [ MethodCall("test", []), MethodCall("test2", []), MethodCall("test3", []) ] result = service.call_batch(*calls) assert isinstance(result, BatchResult) assert len(result) == 3 assert result.get_response_for_call(calls[0]).id == calls[0].id assert result.get_response_for_call(calls[1]).id == calls[1].id assert result.get_response_for_call(calls[2]).id == calls[2].id assert result.get_response_for_call(MethodCall("invalid")) is None
def test_method_call_custom_api_token_header(self): client = RemoteService(self.service_url2, options={ "auth_type": "header", "auth_params": "Custom-Header", "auth_token": "test-token" }) result = client.methods.test() self.assertTrue(result)
def test_async_first_completed_async(self): client = RemoteService(self.service_url) requests = [ client.methods.sleep(1 - x * 0.25, __async=True) for x in range(4) ] first = first_completed(*requests) self.assertIsInstance(first, AsyncMethodCall) self.assertTrue(first in requests)
def test_async_single_call_valid_result(self): client = RemoteService(self.service_url) r = client.methods.method3(1, 2, __async=True) self.assertIsInstance(r, AsyncMethodCall) r.wait() self.assertEqual(r.result(), 3) self.assertIsNone(r.error()) self.assertTrue(r.finished())
def test_client_batch_call(microservice_url): client = RemoteService(microservice_url) requests = [ MethodCall("sum", [1, 2]), MethodCall("divide", [10, 5]), MethodCall("sum", [10, -10]), MethodCall("sum", ["hello", " world"]), MethodCall("sum", [1, 2, 3]), # error Notification("sum", [1, 2]) ] resp = client.call_batch(*requests) assert len(resp) == 5 assert resp.get_response_for_call(requests[0]).result == 3 assert resp.get_response_for_call(requests[1]).result == 2. assert resp.get_response_for_call(requests[2]).result == 0 assert resp.get_response_for_call(requests[3]).result == "hello world" assert resp.get_response_for_call(requests[5]) is None # it was a notification
def test_method_call_with_numeric_args(self): client = RemoteService(self.service_url) result = client.methods.method3(10, 11) self.assertEqual(result, 21) result = client.methods.method3(1, 1) self.assertEqual(result, 2) result = client.methods.method3(131, 33) self.assertEqual(result, 164) with self.assertRaisesRegex(CalledServiceError, "Bad type for a and b"): result = client.methods.method3("abc", "def")
def test_async_add_callbacks_errors(self): client = RemoteService(self.service_url) requests = [ client.methods.sleep_with_error(1 - x * 0.25, __async=True) for x in range(4) ] success_callback = MagicMock() fail_callback = MagicMock() make_callbacks(requests, on_result=success_callback, on_error=fail_callback) success_callback.assert_not_called()
def test_async_single_call_error(self): client = RemoteService(self.service_url) r = client.methods.method3("a", "b", __async=True) self.assertIsInstance(r, AsyncMethodCall) r.wait() self.assertIsNone(r.result()) self.assertIsNotNone(r.error()) self.assertEqual(r.error()["message"].lower(), "internal error") self.assertEqual(r.error()["code"], -32603) self.assertEqual(r.error()["data"]["class"], "ValueError") self.assertTrue(r.finished())
def test_async_add_callbacks_main_thread(self): client = RemoteService(self.service_url) requests = [ client.methods.sleep(1 - x * 0.25, __async=True) for x in range(4) ] success_callback = MagicMock() fail_callback = MagicMock() make_callbacks(requests, on_result=success_callback, on_error=fail_callback) success_callback.assert_has_calls( [call(0.25), call(0.5), call(0.75), call(1.0)], any_order=True) fail_callback.assert_not_called()
def test_client_simple_method_call_with_errors(microservice_url): client = RemoteService(microservice_url) # too few positional args result = client.call_method("sum", params=[1]) assert isinstance(result, Result) assert result.result is None assert result.error["code"] == -32602 # too many positional args result = client.call_method("sum", params=[1, 2, 3]) assert isinstance(result, Result) assert result.result is None assert result.error["code"] == -32602 # too few kw args result = client.call_method("sum", params={"a": 1}) assert isinstance(result, Result) assert result.result is None assert result.error["code"] == -32602 # too many kw args result = client.call_method("sum", params={"a": 1, "b": 2, "c": 3}) assert isinstance(result, Result) assert result.result is None assert result.error["code"] == -32602 # method not found result = client.call_method("invalid", params={"a": 1, "b": 2, "c": 3}) assert isinstance(result, Result) assert result.result is None assert result.error["code"] == -32601 # internal error result = client.call_method("sum", params=[None, 3]) assert isinstance(result, Result) assert result.result is None assert result.error["code"] == -32603
def _periodic_task_iter(self): """ Iterates through all the periodic tasks: - the service registry pinging - default dummy task if on Windows - user defined periodic tasks :return: """ for url in self.service_registry_urls: registry = RemoteService(url) self.registries.append(registry) periodic_servreg_ping = functools.partial( self._ping_to_service_registry, registry) periodic_servreg_ping() # initial ping self.default_periodic_tasks.append( (periodic_servreg_ping, self.service_registry_ping_interval)) all_periodic_tasks = self.default_periodic_tasks + self.periodic_tasks for func, timer_in_seconds in all_periodic_tasks: timer_milisec = timer_in_seconds * 1000 yield PeriodicCallback(func, timer_milisec, io_loop=self.io_loop)
def test_method_call_private_token_missing(self): client = RemoteService(self.service_url) # no api token with self.assertRaises(CalledServiceError): result = client.methods.method5("test")
def test_method_call_method_does_not_exist(self): client = RemoteService(self.service_url) with self.assertRaises(AttributeError): result = client.methods.does_not_exist()
def test_method_call_with_args(self): client = RemoteService(self.service_url) result = client.methods.method2("hello") self.assertEqual(result, "hello there hello")