예제 #1
0
def test_graceful_stop_on_one_container_error(runner_factory, rabbit_config):

    runner = runner_factory(rabbit_config, ExampleService, SecondService)
    runner.start()

    container = get_container(runner, ExampleService)
    second_container = get_container(runner, SecondService)
    original_stop = second_container.stop
    with patch.object(second_container,
                      'stop',
                      autospec=True,
                      wraps=original_stop) as stop:
        rpc_consumer = get_extension(container, RpcConsumer)
        with patch.object(rpc_consumer, 'handle_result',
                          autospec=True) as handle_result:
            exception = Exception("error")
            handle_result.side_effect = exception

            # use a standalone rpc proxy to call exampleservice.task()
            with ServiceRpcProxy("exampleservice", rabbit_config) as proxy:
                # proxy.task() will hang forever because it generates an error
                # in the remote container (so never receives a response).
                proxy.task.call_async()

            # verify that the error bubbles up to runner.wait()
            with pytest.raises(Exception) as exc_info:
                runner.wait()
            assert exc_info.value == exception

            # Check that the second service was stopped due to the first
            # service being killed
            stop.assert_called_once_with()
예제 #2
0
def test_integration(runner_factory, config):

    runner = runner_factory(config, Command, Query)
    runner.start()

    container = get_container(runner, Command)
    
    with entrypoint_hook(container, 'add_news') as entrypoint:
        data = {
            "title": "title test",
            "author": "author test",
            "content": "content test",
            "tags": [
                "test tag1",
                "test tag2",
            ],
        }
        result = entrypoint(data)
        
        assert result == data
        
    container = get_container(runner, Query)
    with entrypoint_hook(container, 'get_news') as entrypoint:

        news = json.loads(entrypoint(result['id']))

        assert news["_id"] == result['id']

    with entrypoint_hook(container, 'get_all_news') as get_all_news:

        news = json.loads(get_all_news(1, 10))

        assert len(news) > 0
예제 #3
0
def test_shop_checkout_integration(
    rabbit_config, runner_factory, rpc_proxy_factory
):
    """ Simulate a checkout flow as an integration test.

    Requires instances of AcmeShopService, StockService and InvoiceService
    to be running. Explicitly replaces the rpc proxy to PaymentService so
    that service doesn't need to be hosted.

    Also replaces the event dispatcher dependency on AcmeShopService and
    disables the timer entrypoint on StockService. Limiting the interactions
    of services in this way reduces the scope of the integration test and
    eliminates undesirable side-effects (e.g. processing events unnecessarily).
    """
    context_data = {'user_id': 'wile_e_coyote'}
    shop = rpc_proxy_factory('acmeshopservice', context_data=context_data)

    runner = runner_factory(
        rabbit_config, AcmeShopService, StockService, InvoiceService)

    # replace ``event_dispatcher`` and ``payment_rpc``  dependencies on
    # AcmeShopService with ``MockDependencyProvider``\s
    shop_container = get_container(runner, AcmeShopService)
    fire_event, payment_rpc = replace_dependencies(
        shop_container, "fire_event", "payment_rpc")

    # restrict entrypoints on StockService
    stock_container = get_container(runner, StockService)
    restrict_entrypoints(stock_container, "check_price", "check_stock")

    runner.start()

    # add some items to the basket
    assert shop.add_to_basket("anvil") == "anvil"
    assert shop.add_to_basket("invisible_paint") == "invisible_paint"

    # try to buy something that's out of stock
    with pytest.raises(RemoteError) as exc_info:
        shop.add_to_basket("toothpicks")
    assert exc_info.value.exc_type == "ItemOutOfStockError"

    # provide a mock response from the payment service
    payment_rpc.take_payment.return_value = "Payment complete."

    # checkout
    res = shop.checkout()

    total_amount = 100 + 10
    assert res == total_amount

    # verify integration with mocked out payment service
    payment_rpc.take_payment.assert_called_once_with({
        'customer': "wile_e_coyote",
        'address': "12 Long Road, High Cliffs, Utah",
        'amount': total_amount,
        'message': "Dear Wile E Coyote. Please pay $110 to ACME Corp."
    })

    # verify events fired as expected
    assert fire_event.call_count == 3
예제 #4
0
def test_nameko_services_can_subscribe_to_other_nameko_services(
        runner_factory, config_path, router
):
    config = {
        WAMP_CONFIG_KEY: {
            'config_path': config_path,
        }
    }

    runner = runner_factory(config, WampSubscriber, WampPublisher)
    runner.start()

    container = get_container(runner, WampSubscriber)
    wait_for_subscriptions(container, number_of_subscriptions=2)

    assert WampSubscriber.messages == []

    container = get_container(runner, WampPublisher)
    wait_for_registrations(container, number_of_registrations=1)

    with entrypoint_hook(container, "publish_foo") as entrypoint:
        entrypoint()

    def waiting_for_the_message():
        assert len(WampSubscriber.messages) == 1
        assert WampSubscriber.messages == [
            ((u'hello foo',), {})
        ]

    assert_stops_raising(waiting_for_the_message)
    WampSubscriber.messages = []
