summaryrefslogtreecommitdiff
path: root/tests/model_fields
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2014-03-03 20:12:42 -0500
committerSimon Charette <charette.s@gmail.com>2014-03-25 14:31:54 -0400
commit78211b13a51f2ada1c7beb81ff97ef11f9e239eb (patch)
tree2bd0dd1116c06a3705f423d278ee8bf723128995 /tests/model_fields
parent7eaf329ad38ff7ea6b47f1b0a3c20ca7a5ad079b (diff)
[1.7.x] Fixed #12030 -- Validate integer field range at the model level.
Thanks to @timgraham for the review. Backport of 1506c71a95 from master
Diffstat (limited to 'tests/model_fields')
-rw-r--r--tests/model_fields/models.py18
-rw-r--r--tests/model_fields/tests.py109
2 files changed, 101 insertions, 26 deletions
diff --git a/tests/model_fields/models.py b/tests/model_fields/models.py
index c4e99c949a..d71f396d05 100644
--- a/tests/model_fields/models.py
+++ b/tests/model_fields/models.py
@@ -57,11 +57,27 @@ class BigS(models.Model):
s = models.SlugField(max_length=255)
-class BigInt(models.Model):
+class SmallIntegerModel(models.Model):
+ value = models.SmallIntegerField()
+
+
+class IntegerModel(models.Model):
+ value = models.IntegerField()
+
+
+class BigIntegerModel(models.Model):
value = models.BigIntegerField()
null_value = models.BigIntegerField(null=True, blank=True)
+class PositiveSmallIntegerModel(models.Model):
+ value = models.PositiveSmallIntegerField()
+
+
+class PositiveIntegerModel(models.Model):
+ value = models.PositiveIntegerField()
+
+
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
diff --git a/tests/model_fields/tests.py b/tests/model_fields/tests.py
index 421672e4d2..754ad20e5d 100644
--- a/tests/model_fields/tests.py
+++ b/tests/model_fields/tests.py
@@ -7,6 +7,7 @@ import warnings
from django import test
from django import forms
+from django.core import validators
from django.core.exceptions import ValidationError
from django.db import connection, transaction, models, IntegrityError
from django.db.models.fields import (
@@ -21,9 +22,10 @@ from django.utils import six
from django.utils.functional import lazy
from .models import (
- Foo, Bar, Whiz, BigD, BigS, BigInt, Post, NullBooleanModel,
+ Foo, Bar, Whiz, BigD, BigS, BigIntegerModel, Post, NullBooleanModel,
BooleanModel, PrimaryKeyCharModel, DataModel, Document, RenamedField,
- DateTimeModel, VerboseNameField, FksToBooleans, FkToChar, FloatModel)
+ DateTimeModel, VerboseNameField, FksToBooleans, FkToChar, FloatModel,
+ SmallIntegerModel, IntegerModel, PositiveSmallIntegerModel, PositiveIntegerModel)
class BasicFieldTests(test.TestCase):
@@ -131,7 +133,6 @@ class DecimalFieldTests(test.TestCase):
self.assertEqual(f._format(None), None)
def test_get_db_prep_lookup(self):
- from django.db import connection
f = models.DecimalField(max_digits=5, decimal_places=1)
self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None])
@@ -212,7 +213,6 @@ class DateTimeFieldTests(unittest.TestCase):
class BooleanFieldTests(unittest.TestCase):
def _test_get_db_prep_lookup(self, f):
- from django.db import connection
self.assertEqual(f.get_db_prep_lookup('exact', True, connection=connection), [True])
self.assertEqual(f.get_db_prep_lookup('exact', '1', connection=connection), [True])
self.assertEqual(f.get_db_prep_lookup('exact', 1, connection=connection), [True])
@@ -451,33 +451,92 @@ class ValidationTest(test.TestCase):
self.assertRaises(ValidationError, f.clean, None, None)
-class BigIntegerFieldTests(test.TestCase):
- def test_limits(self):
- # Ensure that values that are right at the limits can be saved
- # and then retrieved without corruption.
- maxval = 9223372036854775807
- minval = -maxval - 1
- BigInt.objects.create(value=maxval)
- qs = BigInt.objects.filter(value__gte=maxval)
+class IntegerFieldTests(test.TestCase):
+ model = IntegerModel
+ documented_range = (-2147483648, 2147483647)
+
+ def test_documented_range(self):
+ """
+ Ensure that values within the documented safe range pass validation,
+ 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, maxval)
- BigInt.objects.create(value=minval)
- qs = BigInt.objects.filter(value__lte=minval)
+ 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, minval)
+ self.assertEqual(qs[0].value, max_value)
+
+ def test_backend_range_validation(self):
+ """
+ Ensure that backend specific range are enforced at the model
+ validation level. ref #12030.
+ """
+ field = self.model._meta.get_field('value')
+ internal_type = field.get_internal_type()
+ min_value, max_value = connection.ops.integer_field_range(internal_type)
+
+ 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):
- b = BigInt(value=0)
- self.assertIsInstance(b.value, six.integer_types)
- b.save()
- self.assertIsInstance(b.value, six.integer_types)
- b = BigInt.objects.all()[0]
- self.assertIsInstance(b.value, six.integer_types)
+ 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):
- BigInt.objects.create(value='10')
- b = BigInt.objects.get(value='10')
- self.assertEqual(b.value, 10)
+ 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 TypeCoercionTests(test.TestCase):