diff options
Diffstat (limited to 'tests/model_fields/test_integerfield.py')
| -rw-r--r-- | tests/model_fields/test_integerfield.py | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/tests/model_fields/test_integerfield.py b/tests/model_fields/test_integerfield.py new file mode 100644 index 0000000000..27cbdb5259 --- /dev/null +++ b/tests/model_fields/test_integerfield.py @@ -0,0 +1,161 @@ +from django.core import validators +from django.core.exceptions import ValidationError +from django.db import connection, models +from django.test import SimpleTestCase, TestCase +from django.utils import six + +from .models import ( + BigIntegerModel, IntegerModel, PositiveIntegerModel, + PositiveSmallIntegerModel, SmallIntegerModel, +) + + +class IntegerFieldTests(TestCase): + model = IntegerModel + documented_range = (-2147483648, 2147483647) + + @property + def backend_range(self): + field = self.model._meta.get_field('value') + internal_type = field.get_internal_type() + return connection.ops.integer_field_range(internal_type) + + def test_documented_range(self): + """ + Values within the documented safe range pass validation, and can be + saved and retrieved without corruption. + """ + min_value, max_value = self.documented_range + + instance = self.model(value=min_value) + instance.full_clean() + instance.save() + qs = self.model.objects.filter(value__lte=min_value) + self.assertEqual(qs.count(), 1) + self.assertEqual(qs[0].value, min_value) + + instance = self.model(value=max_value) + instance.full_clean() + instance.save() + qs = self.model.objects.filter(value__gte=max_value) + self.assertEqual(qs.count(), 1) + self.assertEqual(qs[0].value, max_value) + + def test_backend_range_save(self): + """ + Backend specific ranges can be saved without corruption. + """ + min_value, max_value = self.backend_range + + if min_value is not None: + instance = self.model(value=min_value) + instance.full_clean() + instance.save() + qs = self.model.objects.filter(value__lte=min_value) + self.assertEqual(qs.count(), 1) + self.assertEqual(qs[0].value, min_value) + + if max_value is not None: + instance = self.model(value=max_value) + instance.full_clean() + instance.save() + qs = self.model.objects.filter(value__gte=max_value) + self.assertEqual(qs.count(), 1) + self.assertEqual(qs[0].value, max_value) + + def test_backend_range_validation(self): + """ + Backend specific ranges are enforced at the model validation level + (#12030). + """ + min_value, max_value = self.backend_range + + if min_value is not None: + instance = self.model(value=min_value - 1) + expected_message = validators.MinValueValidator.message % { + 'limit_value': min_value, + } + with self.assertRaisesMessage(ValidationError, expected_message): + instance.full_clean() + instance.value = min_value + instance.full_clean() + + if max_value is not None: + instance = self.model(value=max_value + 1) + expected_message = validators.MaxValueValidator.message % { + 'limit_value': max_value, + } + with self.assertRaisesMessage(ValidationError, expected_message): + instance.full_clean() + instance.value = max_value + instance.full_clean() + + def test_types(self): + instance = self.model(value=0) + self.assertIsInstance(instance.value, six.integer_types) + instance.save() + self.assertIsInstance(instance.value, six.integer_types) + instance = self.model.objects.get() + self.assertIsInstance(instance.value, six.integer_types) + + def test_coercing(self): + self.model.objects.create(value='10') + instance = self.model.objects.get(value='10') + self.assertEqual(instance.value, 10) + + +class SmallIntegerFieldTests(IntegerFieldTests): + model = SmallIntegerModel + documented_range = (-32768, 32767) + + +class BigIntegerFieldTests(IntegerFieldTests): + model = BigIntegerModel + documented_range = (-9223372036854775808, 9223372036854775807) + + +class PositiveSmallIntegerFieldTests(IntegerFieldTests): + model = PositiveSmallIntegerModel + documented_range = (0, 32767) + + +class PositiveIntegerFieldTests(IntegerFieldTests): + model = PositiveIntegerModel + documented_range = (0, 2147483647) + + +class ValidationTests(SimpleTestCase): + + def test_integerfield_cleans_valid_string(self): + f = models.IntegerField() + self.assertEqual(f.clean('2', None), 2) + + def test_integerfield_raises_error_on_invalid_intput(self): + f = models.IntegerField() + with self.assertRaises(ValidationError): + f.clean('a', None) + + def test_choices_validation_supports_named_groups(self): + f = models.IntegerField(choices=(('group', ((10, 'A'), (20, 'B'))), (30, 'C'))) + self.assertEqual(10, f.clean(10, None)) + + def test_nullable_integerfield_raises_error_with_blank_false(self): + f = models.IntegerField(null=True, blank=False) + with self.assertRaises(ValidationError): + f.clean(None, None) + + def test_nullable_integerfield_cleans_none_on_null_and_blank_true(self): + f = models.IntegerField(null=True, blank=True) + self.assertIsNone(f.clean(None, None)) + + def test_integerfield_raises_error_on_empty_input(self): + f = models.IntegerField(null=False) + with self.assertRaises(ValidationError): + f.clean(None, None) + with self.assertRaises(ValidationError): + f.clean('', None) + + def test_integerfield_validates_zero_against_choices(self): + f = models.IntegerField(choices=((1, 1),)) + with self.assertRaises(ValidationError): + f.clean('0', None) |