예제 #5
0
def test_graceful_stop_on_one_container_error(runner_factory, rabbit_config):

    runner = runner_factory(rabbit_config, ExampleService, SecondService)
    runner.start()

    container = get_container(runner, ExampleService)
    second_container = get_container(runner, SecondService)
    original_stop = second_container.stop
    with patch.object(second_container, 'stop', autospec=True,
                      wraps=original_stop) as stop:
        rpc_consumer = get_extension(container, RpcConsumer)
        with patch.object(
                rpc_consumer, 'handle_result', autospec=True) as handle_result:
            exception = Exception("error")
            handle_result.side_effect = exception

            # use a standalone rpc proxy to call exampleservice.task()
            with ServiceRpcProxy("exampleservice", rabbit_config) as proxy:
                # proxy.task() will hang forever because it generates an error
                # in the remote container (so never receives a response).
                proxy.task.call_async()

            # verify that the error bubbles up to runner.wait()
            with pytest.raises(Exception) as exc_info:
                runner.wait()
            assert exc_info.value == exception

            # Check that the second service was stopped due to the first
            # service being killed
            stop.assert_called_once_with()
예제 #6
0
def test_request_numbers_integration(runner_factory, rabbit_config):
    config = rabbit_config
    config['REDIS_URIS'] = MY_REDIS_URIS
    runner = runner_factory(config, Service1, Service2, Service3, Service4)
    runner.start()

    service3 = get_container(runner, Service3)
    service4 = get_container(runner, Service4)
    with entrypoint_hook(service3, 'request_numbers') as request_numbers:
        with entrypoint_waiter(service4, 'receive_publication'):
            request_numbers()
예제 #7
0
def test_consumer_integration(runner_factory, rabbit_config):
    config = rabbit_config
    config['REDIS_URIS'] = {'my_redis': 'redis://localhost:6379/0'}
    runner = runner_factory(config, Service1, Service2, Service3, Service4,
                            ConsumerService)
    runner.start()

    service3 = get_container(runner, Service3)
    consumer = get_container(runner, ConsumerService)
    with entrypoint_hook(service3, 'request_numbers') as request_numbers:
        with entrypoint_waiter(consumer, 'receive_new_publication'):
            request_numbers()
예제 #8
0
def test_get_container(runner_factory, rabbit_config):
    class ServiceX(object):
        name = "service_x"

    class ServiceY(object):
        name = "service_y"

    runner = runner_factory(rabbit_config, ServiceX, ServiceY)

    assert get_container(runner, ServiceX).service_cls is ServiceX
    assert get_container(runner, ServiceY).service_cls is ServiceY
    assert get_container(runner, object) is None
예제 #9
0
def test_get_container(runner_factory, rabbit_config):

    class ServiceX(object):
        name = "service_x"

    class ServiceY(object):
        name = "service_y"

    runner = runner_factory(rabbit_config, ServiceX, ServiceY)

    assert get_container(runner, ServiceX).service_cls is ServiceX
    assert get_container(runner, ServiceY).service_cls is ServiceY
    assert get_container(runner, object) is None
예제 #10
0
def test_call_id_over_events(rabbit_config, predictable_call_ids,
                             runner_factory):
    one_called = Mock()
    two_called = Mock()

    stack_request = Mock()
    LoggingWorkerContext = get_logging_worker_context(stack_request)

    class EventListeningServiceOne(object):
        name = "listener_one"

        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            one_called()

    class EventListeningServiceTwo(object):
        name = "listener_two"

        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            two_called()

    class EventRaisingService(object):
        name = "event_raiser"
        dispatch = EventDispatcher()

        @rpc
        def say_hello(self):
            self.dispatch('hello', self.name)

    runner = runner_factory(rabbit_config)
    runner.add_service(EventListeningServiceOne, LoggingWorkerContext)
    runner.add_service(EventListeningServiceTwo, LoggingWorkerContext)
    runner.add_service(EventRaisingService, LoggingWorkerContext)
    runner.start()

    container = get_container(runner, EventRaisingService)
    listener1 = get_container(runner, EventListeningServiceOne)
    listener2 = get_container(runner, EventListeningServiceTwo)
    with entrypoint_hook(container, "say_hello") as say_hello:
        waiter1 = entrypoint_waiter(listener1, 'hello')
        waiter2 = entrypoint_waiter(listener2, 'hello')
        with waiter1, waiter2:
            say_hello()

    assert predictable_call_ids.call_count == 3
    stack_request.assert_has_calls([
        call(None),
        call(['event_raiser.say_hello.0']),
        call(['event_raiser.say_hello.0']),
    ])
예제 #11
0
def test_call_id_over_events(rabbit_config, predictable_call_ids,
                             runner_factory):
    one_called = Mock()
    two_called = Mock()

    stack_request = Mock()
    LoggingWorkerContext = get_logging_worker_context(stack_request)

    class EventListeningServiceOne(object):
        name = "listener_one"

        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            one_called()

    class EventListeningServiceTwo(object):
        name = "listener_two"

        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            two_called()

    class EventRaisingService(object):
        name = "event_raiser"
        dispatch = EventDispatcher()

        @rpc
        def say_hello(self):
            self.dispatch('hello', self.name)

    runner = runner_factory(rabbit_config)
    runner.add_service(EventListeningServiceOne, LoggingWorkerContext)
    runner.add_service(EventListeningServiceTwo, LoggingWorkerContext)
    runner.add_service(EventRaisingService, LoggingWorkerContext)
    runner.start()

    container = get_container(runner, EventRaisingService)
    listener1 = get_container(runner, EventListeningServiceOne)
    listener2 = get_container(runner, EventListeningServiceTwo)
    with entrypoint_hook(container, "say_hello") as say_hello:
        waiter1 = entrypoint_waiter(listener1, 'hello')
        waiter2 = entrypoint_waiter(listener2, 'hello')
        with waiter1, waiter2:
            say_hello()

    assert predictable_call_ids.call_count == 3
    stack_request.assert_has_calls([
        call(None),
        call(['event_raiser.say_hello.0']),
        call(['event_raiser.say_hello.0']),
    ])
