Commit | Line | Data |
---|---|---|
ffad1322 MW |
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() |