from unittest import TestCase from unittest.mock import MagicMock, patch from openslides.core.models import Projector from openslides.utils import collection class TestCacheKeys(TestCase): def test_get_collection_id_from_cache_key(self): """ Test that get_collection_id_from_cache_key works together with get_single_element_cache_key. """ element = ('some/testkey', 42) self.assertEqual( element, collection.get_collection_id_from_cache_key( collection.get_single_element_cache_key(*element))) def test_get_collection_id_from_cache_key_for_strings(self): """ Test get_collection_id_from_cache_key for strings """ element = ('some/testkey', 'my_config_value') self.assertEqual( element, collection.get_collection_id_from_cache_key( collection.get_single_element_cache_key(*element))) def test_get_single_element_cache_key_prefix(self): """ Tests that the cache prefix is realy a prefix. """ element = ('some/testkey', 42) cache_key = collection.get_single_element_cache_key(*element) prefix = collection.get_single_element_cache_key_prefix(element[0]) self.assertTrue(cache_key.startswith(prefix)) def test_prefix_different_then_list(self): """ Test that the return value of get_single_element_cache_key_prefix is something different then get_element_list_cache_key. """ collection_string = 'some/testkey' prefix = collection.get_single_element_cache_key_prefix(collection_string) list_cache_key = collection.get_element_list_cache_key(collection_string) self.assertNotEqual(prefix, list_cache_key) class TestGetModelFromCollectionString(TestCase): def test_known_app(self): projector_model = collection.get_model_from_collection_string('core/projector') self.assertEqual(projector_model, Projector) def test_unknown_app(self): with self.assertRaises(ValueError): collection.get_model_from_collection_string('invalid/model') class TestCollectionElement(TestCase): def test_from_values(self): with patch.object(collection.CollectionElement, 'get_full_data'): collection_element = collection.CollectionElement.from_values('testmodule/model', 42) self.assertEqual(collection_element.collection_string, 'testmodule/model') self.assertEqual(collection_element.id, 42) @patch('openslides.utils.collection.Collection') @patch('openslides.utils.collection.cache') def test_from_values_deleted(self, mock_cache, mock_collection): """ Tests that when createing a CollectionElement with deleted=True the element is deleted from the cache. """ collection_element = collection.CollectionElement.from_values('testmodule/model', 42, deleted=True) self.assertTrue(collection_element.is_deleted()) mock_cache.delete.assert_called_with('testmodule/model:42') mock_collection.assert_called_with('testmodule/model') mock_collection().delete_id_from_cache.assert_called_with(42) def test_as_channel_message(self): with patch.object(collection.CollectionElement, 'get_full_data'): collection_element = collection.CollectionElement.from_values('testmodule/model', 42) self.assertEqual( collection_element.as_channels_message(), {'collection_string': 'testmodule/model', 'id': 42, 'deleted': False}) def test_channel_message(self): """ Test that CollectionElement.from_values() works together with collection_element.as_channels_message(). """ collection_element = collection.CollectionElement.from_values( 'testmodule/model', 42, full_data={'data': 'value'}, information={'some': 'information'}) created_collection_element = collection.CollectionElement.from_values( **collection_element.as_channels_message()) self.assertEqual( collection_element, created_collection_element) self.assertEqual(created_collection_element.full_data, {'data': 'value'}) self.assertEqual(created_collection_element.information, {'some': 'information'}) def test_as_autoupdate_for_user(self): with patch.object(collection.CollectionElement, 'get_full_data'): collection_element = collection.CollectionElement.from_values('testmodule/model', 42) fake_user = MagicMock() collection_element.get_access_permissions = MagicMock() collection_element.get_access_permissions().get_restricted_data.return_value = 'restricted_data' collection_element.get_full_data = MagicMock() self.assertEqual( collection_element.as_autoupdate_for_user(fake_user), {'collection': 'testmodule/model', 'id': 42, 'action': 'changed', 'data': 'restricted_data'}) collection_element.get_full_data.assert_not_called() def test_as_autoupdate_for_user_no_permission(self): with patch.object(collection.CollectionElement, 'get_full_data'): collection_element = collection.CollectionElement.from_values('testmodule/model', 42) fake_user = MagicMock() collection_element.get_access_permissions = MagicMock() collection_element.get_access_permissions().get_restricted_data.return_value = None collection_element.get_full_data = MagicMock() self.assertEqual( collection_element.as_autoupdate_for_user(fake_user), {'collection': 'testmodule/model', 'id': 42, 'action': 'deleted'}) collection_element.get_full_data.assert_not_called() def test_as_autoupdate_for_user_deleted(self): collection_element = collection.CollectionElement.from_values('testmodule/model', 42, deleted=True) fake_user = MagicMock() self.assertEqual( collection_element.as_autoupdate_for_user(fake_user), {'collection': 'testmodule/model', 'id': 42, 'action': 'deleted'}) def test_get_instance_deleted(self): collection_element = collection.CollectionElement.from_values('testmodule/model', 42, deleted=True) with self.assertRaises(RuntimeError): collection_element.get_instance() @patch('openslides.core.config.config') def test_get_instance_config_str(self, mock_config): mock_config.get_collection_string.return_value = 'core/config' mock_config.__getitem__.return_value = 'config_value' collection_element = collection.CollectionElement.from_values('core/config', 'my_config_value') instance = collection_element.get_instance() self.assertEqual( instance, {'key': 'my_config_value', 'value': 'config_value'}) def test_get_instance(self): with patch.object(collection.CollectionElement, 'get_full_data'): collection_element = collection.CollectionElement.from_values('testmodule/model', 42) collection_element.get_model = MagicMock() collection_element.get_instance() collection_element.get_model().objects.get_full_queryset().get.assert_called_once_with(pk=42) @patch('openslides.utils.collection.cache') def test_get_full_data_already_loaded(self, mock_cache): """ Test that the cache and the self.get_instance() is not hit, when the instance is already loaded. """ with patch.object(collection.CollectionElement, 'get_full_data'): collection_element = collection.CollectionElement.from_values('testmodule/model', 42) collection_element.full_data = 'my_full_data' collection_element.get_instance = MagicMock() collection_element.get_full_data() mock_cache.get.assert_not_called() collection_element.get_instance.assert_not_called() @patch('openslides.utils.collection.cache') def test_get_full_data_from_cache(self, mock_cache): """ Test that the value from the cache is used not get_instance is not called. """ with patch.object(collection.CollectionElement, 'get_full_data'): collection_element = collection.CollectionElement.from_values('testmodule/model', 42) collection_element.get_instance = MagicMock() mock_cache.get.return_value = 'cache_value' instance = collection_element.get_full_data() self.assertEqual(instance, 'cache_value') mock_cache.get.assert_called_once_with('testmodule/model:42') collection_element.get_instance.assert_not_called @patch('openslides.utils.collection.Collection') @patch('openslides.utils.collection.cache') def test_get_full_data_from_get_instance(self, mock_cache, mock_Collection): """ Test that the value from get_instance is used and saved to the cache """ with patch.object(collection.CollectionElement, 'get_full_data'): collection_element = collection.CollectionElement.from_values('testmodule/model', 42) collection_element.get_instance = MagicMock() collection_element.get_access_permissions = MagicMock() collection_element.get_access_permissions().get_full_data.return_value = 'get_instance_value' mock_cache.get.return_value = None instance = collection_element.get_full_data() self.assertEqual(instance, 'get_instance_value') mock_cache.get.assert_called_once_with('testmodule/model:42') collection_element.get_instance.assert_called_once_with() mock_cache.set.assert_called_once_with('testmodule/model:42', 'get_instance_value') mock_Collection.assert_called_once_with('testmodule/model') mock_Collection().add_id_to_cache.assert_called_once_with(42) @patch.object(collection.CollectionElement, 'get_full_data') def test_equal(self, mock_get_full_data): self.assertEqual( collection.CollectionElement.from_values('testmodule/model', 1), collection.CollectionElement.from_values('testmodule/model', 1)) self.assertEqual( collection.CollectionElement.from_values('testmodule/model', 1), collection.CollectionElement.from_values('testmodule/model', 1, deleted=True)) self.assertNotEqual( collection.CollectionElement.from_values('testmodule/model', 1), collection.CollectionElement.from_values('testmodule/model', 2)) self.assertNotEqual( collection.CollectionElement.from_values('testmodule/model', 1), collection.CollectionElement.from_values('testmodule/other_model', 1)) @patch.object(collection.CollectionElement, 'get_full_data') def test_config_cache_key(self, mock_get_full_data): """ Test that collection elements for config values do always use the config key as cache key. """ fake_config_instance = MagicMock() fake_config_instance.get_collection_string.return_value = 'core/config' fake_config_instance.key = 'test_config_key' self.assertEqual( collection.CollectionElement.from_values('core/config', 'test_config_key').get_cache_key(), 'core/config:test_config_key') self.assertEqual( collection.CollectionElement.from_instance(fake_config_instance).get_cache_key(), 'core/config:test_config_key') class TestcollectionElementList(TestCase): @patch.object(collection.CollectionElement, 'get_full_data') def test_channel_message(self, mock_get_full_data): """ Test that a channel message from three collection elements can crate the same collection element list. """ collection_elements = collection.CollectionElementList(( collection.CollectionElement.from_values('testmodule/model', 1), collection.CollectionElement.from_values('testmodule/model', 2), collection.CollectionElement.from_values('testmodule/model2', 1))) self.assertEqual( collection_elements, collection.CollectionElementList.from_channels_message(collection_elements.as_channels_message())) @patch.object(collection.CollectionElement, 'get_full_data') def test_as_autoupdate_for_user(self, mock_get_full_data): """ Test that as_autoupdate_for_user is a list of as_autoupdate_for_user for each individual element in the list. """ fake_user = MagicMock() collection_elements = collection.CollectionElementList(( collection.CollectionElement.from_values('testmodule/model', 1), collection.CollectionElement.from_values('testmodule/model', 2), collection.CollectionElement.from_values('testmodule/model2', 1))) with patch.object(collection.CollectionElement, 'as_autoupdate_for_user', return_value='for_user'): value = collection_elements.as_autoupdate_for_user(fake_user) self.assertEqual(value, ['for_user'] * 3) class TestCollection(TestCase): @patch('openslides.utils.collection.CollectionElement') @patch('openslides.utils.collection.cache') def test_element_generator(self, mock_cache, mock_CollectionElement): """ Test with the following scenario: The collection has three elements. Two are in the cache and one is not. """ test_collection = collection.Collection('testmodule/model') test_collection.get_all_ids = MagicMock(return_value=set([1, 2, 3])) test_collection.get_model = MagicMock() test_collection.get_model().objects.get_full_queryset().filter.return_value = ['my_instance'] mock_cache.get_many.return_value = { 'testmodule/model:1': 'element1', 'testmodule/model:2': 'element2'} list(test_collection.element_generator()) mock_cache.get_many.assert_called_once_with( ['testmodule/model:1', 'testmodule/model:2', 'testmodule/model:3']) test_collection.get_model().objects.get_full_queryset().filter.assert_called_once_with(pk__in={3}) self.assertEqual(mock_CollectionElement.from_values.call_count, 2) self.assertEqual(mock_CollectionElement.from_instance.call_count, 1) def test_raw_cache_key(self): test_collection = collection.Collection('testmodule/model') self.assertEqual(test_collection.get_cache_key(raw=True), ':1:testmodule/model')