|
1 | 1 | #!/usr/bin/env python |
2 | 2 |
|
3 | | -import binascii |
4 | | -import hashlib |
5 | 3 | import os |
6 | 4 | import random |
7 | 5 | import unittest |
8 | 6 |
|
9 | 7 | import bchlib |
10 | 8 |
|
11 | 9 |
|
12 | | -def bitflip(data, bits): |
13 | | - bit = random.randint(8 - (bits % 8), bits) |
14 | | - data[bit // 8] ^= 0x80 >> (bit % 8) |
| 10 | +def bitflip(data): |
| 11 | + bit = random.randint(0, len(data) * 8 - 1) |
| 12 | + data[bit // 8] ^= 1 << (bit % 8) |
15 | 13 |
|
16 | | -class BCHTestCase(unittest.TestCase): |
| 14 | +class Tests(unittest.TestCase): |
17 | 15 | def exercise(self, *args, **kwargs): |
18 | | - # create a bch object |
19 | 16 | bch = bchlib.BCH(*args, **kwargs) |
20 | | - max_data_len = (bch.n + 7) // 8 - (bch.ecc_bits + 7) // 8 |
| 17 | + bits = bch.n - bch.ecc_bits |
21 | 18 |
|
22 | | - print('max_data_len: %d' % (max_data_len,)) |
23 | | - print('ecc_bits: %d (ecc_bytes: %d)' % (bch.ecc_bits, bch.ecc_bytes)) |
24 | | - print('m: %d' % (bch.m,)) |
25 | | - print('n: %d (%d bytes)' % (bch.n, bch.n // 8)) |
26 | | - print('prim_poly: 0x%x' % (bch.prim_poly,)) |
27 | | - print('t: %d' % (bch.t,)) |
| 19 | + # print(f'data:\t{bits} bits (usable bytes: {bits // 8})') |
| 20 | + # print(f'ecc: \t{bch.ecc_bits} bits (bytes: {bch.ecc_bytes})') |
| 21 | + # print(f'm: \t{bch.m}') |
| 22 | + # print(f'n: \t{bch.n} ({(bch.n + 7) // 8} bytes)') |
| 23 | + # print(f'poly:\t{bch.prim_poly}') |
| 24 | + # print(f't: \t{bch.t}') |
28 | 25 |
|
29 | | - # random data |
30 | | - data = bytearray(os.urandom(max_data_len)) |
31 | | - |
32 | | - # encode and make a "packet" |
| 26 | + data = bytearray(os.urandom(bits // 8)) |
33 | 27 | ecc = bch.encode(data) |
34 | | - print('encoded ecc:', binascii.hexlify(ecc).decode('utf-8')) |
35 | 28 | packet = data + ecc |
| 29 | + corrupted_packet = bytearray(packet) |
36 | 30 |
|
37 | | - # print hash of packet |
38 | | - sha1_initial = hashlib.sha1(packet) |
39 | | - print('packet sha1: %s' % (sha1_initial.hexdigest(),)) |
40 | | - |
41 | | - # make BCH_BITS errors |
42 | 31 | for _ in range(bch.t): |
43 | | - bitflip(packet, bch.n) |
| 32 | + bitflip(corrupted_packet) |
44 | 33 |
|
45 | | - # print hash of packet |
46 | | - sha1_corrupt = hashlib.sha1(packet) |
47 | | - print('packet sha1: %s' % (sha1_corrupt.hexdigest(),)) |
| 34 | + corrupted_data = corrupted_packet[:-bch.ecc_bytes] |
| 35 | + corrupted_ecc = corrupted_packet[-bch.ecc_bytes:] |
48 | 36 |
|
49 | | - # de-packetize |
50 | | - data, ecc = packet[:-bch.ecc_bytes], packet[-bch.ecc_bytes:] |
| 37 | + nerr = bch.decode(corrupted_data, corrupted_ecc) |
| 38 | + # print(f'nerr: \t{nerr}') |
| 39 | + assert(nerr >= 0) |
| 40 | + # print(bch.errloc) |
51 | 41 |
|
52 | | - # decode |
53 | | - nerr = bch.decode(data, ecc) |
| 42 | + corrected_data = bytearray(corrupted_data) |
| 43 | + corrected_ecc = bytearray(corrupted_ecc) |
| 44 | + bch.correct(corrected_data, corrected_ecc) |
| 45 | + corrected_packet = corrected_data + corrected_ecc |
54 | 46 |
|
55 | | - print('nerr:', nerr) |
56 | | - print('syn:', bch.syn) |
57 | | - print('errloc:', bch.errloc) |
| 47 | + assert(corrected_packet == packet) |
58 | 48 |
|
59 | | - # correct |
60 | | - bch.correct(data, ecc) |
61 | | - |
62 | | - # packetize |
63 | | - packet = data + ecc |
| 49 | + def test_t_eq_6_285(self): |
| 50 | + for _ in range(1000): |
| 51 | + self.exercise(6, prim_poly=285) |
64 | 52 |
|
65 | | - # print hash of packet |
66 | | - sha1_corrected = hashlib.sha1(packet) |
67 | | - print('packet sha1: %s' % (sha1_corrected.hexdigest(),)) |
| 53 | + def test_t_eq_6_285_swap(self): |
| 54 | + for _ in range(1000): |
| 55 | + self.exercise(6, prim_poly=285, swap_bits=True) |
68 | 56 |
|
69 | | - if sha1_initial.digest() == sha1_corrected.digest(): |
70 | | - print('Corrected!') |
71 | | - else: |
72 | | - print('Failed') |
| 57 | + def test_t_eq_6_487(self): |
| 58 | + for _ in range(1000): |
| 59 | + self.exercise(6, prim_poly=487) |
73 | 60 |
|
74 | | - assert sha1_initial.digest() == sha1_corrected.digest() |
| 61 | + def test_t_eq_6_487_swap(self): |
| 62 | + for _ in range(1000): |
| 63 | + self.exercise(6, prim_poly=487, swap_bits=True) |
75 | 64 |
|
76 | | - def test_t_eq_6(self): |
77 | | - self.exercise(6, prim_poly=487) |
| 65 | + def test_t_eq_12_17475(self): |
| 66 | + for _ in range(1000): |
| 67 | + self.exercise(12, prim_poly=17475) |
78 | 68 |
|
79 | | - def test_t_eq_12(self): |
80 | | - self.exercise(12, prim_poly=17475, swap_bits=True) |
| 69 | + def test_t_eq_12_17475_swap(self): |
| 70 | + for _ in range(1000): |
| 71 | + self.exercise(12, prim_poly=17475, swap_bits=True) |
81 | 72 |
|
82 | 73 | def test_t_eq_16(self): |
83 | | - self.exercise(16, m=13) |
| 74 | + for _ in range(1000): |
| 75 | + self.exercise(16, m=13) |
| 76 | + |
| 77 | + def test_t_eq_16_swap(self): |
| 78 | + for _ in range(1000): |
| 79 | + self.exercise(16, m=13, swap_bits=True) |
84 | 80 |
|
85 | 81 | def test_t_eq_32(self): |
86 | | - self.exercise(32, m=14) |
| 82 | + for _ in range(1000): |
| 83 | + self.exercise(32, m=14) |
| 84 | + |
| 85 | + def test_t_eq_32_swap(self): |
| 86 | + for _ in range(1000): |
| 87 | + self.exercise(32, m=14, swap_bits=True) |
87 | 88 |
|
88 | 89 | def test_t_eq_64(self): |
89 | | - self.exercise(64, m=15) |
| 90 | + for _ in range(1000): |
| 91 | + self.exercise(64, m=15) |
| 92 | + |
| 93 | + def test_t_eq_64_swap(self): |
| 94 | + for _ in range(1000): |
| 95 | + self.exercise(64, m=15, swap_bits=True) |
90 | 96 |
|
91 | 97 | if __name__ == '__main__': |
92 | 98 | unittest.main() |
0 commit comments