chiark / gitweb /
t/: Add a test suite.
[catacomb-python] / t / t-convert.py
diff --git a/t/t-convert.py b/t/t-convert.py
new file mode 100644 (file)
index 0000000..08c660f
--- /dev/null
@@ -0,0 +1,114 @@
+### -*- mode: python, coding: utf-8 -*-
+###
+### Testing implicit conversions
+###
+### (c) 2019 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Python interface to Catacomb.
+###
+### Catacomb/Python is free software: you can redistribute it and/or
+### modify it under the terms of the GNU General Public License as
+### published by the Free Software Foundation; either version 2 of the
+### License, or (at your option) any later version.
+###
+### Catacomb/Python is distributed in the hope that it will be useful, but
+### WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+### General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with Catacomb/Python.  If not, write to the Free Software
+### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+### USA.
+
+###--------------------------------------------------------------------------
+### Imported modules.
+
+import catacomb as C
+import sys as SYS
+import unittest as U
+import testutils as T
+
+###--------------------------------------------------------------------------
+class TestConvert (U.TestCase):
+  """Test implicit conversions between various mathematical types."""
+
+  def test(me):
+
+    k = C.PrimeField(17)
+    E = k.ec(-3, 4)
+    P = E(1) # order 15
+    kk = C.BinPolyField(0x13)
+    EE = kk.ec(1, 2)
+    PP = E(9) # order 16
+
+    ## `MP' asymmetric operations.
+    me.assertEqual(pow(C.MP(5), 2), 25)
+    me.assertEqual(pow(5, C.MP(2)), 25)
+    me.assertEqual(pow(C.MP(5), 2, 7), 4)
+    me.assertEqual(pow(5, C.MP(2), 7), 4)
+    me.assertEqual(pow(5, 2, C.MP(7)), 4)
+    for bad in [lambda x: [x]]:
+      me.assertRaises(TypeError, pow, C.MP(5), bad(2))
+      me.assertRaises(TypeError, pow, C.MP(5), bad(2), 7)
+      if not T.DEBUGP:
+        ## Debug builds of Python 2 crash here, and it's not our fault.  Run
+        ##
+        ## $ python2.7-dbg -c 'pow(long(5), 2, [7])'
+        ##
+        ## to confirm.  The `[7]' causes coercion to occur.  The first and
+        ## second operands are coerced first, and successfully replaced by
+        ## the results: the first operand (in this case) is unchanged, but
+        ## has its refcount bumped, and the second operand is replaced by the
+        ## result of coercion, which now has a refcount of 1.  Then the first
+        ## and third operands are coerced, which fails.  Python decrements
+        ## the refcounts of the results of the first coercion, so the second
+        ## operand is now freed and, in debug builds, clobbered.  Python then
+        ## tries to format an error message, quoting the types of the
+        ## operands, but one of them has been lost.
+        me.assertRaises(TypeError, pow, C.MP(5), 2, bad(7))
+      me.assertRaises(TypeError, T.lsl, C.MP(5), bad(2))
+
+    ## `GF' asymmetric operations.
+    me.assertEqual(pow(C.GF(0x5), 2), C.GF(0x11))
+    me.assertEqual(pow(C.GF(0x5), C.MP(2)), C.GF(0x11))
+    me.assertEqual(pow(C.GF(5), 2, C.GF(0x13)), C.GF(0x2))
+    for bad in [lambda x: [x]]:
+      me.assertRaises(TypeError, pow, C.GF(5), bad(2))
+      me.assertRaises(TypeError, T.lsl, C.GF(5), bad(2))
+    for bad in [lambda x: [x]]:
+      me.assertRaises(TypeError, pow, bad(5), C.GF(2))
+      me.assertRaises(TypeError, pow, bad(5), C.GF(2), bad(7))
+      me.assertRaises(TypeError, pow, bad(5), bad(2), C.GF(7))
+      me.assertRaises(TypeError, pow, C.GF(5), bad(2), bad(7))
+      if not T.DEBUGP:
+        ## Python bug: see above.
+        me.assertRaises(TypeError, pow, C.GF(5), 2, bad(7))
+
+    ## `MP' and `GF'.
+    me.assertEqual(C.MP(5), 5)
+    me.assertEqual(5, C.MP(5))
+
+    me.assertEqual(C.MP(5) + 3, 8)
+    me.assertEqual(3 + C.MP(5), 8)
+    me.assertRaises(TypeError, T.add, C.MP(5), C.GF(3))
+    me.assertRaises(TypeError, T.add, C.GF(3), C.MP(5))
+
+    ## Field elements.
+    me.assertEqual(k(3) + 4, 7)
+    me.assertEqual(4 + k(3), 7)
+    me.assertEqual(k(3) + C.MP(4), 7)
+    me.assertEqual(C.MP(4) + k(3), 7)
+    me.assertEqual(k(3) + 4, 7)
+    me.assertEqual(C.GF(7) + kk(3), C.GF(4))
+    me.assertEqual(kk(3) + C.GF(7), C.GF(4))
+
+    me.assertRaises(TypeError, T.add, k(3), kk(3))
+    me.assertRaises(TypeError, T.add, kk(3), k(3))
+
+###----- That's all, folks --------------------------------------------------
+
+if __name__ == "__main__": U.main()