Commit | Line | Data |
---|---|---|
553d59fe 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 | ||
30 | import sys as SYS | |
31 | import catacomb as C | |
32 | import unittest as U | |
33 | import testutils as T | |
34 | ||
35 | ###-------------------------------------------------------------------------- | |
36 | class 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 | ||
f7623015 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') | |
553d59fe 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 | ||
49e3a113 MW |
65 | ## Check slicing. This should always give us bytes. |
66 | me.assertEqual(type(x[7:17]), C.ByteString) | |
553d59fe 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. | |
49e3a113 | 154 | me.assertEqual(type(x + y), C.ByteString) |
553d59fe MW |
155 | me.assertEqual(x + y, C.bytes("03a5fc5fac30")) |
156 | ||
157 | ## Replication (asymmetric but commutative). | |
49e3a113 MW |
158 | me.assertEqual(type(3*x), C.ByteString) |
159 | me.assertEqual(type(x*3), C.ByteString) | |
553d59fe MW |
160 | me.assertEqual(3*x, C.bytes("03a5fc03a5fc03a5fc")) |
161 | me.assertEqual(x*3, C.bytes("03a5fc03a5fc03a5fc")) | |
162 | ||
163 | ## Replication by zero (regression test). | |
49e3a113 MW |
164 | me.assertEqual(type(0*x), C.ByteString) |
165 | me.assertEqual(type(x*0), C.ByteString) | |
553d59fe 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 | ||
175 | if __name__ == "__main__": U.main() |