-
Notifications
You must be signed in to change notification settings - Fork 2
/
viterbi_test.go
151 lines (125 loc) · 3.5 KB
/
viterbi_test.go
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
package viterbi
import (
"bytes"
"math/rand"
"testing"
"time"
)
func init() {
// Seed random number generator
rand.Seed(time.Now().UnixNano())
}
// Function that takes in a string of 1s and 0s and randomly flips n unique bits.
func corruptBits(bits string, n int) string {
corrupted := []rune(bits)
indices := make(map[int]bool)
for i := 0; i < n; i++ {
// Pick a random index
index := rand.Intn(len(bits))
// If we've already flipped this bit, pick another index
for indices[index] {
index = rand.Intn(len(bits))
}
// Flip the bit
if corrupted[index] == '0' {
corrupted[index] = '1'
} else {
corrupted[index] = '0'
}
// Mark this index as flipped
indices[index] = true
}
return string(corrupted)
}
func TestEncodeDecode(t *testing.T) {
// Vars
constraint := 7
polynomials := []int{91, 109, 121}
inputLen := 20
numOfCorruptBits := 1
reversePolynomials := false
// Generate random input bytes
inputBytes := make([]byte, inputLen)
for i := 0; i < 6; i++ {
inputBytes[i] = byte(rand.Intn(256))
}
codec, err := Init(Input{Constraint: constraint, Polynomials: polynomials, ReversePolynomials: reversePolynomials})
if err != nil {
t.Fatal(err)
}
// Encode
encoded := codec.Encode(BytesToBits(inputBytes))
// Corrupt bits
encoded = corruptBits(encoded, numOfCorruptBits)
// Decode
decoded := codec.Decode(encoded)
// Check if decoded is equal to input
if !bytes.Equal(BitsToBytes(decoded), inputBytes) {
t.Errorf("Expected %s, got %s", BytesToBits(inputBytes), decoded)
}
}
// Test EncodeDecode 100 times
func TestEncodeDecode100(t *testing.T) {
for i := 0; i < 1000; i++ {
TestEncodeDecode(t)
}
}
// Test encode/decode using EncodeBytes and DecodeBytes
func TestEncodeDecodeBytes(t *testing.T) {
// Vars
constraint := 7
polynomials := []int{91, 109, 121}
inputLen := 20
numOfCorruptBits := 1
reversePolynomials := false
// Generate random input bytes
inputBytes := make([]byte, inputLen)
for i := 0; i < 6; i++ {
inputBytes[i] = byte(rand.Intn(256))
}
codec, err := Init(Input{Constraint: constraint, Polynomials: polynomials, ReversePolynomials: reversePolynomials})
if err != nil {
t.Fatal(err)
}
// Encode
encoded := codec.EncodeBytes(inputBytes)
// Corrupt bits
encoded = corruptBits(encoded, numOfCorruptBits)
// Decode
decoded := codec.DecodeBytes(encoded)
// Check if decoded is equal to input
if !bytes.Equal(decoded, inputBytes) {
t.Errorf("Expected %s, got %s", BytesToBits(inputBytes), decoded)
}
}
func TestSeparateEncodeDecoders(t *testing.T) {
// Vars
constraint := 7
polynomials := []int{91, 109, 121}
inputLen := 20
numOfCorruptBits := 1
reversePolynomials := false // Somehow when this is true and using different encode/decode codecs, the test fails
// Generate random input bytes
inputBytes := make([]byte, inputLen)
for i := 0; i < 6; i++ {
inputBytes[i] = byte(rand.Intn(256))
}
codec, err := Init(Input{Constraint: constraint, Polynomials: polynomials, ReversePolynomials: reversePolynomials})
if err != nil {
t.Fatal(err)
}
// Encode
encoded := codec.Encode(BytesToBits(inputBytes))
// Corrupt bits
encoded = corruptBits(encoded, numOfCorruptBits)
decodeCodec, err := Init(Input{Constraint: constraint, Polynomials: polynomials, ReversePolynomials: reversePolynomials})
if err != nil {
t.Fatal(err)
}
// Decode
decoded := decodeCodec.Decode(encoded)
// Check if decoded is equal to input
if !bytes.Equal(BitsToBytes(decoded), inputBytes) {
t.Errorf("Expected %s, got %s", BytesToBits(inputBytes), decoded)
}
}