# -*- coding: utf-8 -*- """ Tests of ConfigurationModel """ import ddt from django.contrib.auth.models import User from django.db import models from django.test import TestCase from freezegun import freeze_time from mock import patch from config_models.models import ConfigurationModel class ExampleConfig(ConfigurationModel): """ Test model for testing ``ConfigurationModels``. """ cache_timeout = 300 string_field = models.TextField() int_field = models.IntegerField(default=10) @patch('config_models.models.cache') class ConfigurationModelTests(TestCase): """ Tests of ConfigurationModel """ def setUp(self): super(ConfigurationModelTests, self).setUp() self.user = User() self.user.save() def test_cache_deleted_on_save(self, mock_cache): ExampleConfig(changed_by=self.user).save() mock_cache.delete.assert_called_with(ExampleConfig.cache_key_name()) def test_cache_key_name(self, _mock_cache): self.assertEquals(ExampleConfig.cache_key_name(), 'configuration/ExampleConfig/current') def test_no_config_empty_cache(self, mock_cache): mock_cache.get.return_value = None current = ExampleConfig.current() self.assertEquals(current.int_field, 10) self.assertEquals(current.string_field, '') mock_cache.set.assert_called_with(ExampleConfig.cache_key_name(), current, 300) def test_no_config_full_cache(self, mock_cache): current = ExampleConfig.current() self.assertEquals(current, mock_cache.get.return_value) def test_config_ordering(self, mock_cache): mock_cache.get.return_value = None with freeze_time('2012-01-01'): first = ExampleConfig(changed_by=self.user) first.string_field = 'first' first.save() second = ExampleConfig(changed_by=self.user) second.string_field = 'second' second.save() self.assertEquals(ExampleConfig.current().string_field, 'second') def test_cache_set(self, mock_cache): mock_cache.get.return_value = None first = ExampleConfig(changed_by=self.user) first.string_field = 'first' first.save() ExampleConfig.current() mock_cache.set.assert_called_with(ExampleConfig.cache_key_name(), first, 300) def test_active_annotation(self, mock_cache): mock_cache.get.return_value = None with freeze_time('2012-01-01'): ExampleConfig.objects.create(string_field='first') ExampleConfig.objects.create(string_field='second') rows = ExampleConfig.objects.with_active_flag().order_by('-change_date') self.assertEqual(len(rows), 2) self.assertEqual(rows[0].string_field, 'second') self.assertEqual(rows[0].is_active, True) self.assertEqual(rows[1].string_field, 'first') self.assertEqual(rows[1].is_active, False) class ExampleKeyedConfig(ConfigurationModel): """ Test model for testing ``ConfigurationModels`` with keyed configuration. Does not inherit from ExampleConfig due to how Django handles model inheritance. """ cache_timeout = 300 KEY_FIELDS = ('left', 'right') left = models.CharField(max_length=30) right = models.CharField(max_length=30) string_field = models.TextField() int_field = models.IntegerField(default=10) @ddt.ddt @patch('config_models.models.cache') class KeyedConfigurationModelTests(TestCase): """ Tests for ``ConfigurationModels`` with keyed configuration. """ def setUp(self): super(KeyedConfigurationModelTests, self).setUp() self.user = User() self.user.save() @ddt.data(('a', 'b'), ('c', 'd')) @ddt.unpack def test_cache_key_name(self, left, right, _mock_cache): self.assertEquals( ExampleKeyedConfig.cache_key_name(left, right), 'configuration/ExampleKeyedConfig/current/{},{}'.format(left, right) ) @ddt.data( ((), 'left,right'), (('left', 'right'), 'left,right'), (('left', ), 'left') ) @ddt.unpack def test_key_values_cache_key_name(self, args, expected_key, _mock_cache): self.assertEquals( ExampleKeyedConfig.key_values_cache_key_name(*args), 'configuration/ExampleKeyedConfig/key_values/{}'.format(expected_key)) @ddt.data(('a', 'b'), ('c', 'd')) @ddt.unpack def test_no_config_empty_cache(self, left, right, mock_cache): mock_cache.get.return_value = None current = ExampleKeyedConfig.current(left, right) self.assertEquals(current.int_field, 10) self.assertEquals(current.string_field, '') mock_cache.set.assert_called_with(ExampleKeyedConfig.cache_key_name(left, right), current, 300) @ddt.data(('a', 'b'), ('c', 'd')) @ddt.unpack def test_no_config_full_cache(self, left, right, mock_cache): current = ExampleKeyedConfig.current(left, right) self.assertEquals(current, mock_cache.get.return_value) def test_config_ordering(self, mock_cache): mock_cache.get.return_value = None with freeze_time('2012-01-01'): ExampleKeyedConfig( changed_by=self.user, left='left_a', right='right_a', string_field='first_a', ).save() ExampleKeyedConfig( changed_by=self.user, left='left_b', right='right_b', string_field='first_b', ).save() ExampleKeyedConfig( changed_by=self.user, left='left_a', right='right_a', string_field='second_a', ).save() ExampleKeyedConfig( changed_by=self.user, left='left_b', right='right_b', string_field='second_b', ).save() self.assertEquals(ExampleKeyedConfig.current('left_a', 'right_a').string_field, 'second_a') self.assertEquals(ExampleKeyedConfig.current('left_b', 'right_b').string_field, 'second_b') def test_cache_set(self, mock_cache): mock_cache.get.return_value = None first = ExampleKeyedConfig( changed_by=self.user, left='left', right='right', string_field='first', ) first.save() ExampleKeyedConfig.current('left', 'right') mock_cache.set.assert_called_with(ExampleKeyedConfig.cache_key_name('left', 'right'), first, 300) def test_key_values(self, mock_cache): mock_cache.get.return_value = None with freeze_time('2012-01-01'): ExampleKeyedConfig(left='left_a', right='right_a', changed_by=self.user).save() ExampleKeyedConfig(left='left_b', right='right_b', changed_by=self.user).save() ExampleKeyedConfig(left='left_a', right='right_a', changed_by=self.user).save() ExampleKeyedConfig(left='left_b', right='right_b', changed_by=self.user).save() unique_key_pairs = ExampleKeyedConfig.key_values() self.assertEquals(len(unique_key_pairs), 2) self.assertEquals(set(unique_key_pairs), set([('left_a', 'right_a'), ('left_b', 'right_b')])) unique_left_keys = ExampleKeyedConfig.key_values('left', flat=True) self.assertEquals(len(unique_left_keys), 2) self.assertEquals(set(unique_left_keys), set(['left_a', 'left_b'])) def test_key_string_values(self, mock_cache): """ Ensure str() vs unicode() doesn't cause duplicate cache entries """ ExampleKeyedConfig(left='left', right=u'〉☃', enabled=True, int_field=10, changed_by=self.user).save() mock_cache.get.return_value = None entry = ExampleKeyedConfig.current('left', u'〉☃') key = mock_cache.get.call_args[0][0] self.assertEqual(entry.int_field, 10) mock_cache.get.assert_called_with(key) self.assertEqual(mock_cache.set.call_args[0][0], key) mock_cache.get.reset_mock() entry = ExampleKeyedConfig.current(u'left', u'〉☃') self.assertEqual(entry.int_field, 10) mock_cache.get.assert_called_with(key) def test_current_set(self, mock_cache): mock_cache.get.return_value = None with freeze_time('2012-01-01'): ExampleKeyedConfig(left='left_a', right='right_a', int_field=0, changed_by=self.user).save() ExampleKeyedConfig(left='left_b', right='right_b', int_field=0, changed_by=self.user).save() ExampleKeyedConfig(left='left_a', right='right_a', int_field=1, changed_by=self.user).save() ExampleKeyedConfig(left='left_b', right='right_b', int_field=2, changed_by=self.user).save() queryset = ExampleKeyedConfig.objects.current_set() self.assertEqual(len(queryset.all()), 2) self.assertEqual( set(queryset.order_by('int_field').values_list('int_field', flat=True)), set([1, 2]) ) def test_active_annotation(self, mock_cache): mock_cache.get.return_value = None with freeze_time('2012-01-01'): ExampleKeyedConfig.objects.create(left='left_a', right='right_a', string_field='first') ExampleKeyedConfig.objects.create(left='left_b', right='right_b', string_field='first') ExampleKeyedConfig.objects.create(left='left_a', right='right_a', string_field='second') rows = ExampleKeyedConfig.objects.with_active_flag() self.assertEqual(len(rows), 3) for row in rows: if row.left == 'left_a': self.assertEqual(row.is_active, row.string_field == 'second') else: self.assertEqual(row.left, 'left_b') self.assertEqual(row.string_field, 'first') self.assertEqual(row.is_active, True) def test_key_values_cache(self, mock_cache): mock_cache.get.return_value = None self.assertEquals(ExampleKeyedConfig.key_values(), []) mock_cache.set.assert_called_with(ExampleKeyedConfig.key_values_cache_key_name(), [], 300) fake_result = [('a', 'b'), ('c', 'd')] mock_cache.get.return_value = fake_result self.assertEquals(ExampleKeyedConfig.key_values(), fake_result)