def test_single_request(self, mock_request): # mock http server Response = NamedTuple('Response', status_code=int, text=str, url=str, method=str) def fake_response(method, url): return Response(200, 'ok', url, method) mock_request.side_effect = fake_response # overwrite `Context` used by client ctx = Context() ctx.create_redis = lambda: self.redis_resource.rds # create routing record self.rtbl.set_routing( RoutingRecord('myservice', ['localhost:8000'], [1])) # make request response = single_request(ClientConfig('myservice'), ctx, router_type='SymmetryHostRouter') self.assertEqual(200, response.status_code)
def spawn(self, service, num: int = 1, client: str = None, parameters: dict = None, worker_labels: dict = None) -> ClientGroup: """ Spawn clients for the given service and distribute them across workers. If no client app is specified, a default http client will be created that creates http requests from the (optional) parameters:: spawn('myservice', parameters={'method': 'get', 'path': '/', 'kwargs': None} is equivalent to:: spawn('myservice') Another example:: spawn('myservice', 2, parameters={'method': 'post', 'path': '/', 'kwargs': {'data': 'my post data'}}) will result is POST requests to the path '/' where the 'kwargs' dict is passed to the python ``requests.request`` call as keyword arguments. :param service: the service name :param num: the number of clients :param client: the client app name (optional, if not given will use service name) :param parameters: parameters for the app (optional, e.g.: '{ "size": "small" }' :param worker_labels: labels that workers must match to be part of the group :return a new ClientGroup for the created clients """ cfg = ClientConfig(service, client=client, parameters=parameters, worker_labels=worker_labels) clients = self.ctrl.create_clients(cfg, num) return ClientGroup(self.ctrl, clients, cfg)
def test_debug_router(self): env = dict(os.environ) env['galileo_router_type'] = 'DebugRouter' client_id = 'unittest_client' ctx = Context(env) trace_queue = Queue() description = ClientDescription(client_id, 'unittest_worker', ClientConfig('aservice')) # ctx: Context, trace_queue: Queue, description: ClientDescription client = Client(ctx, trace_queue, description, eventbus=SimpleEventBus()) client.request_generator = StaticRequestGenerator( [ServiceRequest('aservice') for _ in range(self.n)]) then = time.time() client.run() now = time.time() total = now - then print('DebugRouter: %.2f req/sec (%.4fs total)' % (self.n / total, total))
def request(self, service, client: str = None, parameters: dict = None, router_type='SymmetryHostRouter', worker_labels: dict = None): """ Send a request with the given configuration like a client would. See ``spawn`` for the parameters. An additional parameter is the ``router_type`` which specifies which router to use (see `Context.create_router`) """ cfg = ClientConfig(service, client=client, parameters=parameters, worker_labels=worker_labels) resp = single_request(cfg, router_type=router_type) return resp
def test_symmetry_router(self, mock_request): # mock http server Response = NamedTuple('Response', status_code=int, text=str, url=str, method=str) def fake_response(method, url): return Response(200, 'ok', url, method) mock_request.side_effect = fake_response self.rtbl.set_routing( RoutingRecord('aservice', ['host1', 'host2', 'host3'], [1, 2, 3])) env = dict(os.environ) env['galileo_router_type'] = 'CachingSymmetryHostRouter' client_id = 'unittest_client' ctx = Context(env) ctx.create_redis = lambda: self.rds trace_queue = Queue() description = ClientDescription(client_id, 'unittest_worker', ClientConfig('aservice')) # ctx: Context, trace_queue: Queue, description: ClientDescription client = Client(ctx, trace_queue, description, eventbus=SimpleEventBus()) client.request_generator = StaticRequestGenerator( [ServiceRequest('aservice') for _ in range(self.n)]) then = time.time() client.run() now = time.time() total = now - then print('CachingSymmetryHostRouter: %.2f req/sec (%.4f total)' % (self.n / total, total))
def test_with_router_fault(self): class FaultInjectingRouter(DebugRouter): def request(self, req: ServiceRequest) -> 'requests.Response': if req.path == '/api/nonexisting': raise ValueError('some error') return super().request(req) router = FaultInjectingRouter() ctx = Context() ctx.create_router = lambda: router client_id = 'unittest_client' trace_queue = Queue() description = ClientDescription(client_id, 'unittest_worker', ClientConfig('aservice')) # ctx: Context, trace_queue: Queue, description: ClientDescription client = Client(ctx, trace_queue, description, eventbus=SimpleEventBus()) client.request_generator = StaticRequestGenerator([ ServiceRequest('aservice', path='/api/nonexisting'), ServiceRequest('aservice', path='/api/unittest'), ]) client.run() trace1 = trace_queue.get(timeout=2) trace2 = trace_queue.get(timeout=2) self.assertEqual(-1, trace1.sent) self.assertAlmostEqual(trace2.sent, time.time(), delta=2)
def test_client_integration(self): env = dict(os.environ) env['galileo_router_type'] = 'DebugRouter' client_id = 'unittest_client' ctx = Context(env) trace_queue = Queue() description = ClientDescription(client_id, 'unittest_worker', ClientConfig('aservice')) # ctx: Context, trace_queue: Queue, description: ClientDescription client = Client(ctx, trace_queue, description, eventbus=SimpleEventBus()) client.request_generator = StaticRequestGenerator([ ServiceRequest('aservice'), ServiceRequest('aservice'), ]) client.run() trace1 = trace_queue.get(timeout=2) trace2 = trace_queue.get(timeout=2) self.assertEqual('aservice', trace1.service) self.assertEqual('aservice', trace2.service) self.assertEqual('debughost', trace1.server) self.assertEqual('debughost', trace2.server) now = time.time() self.assertAlmostEqual(now, trace1.done, delta=2) self.assertAlmostEqual(now, trace2.done, delta=2)