Skip to content

Commit 7c48af2

Browse files
committed
add QuerySet tests
1 parent d44bb8b commit 7c48af2

File tree

3 files changed

+154
-1
lines changed

3 files changed

+154
-1
lines changed

django_mongodb_backend/query.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def wrapper(*args, **kwargs):
2424
except DuplicateKeyError as e:
2525
raise IntegrityError from e
2626
except PyMongoError as e:
27-
raise DatabaseError from e
27+
raise DatabaseError(str(e)) from e
2828

2929
return wrapper
3030

tests/encryption_/models.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@
3030
from django_mongodb_backend.models import EmbeddedModel
3131

3232

33+
class Author(models.Model):
34+
name = models.CharField(max_length=255)
35+
36+
37+
class Book(models.Model):
38+
title = models.CharField(max_length=255)
39+
author = models.ForeignKey(Author, models.CASCADE)
40+
41+
3342
class EncryptedTestModel(models.Model):
3443
class Meta:
3544
abstract = True

tests/encryption_/test_fields.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import datetime
22
import uuid
33
from decimal import Decimal
4+
from operator import attrgetter
45

56
from bson import ObjectId
7+
from django.db import DatabaseError
8+
from django.db.models import Avg
69

710
from django_mongodb_backend.fields import (
811
EncryptedArrayField,
@@ -18,6 +21,7 @@
1821
BigIntegerModel,
1922
Billing,
2023
BinaryModel,
24+
Book,
2125
BooleanModel,
2226
CharModel,
2327
DateModel,
@@ -214,6 +218,146 @@ def test_time(self):
214218
self.assertEncrypted(TimeModel, "value")
215219

216220

221+
class QueryTests(EncryptionTestCase):
222+
def test_aggregate(self):
223+
msg = (
224+
"Aggregation stage $internalFacetTeeConsumer is not allowed or "
225+
"supported with automatic encryption."
226+
)
227+
with self.assertRaisesMessage(DatabaseError, msg):
228+
list(IntegerModel.objects.aggregate(Avg("value")))
229+
230+
def test_alias(self):
231+
msg = (
232+
"Cannot group on field '_id.value' which is encrypted with the "
233+
"random algorithm or whose encryption properties are not known "
234+
"until runtime"
235+
)
236+
with self.assertRaisesMessage(DatabaseError, msg):
237+
list(IntegerModel.objects.alias(avg=Avg("value")))
238+
239+
def test_annotate(self):
240+
msg = (
241+
"Cannot group on field '_id.value' which is encrypted with the "
242+
"random algorithm or whose encryption properties are not known "
243+
"until runtime"
244+
)
245+
with self.assertRaisesMessage(DatabaseError, msg):
246+
list(IntegerModel.objects.annotate(avg=Avg("value")))
247+
248+
def test_bulk_create(self):
249+
CharModel.objects.bulk_create([CharModel(value="abc"), CharModel(value="xyz")])
250+
self.assertQuerySetEqual(
251+
CharModel.objects.order_by("pk"), ["abc", "xyz"], attrgetter("value")
252+
)
253+
254+
def test_bulk_update(self):
255+
objs = [
256+
CharModel.objects.create(value="abc"),
257+
CharModel.objects.create(value="xyz"),
258+
]
259+
objs[0].value = "def"
260+
objs[1].value = "mno"
261+
msg = "Multi-document updates are not allowed with Queryable Encryption"
262+
with self.assertRaisesMessage(DatabaseError, msg):
263+
CharModel.objects.bulk_update(objs, ["value"])
264+
265+
def test_contains(self):
266+
obj = CharModel.objects.create(value="abc")
267+
self.assertIs(CharModel.objects.contains(obj), True)
268+
269+
def test_count(self):
270+
msg = (
271+
"Aggregation stage $internalFacetTeeConsumer is not allowed or "
272+
"supported with automatic encryption."
273+
)
274+
with self.assertRaisesMessage(DatabaseError, msg):
275+
list(CharModel.objects.count())
276+
277+
def test_dates(self):
278+
msg = (
279+
"If the value type is a date, the type of the index must also be date (and vice versa)."
280+
)
281+
with self.assertRaisesMessage(DatabaseError, msg):
282+
list(DateModel.objects.dates("value", "year"))
283+
284+
def test_datetimes(self):
285+
msg = (
286+
"If the value type is a date, the type of the index must also be date (and vice versa)."
287+
)
288+
with self.assertRaisesMessage(DatabaseError, msg):
289+
list(DateTimeModel.objects.datetimes("value", "year"))
290+
291+
def test_distinct(self):
292+
msg = (
293+
"Cannot group on field '_id.value' which is encrypted with the "
294+
"random algorithm or whose encryption properties are not known "
295+
"until runtime"
296+
)
297+
with self.assertRaisesMessage(DatabaseError, msg):
298+
list(CharModel.objects.distinct("value"))
299+
300+
def test_exclude(self):
301+
obj1 = CharModel.objects.create(value="abc")
302+
obj2 = CharModel.objects.create(value="xyz")
303+
self.assertSequenceEqual(CharModel.objects.exclude(value=obj1.value), [obj2])
304+
305+
def test_exists(self):
306+
self.assertIs(CharModel.objects.exists(), False)
307+
308+
def test_get_or_create(self):
309+
obj1, created1 = CharModel.objects.get_or_create(value="abc")
310+
self.assertIs(created1, True)
311+
obj2, created2 = CharModel.objects.get_or_create(value="abc")
312+
self.assertIs(created2, False)
313+
self.assertEqual(obj1, obj2)
314+
315+
def test_join(self):
316+
msg = (
317+
"Non-empty 'let' field is not allowed in the $lookup aggregation "
318+
"stage over an encrypted collection."
319+
)
320+
with self.assertRaisesMessage(DatabaseError, msg):
321+
list(Book.objects.filter(author__name="xxx"))
322+
323+
def test_order_by(self):
324+
msg = "Cannot add an encrypted field as a prefix of another encrypted field"
325+
with self.assertRaisesMessage(DatabaseError, msg):
326+
list(CharModel.objects.order_by("value"))
327+
328+
def test_select_related(self):
329+
msg = (
330+
"Non-empty 'let' field is not allowed in the $lookup aggregation "
331+
"stage over an encrypted collection."
332+
)
333+
with self.assertRaisesMessage(DatabaseError, msg):
334+
list(Book.objects.select_related("author"))
335+
336+
def test_update(self):
337+
msg = "Multi-document updates are not allowed with Queryable Encryption"
338+
with self.assertRaisesMessage(DatabaseError, msg):
339+
self.assertEqual(CharModel.objects.update(value="xyz"), 1)
340+
341+
def test_update_or_create(self):
342+
CharModel.objects.create(value="xyz")
343+
msg = "Multi-document updates are not allowed with Queryable Encryption"
344+
with self.assertRaisesMessage(DatabaseError, msg):
345+
CharModel.objects.update_or_create(value="xyz", defaults={"plain": "abc"})
346+
347+
def test_union(self):
348+
msg = "Aggregation stage $unionWith is not allowed or supported with automatic encryption."
349+
qs1 = IntegerModel.objects.filter(value__gt=1)
350+
qs2 = IntegerModel.objects.filter(value__gte=8)
351+
with self.assertRaisesMessage(DatabaseError, msg):
352+
list(qs1.union(qs2))
353+
354+
def test_values(self):
355+
list(CharModel.objects.values("value"))
356+
357+
def test_values_list(self):
358+
list(CharModel.objects.values_list("value"))
359+
360+
217361
class FieldMixinTests(EncryptionTestCase):
218362
def test_db_index(self):
219363
msg = "'db_index=True' is not supported on encrypted fields."

0 commit comments

Comments
 (0)