Ejemplo n.º 1
0
class ActorManagerTimerTests(unittest.TestCase):
    def setUp(self):
        self._serializer = DefaultJSONSerializer()

        self._fake_client = FakeDaprActorClient

    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.invoke_method',
        new=_async_mock(return_value=b'"expected_response"'))
    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.register_timer',
        new=_async_mock())
    def test_fire_timer_success(self):
        test_actor_id = ActorId('testid')
        test_type_info = ActorTypeInformation.create(FakeSimpleTimerActor)
        ctx = ActorRuntimeContext(
            test_type_info, self._serializer,
            self._serializer, self._fake_client)
        manager = ActorManager(ctx)

        _run(manager.activate_actor(test_actor_id))
        actor = manager._active_actors.get(test_actor_id.id, None)

        # Setup timer
        _run(actor.register_timer(
            'test_timer', actor.timer_callback,
            "timer call", timedelta(seconds=1), timedelta(seconds=1), timedelta(seconds=1)))

        # Fire timer
        _run(manager.fire_timer(
            test_actor_id,
            'test_timer',
            '{ "callback": "timer_callback", "data": "timer call" }'.encode('UTF8')))

        self.assertTrue(actor.timer_called)
Ejemplo n.º 2
0
class ActorProxyTests(unittest.TestCase):
    def setUp(self):
        # Create mock client
        self._fake_client = FakeDaprActorClient
        self._fake_factory = FakeActoryProxyFactory(self._fake_client)
        self._proxy = ActorProxy.create(
            FakeMultiInterfacesActor.__name__,
            ActorId('fake-id'),
            FakeActorCls2Interface,
            self._fake_factory)

    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.invoke_method',
        new=_async_mock(return_value=b'"expected_response"'))
    def test_invoke(self):
        response = _run(self._proxy.invoke_method('ActionMethod', b'arg0'))
        self.assertEqual(b'"expected_response"', response)
        self._fake_client.invoke_method.mock.assert_called_once_with(
            FakeMultiInterfacesActor.__name__, 'fake-id', 'ActionMethod', b'arg0')

    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.invoke_method',
        new=_async_mock(return_value=b'"expected_response"'))
    def test_invoke_no_arg(self):
        response = _run(self._proxy.invoke_method('ActionMethodWithoutArg'))
        self.assertEqual(b'"expected_response"', response)
        self._fake_client.invoke_method.mock.assert_called_once_with(
            FakeMultiInterfacesActor.__name__, 'fake-id', 'ActionMethodWithoutArg', None)

    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.invoke_method',
        new=_async_mock(return_value=b'"expected_response"'))
    def test_invoke_with_static_typing(self):
        response = _run(self._proxy.ActionMethod(b'arg0'))
        self.assertEqual('expected_response', response)
        self._fake_client.invoke_method.mock.assert_called_once_with(
            FakeMultiInterfacesActor.__name__, 'fake-id', 'ActionMethod', b'arg0')

    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.invoke_method',
        new=_async_mock(return_value=b'"expected_response"'))
    def test_invoke_with_static_typing_no_arg(self):
        response = _run(self._proxy.ActionMethodWithoutArg())
        self.assertEqual('expected_response', response)
        self._fake_client.invoke_method.mock.assert_called_once_with(
            FakeMultiInterfacesActor.__name__, 'fake-id', 'ActionMethodWithoutArg', None)

    def test_raise_exception_non_existing_method(self):
        with self.assertRaises(AttributeError):
            _run(self._proxy.non_existing())