def test_resend_user_token_already_verified(config, runner_factory):
    runner = runner_factory(AccountsService)
    container = get_container(runner, AccountsService)
    storage, send_grid = replace_dependencies(container, "storage", "send_grid")
    runner.start()

    email = "*****@*****.**"
    password = "******"
    user_id = 1

    storage.users.is_correct_password.return_value = True

    storage.users.get_from_email.return_value = {
        "id": user_id,
        "email": email,
        "verified": True,
    }

    with entrypoint_hook(container, "resend_user_token") as resend_user_token:
        with pytest.raises(UserNotAuthorised):
            resend_user_token(email, password)

        assert storage.users.is_correct_password.call_args == call(email, password)

        assert storage.users.get_from_email.call_args == call(email)
def test_resend_user_token(config, runner_factory):
    runner = runner_factory(AccountsService)
    container = get_container(runner, AccountsService)
    storage, send_grid = replace_dependencies(container, "storage", "send_grid")
    runner.start()

    email = "*****@*****.**"
    password = "******"
    user_id = 1

    storage.users.is_correct_password.return_value = True

    storage.users.get_from_email.return_value = {
        "id": user_id,
        "email": email,
        "verified": False,
    }

    storage.user_tokens.create.return_value = None

    send_grid.send_signup_verification.return_value = None

    with entrypoint_hook(container, "resend_user_token") as resend_user_token:
        result = resend_user_token(email, password)

        assert storage.users.is_correct_password.call_args == call(email, password)

        assert storage.users.get_from_email.call_args == call(email)

        assert storage.user_tokens.create.call_args == call(user_id, ANY)

        assert send_grid.send_signup_verification.call_args == call(email, ANY)

        assert result is None
예제 #14
0
def test_create_stripe_checkout_session_unsuccessful(config, runner_factory):
    runner = runner_factory(AccountsService)
    container = get_container(runner, AccountsService)
    stripe = replace_dependencies(container, "stripe")
    runner.start()

    user_id = 123
    email = "*****@*****.**"
    plan = "plan1"
    success_url = "http://success.com"
    cancel_url = "http://cancel.com"
    project_id = 1

    stripe.checkout.Session.create.side_effect = stripe_payment.error.StripeError()

    with entrypoint_hook(
        container, "create_stripe_checkout_session"
    ) as create_stripe_checkout_session:
        with pytest.raises(UnableToCreateCheckoutSession):
            create_stripe_checkout_session(
                {
                    "user_id": user_id,
                    "email": email,
                    "plan": plan,
                    "success_url": success_url,
                    "cancel_url": cancel_url,
                    "project_id": project_id,
                }
            )
def test_create_user_successful(config, runner_factory):
    runner = runner_factory(AccountsService)
    container = get_container(runner, AccountsService)
    storage, send_grid = replace_dependencies(container, "storage",
                                              "send_grid")
    runner.start()

    storage.users.create.return_value = 1
    storage.user_tokens.create.return_value = "randomtoken"

    payload = {
        "email": "*****@*****.**",
        "password": "******",
        "display_name": "Test Account",
    }
    with entrypoint_hook(container, "create_user") as create_user:
        with patch("accounts.service.users.generate_token",
                   return_value="token"):

            result = create_user(user_details=payload)

        assert result == 1

        assert storage.users.create.call_args == call(payload["email"],
                                                      payload["password"],
                                                      payload["display_name"])

        assert send_grid.send_signup_verification.call_args == call(
            payload["email"], "token")
예제 #16
0
def test_runner_catches_container_errors(runner_factory, rabbit_config):

    runner = runner_factory(rabbit_config, ExampleService)
    runner.start()

    container = get_container(runner, ExampleService)

    rpc_consumer = get_dependency(container, RpcConsumer)
    with patch.object(rpc_consumer, 'handle_result',
                      autospec=True) as handle_result:
        exception = Exception("error")
        handle_result.side_effect = exception

        # use a standalone rpc proxy to call exampleservice.task()
        with RpcProxy("exampleservice", rabbit_config) as proxy:
            # proxy.task() will hang forever because it generates an error
            # in the remote container (so never receives a response).
            # generate and then swallow a timeout as soon as the thread yields
            try:
                with eventlet.Timeout(0):
                    proxy.task()
            except eventlet.Timeout:
                pass

        # verify that the error bubbles up to runner.wait()
        with pytest.raises(Exception) as exc_info:
            runner.wait()
        assert exc_info.value == exception
