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