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)
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())
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)))
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())