summaryrefslogtreecommitdiff
path: root/tests/db_functions
diff options
context:
space:
mode:
authorJunyi Jiao <jiaojunyi90@gmail.com>2018-07-05 11:02:12 -0400
committerTim Graham <timograham@gmail.com>2018-07-05 11:02:12 -0400
commita0b19a0f5b1731cf575546175034da53f5af5367 (patch)
tree912f6367180636e4c9e1aecc4045830046a70ea6 /tests/db_functions
parent48aeca44d885929106e71fe78379fe50850af001 (diff)
Refs #28643 -- Added math database functions.
Thanks Nick Pope for much review.
Diffstat (limited to 'tests/db_functions')
-rw-r--r--tests/db_functions/math/__init__.py0
-rw-r--r--tests/db_functions/math/test_abs.py50
-rw-r--r--tests/db_functions/math/test_acos.py51
-rw-r--r--tests/db_functions/math/test_asin.py51
-rw-r--r--tests/db_functions/math/test_atan.py51
-rw-r--r--tests/db_functions/math/test_atan2.py33
-rw-r--r--tests/db_functions/math/test_ceil.py51
-rw-r--r--tests/db_functions/math/test_cos.py51
-rw-r--r--tests/db_functions/math/test_cot.py51
-rw-r--r--tests/db_functions/math/test_degrees.py51
-rw-r--r--tests/db_functions/math/test_exp.py51
-rw-r--r--tests/db_functions/math/test_floor.py51
-rw-r--r--tests/db_functions/math/test_ln.py51
-rw-r--r--tests/db_functions/math/test_log.py36
-rw-r--r--tests/db_functions/math/test_mod.py36
-rw-r--r--tests/db_functions/math/test_pi.py15
-rw-r--r--tests/db_functions/math/test_power.py35
-rw-r--r--tests/db_functions/math/test_radians.py51
-rw-r--r--tests/db_functions/math/test_round.py50
-rw-r--r--tests/db_functions/math/test_sin.py51
-rw-r--r--tests/db_functions/math/test_sqrt.py51
-rw-r--r--tests/db_functions/math/test_tan.py51
-rw-r--r--tests/db_functions/models.py11
23 files changed, 980 insertions, 0 deletions
diff --git a/tests/db_functions/math/__init__.py b/tests/db_functions/math/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/db_functions/math/__init__.py
diff --git a/tests/db_functions/math/test_abs.py b/tests/db_functions/math/test_abs.py
new file mode 100644
index 0000000000..99f2a336f7
--- /dev/null
+++ b/tests/db_functions/math/test_abs.py
@@ -0,0 +1,50 @@
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Abs
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class AbsTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-0.8'), n2=Decimal('1.2'))
+ obj = DecimalModel.objects.annotate(n1_abs=Abs('n1'), n2_abs=Abs('n2')).first()
+ self.assertIsInstance(obj.n1_abs, Decimal)
+ self.assertIsInstance(obj.n2_abs, Decimal)
+ self.assertEqual(obj.n1, -obj.n1_abs)
+ self.assertEqual(obj.n2, obj.n2_abs)
+
+ def test_float(self):
+ obj = FloatModel.objects.create(f1=-0.5, f2=12)
+ obj = FloatModel.objects.annotate(f1_abs=Abs('f1'), f2_abs=Abs('f2')).first()
+ self.assertIsInstance(obj.f1_abs, float)
+ self.assertIsInstance(obj.f2_abs, float)
+ self.assertEqual(obj.f1, -obj.f1_abs)
+ self.assertEqual(obj.f2, obj.f2_abs)
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=12, normal=0, big=-45)
+ obj = IntegerModel.objects.annotate(
+ small_abs=Abs('small'),
+ normal_abs=Abs('normal'),
+ big_abs=Abs('big'),
+ ).first()
+ self.assertIsInstance(obj.small_abs, int)
+ self.assertIsInstance(obj.normal_abs, int)
+ self.assertIsInstance(obj.big_abs, int)
+ self.assertEqual(obj.small, obj.small_abs)
+ self.assertEqual(obj.normal, obj.normal_abs)
+ self.assertEqual(obj.big, -obj.big_abs)
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Abs)
+ DecimalModel.objects.create(n1=Decimal('-1.5'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('-0.5'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__abs__gt=1)
+ self.assertQuerysetEqual(objs, [Decimal('-1.5')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Abs)
diff --git a/tests/db_functions/math/test_acos.py b/tests/db_functions/math/test_acos.py
new file mode 100644
index 0000000000..041412123b
--- /dev/null
+++ b/tests/db_functions/math/test_acos.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import ACos
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class ACosTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-0.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_acos=ACos('n1'), n2_acos=ACos('n2')).first()
+ self.assertIsInstance(obj.n1_acos, Decimal)
+ self.assertIsInstance(obj.n2_acos, Decimal)
+ self.assertAlmostEqual(obj.n1_acos, Decimal(math.acos(obj.n1)))
+ self.assertAlmostEqual(obj.n2_acos, Decimal(math.acos(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-0.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_acos=ACos('f1'), f2_acos=ACos('f2')).first()
+ self.assertIsInstance(obj.f1_acos, float)
+ self.assertIsInstance(obj.f2_acos, float)
+ self.assertAlmostEqual(obj.f1_acos, math.acos(obj.f1))
+ self.assertAlmostEqual(obj.f2_acos, math.acos(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=0, normal=1, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_acos=ACos('small'),
+ normal_acos=ACos('normal'),
+ big_acos=ACos('big'),
+ ).first()
+ self.assertIsInstance(obj.small_acos, float)
+ self.assertIsInstance(obj.normal_acos, float)
+ self.assertIsInstance(obj.big_acos, float)
+ self.assertAlmostEqual(obj.small_acos, math.acos(obj.small))
+ self.assertAlmostEqual(obj.normal_acos, math.acos(obj.normal))
+ self.assertAlmostEqual(obj.big_acos, math.acos(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(ACos)
+ DecimalModel.objects.create(n1=Decimal('0.5'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('-0.9'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__acos__lt=2)
+ self.assertQuerysetEqual(objs, [Decimal('0.5')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(ACos)
diff --git a/tests/db_functions/math/test_asin.py b/tests/db_functions/math/test_asin.py
new file mode 100644
index 0000000000..5572449834
--- /dev/null
+++ b/tests/db_functions/math/test_asin.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import ASin
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class ASinTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('0.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_asin=ASin('n1'), n2_asin=ASin('n2')).first()
+ self.assertIsInstance(obj.n1_asin, Decimal)
+ self.assertIsInstance(obj.n2_asin, Decimal)
+ self.assertAlmostEqual(obj.n1_asin, Decimal(math.asin(obj.n1)))
+ self.assertAlmostEqual(obj.n2_asin, Decimal(math.asin(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-0.5, f2=0.87)
+ obj = FloatModel.objects.annotate(f1_asin=ASin('f1'), f2_asin=ASin('f2')).first()
+ self.assertIsInstance(obj.f1_asin, float)
+ self.assertIsInstance(obj.f2_asin, float)
+ self.assertAlmostEqual(obj.f1_asin, math.asin(obj.f1))
+ self.assertAlmostEqual(obj.f2_asin, math.asin(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=0, normal=1, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_asin=ASin('small'),
+ normal_asin=ASin('normal'),
+ big_asin=ASin('big'),
+ ).first()
+ self.assertIsInstance(obj.small_asin, float)
+ self.assertIsInstance(obj.normal_asin, float)
+ self.assertIsInstance(obj.big_asin, float)
+ self.assertAlmostEqual(obj.small_asin, math.asin(obj.small))
+ self.assertAlmostEqual(obj.normal_asin, math.asin(obj.normal))
+ self.assertAlmostEqual(obj.big_asin, math.asin(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(ASin)
+ DecimalModel.objects.create(n1=Decimal('0.1'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('1.0'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__asin__gt=1)
+ self.assertQuerysetEqual(objs, [Decimal('1.0')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(ASin)
diff --git a/tests/db_functions/math/test_atan.py b/tests/db_functions/math/test_atan.py
new file mode 100644
index 0000000000..62af5d1587
--- /dev/null
+++ b/tests/db_functions/math/test_atan.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import ATan
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class ATanTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_atan=ATan('n1'), n2_atan=ATan('n2')).first()
+ self.assertIsInstance(obj.n1_atan, Decimal)
+ self.assertIsInstance(obj.n2_atan, Decimal)
+ self.assertAlmostEqual(obj.n1_atan, Decimal(math.atan(obj.n1)))
+ self.assertAlmostEqual(obj.n2_atan, Decimal(math.atan(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_atan=ATan('f1'), f2_atan=ATan('f2')).first()
+ self.assertIsInstance(obj.f1_atan, float)
+ self.assertIsInstance(obj.f2_atan, float)
+ self.assertAlmostEqual(obj.f1_atan, math.atan(obj.f1))
+ self.assertAlmostEqual(obj.f2_atan, math.atan(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-20, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_atan=ATan('small'),
+ normal_atan=ATan('normal'),
+ big_atan=ATan('big'),
+ ).first()
+ self.assertIsInstance(obj.small_atan, float)
+ self.assertIsInstance(obj.normal_atan, float)
+ self.assertIsInstance(obj.big_atan, float)
+ self.assertAlmostEqual(obj.small_atan, math.atan(obj.small))
+ self.assertAlmostEqual(obj.normal_atan, math.atan(obj.normal))
+ self.assertAlmostEqual(obj.big_atan, math.atan(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(ATan)
+ DecimalModel.objects.create(n1=Decimal('3.12'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('-5'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__atan__gt=0)
+ self.assertQuerysetEqual(objs, [Decimal('3.12')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(ATan)
diff --git a/tests/db_functions/math/test_atan2.py b/tests/db_functions/math/test_atan2.py
new file mode 100644
index 0000000000..195892dfdd
--- /dev/null
+++ b/tests/db_functions/math/test_atan2.py
@@ -0,0 +1,33 @@
+import math
+from decimal import Decimal
+
+from django.db.models.functions import ATan2
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class ATan2Tests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-9.9'), n2=Decimal('4.6'))
+ obj = DecimalModel.objects.annotate(n_atan2=ATan2('n1', 'n2')).first()
+ self.assertIsInstance(obj.n_atan2, Decimal)
+ self.assertAlmostEqual(obj.n_atan2, Decimal(math.atan2(obj.n1, obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-25, f2=0.33)
+ obj = FloatModel.objects.annotate(f_atan2=ATan2('f1', 'f2')).first()
+ self.assertIsInstance(obj.f_atan2, float)
+ self.assertAlmostEqual(obj.f_atan2, math.atan2(obj.f1, obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=0, normal=1, big=10)
+ obj = IntegerModel.objects.annotate(
+ atan2_sn=ATan2('small', 'normal'),
+ atan2_nb=ATan2('normal', 'big'),
+ ).first()
+ self.assertIsInstance(obj.atan2_sn, float)
+ self.assertIsInstance(obj.atan2_nb, float)
+ self.assertAlmostEqual(obj.atan2_sn, math.atan2(obj.small, obj.normal))
+ self.assertAlmostEqual(obj.atan2_nb, math.atan2(obj.normal, obj.big))
diff --git a/tests/db_functions/math/test_ceil.py b/tests/db_functions/math/test_ceil.py
new file mode 100644
index 0000000000..93e9713eb2
--- /dev/null
+++ b/tests/db_functions/math/test_ceil.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Ceil
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class CeilTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_ceil=Ceil('n1'), n2_ceil=Ceil('n2')).first()
+ self.assertIsInstance(obj.n1_ceil, Decimal)
+ self.assertIsInstance(obj.n2_ceil, Decimal)
+ self.assertEqual(obj.n1_ceil, Decimal(math.ceil(obj.n1)))
+ self.assertEqual(obj.n2_ceil, Decimal(math.ceil(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-12.5, f2=21.33)
+ obj = FloatModel.objects.annotate(f1_ceil=Ceil('f1'), f2_ceil=Ceil('f2')).first()
+ self.assertIsInstance(obj.f1_ceil, float)
+ self.assertIsInstance(obj.f2_ceil, float)
+ self.assertEqual(obj.f1_ceil, math.ceil(obj.f1))
+ self.assertEqual(obj.f2_ceil, math.ceil(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-11, normal=0, big=-100)
+ obj = IntegerModel.objects.annotate(
+ small_ceil=Ceil('small'),
+ normal_ceil=Ceil('normal'),
+ big_ceil=Ceil('big'),
+ ).first()
+ self.assertIsInstance(obj.small_ceil, int)
+ self.assertIsInstance(obj.normal_ceil, int)
+ self.assertIsInstance(obj.big_ceil, int)
+ self.assertEqual(obj.small_ceil, math.ceil(obj.small))
+ self.assertEqual(obj.normal_ceil, math.ceil(obj.normal))
+ self.assertEqual(obj.big_ceil, math.ceil(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Ceil)
+ DecimalModel.objects.create(n1=Decimal('3.12'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('1.25'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__ceil__gt=3)
+ self.assertQuerysetEqual(objs, [Decimal('3.12')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Ceil)
diff --git a/tests/db_functions/math/test_cos.py b/tests/db_functions/math/test_cos.py
new file mode 100644
index 0000000000..4d6a16f5fc
--- /dev/null
+++ b/tests/db_functions/math/test_cos.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Cos
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class CosTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_cos=Cos('n1'), n2_cos=Cos('n2')).first()
+ self.assertIsInstance(obj.n1_cos, Decimal)
+ self.assertIsInstance(obj.n2_cos, Decimal)
+ self.assertAlmostEqual(obj.n1_cos, Decimal(math.cos(obj.n1)))
+ self.assertAlmostEqual(obj.n2_cos, Decimal(math.cos(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_cos=Cos('f1'), f2_cos=Cos('f2')).first()
+ self.assertIsInstance(obj.f1_cos, float)
+ self.assertIsInstance(obj.f2_cos, float)
+ self.assertAlmostEqual(obj.f1_cos, math.cos(obj.f1))
+ self.assertAlmostEqual(obj.f2_cos, math.cos(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-20, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_cos=Cos('small'),
+ normal_cos=Cos('normal'),
+ big_cos=Cos('big'),
+ ).first()
+ self.assertIsInstance(obj.small_cos, float)
+ self.assertIsInstance(obj.normal_cos, float)
+ self.assertIsInstance(obj.big_cos, float)
+ self.assertAlmostEqual(obj.small_cos, math.cos(obj.small))
+ self.assertAlmostEqual(obj.normal_cos, math.cos(obj.normal))
+ self.assertAlmostEqual(obj.big_cos, math.cos(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Cos)
+ DecimalModel.objects.create(n1=Decimal('-8.0'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('3.14'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__cos__gt=-0.2)
+ self.assertQuerysetEqual(objs, [Decimal('-8.0')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Cos)
diff --git a/tests/db_functions/math/test_cot.py b/tests/db_functions/math/test_cot.py
new file mode 100644
index 0000000000..a1a13c9ee5
--- /dev/null
+++ b/tests/db_functions/math/test_cot.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Cot
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class CotTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_cot=Cot('n1'), n2_cot=Cot('n2')).first()
+ self.assertIsInstance(obj.n1_cot, Decimal)
+ self.assertIsInstance(obj.n2_cot, Decimal)
+ self.assertAlmostEqual(obj.n1_cot, Decimal(1 / math.tan(obj.n1)))
+ self.assertAlmostEqual(obj.n2_cot, Decimal(1 / math.tan(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_cot=Cot('f1'), f2_cot=Cot('f2')).first()
+ self.assertIsInstance(obj.f1_cot, float)
+ self.assertIsInstance(obj.f2_cot, float)
+ self.assertAlmostEqual(obj.f1_cot, 1 / math.tan(obj.f1))
+ self.assertAlmostEqual(obj.f2_cot, 1 / math.tan(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-5, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_cot=Cot('small'),
+ normal_cot=Cot('normal'),
+ big_cot=Cot('big'),
+ ).first()
+ self.assertIsInstance(obj.small_cot, float)
+ self.assertIsInstance(obj.normal_cot, float)
+ self.assertIsInstance(obj.big_cot, float)
+ self.assertAlmostEqual(obj.small_cot, 1 / math.tan(obj.small))
+ self.assertAlmostEqual(obj.normal_cot, 1 / math.tan(obj.normal))
+ self.assertAlmostEqual(obj.big_cot, 1 / math.tan(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Cot)
+ DecimalModel.objects.create(n1=Decimal('12.0'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('1.0'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__cot__gt=0)
+ self.assertQuerysetEqual(objs, [Decimal('1.0')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Cot)
diff --git a/tests/db_functions/math/test_degrees.py b/tests/db_functions/math/test_degrees.py
new file mode 100644
index 0000000000..d3c70fcbee
--- /dev/null
+++ b/tests/db_functions/math/test_degrees.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Degrees
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class DegreesTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_degrees=Degrees('n1'), n2_degrees=Degrees('n2')).first()
+ self.assertIsInstance(obj.n1_degrees, Decimal)
+ self.assertIsInstance(obj.n2_degrees, Decimal)
+ self.assertAlmostEqual(obj.n1_degrees, Decimal(math.degrees(obj.n1)))
+ self.assertAlmostEqual(obj.n2_degrees, Decimal(math.degrees(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_degrees=Degrees('f1'), f2_degrees=Degrees('f2')).first()
+ self.assertIsInstance(obj.f1_degrees, float)
+ self.assertIsInstance(obj.f2_degrees, float)
+ self.assertAlmostEqual(obj.f1_degrees, math.degrees(obj.f1))
+ self.assertAlmostEqual(obj.f2_degrees, math.degrees(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-20, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_degrees=Degrees('small'),
+ normal_degrees=Degrees('normal'),
+ big_degrees=Degrees('big'),
+ ).first()
+ self.assertIsInstance(obj.small_degrees, float)
+ self.assertIsInstance(obj.normal_degrees, float)
+ self.assertIsInstance(obj.big_degrees, float)
+ self.assertAlmostEqual(obj.small_degrees, math.degrees(obj.small))
+ self.assertAlmostEqual(obj.normal_degrees, math.degrees(obj.normal))
+ self.assertAlmostEqual(obj.big_degrees, math.degrees(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Degrees)
+ DecimalModel.objects.create(n1=Decimal('5.4'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('-30'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__degrees__gt=0)
+ self.assertQuerysetEqual(objs, [Decimal('5.4')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Degrees)
diff --git a/tests/db_functions/math/test_exp.py b/tests/db_functions/math/test_exp.py
new file mode 100644
index 0000000000..c44f7adefe
--- /dev/null
+++ b/tests/db_functions/math/test_exp.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Exp
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class ExpTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_exp=Exp('n1'), n2_exp=Exp('n2')).first()
+ self.assertIsInstance(obj.n1_exp, Decimal)
+ self.assertIsInstance(obj.n2_exp, Decimal)
+ self.assertAlmostEqual(obj.n1_exp, Decimal(math.exp(obj.n1)))
+ self.assertAlmostEqual(obj.n2_exp, Decimal(math.exp(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_exp=Exp('f1'), f2_exp=Exp('f2')).first()
+ self.assertIsInstance(obj.f1_exp, float)
+ self.assertIsInstance(obj.f2_exp, float)
+ self.assertAlmostEqual(obj.f1_exp, math.exp(obj.f1))
+ self.assertAlmostEqual(obj.f2_exp, math.exp(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-20, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_exp=Exp('small'),
+ normal_exp=Exp('normal'),
+ big_exp=Exp('big'),
+ ).first()
+ self.assertIsInstance(obj.small_exp, float)
+ self.assertIsInstance(obj.normal_exp, float)
+ self.assertIsInstance(obj.big_exp, float)
+ self.assertAlmostEqual(obj.small_exp, math.exp(obj.small))
+ self.assertAlmostEqual(obj.normal_exp, math.exp(obj.normal))
+ self.assertAlmostEqual(obj.big_exp, math.exp(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Exp)
+ DecimalModel.objects.create(n1=Decimal('12.0'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('-1.0'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__exp__gt=10)
+ self.assertQuerysetEqual(objs, [Decimal('12.0')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Exp)
diff --git a/tests/db_functions/math/test_floor.py b/tests/db_functions/math/test_floor.py
new file mode 100644
index 0000000000..8404184c3e
--- /dev/null
+++ b/tests/db_functions/math/test_floor.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Floor
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class FloorTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_floor=Floor('n1'), n2_floor=Floor('n2')).first()
+ self.assertIsInstance(obj.n1_floor, Decimal)
+ self.assertIsInstance(obj.n2_floor, Decimal)
+ self.assertEqual(obj.n1_floor, Decimal(math.floor(obj.n1)))
+ self.assertEqual(obj.n2_floor, Decimal(math.floor(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_floor=Floor('f1'), f2_floor=Floor('f2')).first()
+ self.assertIsInstance(obj.f1_floor, float)
+ self.assertIsInstance(obj.f2_floor, float)
+ self.assertEqual(obj.f1_floor, math.floor(obj.f1))
+ self.assertEqual(obj.f2_floor, math.floor(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-20, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_floor=Floor('small'),
+ normal_floor=Floor('normal'),
+ big_floor=Floor('big'),
+ ).first()
+ self.assertIsInstance(obj.small_floor, int)
+ self.assertIsInstance(obj.normal_floor, int)
+ self.assertIsInstance(obj.big_floor, int)
+ self.assertEqual(obj.small_floor, math.floor(obj.small))
+ self.assertEqual(obj.normal_floor, math.floor(obj.normal))
+ self.assertEqual(obj.big_floor, math.floor(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Floor)
+ DecimalModel.objects.create(n1=Decimal('5.4'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('3.4'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__floor__gt=4)
+ self.assertQuerysetEqual(objs, [Decimal('5.4')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Floor)
diff --git a/tests/db_functions/math/test_ln.py b/tests/db_functions/math/test_ln.py
new file mode 100644
index 0000000000..f30cf8e84e
--- /dev/null
+++ b/tests/db_functions/math/test_ln.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Ln
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class LnTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_ln=Ln('n1'), n2_ln=Ln('n2')).first()
+ self.assertIsInstance(obj.n1_ln, Decimal)
+ self.assertIsInstance(obj.n2_ln, Decimal)
+ self.assertAlmostEqual(obj.n1_ln, Decimal(math.log(obj.n1)))
+ self.assertAlmostEqual(obj.n2_ln, Decimal(math.log(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_ln=Ln('f1'), f2_ln=Ln('f2')).first()
+ self.assertIsInstance(obj.f1_ln, float)
+ self.assertIsInstance(obj.f2_ln, float)
+ self.assertAlmostEqual(obj.f1_ln, math.log(obj.f1))
+ self.assertAlmostEqual(obj.f2_ln, math.log(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=20, normal=15, big=1)
+ obj = IntegerModel.objects.annotate(
+ small_ln=Ln('small'),
+ normal_ln=Ln('normal'),
+ big_ln=Ln('big'),
+ ).first()
+ self.assertIsInstance(obj.small_ln, float)
+ self.assertIsInstance(obj.normal_ln, float)
+ self.assertIsInstance(obj.big_ln, float)
+ self.assertAlmostEqual(obj.small_ln, math.log(obj.small))
+ self.assertAlmostEqual(obj.normal_ln, math.log(obj.normal))
+ self.assertAlmostEqual(obj.big_ln, math.log(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Ln)
+ DecimalModel.objects.create(n1=Decimal('12.0'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('1.0'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__ln__gt=0)
+ self.assertQuerysetEqual(objs, [Decimal('12.0')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Ln)
diff --git a/tests/db_functions/math/test_log.py b/tests/db_functions/math/test_log.py
new file mode 100644
index 0000000000..02cbe084d3
--- /dev/null
+++ b/tests/db_functions/math/test_log.py
@@ -0,0 +1,36 @@
+import math
+from decimal import Decimal
+
+from django.db.models.functions import Log
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class LogTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('12.9'), n2=Decimal('3.6'))
+ obj = DecimalModel.objects.annotate(n_log=Log('n1', 'n2')).first()
+ self.assertIsInstance(obj.n_log, Decimal)
+ self.assertAlmostEqual(obj.n_log, Decimal(math.log(obj.n2, obj.n1)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=2.0, f2=4.0)
+ obj = FloatModel.objects.annotate(f_log=Log('f1', 'f2')).first()
+ self.assertIsInstance(obj.f_log, float)
+ self.assertAlmostEqual(obj.f_log, math.log(obj.f2, obj.f1))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=4, normal=8, big=2)
+ obj = IntegerModel.objects.annotate(
+ small_log=Log('small', 'big'),
+ normal_log=Log('normal', 'big'),
+ big_log=Log('big', 'big'),
+ ).first()
+ self.assertIsInstance(obj.small_log, float)
+ self.assertIsInstance(obj.normal_log, float)
+ self.assertIsInstance(obj.big_log, float)
+ self.assertAlmostEqual(obj.small_log, math.log(obj.big, obj.small))
+ self.assertAlmostEqual(obj.normal_log, math.log(obj.big, obj.normal))
+ self.assertAlmostEqual(obj.big_log, math.log(obj.big, obj.big))
diff --git a/tests/db_functions/math/test_mod.py b/tests/db_functions/math/test_mod.py
new file mode 100644
index 0000000000..0e90175ddc
--- /dev/null
+++ b/tests/db_functions/math/test_mod.py
@@ -0,0 +1,36 @@
+import math
+from decimal import Decimal
+
+from django.db.models.functions import Mod
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class ModTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-9.9'), n2=Decimal('4.6'))
+ obj = DecimalModel.objects.annotate(n_mod=Mod('n1', 'n2')).first()
+ self.assertIsInstance(obj.n_mod, Decimal)
+ self.assertAlmostEqual(obj.n_mod, Decimal(math.fmod(obj.n1, obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-25, f2=0.33)
+ obj = FloatModel.objects.annotate(f_mod=Mod('f1', 'f2')).first()
+ self.assertIsInstance(obj.f_mod, float)
+ self.assertAlmostEqual(obj.f_mod, math.fmod(obj.f1, obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=20, normal=15, big=1)
+ obj = IntegerModel.objects.annotate(
+ small_mod=Mod('small', 'normal'),
+ normal_mod=Mod('normal', 'big'),
+ big_mod=Mod('big', 'small'),
+ ).first()
+ self.assertIsInstance(obj.small_mod, float)
+ self.assertIsInstance(obj.normal_mod, float)
+ self.assertIsInstance(obj.big_mod, float)
+ self.assertEqual(obj.small_mod, math.fmod(obj.small, obj.normal))
+ self.assertEqual(obj.normal_mod, math.fmod(obj.normal, obj.big))
+ self.assertEqual(obj.big_mod, math.fmod(obj.big, obj.small))
diff --git a/tests/db_functions/math/test_pi.py b/tests/db_functions/math/test_pi.py
new file mode 100644
index 0000000000..2446420fd3
--- /dev/null
+++ b/tests/db_functions/math/test_pi.py
@@ -0,0 +1,15 @@
+import math
+
+from django.db.models.functions import Pi
+from django.test import TestCase
+
+from ..models import FloatModel
+
+
+class PiTests(TestCase):
+
+ def test(self):
+ FloatModel.objects.create(f1=2.5, f2=15.9)
+ obj = FloatModel.objects.annotate(pi=Pi()).first()
+ self.assertIsInstance(obj.pi, float)
+ self.assertAlmostEqual(obj.pi, math.pi, places=5)
diff --git a/tests/db_functions/math/test_power.py b/tests/db_functions/math/test_power.py
new file mode 100644
index 0000000000..01ca2b34d9
--- /dev/null
+++ b/tests/db_functions/math/test_power.py
@@ -0,0 +1,35 @@
+from decimal import Decimal
+
+from django.db.models.functions import Power
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class PowerTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('1.0'), n2=Decimal('-0.6'))
+ obj = DecimalModel.objects.annotate(n_power=Power('n1', 'n2')).first()
+ self.assertIsInstance(obj.n_power, Decimal)
+ self.assertAlmostEqual(obj.n_power, Decimal(obj.n1 ** obj.n2))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=2.3, f2=1.1)
+ obj = FloatModel.objects.annotate(f_power=Power('f1', 'f2')).first()
+ self.assertIsInstance(obj.f_power, float)
+ self.assertAlmostEqual(obj.f_power, obj.f1 ** obj.f2)
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-1, normal=20, big=3)
+ obj = IntegerModel.objects.annotate(
+ small_power=Power('small', 'normal'),
+ normal_power=Power('normal', 'big'),
+ big_power=Power('big', 'small'),
+ ).first()
+ self.assertIsInstance(obj.small_power, float)
+ self.assertIsInstance(obj.normal_power, float)
+ self.assertIsInstance(obj.big_power, float)
+ self.assertAlmostEqual(obj.small_power, obj.small ** obj.normal)
+ self.assertAlmostEqual(obj.normal_power, obj.normal ** obj.big)
+ self.assertAlmostEqual(obj.big_power, obj.big ** obj.small)
diff --git a/tests/db_functions/math/test_radians.py b/tests/db_functions/math/test_radians.py
new file mode 100644
index 0000000000..296c21e692
--- /dev/null
+++ b/tests/db_functions/math/test_radians.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Radians
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class RadiansTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_radians=Radians('n1'), n2_radians=Radians('n2')).first()
+ self.assertIsInstance(obj.n1_radians, Decimal)
+ self.assertIsInstance(obj.n2_radians, Decimal)
+ self.assertAlmostEqual(obj.n1_radians, Decimal(math.radians(obj.n1)))
+ self.assertAlmostEqual(obj.n2_radians, Decimal(math.radians(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_radians=Radians('f1'), f2_radians=Radians('f2')).first()
+ self.assertIsInstance(obj.f1_radians, float)
+ self.assertIsInstance(obj.f2_radians, float)
+ self.assertAlmostEqual(obj.f1_radians, math.radians(obj.f1))
+ self.assertAlmostEqual(obj.f2_radians, math.radians(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-20, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_radians=Radians('small'),
+ normal_radians=Radians('normal'),
+ big_radians=Radians('big'),
+ ).first()
+ self.assertIsInstance(obj.small_radians, float)
+ self.assertIsInstance(obj.normal_radians, float)
+ self.assertIsInstance(obj.big_radians, float)
+ self.assertAlmostEqual(obj.small_radians, math.radians(obj.small))
+ self.assertAlmostEqual(obj.normal_radians, math.radians(obj.normal))
+ self.assertAlmostEqual(obj.big_radians, math.radians(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Radians)
+ DecimalModel.objects.create(n1=Decimal('2.0'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('-1.0'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__radians__gt=0)
+ self.assertQuerysetEqual(objs, [Decimal('2.0')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Radians)
diff --git a/tests/db_functions/math/test_round.py b/tests/db_functions/math/test_round.py
new file mode 100644
index 0000000000..9ad390bd24
--- /dev/null
+++ b/tests/db_functions/math/test_round.py
@@ -0,0 +1,50 @@
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Round
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class RoundTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_round=Round('n1'), n2_round=Round('n2')).first()
+ self.assertIsInstance(obj.n1_round, Decimal)
+ self.assertIsInstance(obj.n2_round, Decimal)
+ self.assertAlmostEqual(obj.n1_round, round(obj.n1))
+ self.assertAlmostEqual(obj.n2_round, round(obj.n2))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.55, f2=0.55)
+ obj = FloatModel.objects.annotate(f1_round=Round('f1'), f2_round=Round('f2')).first()
+ self.assertIsInstance(obj.f1_round, float)
+ self.assertIsInstance(obj.f2_round, float)
+ self.assertAlmostEqual(obj.f1_round, round(obj.f1))
+ self.assertAlmostEqual(obj.f2_round, round(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-20, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_round=Round('small'),
+ normal_round=Round('normal'),
+ big_round=Round('big'),
+ ).first()
+ self.assertIsInstance(obj.small_round, int)
+ self.assertIsInstance(obj.normal_round, int)
+ self.assertIsInstance(obj.big_round, int)
+ self.assertEqual(obj.small_round, round(obj.small))
+ self.assertEqual(obj.normal_round, round(obj.normal))
+ self.assertEqual(obj.big_round, round(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Round)
+ DecimalModel.objects.create(n1=Decimal('2.0'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('-1.0'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__round__gt=0)
+ self.assertQuerysetEqual(objs, [Decimal('2.0')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Round)
diff --git a/tests/db_functions/math/test_sin.py b/tests/db_functions/math/test_sin.py
new file mode 100644
index 0000000000..efcf3319f0
--- /dev/null
+++ b/tests/db_functions/math/test_sin.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Sin
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class SinTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_sin=Sin('n1'), n2_sin=Sin('n2')).first()
+ self.assertIsInstance(obj.n1_sin, Decimal)
+ self.assertIsInstance(obj.n2_sin, Decimal)
+ self.assertAlmostEqual(obj.n1_sin, Decimal(math.sin(obj.n1)))
+ self.assertAlmostEqual(obj.n2_sin, Decimal(math.sin(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_sin=Sin('f1'), f2_sin=Sin('f2')).first()
+ self.assertIsInstance(obj.f1_sin, float)
+ self.assertIsInstance(obj.f2_sin, float)
+ self.assertAlmostEqual(obj.f1_sin, math.sin(obj.f1))
+ self.assertAlmostEqual(obj.f2_sin, math.sin(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-20, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_sin=Sin('small'),
+ normal_sin=Sin('normal'),
+ big_sin=Sin('big'),
+ ).first()
+ self.assertIsInstance(obj.small_sin, float)
+ self.assertIsInstance(obj.normal_sin, float)
+ self.assertIsInstance(obj.big_sin, float)
+ self.assertAlmostEqual(obj.small_sin, math.sin(obj.small))
+ self.assertAlmostEqual(obj.normal_sin, math.sin(obj.normal))
+ self.assertAlmostEqual(obj.big_sin, math.sin(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Sin)
+ DecimalModel.objects.create(n1=Decimal('5.4'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('0.1'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__sin__lt=0)
+ self.assertQuerysetEqual(objs, [Decimal('5.4')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Sin)
diff --git a/tests/db_functions/math/test_sqrt.py b/tests/db_functions/math/test_sqrt.py
new file mode 100644
index 0000000000..c391a6f5a9
--- /dev/null
+++ b/tests/db_functions/math/test_sqrt.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Sqrt
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class SqrtTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_sqrt=Sqrt('n1'), n2_sqrt=Sqrt('n2')).first()
+ self.assertIsInstance(obj.n1_sqrt, Decimal)
+ self.assertIsInstance(obj.n2_sqrt, Decimal)
+ self.assertAlmostEqual(obj.n1_sqrt, Decimal(math.sqrt(obj.n1)))
+ self.assertAlmostEqual(obj.n2_sqrt, Decimal(math.sqrt(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_sqrt=Sqrt('f1'), f2_sqrt=Sqrt('f2')).first()
+ self.assertIsInstance(obj.f1_sqrt, float)
+ self.assertIsInstance(obj.f2_sqrt, float)
+ self.assertAlmostEqual(obj.f1_sqrt, math.sqrt(obj.f1))
+ self.assertAlmostEqual(obj.f2_sqrt, math.sqrt(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=20, normal=15, big=1)
+ obj = IntegerModel.objects.annotate(
+ small_sqrt=Sqrt('small'),
+ normal_sqrt=Sqrt('normal'),
+ big_sqrt=Sqrt('big'),
+ ).first()
+ self.assertIsInstance(obj.small_sqrt, float)
+ self.assertIsInstance(obj.normal_sqrt, float)
+ self.assertIsInstance(obj.big_sqrt, float)
+ self.assertAlmostEqual(obj.small_sqrt, math.sqrt(obj.small))
+ self.assertAlmostEqual(obj.normal_sqrt, math.sqrt(obj.normal))
+ self.assertAlmostEqual(obj.big_sqrt, math.sqrt(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Sqrt)
+ DecimalModel.objects.create(n1=Decimal('6.0'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('1.0'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__sqrt__gt=2)
+ self.assertQuerysetEqual(objs, [Decimal('6.0')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Sqrt)
diff --git a/tests/db_functions/math/test_tan.py b/tests/db_functions/math/test_tan.py
new file mode 100644
index 0000000000..1df294150f
--- /dev/null
+++ b/tests/db_functions/math/test_tan.py
@@ -0,0 +1,51 @@
+import math
+from decimal import Decimal
+
+from django.db.models import DecimalField
+from django.db.models.functions import Tan
+from django.test import TestCase
+
+from ..models import DecimalModel, FloatModel, IntegerModel
+
+
+class TanTests(TestCase):
+
+ def test_decimal(self):
+ DecimalModel.objects.create(n1=Decimal('-12.9'), n2=Decimal('0.6'))
+ obj = DecimalModel.objects.annotate(n1_tan=Tan('n1'), n2_tan=Tan('n2')).first()
+ self.assertIsInstance(obj.n1_tan, Decimal)
+ self.assertIsInstance(obj.n2_tan, Decimal)
+ self.assertAlmostEqual(obj.n1_tan, Decimal(math.tan(obj.n1)))
+ self.assertAlmostEqual(obj.n2_tan, Decimal(math.tan(obj.n2)))
+
+ def test_float(self):
+ FloatModel.objects.create(f1=-27.5, f2=0.33)
+ obj = FloatModel.objects.annotate(f1_tan=Tan('f1'), f2_tan=Tan('f2')).first()
+ self.assertIsInstance(obj.f1_tan, float)
+ self.assertIsInstance(obj.f2_tan, float)
+ self.assertAlmostEqual(obj.f1_tan, math.tan(obj.f1))
+ self.assertAlmostEqual(obj.f2_tan, math.tan(obj.f2))
+
+ def test_integer(self):
+ IntegerModel.objects.create(small=-20, normal=15, big=-1)
+ obj = IntegerModel.objects.annotate(
+ small_tan=Tan('small'),
+ normal_tan=Tan('normal'),
+ big_tan=Tan('big'),
+ ).first()
+ self.assertIsInstance(obj.small_tan, float)
+ self.assertIsInstance(obj.normal_tan, float)
+ self.assertIsInstance(obj.big_tan, float)
+ self.assertAlmostEqual(obj.small_tan, math.tan(obj.small))
+ self.assertAlmostEqual(obj.normal_tan, math.tan(obj.normal))
+ self.assertAlmostEqual(obj.big_tan, math.tan(obj.big))
+
+ def test_transform(self):
+ try:
+ DecimalField.register_lookup(Tan)
+ DecimalModel.objects.create(n1=Decimal('0.0'), n2=Decimal('0'))
+ DecimalModel.objects.create(n1=Decimal('12.0'), n2=Decimal('0'))
+ objs = DecimalModel.objects.filter(n1__tan__lt=0)
+ self.assertQuerysetEqual(objs, [Decimal('12.0')], lambda a: a.n1)
+ finally:
+ DecimalField._unregister_lookup(Tan)
diff --git a/tests/db_functions/models.py b/tests/db_functions/models.py
index 24ffba78fc..c31de39b85 100644
--- a/tests/db_functions/models.py
+++ b/tests/db_functions/models.py
@@ -54,3 +54,14 @@ class DTModel(models.Model):
class DecimalModel(models.Model):
n1 = models.DecimalField(decimal_places=2, max_digits=6)
n2 = models.DecimalField(decimal_places=2, max_digits=6)
+
+
+class IntegerModel(models.Model):
+ big = models.BigIntegerField(null=True, blank=True)
+ normal = models.IntegerField(null=True, blank=True)
+ small = models.SmallIntegerField(null=True, blank=True)
+
+
+class FloatModel(models.Model):
+ f1 = models.FloatField(null=True, blank=True)
+ f2 = models.FloatField(null=True, blank=True)