Ejemplo n.º 3
0
class ActorTests(unittest.TestCase):
    def setUp(self):
        ActorRuntime._actor_managers = {}
        ActorRuntime.set_actor_config(ActorRuntimeConfig())
        self._serializer = DefaultJSONSerializer()
        _run(ActorRuntime.register_actor(FakeSimpleActor))
        _run(ActorRuntime.register_actor(FakeMultiInterfacesActor))

    def test_get_registered_actor_types(self):
        actor_types = ActorRuntime.get_registered_actor_types()
        self.assertTrue(actor_types.index('FakeSimpleActor') >= 0)
        self.assertTrue(actor_types.index(FakeMultiInterfacesActor.__name__) >= 0)

    def test_actor_config(self):
        config = ActorRuntime.get_actor_config()

        self.assertTrue(config._drain_rebalanced_actors)
        self.assertEqual(timedelta(hours=1), config._actor_idle_timeout)
        self.assertEqual(timedelta(seconds=30), config._actor_scan_interval)
        self.assertEqual(timedelta(minutes=1), config._drain_ongoing_call_timeout)
        self.assertEqual(2, len(config._entities))

        # apply new config
        new_config = ActorRuntimeConfig(
            timedelta(hours=3), timedelta(seconds=10), timedelta(minutes=1), False)

        ActorRuntime.set_actor_config(new_config)
        config = ActorRuntime.get_actor_config()

        self.assertFalse(config._drain_rebalanced_actors)
        self.assertEqual(timedelta(hours=3), config._actor_idle_timeout)
        self.assertEqual(timedelta(seconds=10), config._actor_scan_interval)
        self.assertEqual(timedelta(minutes=1), config._drain_ongoing_call_timeout)
        self.assertEqual(2, len(config._entities))

    def test_entities_update(self):
        # Clean up managers
        ActorRuntime._actor_managers = {}
        ActorRuntime.set_actor_config(ActorRuntimeConfig())

        config = ActorRuntime.get_actor_config()
        with self.assertRaises(ValueError):
            config._entities.index(FakeSimpleActor.__name__)

        _run(ActorRuntime.register_actor(FakeSimpleActor))
        config = ActorRuntime.get_actor_config()
        self.assertTrue(config._entities.index(FakeSimpleActor.__name__) >= 0)

    def test_dispatch(self):
        _run(ActorRuntime.register_actor(FakeMultiInterfacesActor))

        request_body = {
            "message": "hello dapr",
        }

        test_request_body = self._serializer.serialize(request_body)
        response = _run(ActorRuntime.dispatch(
            FakeMultiInterfacesActor.__name__, 'test-id',
            "ActionMethod", test_request_body))

        self.assertEqual(b'"hello dapr"', response)

        _run(ActorRuntime.deactivate(FakeMultiInterfacesActor.__name__, 'test-id'))

        # Ensure test-id is deactivated
        with self.assertRaises(ValueError):
            _run(ActorRuntime.deactivate(FakeMultiInterfacesActor.__name__, 'test-id'))

    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.register_reminder',
        new=_async_mock(return_value=b'"ok"'))
    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.unregister_reminder',
        new=_async_mock(return_value=b'"ok"'))
    def test_register_reminder(self):

        test_actor_id = ActorId('test_id')
        test_type_info = ActorTypeInformation.create(FakeSimpleReminderActor)
        test_client = FakeDaprActorClient
        ctx = ActorRuntimeContext(
            test_type_info, self._serializer,
            self._serializer, test_client)
        test_actor = FakeSimpleReminderActor(ctx, test_actor_id)

        # register reminder
        _run(test_actor.register_reminder(
            'test_reminder', b'reminder_message',
            timedelta(seconds=1), timedelta(seconds=1)))
        test_client.register_reminder.mock.assert_called_once()
        test_client.register_reminder.mock.assert_called_with(
            'FakeSimpleReminderActor', 'test_id',
            'test_reminder',
            b'{"name":"test_reminder","dueTime":"0h0m1s","period":"0h0m1s","data":"cmVtaW5kZXJfbWVzc2FnZQ=="}')  # noqa E501

        # unregister reminder
        _run(test_actor.unregister_reminder('test_reminder'))
        test_client.unregister_reminder.mock.assert_called_once()
        test_client.unregister_reminder.mock.assert_called_with(
            'FakeSimpleReminderActor', 'test_id', 'test_reminder')

    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.register_timer',
        new=_async_mock(return_value=b'"ok"'))
    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.unregister_timer',
        new=_async_mock(return_value=b'"ok"'))
    def test_register_timer(self):

        test_actor_id = ActorId('test_id')
        test_type_info = ActorTypeInformation.create(FakeSimpleTimerActor)
        test_client = FakeDaprActorClient
        ctx = ActorRuntimeContext(
            test_type_info, self._serializer,
            self._serializer, test_client)
        test_actor = FakeSimpleTimerActor(ctx, test_actor_id)

        # register timer
        _run(test_actor.register_timer(
            'test_timer', test_actor.timer_callback,
            "mydata", timedelta(seconds=1), timedelta(seconds=2)))
        test_client.register_timer.mock.assert_called_once()
        test_client.register_timer.mock.assert_called_with(
            'FakeSimpleTimerActor', 'test_id', 'test_timer',
            b'{"callback":"timer_callback","data":"mydata","dueTime":"0h0m1s","period":"0h0m2s"}')

        # unregister timer
        _run(test_actor.unregister_timer('test_timer'))
        test_client.unregister_timer.mock.assert_called_once()
        test_client.unregister_timer.mock.assert_called_with(
            'FakeSimpleTimerActor', 'test_id', 'test_timer')

        # register timer without timer name
        _run(test_actor.register_timer(
            None, test_actor.timer_callback,
            "timer call", timedelta(seconds=1), timedelta(seconds=1)))
