Port to Python 3.
[catacomb-python] / t / t-bytes.py
CommitLineData
ffad1322
MW
1### -*- mode: python, coding: utf-8 -*-
2###
3### Test `ByteString'
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
30import sys as SYS
31import catacomb as C
32import unittest as U
33import testutils as T
34
35###--------------------------------------------------------------------------
36class TestByteString (U.TestCase):
37
38 def test_create(me):
39
40 ## Create a string and make sure it looks right.
41 x = C.ByteString(T.bin("abcde"))
42 me.assertEqual(x, T.bin("abcde"))
43 me.assertEqual(x, C.bytes("6162636465"))
44 me.assertEqual(len(x), 5)
45
46 def test_index(me):
47
48 x = C.ByteString(T.bin("once upon a time there was a string"))
49
d472b9a1
MW
50 ## Check that simple indexing works. Alas the behaviour differs between
51 ## Python major versions.
52 if T.PY3:
53 me.assertEqual(type(x[3]), int)
54 me.assertEqual(x[3], 101)
55 me.assertEqual(x[-5], 116)
56 else:
57 me.assertEqual(type(x[3]), C.ByteString)
58 me.assertEqual(x[3], 'e')
59 me.assertEqual(x[-5], 't')
ffad1322
MW
60
61 ## Check out-of-range detection.
62 x[34]; me.assertRaises(IndexError, lambda: x[35])
63 x[-35]; me.assertRaises(IndexError, lambda: x[-36])
64
5a5e2e11
MW
65 ## Check slicing. This should always give us bytes.
66 me.assertEqual(type(x[7:17]), C.ByteString)
ffad1322
MW
67 me.assertEqual(x[7:17], T.bin("on a time "))
68
69 ## Complex slicing is also supported.
70 me.assertEqual(x[5:23:3], C.bytes("756e206d7472"))
71
72 def test_compare(me):
73 """
74 Test byte string comparison.
75
76 This is rather important, since we override it and many of the other
77 tests assume that comparison works.
78 """
79
80 def check(big, small):
81 """Check comparisons between BIG and SMALL strings."""
82
83 ## Equality.
84 me.assertTrue(big == big)
85 me.assertFalse(big == small)
86
87 ## Inequality.
88 me.assertFalse(big != big)
89 me.assertTrue(big != small)
90
91 ## Strict less-than.
92 me.assertFalse(big < big)
93 me.assertFalse(big < small)
94 me.assertTrue(small < big)
95
96 ## Non-strict less-than.
97 me.assertTrue(big <= big)
98 me.assertFalse(big <= small)
99 me.assertTrue(small <= big)
100
101 ## Non-strict greater-than.
102 me.assertTrue(big >= big)
103 me.assertTrue(big >= small)
104 me.assertFalse(small >= big)
105
106 ## Strict greater-than.
107 me.assertFalse(big > big)
108 me.assertTrue(big > small)
109 me.assertFalse(small > big)
110
111 ## Strings with equal length.
112 check(C.ByteString(T.bin("a string which is unlike the second")),
113 C.ByteString(T.bin("a string that is not like the first")))
114
115 ## A string and a prefix of it.
116 check(C.ByteString(T.bin("short strings order before longer ones")),
117 C.ByteString(T.bin("short string")))
118
119 ## The `ctstreq' function.
120 x = T.bin("special test string")
121 y = T.bin("my different string")
122 me.assertTrue(C.ctstreq(x, x))
123 me.assertFalse(C.ctstreq(x, y))
124
125 def test_operators(me):
126
127 ## Some example strings.
128 x = C.bytes("03a5fc")
129 y = C.bytes("5fac30")
130 z = C.bytes("00000000")
131
132 ## Operands of a binary operator must have equal lengths.
133 me.assertRaises(ValueError, lambda: x&z)
134 me.assertRaises(ValueError, lambda: x|z)
135 me.assertRaises(ValueError, lambda: x^z)
136
137 ## Bitwise AND.
138 me.assertEqual(type(x&y), C.ByteString)
139 me.assertEqual(x&y, C.bytes("03a430"))
140
141 ## Bitwise OR.
142 me.assertEqual(type(x | y), C.ByteString)
143 me.assertEqual(x | y, C.bytes("5fadfc"))
144
145 # Bitwise XOR.
146 me.assertEqual(type(x ^ y), C.ByteString)
147 me.assertEqual(x ^ y, C.bytes("5c09cc"))
148
149 # Bitwise NOT.
150 me.assertEqual(type(~x), C.ByteString)
151 me.assertEqual(~x, C.bytes("fc5a03"))
152
153 ## Concatenation.
5a5e2e11 154 me.assertEqual(type(x + y), C.ByteString)
ffad1322
MW
155 me.assertEqual(x + y, C.bytes("03a5fc5fac30"))
156
157 ## Replication (asymmetric but commutative).
5a5e2e11
MW
158 me.assertEqual(type(3*x), C.ByteString)
159 me.assertEqual(type(x*3), C.ByteString)
ffad1322
MW
160 me.assertEqual(3*x, C.bytes("03a5fc03a5fc03a5fc"))
161 me.assertEqual(x*3, C.bytes("03a5fc03a5fc03a5fc"))
162
163 ## Replication by zero (regression test).
5a5e2e11
MW
164 me.assertEqual(type(0*x), C.ByteString)
165 me.assertEqual(type(x*0), C.ByteString)
ffad1322
MW
166 me.assertEqual(0*x, C.ByteString(T.bin("")))
167 me.assertEqual(x*0, C.ByteString(T.bin("")))
168
169 def test_zero(me):
170 me.assertEqual(C.ByteString.zero(7), T.bin(7*"\0"))
171 me.assertEqual(C.ByteString.zero(0), T.bin(""))
172
173###----- That's all, folks --------------------------------------------------
174
175if __name__ == "__main__": U.main()