-
Notifications
You must be signed in to change notification settings - Fork 38
/
rstest.py
176 lines (135 loc) · 5.94 KB
/
rstest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import unittest
import itertools
import rs
class TestRSverify(unittest.TestCase):
def setUp(self):
self.coder = rs.RSCoder(255,223)
def test_one(self):
"""Tests a codeword without errors validates"""
code = self.coder.encode("Hello, world!")
self.assertTrue(self.coder.verify(code))
def test_two(self):
"""Verifies that changing any single character will invalidate the
codeword"""
code = self.coder.encode("Hello, world! This is a test message, to be encoded,"
" and verified.")
for i, c in enumerate(code):
# Change the value at position i and verify that the code is not
# valid
# Change it to a 0, unless it's already a 0
if ord(c) == 0:
c = chr(1)
else:
c = chr(0)
bad_code = code[:i] + c + code[i+1:]
self.assertFalse(self.coder.verify(bad_code))
class TestRSdecoding(unittest.TestCase):
def setUp(self):
self.coder = rs.RSCoder(255,223)
self.string = "Hello, world! This is a long string"
codestr = self.coder.encode(self.string)
self.code = codestr
def test_strip(self):
"""Tests that the nostrip feature works"""
otherstr = self.string.rjust(223, "\0")
codestr = self.coder.encode(otherstr)
self.assertEqual(255, len(codestr))
# Decode with default behavior: stripping of leading null bytes
decode = self.coder.decode(codestr)
decode2 = self.coder.decode(codestr[:5] + "\x50" + codestr[6:])
self.assertEqual(self.string, decode)
self.assertEqual(self.string, decode2)
# Decode with nostrip
decode = self.coder.decode(codestr, nostrip=True)
decode2 = self.coder.decode(codestr[:5] + "\x50" + codestr[6:], nostrip=True)
self.assertEqual(otherstr, decode)
self.assertEqual(otherstr, decode2)
def test_noerr(self):
"""Make sure a codeword with no errors decodes"""
decode = self.coder.decode(self.code)
self.assertEqual(self.string, decode)
def test_oneerr(self):
"""Change just one byte and make sure it decodes"""
for i, c in enumerate(self.code):
newch = chr( (ord(c)+50) % 256 )
r = self.code[:i] + newch + self.code[i+1:]
decode = self.coder.decode(r)
self.assertEqual(self.string, decode)
def disabled_test_twoerr(self):
"""Test that changing every combination of 2 bytes still decodes.
This test is long and probably unnecessary."""
# Test disabled, it takes too long
for i1, i2 in itertools.combinations(range(len(self.code)), 2):
r = list(ord(x) for x in self.code)
# increment the byte by 50
r[i1] = (r[i1] + 50) % 256
r[i2] = (r[i2] + 50) % 256
r = "".join(chr(x) for x in r)
decode = self.coder.decode(r)
self.assertEqual(self.string, decode)
def test_16err(self):
"""Tests if 16 byte errors still decodes"""
errors = [5, 6, 12, 13, 38, 40, 42, 47, 50, 57, 58, 59, 60, 61, 62, 65]
r = list(ord(x) for x in self.code)
for e in errors:
r[e] = (r[e] + 50) % 256
r = "".join(chr(x) for x in r)
decode = self.coder.decode(r)
self.assertEqual(self.string, decode)
def test_17err(self):
"""Kinda pointless, checks that 17 errors doesn't decode.
Actually, this could still decode by coincidence on some inputs,
so this test shouldn't be here at all."""
errors = [5, 6, 12, 13, 22, 38, 40, 42, 47, 50, 57, 58, 59, 60, 61, 62,
65]
r = list(ord(x) for x in self.code)
for e in errors:
r[e] = (r[e] + 50) % 256
r = "".join(chr(x) for x in r)
decode = self.coder.decode(r)
self.assertNotEqual(self.string, decode)
class TestOtherConfig(unittest.TestCase):
"""Tests a configuration of the coder other than RS(255,223)"""
def test255_13(self):
coder = rs.RSCoder(255,13)
m = "Hello, world!"
code = coder.encode(m)
self.assertTrue( coder.verify(code) )
self.assertEqual(m, coder.decode(code) )
self.assertEqual(255, len(code))
# Change 121 bytes. This code should tolerate up to 121 bytes changed
changes = [1, 4, 5, 6, 9, 10, 14, 15, 19, 20, 21, 24, 26, 30, 32, 34,
38, 39, 40, 42, 43, 44, 45, 47, 49, 50, 53, 59, 60, 62, 65, 67,
68, 69, 71, 73, 74, 79, 80, 81, 85, 89, 90, 93, 94, 95, 100,
101, 105, 106, 107, 110, 112, 117, 120, 121, 123, 126, 127,
132, 133, 135, 136, 138, 143, 149, 150, 152, 154, 158, 159,
161, 162, 163, 165, 166, 168, 169, 170, 174, 176, 177, 178,
179, 182, 186, 191, 192, 193, 196, 197, 198, 200, 203, 206,
208, 209, 210, 211, 212, 216, 219, 222, 224, 225, 226, 228,
230, 232, 234, 235, 237, 238, 240, 242, 244, 245, 248, 249,
250, 253]
c = list(ord(x) for x in code)
for pos in changes:
c[pos] = (c[pos] + 50) % 255
c = "".join(chr(x) for x in c)
decode = coder.decode(c)
self.assertEqual(m, decode)
def test30_10(self):
"""Tests the RS(30,10) code"""
coder = rs.RSCoder(30,10)
m = "Hello, wor"
code = coder.encode(m)
self.assertTrue( coder.verify(code) )
self.assertEqual(m, coder.decode(code) )
self.assertEqual(30, len(code))
# Change 10 bytes. This code should tolerate up to 10 bytes changed
changes = [0, 1, 2, 4, 7,
10, 14, 18, 22, 27]
c = list(ord(x) for x in code)
for pos in changes:
c[pos] = (c[pos] + 50) % 255
c = "".join(chr(x) for x in c)
decode = coder.decode(c)
self.assertEqual(m, decode)
if __name__ == "__main__":
unittest.main()