summaryrefslogtreecommitdiff
path: root/tests/postgres_tests
diff options
context:
space:
mode:
authorGagaro <gagaro42@gmail.com>2022-01-31 16:04:13 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-05-10 11:22:23 +0200
commit667105877e6723c6985399803a364848891513cc (patch)
treeb6b3a9fe9f2c8767bc6f6a68f0580eef021b2b55 /tests/postgres_tests
parent441103a04d1d167dc870eaaf90e3fba974f67c93 (diff)
downloaddjango-667105877e6723c6985399803a364848891513cc.tar.gz
Fixed #30581 -- Added support for Meta.constraints validation.
Thanks Simon Charette, Keryn Knight, and Mariusz Felisiak for reviews.
Diffstat (limited to 'tests/postgres_tests')
-rw-r--r--tests/postgres_tests/test_constraints.py101
1 files changed, 75 insertions, 26 deletions
diff --git a/tests/postgres_tests/test_constraints.py b/tests/postgres_tests/test_constraints.py
index 377af41042..b8e53eb4a0 100644
--- a/tests/postgres_tests/test_constraints.py
+++ b/tests/postgres_tests/test_constraints.py
@@ -2,6 +2,7 @@ import datetime
from unittest import mock
from django.contrib.postgres.indexes import OpClass
+from django.core.exceptions import ValidationError
from django.db import IntegrityError, NotSupportedError, connection, transaction
from django.db.models import (
CheckConstraint,
@@ -612,18 +613,26 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
timezone.datetime(2018, 6, 28),
timezone.datetime(2018, 6, 29),
]
- HotelReservation.objects.create(
+ reservation = HotelReservation.objects.create(
datespan=DateRange(datetimes[0].date(), datetimes[1].date()),
start=datetimes[0],
end=datetimes[1],
room=room102,
)
+ constraint.validate(HotelReservation, reservation)
HotelReservation.objects.create(
datespan=DateRange(datetimes[1].date(), datetimes[3].date()),
start=datetimes[1],
end=datetimes[3],
room=room102,
)
+ HotelReservation.objects.create(
+ datespan=DateRange(datetimes[3].date(), datetimes[4].date()),
+ start=datetimes[3],
+ end=datetimes[4],
+ room=room102,
+ cancelled=True,
+ )
# Overlap dates.
with self.assertRaises(IntegrityError), transaction.atomic():
reservation = HotelReservation(
@@ -632,33 +641,58 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
end=datetimes[2],
room=room102,
)
+ msg = f"Constraint “{constraint.name}” is violated."
+ with self.assertRaisesMessage(ValidationError, msg):
+ constraint.validate(HotelReservation, reservation)
reservation.save()
# Valid range.
- HotelReservation.objects.bulk_create(
- [
- # Other room.
- HotelReservation(
- datespan=(datetimes[1].date(), datetimes[2].date()),
- start=datetimes[1],
- end=datetimes[2],
- room=room101,
- ),
- # Cancelled reservation.
- HotelReservation(
- datespan=(datetimes[1].date(), datetimes[1].date()),
- start=datetimes[1],
- end=datetimes[2],
- room=room102,
- cancelled=True,
- ),
- # Other adjacent dates.
- HotelReservation(
- datespan=(datetimes[3].date(), datetimes[4].date()),
- start=datetimes[3],
- end=datetimes[4],
- room=room102,
- ),
- ]
+ other_valid_reservations = [
+ # Other room.
+ HotelReservation(
+ datespan=(datetimes[1].date(), datetimes[2].date()),
+ start=datetimes[1],
+ end=datetimes[2],
+ room=room101,
+ ),
+ # Cancelled reservation.
+ HotelReservation(
+ datespan=(datetimes[1].date(), datetimes[1].date()),
+ start=datetimes[1],
+ end=datetimes[2],
+ room=room102,
+ cancelled=True,
+ ),
+ # Other adjacent dates.
+ HotelReservation(
+ datespan=(datetimes[3].date(), datetimes[4].date()),
+ start=datetimes[3],
+ end=datetimes[4],
+ room=room102,
+ ),
+ ]
+ for reservation in other_valid_reservations:
+ constraint.validate(HotelReservation, reservation)
+ HotelReservation.objects.bulk_create(other_valid_reservations)
+ # Excluded fields.
+ constraint.validate(
+ HotelReservation,
+ HotelReservation(
+ datespan=(datetimes[1].date(), datetimes[2].date()),
+ start=datetimes[1],
+ end=datetimes[2],
+ room=room102,
+ ),
+ exclude={"room"},
+ )
+ constraint.validate(
+ HotelReservation,
+ HotelReservation(
+ datespan=(datetimes[1].date(), datetimes[2].date()),
+ start=datetimes[1],
+ end=datetimes[2],
+ room=room102,
+ ),
+ exclude={"datespan", "start", "end", "room"},
)
@ignore_warnings(category=RemovedInDjango50Warning)
@@ -731,6 +765,21 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
constraint_name, self.get_constraints(RangesModel._meta.db_table)
)
+ def test_validate_range_adjacent(self):
+ constraint = ExclusionConstraint(
+ name="ints_adjacent",
+ expressions=[("ints", RangeOperators.ADJACENT_TO)],
+ violation_error_message="Custom error message.",
+ )
+ range_obj = RangesModel.objects.create(ints=(20, 50))
+ constraint.validate(RangesModel, range_obj)
+ msg = "Custom error message."
+ with self.assertRaisesMessage(ValidationError, msg):
+ constraint.validate(RangesModel, RangesModel(ints=(10, 20)))
+ constraint.validate(RangesModel, RangesModel(ints=(10, 19)))
+ constraint.validate(RangesModel, RangesModel(ints=(51, 60)))
+ constraint.validate(RangesModel, RangesModel(ints=(10, 20)), exclude={"ints"})
+
def test_expressions_with_params(self):
constraint_name = "scene_left_equal"
self.assertNotIn(constraint_name, self.get_constraints(Scene._meta.db_table))