Ejemplo n.º 4
0
class ActorStateManagerTests(unittest.TestCase):
    def setUp(self):
        # Create mock client
        self._fake_client = FakeDaprActorClient

        self._test_actor_id = ActorId('1')
        self._test_type_info = ActorTypeInformation.create(FakeSimpleActor)
        self._serializer = DefaultJSONSerializer()
        self._runtime_ctx = ActorRuntimeContext(self._test_type_info,
                                                self._serializer,
                                                self._serializer,
                                                self._fake_client)
        self._fake_actor = FakeSimpleActor(self._runtime_ctx,
                                           self._test_actor_id)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=base64.b64encode(b'"value1"')))
    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.save_state_transactionally',
        new=_async_mock())
    def test_add_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()

        # Add first 'state1'
        added = _run(state_manager.try_add_state('state1', 'value1'))
        self.assertTrue(added)

        state = state_change_tracker['state1']
        self.assertEqual('value1', state.value)
        self.assertEqual(StateChangeKind.add, state.change_kind)

        # Add 'state1' again
        added = _run(state_manager.try_add_state('state1', 'value1'))
        self.assertFalse(added)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_get_state_for_no_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        has_value, val = _run(state_manager.try_get_state('state1'))
        self.assertFalse(has_value)
        self.assertIsNone(val)

        # Test if the test value is empty string
        self._fake_client.get_state.return_value = ''
        has_value, val = _run(state_manager.try_get_state('state1'))
        self.assertFalse(has_value)
        self.assertIsNone(val)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_get_state_for_existing_value(self):

        state_manager = ActorStateManager(self._fake_actor)
        has_value, val = _run(state_manager.try_get_state('state1'))
        self.assertTrue(has_value)
        self.assertEqual("value1", val)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_get_state_for_removed_value(self):

        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        removed = _run(state_manager.try_remove_state('state1'))
        self.assertTrue(removed)

        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.remove, state.change_kind)

        has_value, val = _run(state_manager.try_get_state('state1'))
        self.assertFalse(has_value)
        self.assertIsNone(val)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_set_state_for_new_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        _run(state_manager.set_state('state1', 'value1'))

        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.add, state.change_kind)
        self.assertEqual('value1', state.value)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_set_state_for_existing_state_only_in_mem(self):

        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        _run(state_manager.set_state('state1', 'value1'))

        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.add, state.change_kind)
        self.assertEqual('value1', state.value)

        _run(state_manager.set_state('state1', 'value2'))
        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.add, state.change_kind)
        self.assertEqual('value2', state.value)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_set_state_for_existing_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        _run(state_manager.set_state('state1', 'value2'))
        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.update, state.change_kind)
        self.assertEqual('value2', state.value)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_remove_state_for_non_existing_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        removed = _run(state_manager.try_remove_state('state1'))
        self.assertFalse(removed)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_remove_state_for_existing_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        removed = _run(state_manager.try_remove_state('state1'))
        self.assertTrue(removed)

        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.remove, state.change_kind)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_remove_state_for_existing_state_in_mem(self):

        state_manager = ActorStateManager(self._fake_actor)
        _run(state_manager.set_state('state1', 'value1'))
        removed = _run(state_manager.try_remove_state('state1'))
        self.assertTrue(removed)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_remove_state_twice_for_existing_state_in_mem(self):

        state_manager = ActorStateManager(self._fake_actor)
        _run(state_manager.set_state('state1', 'value1'))
        removed = _run(state_manager.try_remove_state('state1'))
        self.assertTrue(removed)
        removed = _run(state_manager.try_remove_state('state1'))
        self.assertFalse(removed)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_contains_state_for_removed_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        _run(state_manager.set_state('state1', 'value1'))

        exist = _run(state_manager.contains_state('state1'))
        self.assertTrue(exist)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_contains_state_for_existing_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        exist = _run(state_manager.contains_state('state1'))
        self.assertTrue(exist)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_get_or_add_state_for_existing_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        val = _run(state_manager.get_or_add_state('state1', 'value2'))
        self.assertEqual('value1', val)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_get_or_add_state_for_non_existing_state(self):
        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        val = _run(state_manager.get_or_add_state('state1', 'value2'))

        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.add, state.change_kind)
        self.assertEqual('value2', val)

        self._fake_client.get_state.mock.assert_called_once_with(
            self._test_type_info._name, self._test_actor_id.id, 'state1')

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_get_or_add_state_for_removed_state(self):

        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        _run(state_manager.remove_state('state1'))
        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.remove, state.change_kind)

        val = _run(state_manager.get_or_add_state('state1', 'value2'))
        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.update, state.change_kind)
        self.assertEqual('value2', val)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_add_or_update_state_for_new_state(self):
        """adds state if state does not exist."""
        def test_update_value(name, value):
            return f'{name}-{value}'

        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        val = _run(
            state_manager.add_or_update_state('state1', 'value1',
                                              test_update_value))
        self.assertEqual('value1', val)
        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.add, state.change_kind)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_add_or_update_state_for_state_in_storage(self):
        """updates state value using update_value_factory if state is
        in the storage."""
        def test_update_value(name, value):
            return f'{name}-{value}'

        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        val = _run(
            state_manager.add_or_update_state('state1', 'value1',
                                              test_update_value))
        self.assertEqual('state1-value1', val)
        state = state_change_tracker['state1']
        self.assertEqual(StateChangeKind.update, state.change_kind)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_add_or_update_state_for_removed_state(self):
        """add state value if state was removed."""
        def test_update_value(name, value):
            return f'{name}-{value}'

        state_manager = ActorStateManager(self._fake_actor)
        _run(state_manager.remove_state('state1'))

        val = _run(
            state_manager.add_or_update_state('state1', 'value1',
                                              test_update_value))
        self.assertEqual('value1', val)

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value1"'))
    def test_add_or_update_state_for_none_state_key(self):
        """update state value for StateChangeKind.none state """
        def test_update_value(name, value):
            return f'{name}-{value}'

        state_manager = ActorStateManager(self._fake_actor)
        has_value, val = _run(state_manager.try_get_state('state1'))
        self.assertTrue(has_value)
        self.assertEqual('value1', val)

        val = _run(
            state_manager.add_or_update_state('state1', 'value1',
                                              test_update_value))
        self.assertEqual('state1-value1', val)

    def test_add_or_update_state_without_update_value_factory(self):
        """tries to add or update state without update_value_factory """
        state_manager = ActorStateManager(self._fake_actor)
        with self.assertRaises(AttributeError):
            _run(state_manager.add_or_update_state('state1', 'value1', None))

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock())
    def test_get_state_names(self):
        state_manager = ActorStateManager(self._fake_actor)
        _run(state_manager.set_state('state1', 'value1'))
        _run(state_manager.set_state('state2', 'value2'))
        _run(state_manager.set_state('state3', 'value3'))
        names = _run(state_manager.get_state_names())
        self.assertEqual(['state1', 'state2', 'state3'], names)

        self._fake_client.get_state.mock.assert_any_call(
            self._test_type_info._name, self._test_actor_id.id, 'state1')
        self._fake_client.get_state.mock.assert_any_call(
            self._test_type_info._name, self._test_actor_id.id, 'state2')
        self._fake_client.get_state.mock.assert_any_call(
            self._test_type_info._name, self._test_actor_id.id, 'state3')

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value0"'))
    def test_clear_cache(self):
        state_manager = ActorStateManager(self._fake_actor)
        state_change_tracker = state_manager._get_contextual_state_tracker()
        _run(state_manager.set_state('state1', 'value1'))
        _run(state_manager.set_state('state2', 'value2'))
        _run(state_manager.set_state('state3', 'value3'))
        _run(state_manager.clear_cache())

        self.assertEqual(0, len(state_change_tracker))

    @mock.patch('tests.actor.fake_client.FakeDaprActorClient.get_state',
                new=_async_mock(return_value=b'"value3"'))
    @mock.patch(
        'tests.actor.fake_client.FakeDaprActorClient.save_state_transactionally',
        new=_async_mock())
    def test_save_state(self):
        state_manager = ActorStateManager(self._fake_actor)
        # set states which are StateChangeKind.add
        _run(state_manager.set_state('state1', 'value1'))
        _run(state_manager.set_state('state2', 'value2'))

        has_value, val = _run(state_manager.try_get_state('state3'))
        self.assertTrue(has_value)
        self.assertEqual("value3", val)
        # set state which is StateChangeKind.remove
        _run(state_manager.remove_state('state4'))
        # set state which is StateChangeKind.update
        _run(state_manager.set_state('state5', 'value5'))
        expected = b'[{"operation":"upsert","request":{"key":"state1","value":"value1"}},{"operation":"upsert","request":{"key":"state2","value":"value2"}},{"operation":"delete","request":{"key":"state4"}},{"operation":"upsert","request":{"key":"state5","value":"value5"}}]'  # noqa: E501

        # Save the state
        def mock_save_state(actor_type, actor_id, data):
            self.assertEqual(expected, data)

        self._fake_client.save_state_transactionally.mock = mock_save_state
        _run(state_manager.save_state())