1
0

rs_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. package reedsolomon
  2. import (
  3. "bytes"
  4. "fmt"
  5. "math/rand"
  6. "testing"
  7. )
  8. const (
  9. kb = 1024
  10. mb = 1024 * 1024
  11. testNumIn = 10
  12. testNumOut = 4
  13. )
  14. const verifySize = 256 + 32 + 16 + 15
  15. func TestVerifyEncBase(t *testing.T) {
  16. d := 5
  17. p := 5
  18. vects := [][]byte{
  19. {0, 1},
  20. {4, 5},
  21. {2, 3},
  22. {6, 7},
  23. {8, 9},
  24. {0, 0},
  25. {0, 0},
  26. {0, 0},
  27. {0, 0},
  28. {0, 0},
  29. }
  30. em, err := genEncMatrixVand(d, p)
  31. if err != nil {
  32. t.Fatal(err)
  33. }
  34. g := em[d*d:]
  35. e := &encBase{data: d, parity: p, gen: g}
  36. err = e.Encode(vects)
  37. if err != nil {
  38. t.Fatal(err)
  39. }
  40. if vects[5][0] != 12 || vects[5][1] != 13 {
  41. t.Fatal("vect 5 mismatch")
  42. }
  43. if vects[6][0] != 10 || vects[6][1] != 11 {
  44. t.Fatal("vect 6 mismatch")
  45. }
  46. if vects[7][0] != 14 || vects[7][1] != 15 {
  47. t.Fatal("vect 7 mismatch")
  48. }
  49. if vects[8][0] != 90 || vects[8][1] != 91 {
  50. t.Fatal("vect 8 mismatch")
  51. }
  52. if vects[9][0] != 94 || vects[9][1] != 95 {
  53. t.Fatal("shard 9 mismatch")
  54. }
  55. }
  56. func fillRandom(v []byte) {
  57. for i := 0; i < len(v); i += 7 {
  58. val := rand.Int63()
  59. for j := 0; i+j < len(v) && j < 7; j++ {
  60. v[i+j] = byte(val)
  61. val >>= 8
  62. }
  63. }
  64. }
  65. func verifyEnc(t *testing.T, d, p int) {
  66. for i := 1; i <= verifySize; i++ {
  67. vects1 := make([][]byte, d+p)
  68. vects2 := make([][]byte, d+p)
  69. for j := 0; j < d+p; j++ {
  70. vects1[j] = make([]byte, i)
  71. vects2[j] = make([]byte, i)
  72. }
  73. for j := 0; j < d; j++ {
  74. rand.Seed(int64(j))
  75. fillRandom(vects1[j])
  76. copy(vects2[j], vects1[j])
  77. }
  78. e, err := New(d, p)
  79. if err != nil {
  80. t.Fatal(err)
  81. }
  82. err = e.Encode(vects1)
  83. if err != nil {
  84. t.Fatal(err)
  85. }
  86. em, err := genEncMatrixVand(d, p)
  87. if err != nil {
  88. t.Fatal(err)
  89. }
  90. g := em[d*d:]
  91. e2 := &encBase{data: d, parity: p, gen: g}
  92. err = e2.Encode(vects2)
  93. for k, v1 := range vects1 {
  94. if !bytes.Equal(v1, vects2[k]) {
  95. t.Fatalf("no match enc with encBase; vect: %d; size: %d", k, i)
  96. }
  97. }
  98. }
  99. }
  100. func TestVerifyEnc(t *testing.T) {
  101. verifyEnc(t, testNumIn, testNumOut)
  102. }
  103. func verifyReconst(t *testing.T, d, p int, lost []int) {
  104. for i := 1; i <= verifySize; i++ {
  105. vects1 := make([][]byte, d+p)
  106. vects2 := make([][]byte, d+p)
  107. for j := 0; j < d+p; j++ {
  108. vects1[j] = make([]byte, i)
  109. vects2[j] = make([]byte, i)
  110. }
  111. for j := 0; j < d; j++ {
  112. rand.Seed(int64(j))
  113. fillRandom(vects1[j])
  114. }
  115. e, err := New(d, p)
  116. if err != nil {
  117. t.Fatal(err)
  118. }
  119. err = e.Encode(vects1)
  120. if err != nil {
  121. t.Fatal(err)
  122. }
  123. for j := 0; j < d+p; j++ {
  124. copy(vects2[j], vects1[j])
  125. }
  126. for _, i := range lost {
  127. vects2[i] = nil
  128. }
  129. err = e.Reconstruct(vects2)
  130. if err != nil {
  131. t.Fatal(err)
  132. }
  133. for k, v1 := range vects1 {
  134. if !bytes.Equal(v1, vects2[k]) {
  135. t.Fatalf("no match reconst; vect: %d; size: %d", k, i)
  136. }
  137. }
  138. }
  139. }
  140. func TestVerifyReconst(t *testing.T) {
  141. lost := []int{0, 11, 3, 4}
  142. verifyReconst(t, testNumIn, testNumOut, lost)
  143. }
  144. func benchEnc(b *testing.B, d, p, size int) {
  145. vects := make([][]byte, d+p)
  146. for j := 0; j < d+p; j++ {
  147. vects[j] = make([]byte, size)
  148. }
  149. for j := 0; j < d; j++ {
  150. rand.Seed(int64(j))
  151. fillRandom(vects[j])
  152. }
  153. e, err := New(d, p)
  154. if err != nil {
  155. b.Fatal(err)
  156. }
  157. err = e.Encode(vects)
  158. if err != nil {
  159. b.Fatal(err)
  160. }
  161. b.SetBytes(int64(d * size))
  162. b.ResetTimer()
  163. for i := 0; i < b.N; i++ {
  164. err = e.Encode(vects)
  165. if err != nil {
  166. b.Fatal(err)
  167. }
  168. }
  169. }
  170. func benchEncRun(f func(*testing.B, int, int, int), d, p int, size []int) func(*testing.B) {
  171. return func(b *testing.B) {
  172. for _, s := range size {
  173. b.Run(fmt.Sprintf("%d+%d_%d", d, p, s), func(b *testing.B) {
  174. f(b, d, p, s)
  175. })
  176. }
  177. }
  178. }
  179. func BenchmarkEnc(b *testing.B) {
  180. s1 := []int{1350}
  181. b.Run("", benchEncRun(benchEnc, 10, 3, s1))
  182. s2 := []int{1400, 4 * kb, 64 * kb, mb, 16 * mb}
  183. b.Run("", benchEncRun(benchEnc, testNumIn, testNumOut, s2))
  184. }
  185. func benchReconst(b *testing.B, d, p, size int, lost []int) {
  186. vects := make([][]byte, d+p)
  187. for j := 0; j < d+p; j++ {
  188. vects[j] = make([]byte, size)
  189. }
  190. for j := 0; j < d; j++ {
  191. rand.Seed(int64(j))
  192. fillRandom(vects[j])
  193. }
  194. e, err := New(d, p)
  195. if err != nil {
  196. b.Fatal(err)
  197. }
  198. err = e.Encode(vects)
  199. if err != nil {
  200. b.Fatal(err)
  201. }
  202. for _, i := range lost {
  203. vects[i] = nil
  204. }
  205. err = e.Reconstruct(vects)
  206. if err != nil {
  207. b.Fatal(err)
  208. }
  209. b.SetBytes(int64(d * size))
  210. b.ResetTimer()
  211. for i := 0; i < b.N; i++ {
  212. for _, i := range lost {
  213. vects[i] = nil
  214. }
  215. err = e.Reconstruct(vects)
  216. if err != nil {
  217. b.Fatal(err)
  218. }
  219. }
  220. }
  221. func benchReconstRun(f func(*testing.B, int, int, int, []int), d, p int, size, lost []int) func(*testing.B) {
  222. return func(b *testing.B) {
  223. for _, s := range size {
  224. b.Run(fmt.Sprintf("%d+%d_%d", d, p, s), func(b *testing.B) {
  225. f(b, d, p, s, lost)
  226. })
  227. }
  228. }
  229. }
  230. // Reconstruct p vects
  231. func BenchmarkReconst(b *testing.B) {
  232. l1 := []int{2, 4, 5}
  233. s1 := []int{1350}
  234. b.Run("", benchReconstRun(benchReconst, 10, 3, s1, l1))
  235. l2 := []int{2, 4, 7, 9}
  236. s2 := []int{1400, 4 * kb, 64 * kb, mb, 16 * mb}
  237. b.Run("", benchReconstRun(benchReconst, testNumIn, testNumOut, s2, l2))
  238. }
  239. func benchReconstPos(b *testing.B, d, p, size int, has, dLost, pLost []int) {
  240. vects := make([][]byte, d+p)
  241. for j := 0; j < d+p; j++ {
  242. vects[j] = make([]byte, size)
  243. }
  244. for j := 0; j < d; j++ {
  245. rand.Seed(int64(j))
  246. fillRandom(vects[j])
  247. }
  248. e, err := New(d, p)
  249. if err != nil {
  250. b.Fatal(err)
  251. }
  252. err = e.Encode(vects)
  253. if err != nil {
  254. b.Fatal(err)
  255. }
  256. err = e.ReconstWithPos(vects, has, dLost, pLost)
  257. if err != nil {
  258. b.Fatal(err)
  259. }
  260. b.SetBytes(int64(d * size))
  261. b.ResetTimer()
  262. for i := 0; i < b.N; i++ {
  263. err = e.ReconstWithPos(vects, has, dLost, pLost)
  264. if err != nil {
  265. b.Fatal(err)
  266. }
  267. }
  268. }
  269. func benchReconstPosRun(f func(*testing.B, int, int, int, []int, []int, []int), d, p int, size,
  270. has, dLost, pLost []int) func(*testing.B) {
  271. return func(b *testing.B) {
  272. for _, s := range size {
  273. b.Run(fmt.Sprintf("%dx%d_%d", d, p, s), func(b *testing.B) {
  274. f(b, d, p, s, has, dLost, pLost)
  275. })
  276. }
  277. }
  278. }
  279. // Reconstruct p vects with position
  280. func BenchmarkReconstWithPos(b *testing.B) {
  281. h1 := []int{0, 1, 3, 6, 7, 8, 9, 10, 11, 12}
  282. d1 := []int{2, 4, 5}
  283. p1 := []int{}
  284. s1 := []int{1350}
  285. b.Run("", benchReconstPosRun(benchReconstPos, 10, 3, s1, h1, d1, p1))
  286. h2 := []int{0, 1, 3, 5, 6, 8, 10, 11, 12, 13}
  287. d2 := []int{2, 4, 7, 9}
  288. p2 := []int{}
  289. s2 := []int{1400, 4 * kb, 64 * kb, mb, 16 * mb}
  290. b.Run("", benchReconstPosRun(benchReconstPos, testNumIn, testNumOut, s2, h2, d2, p2))
  291. }