예제 #17
0
def test_get_successful_with_deleted_datetime(config, runner_factory):
    runner = runner_factory(AccountsService)
    container = get_container(runner, AccountsService)
    storage = replace_dependencies(container, "storage")
    runner.start()

    user_id = 123
    email = "*****@*****.**"
    created_datetime_utc = datetime.datetime.utcnow()
    deleted_datetime_utc = datetime.datetime.utcnow()

    storage.users.get.return_value = {
        "id": user_id,
        "email": email,
        "created_datetime_utc": created_datetime_utc,
        "deleted_datetime_utc": deleted_datetime_utc,
        "verified": False,
    }

    with entrypoint_hook(container, "get_user") as get_user:
        result = get_user(user_id=user_id)

        assert storage.users.get.call_args == call(123)

        assert result == {
            "id": user_id,
            "email": email,
            "created_datetime_utc": created_datetime_utc.isoformat(),
            "deleted_datetime_utc": deleted_datetime_utc.isoformat(),
            "verified": False,
        }
예제 #18
0
def test_auth_successful(config, runner_factory):
    runner = runner_factory(AccountsService)
    container = get_container(runner, AccountsService)
    storage = replace_dependencies(container, "storage")
    runner.start()

    user_id = 123
    email = "*****@*****.**"
    password = "******"

    storage.users.is_correct_password.return_value = True
    storage.users.get_from_email.return_value = {
        "id": user_id,
        "email": email,
        "verified": True,
    }

    with entrypoint_hook(container, "auth_user") as auth_user:
        result = auth_user(email=email, password=password)

        assert result == {"JWT": ANY}

        assert storage.users.is_correct_password.call_args == call(
            email, password)

        assert storage.users.get_from_email.call_args == call(email)
예제 #19
0
파일: test_errors.py 프로젝트: ahmb/nameko
def test_runner_catches_container_errors(runner_factory, rabbit_config):

    runner = runner_factory(rabbit_config, ExampleService)
    runner.start()

    container = get_container(runner, ExampleService)

    rpc_consumer = get_dependency(container, RpcConsumer)
    with patch.object(
            rpc_consumer, 'handle_result', autospec=True) as handle_result:
        exception = Exception("error")
        handle_result.side_effect = exception

        # use a standalone rpc proxy to call exampleservice.task()
        with RpcProxy("exampleservice", rabbit_config) as proxy:
            # proxy.task() will hang forever because it generates an error
            # in the remote container (so never receives a response).
            # generate and then swallow a timeout as soon as the thread yields
            try:
                with eventlet.Timeout(0):
                    proxy.task()
            except eventlet.Timeout:
                pass

        # verify that the error bubbles up to runner.wait()
        with pytest.raises(Exception) as exc_info:
            runner.wait()
        assert exc_info.value == exception
예제 #20
0
    def test_config_key(self, service_cls, container_cls):
        config = {'SERVICE_CONTAINER_CLS': "fake_module.ServiceContainerX"}
        runner = ServiceRunner(config)
        runner.add_service(service_cls)

        container = get_container(runner, service_cls)
        assert isinstance(container, container_cls)
def test_create_user_successful(config, db, runner_factory):
    runner = runner_factory(MonitoringService)
    container = get_container(runner, MonitoringService)
    storage = replace_dependencies(container, "storage")
    runner.start()

    storage.api_requests.append.return_value = None

    with entrypoint_hook(
            container,
            "consume_monitoring_stream") as consume_monitoring_stream:
        consume_monitoring_stream(
            "123",
            {
                "__MONITOR_NAME": "API_REQUEST",
                "url": "url",
                "method": "method",
                "duration": "duration",
                "status": "status",
                "status_code": 1,
                "remote_addr": "remote_addr",
            },
        )

    assert storage.api_requests.append.call_args == call(
        "123", "url", "method", "duration", "status", 1, "remote_addr")
예제 #22
0
def test_nameko_service_can_subscribe_to_wamp_topic(
    runner_factory, router, config_path
):
    wamp_client = Client(router=router)

    config = {
        WAMP_CONFIG_KEY: {
            'config_path': config_path,
        }
    }

    runner = runner_factory(config, WampSubscriber)
    runner.start()

    container = get_container(runner, WampSubscriber)

    with wamp_client as client:
        wait_for_session(client)
        wait_for_subscriptions(container, number_of_subscriptions=2)

        client.publish(topic="foo", message="hello foo")
        client.publish(topic="bar", message="hello bar")

    def waiting_for_the_message():
        assert len(WampSubscriber.messages) == 2
        assert sorted(WampSubscriber.messages) == sorted([
            ((u'hello foo',), {}),
            ((u'hello bar',), {})
        ])

    assert_stops_raising(waiting_for_the_message)
    WampSubscriber.messages = []
예제 #23
0
def test_service_x_y_integration(runner_factory, rabbit_config):

    runner = runner_factory(rabbit_config, ServiceX, ServiceY)
    runner.start()

    container = get_container(runner, ServiceX)
    with entrypoint_hook(container, "remote_method") as entrypoint:
        assert entrypoint("value") == "value-x-y"
예제 #24
0
    def test_config_key(self, service_cls, container_cls):
        config = {
            'SERVICE_CONTAINER_CLS': "fake_module.ServiceContainerX"
        }
        runner = ServiceRunner(config)
        runner.add_service(service_cls)

        container = get_container(runner, service_cls)
        assert isinstance(container, container_cls)
