summaryrefslogtreecommitdiff
path: root/tests/model_fields/test_integerfield.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/model_fields/test_integerfield.py')
-rw-r--r--tests/model_fields/test_integerfield.py161
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)