t/: Add a test suite.
[catacomb-python] / t / t-convert.py
1 ### -*- mode: python, coding: utf-8 -*-
2 ###
3 ### Testing implicit conversions
4 ###
5 ### (c) 2019 Straylight/Edgeware
6 ###
7
8 ###----- Licensing notice ---------------------------------------------------
9 ###
10 ### This file is part of the Python interface to Catacomb.
11 ###
12 ### Catacomb/Python is free software: you can redistribute it and/or
13 ### modify it under the terms of the GNU General Public License as
14 ### published by the Free Software Foundation; either version 2 of the
15 ### License, or (at your option) any later version.
16 ###
17 ### Catacomb/Python is distributed in the hope that it will be useful, but
18 ### WITHOUT ANY WARRANTY; without even the implied warranty of
19 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ### General Public License for more details.
21 ###
22 ### You should have received a copy of the GNU General Public License
23 ### along with Catacomb/Python. If not, write to the Free Software
24 ### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 ### USA.
26
27 ###--------------------------------------------------------------------------
28 ### Imported modules.
29
30 import catacomb as C
31 import sys as SYS
32 import unittest as U
33 import testutils as T
34
35 ###--------------------------------------------------------------------------
36 class TestConvert (U.TestCase):
37 """Test implicit conversions between various mathematical types."""
38
39 def test(me):
40
41 k = C.PrimeField(17)
42 E = k.ec(-3, 4)
43 P = E(1) # order 15
44 kk = C.BinPolyField(0x13)
45 EE = kk.ec(1, 2)
46 PP = E(9) # order 16
47
48 ## `MP' asymmetric operations.
49 me.assertEqual(pow(C.MP(5), 2), 25)
50 me.assertEqual(pow(5, C.MP(2)), 25)
51 me.assertEqual(pow(C.MP(5), 2, 7), 4)
52 me.assertEqual(pow(5, C.MP(2), 7), 4)
53 me.assertEqual(pow(5, 2, C.MP(7)), 4)
54 for bad in [lambda x: [x]]:
55 me.assertRaises(TypeError, pow, C.MP(5), bad(2))
56 me.assertRaises(TypeError, pow, C.MP(5), bad(2), 7)
57 if not T.DEBUGP:
58 ## Debug builds of Python 2 crash here, and it's not our fault. Run
59 ##
60 ## $ python2.7-dbg -c 'pow(long(5), 2, [7])'
61 ##
62 ## to confirm. The `[7]' causes coercion to occur. The first and
63 ## second operands are coerced first, and successfully replaced by
64 ## the results: the first operand (in this case) is unchanged, but
65 ## has its refcount bumped, and the second operand is replaced by the
66 ## result of coercion, which now has a refcount of 1. Then the first
67 ## and third operands are coerced, which fails. Python decrements
68 ## the refcounts of the results of the first coercion, so the second
69 ## operand is now freed and, in debug builds, clobbered. Python then
70 ## tries to format an error message, quoting the types of the
71 ## operands, but one of them has been lost.
72 me.assertRaises(TypeError, pow, C.MP(5), 2, bad(7))
73 me.assertRaises(TypeError, T.lsl, C.MP(5), bad(2))
74
75 ## `GF' asymmetric operations.
76 me.assertEqual(pow(C.GF(0x5), 2), C.GF(0x11))
77 me.assertEqual(pow(C.GF(0x5), C.MP(2)), C.GF(0x11))
78 me.assertEqual(pow(C.GF(5), 2, C.GF(0x13)), C.GF(0x2))
79 for bad in [lambda x: [x]]:
80 me.assertRaises(TypeError, pow, C.GF(5), bad(2))
81 me.assertRaises(TypeError, T.lsl, C.GF(5), bad(2))
82 for bad in [lambda x: [x]]:
83 me.assertRaises(TypeError, pow, bad(5), C.GF(2))
84 me.assertRaises(TypeError, pow, bad(5), C.GF(2), bad(7))
85 me.assertRaises(TypeError, pow, bad(5), bad(2), C.GF(7))
86 me.assertRaises(TypeError, pow, C.GF(5), bad(2), bad(7))
87 if not T.DEBUGP:
88 ## Python bug: see above.
89 me.assertRaises(TypeError, pow, C.GF(5), 2, bad(7))
90
91 ## `MP' and `GF'.
92 me.assertEqual(C.MP(5), 5)
93 me.assertEqual(5, C.MP(5))
94
95 me.assertEqual(C.MP(5) + 3, 8)
96 me.assertEqual(3 + C.MP(5), 8)
97 me.assertRaises(TypeError, T.add, C.MP(5), C.GF(3))
98 me.assertRaises(TypeError, T.add, C.GF(3), C.MP(5))
99
100 ## Field elements.
101 me.assertEqual(k(3) + 4, 7)
102 me.assertEqual(4 + k(3), 7)
103 me.assertEqual(k(3) + C.MP(4), 7)
104 me.assertEqual(C.MP(4) + k(3), 7)
105 me.assertEqual(k(3) + 4, 7)
106 me.assertEqual(C.GF(7) + kk(3), C.GF(4))
107 me.assertEqual(kk(3) + C.GF(7), C.GF(4))
108
109 me.assertRaises(TypeError, T.add, k(3), kk(3))
110 me.assertRaises(TypeError, T.add, kk(3), k(3))
111
112 ###----- That's all, folks --------------------------------------------------
113
114 if __name__ == "__main__": U.main()