예제 #25
0
def test_shop_checkout_integration(rabbit_config, runner_factory,
                                   rpc_proxy_factory):
    context_data = {"user_id": "wile_e_coyote"}

    shop = rpc_proxy_factory("acmesshopservice", context_data=context_data)

    runner = runner_factory(rabbit_config, AcmeShopService, StockService,
                            InvoiceService)

    shop_container = get_container(runner, AcmeShopService)
    fire_event, payment_rpc = replace_dependencies(shop_container,
                                                   "fire_event", "payment_rpc")

    stock_container = get_container(runner, StockService)
    restrict_entrypoints(stock_container, "check_price", "check_stock")

    runner.start()

    assert shop.add_to_basket("anvil") == "anvil"
    assert shop.add_to_basket("invisible_paint") == "invisible_paint"

    with pytest.raises(RemoteError) as exc_info:
        shop.add_to_basket("toothpicks")
    assert exc_info.value.exc_type == "ItemOutOfStockError"

    payment_rpc.take_payment.return_value = "Payment complete."

    res = shop.checkout()

    total_amount = 100 + 10
    assert res == total_amount

    payment_rpc.take_payment.assert_called_once_with({
        "customer":
        "wile_e_coyote",
        "address":
        "12 Long Road, High Cliffs, Utah",
        "amount":
        total_amount,
        "message":
        "Dear Wile E Coyote, Please pay $110 to ACME Corp.",
    })

    assert fire_event.call_count == 3
    def test_mail_service_integration(self):
        config = {'AMQP_URI': 'amqp://*****:*****@localhost:5672/'}
        runner = ServiceRunner(config)
        runner.add_service(PaymentService)
        runner.add_service(MailService)

        payment_container = get_container(runner, PaymentService)
        mail_container = get_container(runner, MailService)

        # turns off timer event
        # restrict_entrypoints(payment_container, *[])

        runner.start()

        with entrypoint_hook(payment_container, 'emit_event') as entrypoint:
            with entrypoint_waiter(mail_container, 'on_payment_received'):
                entrypoint()

        assert True
예제 #27
0
def service_container(patched_db):
    config = {'AMQP_URI': settings.NAMEKO_AMQP_URI}
    runner = ServiceRunner(config)
    runner.add_service(NamekoCollectionService)
    runner.start()

    container = get_container(runner, NamekoCollectionService)
    yield container

    runner.stop()
예제 #28
0
def test_call_id_stack(rabbit_config, predictable_call_ids, runner_factory):
    child_do_called = Mock()

    stack_request = Mock()
    LoggingWorkerContext = get_logging_worker_context(stack_request)

    class Child(object):
        name = 'child'

        @rpc
        def child_do(self):
            child_do_called()
            return 1

    class Parent(object):
        name = "parent"

        child_service = RpcProxy('child')

        @rpc
        def parent_do(self):
            return self.child_service.child_do()

    class Grandparent(object):
        name = "grandparent"

        parent_service = RpcProxy('parent')

        @rpc
        def grandparent_do(self):
            return self.parent_service.parent_do()

    runner = runner_factory(rabbit_config)
    runner.add_service(Child, LoggingWorkerContext)
    runner.add_service(Parent, LoggingWorkerContext)
    runner.add_service(Grandparent, LoggingWorkerContext)
    runner.start()

    container = get_container(runner, Grandparent)
    with entrypoint_hook(container, "grandparent_do") as grandparent_do:
        assert grandparent_do() == 1

    # Check child is called
    child_do_called.assert_called_with()
    assert child_do_called.call_count == 1

    # Check IDs were requested
    assert predictable_call_ids.call_count == 3

    # Check call ID stack persisted over RPC
    stack_request.assert_has_calls([
        call(None),
        call(['grandparent.grandparent_do.0']),
        call(['grandparent.grandparent_do.0', 'parent.parent_do.1']),
    ])
예제 #29
0
def test_call_id_stack(rabbit_config, predictable_call_ids, runner_factory):
    child_do_called = Mock()

    stack_request = Mock()
    LoggingWorkerContext = get_logging_worker_context(stack_request)

    class Child(object):
        name = 'child'

        @rpc
        def child_do(self):
            child_do_called()
            return 1

    class Parent(object):
        name = "parent"

        child_service = RpcProxy('child')

        @rpc
        def parent_do(self):
            return self.child_service.child_do()

    class Grandparent(object):
        name = "grandparent"

        parent_service = RpcProxy('parent')

        @rpc
        def grandparent_do(self):
            return self.parent_service.parent_do()

    runner = runner_factory(rabbit_config)
    runner.add_service(Child, LoggingWorkerContext)
    runner.add_service(Parent, LoggingWorkerContext)
    runner.add_service(Grandparent, LoggingWorkerContext)
    runner.start()

    container = get_container(runner, Grandparent)
    with entrypoint_hook(container, "grandparent_do") as grandparent_do:
        assert grandparent_do() == 1

    # Check child is called
    child_do_called.assert_called_with()
    assert child_do_called.call_count == 1

    # Check IDs were requested
    assert predictable_call_ids.call_count == 3

    # Check call ID stack persisted over RPC
    stack_request.assert_has_calls([
        call(None),
        call(['grandparent.grandparent_do.0']),
        call(['grandparent.grandparent_do.0', 'parent.parent_do.1']),
    ])
