| 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() |