You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
4.4 KiB

  1. package keys
  2. import (
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. "github.com/stretchr/testify/require"
  6. cmn "github.com/tendermint/tmlibs/common"
  7. )
  8. func TestLengthCalc(t *testing.T) {
  9. assert := assert.New(t)
  10. cases := []struct {
  11. bytes, words int
  12. flexible bool
  13. }{
  14. {1, 1, false},
  15. {2, 2, false},
  16. // bytes pairs with same word count
  17. {3, 3, true},
  18. {4, 3, true},
  19. {5, 4, false},
  20. // bytes pairs with same word count
  21. {10, 8, true},
  22. {11, 8, true},
  23. {12, 9, false},
  24. {13, 10, false},
  25. {20, 15, false},
  26. // bytes pairs with same word count
  27. {21, 16, true},
  28. {32, 24, true},
  29. }
  30. for _, tc := range cases {
  31. wl := wordlenFromBytes(tc.bytes)
  32. assert.Equal(tc.words, wl, "%d", tc.bytes)
  33. bl, flex := bytelenFromWords(tc.words)
  34. assert.Equal(tc.flexible, flex, "%d", tc.words)
  35. if !flex {
  36. assert.Equal(tc.bytes, bl, "%d", tc.words)
  37. } else {
  38. // check if it is either tc.bytes or tc.bytes +1
  39. choices := []int{tc.bytes, tc.bytes + 1}
  40. assert.Contains(choices, bl, "%d", tc.words)
  41. }
  42. }
  43. }
  44. func TestEncodeDecode(t *testing.T) {
  45. assert, require := assert.New(t), require.New(t)
  46. codec, err := LoadCodec("english")
  47. require.Nil(err, "%+v", err)
  48. cases := [][]byte{
  49. {7, 8, 9}, // TODO: 3 words -> 3 or 4 bytes
  50. {12, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes
  51. {0, 54, 99, 11}, // TODO: 3 words -> 3 or 4 bytes, detect leading 0
  52. {1, 2, 3, 4, 5}, // normal
  53. {0, 0, 0, 0, 122, 23, 82, 195}, // leading 0s (8 chars, unclear)
  54. {0, 0, 0, 0, 5, 22, 123, 55, 22}, // leading 0s (9 chars, clear)
  55. {22, 44, 55, 1, 13, 0, 0, 0, 0}, // trailing 0s (9 chars, clear)
  56. {0, 5, 253, 2, 0}, // leading and trailing zeros
  57. {255, 196, 172, 234, 192, 255}, // big numbers
  58. {255, 196, 172, 1, 234, 192, 255}, // big numbers, two length choices
  59. // others?
  60. }
  61. for i, tc := range cases {
  62. w, err := codec.BytesToWords(tc)
  63. if assert.Nil(err, "%d: %v", i, err) {
  64. b, err := codec.WordsToBytes(w)
  65. if assert.Nil(err, "%d: %v", i, err) {
  66. assert.Equal(len(tc), len(b))
  67. assert.Equal(tc, b)
  68. }
  69. }
  70. }
  71. }
  72. func TestCheckInvalidLists(t *testing.T) {
  73. assert := assert.New(t)
  74. trivial := []string{"abc", "def"}
  75. short := make([]string, 1234)
  76. long := make([]string, BankSize+1)
  77. right := make([]string, BankSize)
  78. dups := make([]string, BankSize)
  79. for _, list := range [][]string{short, long, right, dups} {
  80. for i := range list {
  81. list[i] = cmn.RandStr(8)
  82. }
  83. }
  84. // create one single duplicate
  85. dups[192] = dups[782]
  86. cases := []struct {
  87. words []string
  88. loadable bool
  89. valid bool
  90. }{
  91. {trivial, false, false},
  92. {short, false, false},
  93. {long, false, false},
  94. {dups, true, false}, // we only check dups on first use...
  95. {right, true, true},
  96. }
  97. for i, tc := range cases {
  98. codec, err := NewCodec(tc.words)
  99. if !tc.loadable {
  100. assert.NotNil(err, "%d", i)
  101. } else if assert.Nil(err, "%d: %+v", i, err) {
  102. data := cmn.RandBytes(32)
  103. w, err := codec.BytesToWords(data)
  104. if tc.valid {
  105. assert.Nil(err, "%d: %+v", i, err)
  106. b, err := codec.WordsToBytes(w)
  107. assert.Nil(err, "%d: %+v", i, err)
  108. assert.Equal(data, b)
  109. } else {
  110. assert.NotNil(err, "%d", i)
  111. }
  112. }
  113. }
  114. }
  115. func getRandWord(c *WordCodec) string {
  116. idx := cmn.RandInt() % BankSize
  117. return c.words[idx]
  118. }
  119. func getDiffWord(c *WordCodec, not string) string {
  120. w := getRandWord(c)
  121. if w == not {
  122. w = getRandWord(c)
  123. }
  124. return w
  125. }
  126. func TestCheckTypoDetection(t *testing.T) {
  127. assert, require := assert.New(t), require.New(t)
  128. banks := []string{"english", "spanish", "japanese", "chinese_simplified"}
  129. for _, bank := range banks {
  130. codec, err := LoadCodec(bank)
  131. require.Nil(err, "%s: %+v", bank, err)
  132. for i := 0; i < 1000; i++ {
  133. numBytes := cmn.RandInt()%60 + 1
  134. data := cmn.RandBytes(numBytes)
  135. words, err := codec.BytesToWords(data)
  136. assert.Nil(err, "%s: %+v", bank, err)
  137. good, err := codec.WordsToBytes(words)
  138. assert.Nil(err, "%s: %+v", bank, err)
  139. assert.Equal(data, good, bank)
  140. // now try some tweaks...
  141. cut := words[1:]
  142. _, err = codec.WordsToBytes(cut)
  143. assert.NotNil(err, "%s: %s", bank, words)
  144. // swap a word within the bank, should fails
  145. words[3] = getDiffWord(codec, words[3])
  146. _, err = codec.WordsToBytes(words)
  147. assert.NotNil(err, "%s: %s", bank, words)
  148. // put a random word here, must fail
  149. words[3] = cmn.RandStr(10)
  150. _, err = codec.WordsToBytes(words)
  151. assert.NotNil(err, "%s: %s", bank, words)
  152. }
  153. }
  154. }