예제 #30
0
    def test_mail_service_integration(self):
        config = {'AMQP_URI': 'amqp://*****:*****@localhost:5672/'}
        runner = ServiceRunner(config)
        runner.add_service(PaymentService)
        runner.add_service(MailService)


        payment_container = get_container(runner, PaymentService)
        mail_container = get_container(runner, MailService)

        # turns off timer event
        # restrict_entrypoints(payment_container, *[])

        runner.start()

        with entrypoint_hook(payment_container, 'emit_event') as entrypoint:
            with entrypoint_waiter(mail_container, 'on_payment_received'):
                entrypoint()

        assert True
예제 #31
0
    def test_kwarg_deprecation_warning(self, warnings, service_cls,
                                       container_cls):
        config = {}
        runner = ServiceRunner(config, container_cls=container_cls)
        runner.add_service(service_cls)

        container = get_container(runner, service_cls)
        assert isinstance(container, container_cls)

        # TODO: replace with pytest.warns when eventlet >= 0.19.0 is released
        assert warnings.warn.call_args_list == [call(ANY, DeprecationWarning)]
예제 #32
0
def test_get_unsuccessful(config, runner_factory):
    runner = runner_factory(AccountsService)
    container = get_container(runner, AccountsService)
    storage = replace_dependencies(container, "storage")
    runner.start()

    storage.users.get.side_effect = orm_exc.NoResultFound()

    with entrypoint_hook(container, "get_user") as get_user:
        with pytest.raises(UserDoesNotExist):
            get_user(user_id=123)
def test_raises_if_message_unrecognised(config, db, runner_factory):
    runner = runner_factory(MonitoringService)
    container = get_container(runner, MonitoringService)
    runner.start()

    with entrypoint_hook(
            container,
            "consume_monitoring_stream") as consume_monitoring_stream:
        with pytest.raises(UnrecognizedMonitorName):
            consume_monitoring_stream("123",
                                      {"__MONITOR_NAME": "DONT KNOW MESSAGE"})
예제 #34
0
def test_service_game_deck_integration(runner_factory, rabbit_config):

    # run services in the normal manner
    runner = runner_factory(rabbit_config, GameService, DeckService)
    runner.start()

    # artificially fire the "create" entrypoint on GameService
    container = get_container(runner, GameService)
    with entrypoint_hook(container, "create") as entrypoint:
        # TODO: fix assert, this will only work on first run.
        assert entrypoint("Joe").player_id == 1
예제 #35
0
def test_service_x_y_integration(runner_factory, rabbit_config):

    # run services in the normal manner
    runner = runner_factory(rabbit_config, ServiceX, ServiceY)
    runner.start()

    # artificially fire the "remote_method" entrypoint on ServiceX
    # and verify response
    container = get_container(runner, ServiceX)
    with entrypoint_hook(container, "remote_method") as entrypoint:
        assert entrypoint("value") == "value-x-y"
예제 #36
0
def test_service_integration(runner_factory, rabbit_config):
    config = rabbit_config
    config['REDIS_URIS'] = {'my_redis': 'redis://localhost:6379/0'}
    runner = runner_factory(rabbit_config, Service1, Service2, Service3)

    service3 = get_container(runner, Service3)

    runner.start()

    with entrypoint_hook(service3, 'request_numbers') as request_numbers:
        request_numbers()
예제 #37
0
def test_call_id_stack(
    rabbit_config, predictable_call_ids, runner_factory, stack_logger, tracker
):
    StackLogger = stack_logger

    class Child(object):
        name = 'child'

        stack_logger = StackLogger()

        @rpc
        def method(self):
            return 1

    class Parent(object):
        name = "parent"

        stack_logger = StackLogger()
        child_service = RpcProxy('child')

        @rpc
        def method(self):
            return self.child_service.method()

    class Grandparent(object):
        name = "grandparent"

        stack_logger = StackLogger()
        parent_service = RpcProxy('parent')

        @rpc
        def method(self):
            return self.parent_service.method()

    runner = runner_factory(rabbit_config)
    runner.add_service(Child)
    runner.add_service(Parent)
    runner.add_service(Grandparent)
    runner.start()

    container = get_container(runner, Grandparent)
    with entrypoint_hook(container, "method") as grandparent_method:
        assert grandparent_method() == 1

    # Check IDs were requested
    assert predictable_call_ids.call_count == 3

    # Check call ID stack persisted over RPC
    assert tracker.call_args_list == [
        call(['grandparent.method.0']),
        call(['grandparent.method.0', 'parent.method.1']),
        call(['grandparent.method.0', 'parent.method.1', 'child.method.2']),
    ]
예제 #38
0
    def test_kwarg_deprecation_warning(
        self, warnings, service_cls, container_cls
    ):
        config = {}
        runner = ServiceRunner(config, container_cls=container_cls)
        runner.add_service(service_cls)

        container = get_container(runner, service_cls)
        assert isinstance(container, container_cls)

        # TODO: replace with pytest.warns when eventlet >= 0.19.0 is released
        assert warnings.warn.call_args_list == [call(ANY, DeprecationWarning)]
