1package mnemonicode 2 3import ( 4 "bytes" 5 "encoding/hex" 6 "fmt" 7 "strings" 8 "testing" 9 10 "golang.org/x/text/transform" 11) 12 13func TestWordsReq(t *testing.T) { 14 for i, n := range []int{0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10} { 15 r := WordsRequired(i) 16 if r != n { 17 t.Errorf("WordsRequired(%d) returned %d, expected %d", i, r, n) 18 } 19 } 20} 21 22var testData = []struct { 23 hex string 24 words []string 25}{ 26 {"01", []string{"acrobat"}}, 27 {"0102", []string{"opera", "academy"}}, 28 {"010203", []string{"kayak", "cement", "ego"}}, 29 {"01020304", []string{"papa", "twist", "alpine"}}, 30 {"0102030405", []string{"papa", "twist", "alpine", "admiral"}}, 31 {"010203040506", []string{"papa", "twist", "alpine", "shine", "academy"}}, 32 {"01020304050607", []string{"papa", "twist", "alpine", "chess", "flute", "ego"}}, 33 {"0102030405060708", []string{"papa", "twist", "alpine", "content", "sailor", "athena"}}, 34 {"00", []string{"academy"}}, 35 {"5A06", []string{"academy", "acrobat"}}, 36 {"FE5D28", []string{"academy", "acrobat", "fax"}}, 37 {"A2B55000", []string{"academy", "acrobat", "active"}}, 38 {"A2B5500003", []string{"academy", "acrobat", "active", "actor"}}, 39 {"A2B550006B19", []string{"academy", "acrobat", "active", "actor", "adam"}}, 40 {"A2B550000F7128", []string{"academy", "acrobat", "active", "actor", "adam", "fax"}}, 41 {"A2B550009FCFC900", []string{"academy", "acrobat", "active", "actor", "adam", "admiral"}}, 42 {"FF", []string{"exact"}}, 43 {"FFFF", []string{"nevada", "archive"}}, 44 {"FFFFFF", []string{"claudia", "photo", "yes"}}, 45 {"FFFFFFFF", []string{"natural", "analyze", "verbal"}}, 46 {"123456789ABCDEF123456789ABCDEF012345", []string{ 47 "plastic", "roger", "vincent", "pilgrim", "flame", "secure", "apropos", "polka", "earth", "radio", "modern", "aladdin", "marion", "airline"}}, 48} 49 50func compareWordList(tb testing.TB, expected, got []string, args ...interface{}) { 51 fail := false 52 if len(expected) != len(got) { 53 fail = true 54 } 55 for i := 0; !fail && i < len(expected); i++ { 56 fail = expected[i] != got[i] 57 } 58 if fail { 59 prefix := "" 60 if len(args) > 0 { 61 prefix += fmt.Sprintln(args...) 62 prefix = prefix[:len(prefix)-1] + ": " 63 } 64 tb.Errorf("%vexpected %v, got %v", prefix, expected, got) 65 } 66} 67 68func TestEncodeWordList(t *testing.T) { 69 var result []string 70 for i, d := range testData { 71 raw, err := hex.DecodeString(d.hex) 72 if err != nil { 73 t.Fatal("bad test data:", i, err) 74 } 75 result = EncodeWordList(result, raw) 76 compareWordList(t, d.words, result, i, d.hex) 77 result = result[:0] 78 } 79} 80 81func TestDecodeWordList(t *testing.T) { 82 var result []byte 83 var err error 84 for i, d := range testData { 85 raw, _ := hex.DecodeString(d.hex) 86 result, err = DecodeWordList(result, d.words) 87 if err != nil { 88 t.Errorf("%2d %v failed: %v", i, d.words, err) 89 continue 90 } 91 if !bytes.Equal(raw, result) { 92 t.Errorf("%2d %v expected %v got %v", i, d.words, raw, result) 93 } 94 result = result[:0] 95 } 96} 97 98func TestEncodeTransformer(t *testing.T) { 99 cfg := NewDefaultConfig() 100 cfg.GroupSeparator = " " 101 enc := NewEncodeTransformer(cfg) 102 for i, d := range testData { 103 raw, err := hex.DecodeString(d.hex) 104 if err != nil { 105 t.Fatal("bad test data:", i, err) 106 } 107 result, _, err := transform.Bytes(enc, raw) 108 if err != nil { 109 t.Errorf("%2d %v failed: %v", i, d.words, err) 110 continue 111 } 112 //t.Logf("%q", result) 113 words := strings.Fields(string(result)) 114 compareWordList(t, d.words, words, i, d.hex) 115 } 116 117} 118 119func TestDecodeTransformer(t *testing.T) { 120 dec := NewDecodeTransformer() 121 for i, d := range testData { 122 raw, _ := hex.DecodeString(d.hex) 123 words := strings.Join(d.words, " ") 124 result, _, err := transform.Bytes(dec, []byte(words)) 125 if err != nil { 126 t.Errorf("%2d %v failed: %v", i, d.words, err) 127 continue 128 } 129 if !bytes.Equal(raw, result) { 130 t.Errorf("%2d %v expected %v got %v", i, d.words, raw, result) 131 } 132 } 133} 134 135func TestEncodeFormatting(t *testing.T) { 136 raw, _ := hex.DecodeString(testData[20].hex) 137 input := string(raw) 138 //words := testData[20].words 139 tests := []struct { 140 cfg *Config 141 formatted string 142 }{ 143 {nil, "plastic roger vincent - pilgrim flame secure - apropos polka earth \nradio modern aladdin - marion airline"}, 144 {&Config{ 145 LinePrefix: "{P}", 146 LineSuffix: "{S}\n", 147 WordSeparator: "{w}", 148 GroupSeparator: "{g}", 149 WordsPerGroup: 2, 150 GroupsPerLine: 2, 151 WordPadding: '·', 152 }, 153 `{P}plastic{w}roger··{g}vincent{w}pilgrim{S} 154{P}flame··{w}secure·{g}apropos{w}polka··{S} 155{P}earth··{w}radio··{g}modern·{w}aladdin{S} 156{P}marion·{w}airline`}, 157 } 158 for i, d := range tests { 159 enc := NewEncodeTransformer(d.cfg) 160 result, _, err := transform.String(enc, input) 161 if err != nil { 162 t.Errorf("%2d transform failed: %v", i, err) 163 continue 164 } 165 if result != d.formatted { 166 t.Errorf("%2d expected:\n%q\ngot:\n%q", i, d.formatted, result) 167 } 168 } 169} 170 171func BenchmarkEncodeWordList(b *testing.B) { 172 // the list of all known words (except the short end words) 173 data, err := DecodeWordList(nil, wordList[:base]) 174 if err != nil { 175 b.Fatal("DecodeWordList failed:", err) 176 } 177 b.SetBytes(int64(len(data))) 178 b.ReportAllocs() 179 b.ResetTimer() 180 var words []string 181 for i := 0; i < b.N; i++ { 182 words = EncodeWordList(words[:0], data) 183 } 184} 185 186func BenchmarkDencodeWordList(b *testing.B) { 187 b.ReportAllocs() 188 var buf []byte 189 var err error 190 // decode the list of all known words (except the short end words) 191 for i := 0; i < b.N; i++ { 192 buf, err = DecodeWordList(buf[:0], wordList[:base]) 193 if err != nil { 194 b.Fatal("DecodeWordList failed:", err) 195 } 196 } 197 b.SetBytes(int64(len(buf))) 198} 199 200func BenchmarkEncodeTransformer(b *testing.B) { 201 // the list of all known words (except the short end words) 202 data, err := DecodeWordList(nil, wordList[:base]) 203 if err != nil { 204 b.Fatal("DecodeWordList failed:", err) 205 } 206 enc := NewEncodeTransformer(nil) 207 b.SetBytes(int64(len(data))) 208 b.ReportAllocs() 209 b.ResetTimer() 210 for i := 0; i < b.N; i++ { 211 _, _, err := transform.Bytes(enc, data) 212 if err != nil { 213 b.Fatal("encode transformer error:", err) 214 } 215 } 216} 217 218func BenchmarkDecodeTransformer(b *testing.B) { 219 data, err := DecodeWordList(nil, wordList[:base]) 220 if err != nil { 221 b.Fatal("DecodeWordList failed:", err) 222 } 223 enc := NewEncodeTransformer(nil) 224 words, _, err := transform.Bytes(enc, data) 225 if err != nil { 226 b.Fatal("encode transformer error:", err) 227 } 228 b.SetBytes(int64(len(data))) 229 dec := NewDecodeTransformer() 230 b.ReportAllocs() 231 b.ResetTimer() 232 for i := 0; i < b.N; i++ { 233 _, _, err := transform.Bytes(dec, words) 234 if err != nil { 235 b.Fatal("decode transformer error:", err) 236 } 237 } 238} 239