예제 #39
0
def test_call_id_stack(rabbit_config, predictable_call_ids, runner_factory,
                       stack_logger, tracker):
    StackLogger = stack_logger

    class Child(object):
        name = 'child'

        stack_logger = StackLogger()

        @rpc
        def method(self):
            return 1

    class Parent(object):
        name = "parent"

        stack_logger = StackLogger()
        child_service = RpcProxy('child')

        @rpc
        def method(self):
            return self.child_service.method()

    class Grandparent(object):
        name = "grandparent"

        stack_logger = StackLogger()
        parent_service = RpcProxy('parent')

        @rpc
        def method(self):
            return self.parent_service.method()

    runner = runner_factory(rabbit_config)
    runner.add_service(Child)
    runner.add_service(Parent)
    runner.add_service(Grandparent)
    runner.start()

    container = get_container(runner, Grandparent)
    with entrypoint_hook(container, "method") as grandparent_method:
        assert grandparent_method() == 1

    # Check IDs were requested
    assert predictable_call_ids.call_count == 3

    # Check call ID stack persisted over RPC
    assert tracker.call_args_list == [
        call(['grandparent.method.0']),
        call(['grandparent.method.0', 'parent.method.1']),
        call(['grandparent.method.0', 'parent.method.1', 'child.method.2']),
    ]
예제 #40
0
def test_entrypoint_hook(runner_factory, rabbit_config):

    service_classes = (Service, ServiceA, ServiceB, ServiceC)
    runner = runner_factory(rabbit_config, *service_classes)
    runner.start()

    service_container = get_container(runner, Service)

    event_payload = "msg"
    with entrypoint_hook(service_container, 'handle') as handle:
        with entrypoint_waiter(service_container, 'handle'):
            handle(event_payload)
    handle_event.assert_called_once_with(event_payload)
예제 #41
0
def test_crawler_triggers_webhook(runner_factory, web_container_config):
    """Is crawler_container dispatching to webhook_container?"""
    runner = runner_factory(web_container_config, CrawlerService,
                            WebhookService)
    webhook_container = get_container(runner, WebhookService)
    storage_w = replace_dependencies(webhook_container, 'storage')
    dispatch = event_dispatcher(web_container_config)
    runner.start()
    with entrypoint_waiter(webhook_container, 'send_response'):
        dispatch('http_server', 'url_to_check',
                 ['http://example.org/test_crawling_group',
                  'datagouvfr', None])
    assert storage_w.get_webhooks_for_url.call_count == 1
예제 #42
0
def test_service_integration():
    config = {"AMQP_URI": "amqp://*****:*****@localhost:5672/"}
    runner = ServiceRunner(config)
    runner.add_service(ServiceX)
    runner.add_service(ServiceY)
    runner.start()

    container = get_container(runner, ServiceX)

    with entrypoint_hook(container, "remote_method") as entrypoint:
        assert entrypoint("value") == "value-x-y"

    runner.stop()
예제 #43
0
def test_entrypoint_hook(runner_factory, rabbit_config):

    service_classes = (Service, ServiceA, ServiceB, ServiceC)
    runner = runner_factory(rabbit_config, *service_classes)
    runner.start()

    service_container = get_container(runner, Service)

    event_payload = "msg"
    with entrypoint_hook(service_container, "handle") as handle:
        with entrypoint_waiter(service_container, "handle"):
            handle(event_payload)
    handle_event.assert_called_once_with(event_payload)
예제 #44
0
def test_service_integration():
    config = {'AMQP_URI': 'amqp://*****:*****@localhost:5672/'}
    runner = ServiceRunner(config)
    runner.add_service(ServiceX)
    runner.add_service(ServiceY)
    runner.start()

    container = get_container(runner, ServiceX)

    with entrypoint_hook(container, "remote_method") as entrypoint:
        assert entrypoint("value") == "value-x-y"

    runner.stop()
예제 #45
0
def test_entrypoint_hook_with_return(runner_factory, rabbit_config):

    service_classes = (Service, ServiceA, ServiceB, ServiceC)
    runner = runner_factory(rabbit_config, *service_classes)
    runner.start()

    service_container = get_container(runner, Service)

    with entrypoint_hook(service_container, "working") as working:
        assert working("value") == "value-a-b-c"

    with entrypoint_hook(service_container, "broken") as broken:
        with pytest.raises(ExampleError):
            broken("value")
예제 #46
0
    def test_kwarg_deprecation_warning(
        self, warnings, service_cls, worker_ctx_cls
    ):
        config = {}
        runner = ServiceRunner(config)
        runner.add_service(service_cls, worker_ctx_cls=worker_ctx_cls)

        container = get_container(runner, service_cls)
        entrypoint = list(container.entrypoints)[0]

        worker_ctx = container.spawn_worker(entrypoint, (), {})
        assert isinstance(worker_ctx, worker_ctx_cls)

        # TODO: replace with pytest.warns when eventlet >= 0.19.0 is released
        assert warnings.warn.call_args_list == [call(ANY, DeprecationWarning)]
예제 #47
0
def test_runner_catches_managed_thread_errors(runner_factory, rabbit_config):

    class Broken(Exception):
        pass

    def raises():
        raise Broken('error')

    runner = runner_factory(rabbit_config, Service)

    container = get_container(runner, Service)
    container.spawn_managed_thread(raises)

    with pytest.raises(Broken):
        runner.wait()
예제 #48
0
def test_service_x_y_integration():

    # run services in the normal manner
    config = {'AMQP_URI': 'amqp://*****:*****@localhost:5672/'}
    runner = ServiceRunner(config)
    runner.add_service(ServiceX)
    runner.add_service(ServiceY)
    runner.start()

    # artificially fire the "remote_method" entrypoint on ServiceX
    # and verify response
    container = get_container(runner, ServiceX)
    with entrypoint_hook(container, "remote_method") as entrypoint:
        assert entrypoint("value") == "value-x-y"

    runner.stop()
예제 #49
0
def test_call_id_over_events(rabbit_config, predictable_call_ids,
                             runner_factory):
    one_called = Mock()
    two_called = Mock()

    stack_request = Mock()
    LoggingWorkerContext = get_logging_worker_context(stack_request)

    class HelloEvent(NamekoEvent):
        type = "hello"

    class EventListeningServiceOne(object):
        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            one_called()

    class EventListeningServiceTwo(object):
        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            two_called()

    class EventRaisingService(object):
        name = "event_raiser"
        dispatch = event_dispatcher()

        @rpc
        def say_hello(self):
            self.dispatch(HelloEvent(self.name))

    runner = runner_factory(rabbit_config)
    runner.add_service(EventListeningServiceOne, LoggingWorkerContext)
    runner.add_service(EventListeningServiceTwo, LoggingWorkerContext)
    runner.add_service(EventRaisingService, LoggingWorkerContext)
    runner.start()

    container = get_container(runner, EventRaisingService)
    with entrypoint_hook(container, "say_hello") as say_hello:
        say_hello()

    with wait_for_call(5, one_called), wait_for_call(5, two_called):

        assert predictable_call_ids.call_count == 3
        stack_request.assert_has_calls([
            call(None),
            call(['event_raiser.say_hello.0']),
            call(['event_raiser.say_hello.0']),
        ])
예제 #50
0
def test_runner_catches_container_errors(runner_factory, rabbit_config):

    runner = runner_factory(rabbit_config, ExampleService)
    runner.start()

    container = get_container(runner, ExampleService)

    rpc_consumer = get_extension(container, RpcConsumer)
    with patch.object(
            rpc_consumer, 'handle_result', autospec=True) as handle_result:
        exception = Exception("error")
        handle_result.side_effect = exception

        # use a standalone rpc proxy to call exampleservice.task()
        with ServiceRpcProxy("exampleservice", rabbit_config) as proxy:
            # proxy.task() will hang forever because it generates an error
            # in the remote container (so never receives a response).
            proxy.task.call_async()

        # verify that the error bubbles up to runner.wait()
        with pytest.raises(Exception) as exc_info:
            runner.wait()
        assert exc_info.value == exception
예제 #51
0
def test_call_id_over_events(
    rabbit_config, predictable_call_ids, runner_factory, stack_logger, tracker
):
    StackLogger = stack_logger

    one_called = Mock()
    two_called = Mock()

    class EventListeningServiceOne(object):
        name = "listener_one"

        stack_logger = StackLogger()

        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            one_called()

    class EventListeningServiceTwo(object):
        name = "listener_two"

        stack_logger = StackLogger()

        @event_handler('event_raiser', 'hello')
        def hello(self, name):
            two_called()

    class EventRaisingService(object):
        name = "event_raiser"
        dispatch = EventDispatcher()

        stack_logger = StackLogger()

        @rpc
        def say_hello(self):
            self.dispatch('hello', self.name)

    runner = runner_factory(rabbit_config)
    runner.add_service(EventListeningServiceOne)
    runner.add_service(EventListeningServiceTwo)
    runner.add_service(EventRaisingService)
    runner.start()

    container = get_container(runner, EventRaisingService)
    listener1 = get_container(runner, EventListeningServiceOne)
    listener2 = get_container(runner, EventListeningServiceTwo)
    with entrypoint_hook(container, "say_hello") as say_hello:
        waiter1 = entrypoint_waiter(listener1, 'hello')
        waiter2 = entrypoint_waiter(listener2, 'hello')
        with waiter1, waiter2:
            say_hello()

    assert predictable_call_ids.call_count == 3

    # order of event handlers and dependencies is non-deterministic,
    # so there are four permutations of valid call stacks
    possible_call_lists = (
        [
            call(['event_raiser.say_hello.0']),
            call(['event_raiser.say_hello.0', 'listener_one.hello.1']),
            call(['event_raiser.say_hello.0', 'listener_two.hello.2']),
        ],
        [
            call(['event_raiser.say_hello.0']),
            call(['event_raiser.say_hello.0', 'listener_one.hello.2']),
            call(['event_raiser.say_hello.0', 'listener_two.hello.1']),
        ],
        [
            call(['event_raiser.say_hello.0']),
            call(['event_raiser.say_hello.0', 'listener_two.hello.1']),
            call(['event_raiser.say_hello.0', 'listener_one.hello.2']),
        ],
        [
            call(['event_raiser.say_hello.0']),
            call(['event_raiser.say_hello.0', 'listener_two.hello.2']),
            call(['event_raiser.say_hello.0', 'listener_one.hello.1']),
        ]
    )
    assert tracker.call_args_list in possible_call_lists
예제 #52
0
from nameko.runners import ServiceRunner
from nameko.testing.utils import get_container

class ServiceA(object):
    name = "service_a"

class ServiceB(object):
    name = "service_b"

# create a runner for ServiceA and ServiceB
runner = ServiceRunner(config={})
runner.add_service(ServiceA)
runner.add_service(ServiceB)

# ``get_container`` will return the container for a particular service
container_a = get_container(runner, ServiceA)

# start both services
runner.start()

# stop both services
runner.stop()