reedsolomon_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /**
  2. * Unit tests for ReedSolomon
  3. *
  4. * Copyright 2015, Klaus Post
  5. * Copyright 2015, Backblaze, Inc. All rights reserved.
  6. */
  7. package reedsolomon
  8. import (
  9. "bytes"
  10. "math/rand"
  11. "runtime"
  12. "testing"
  13. )
  14. func testOpts() [][]Option {
  15. if !testing.Short() {
  16. return [][]Option{}
  17. }
  18. opts := [][]Option{
  19. {WithMaxGoroutines(1), WithMinSplitSize(500), withSSE3(false), withAVX2(false)},
  20. {WithMaxGoroutines(5000), WithMinSplitSize(50), withSSE3(false), withAVX2(false)},
  21. {WithMaxGoroutines(5000), WithMinSplitSize(500000), withSSE3(false), withAVX2(false)},
  22. {WithMaxGoroutines(1), WithMinSplitSize(500000), withSSE3(false), withAVX2(false)},
  23. }
  24. for _, o := range opts[:] {
  25. if defaultOptions.useSSSE3 {
  26. n := make([]Option, len(o), len(o)+1)
  27. copy(n, o)
  28. n = append(n, withSSE3(true))
  29. opts = append(opts, n)
  30. }
  31. if defaultOptions.useAVX2 {
  32. n := make([]Option, len(o), len(o)+1)
  33. copy(n, o)
  34. n = append(n, withAVX2(true))
  35. opts = append(opts, n)
  36. }
  37. }
  38. return opts
  39. }
  40. func TestEncoding(t *testing.T) {
  41. testEncoding(t)
  42. for _, o := range testOpts() {
  43. testEncoding(t, o...)
  44. }
  45. }
  46. func testEncoding(t *testing.T, o ...Option) {
  47. perShard := 50000
  48. r, err := New(10, 3, o...)
  49. if err != nil {
  50. t.Fatal(err)
  51. }
  52. shards := make([][]byte, 13)
  53. for s := range shards {
  54. shards[s] = make([]byte, perShard)
  55. }
  56. rand.Seed(0)
  57. for s := 0; s < 13; s++ {
  58. fillRandom(shards[s])
  59. }
  60. err = r.Encode(shards)
  61. if err != nil {
  62. t.Fatal(err)
  63. }
  64. ok, err := r.Verify(shards)
  65. if err != nil {
  66. t.Fatal(err)
  67. }
  68. if !ok {
  69. t.Fatal("Verification failed")
  70. }
  71. err = r.Encode(make([][]byte, 1))
  72. if err != ErrTooFewShards {
  73. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  74. }
  75. badShards := make([][]byte, 13)
  76. badShards[0] = make([]byte, 1)
  77. err = r.Encode(badShards)
  78. if err != ErrShardSize {
  79. t.Errorf("expected %v, got %v", ErrShardSize, err)
  80. }
  81. }
  82. func TestReconstruct(t *testing.T) {
  83. testReconstruct(t)
  84. for _, o := range testOpts() {
  85. testReconstruct(t, o...)
  86. }
  87. }
  88. func testReconstruct(t *testing.T, o ...Option) {
  89. perShard := 50000
  90. r, err := New(10, 3, o...)
  91. if err != nil {
  92. t.Fatal(err)
  93. }
  94. shards := make([][]byte, 13)
  95. for s := range shards {
  96. shards[s] = make([]byte, perShard)
  97. }
  98. rand.Seed(0)
  99. for s := 0; s < 13; s++ {
  100. fillRandom(shards[s])
  101. }
  102. err = r.Encode(shards)
  103. if err != nil {
  104. t.Fatal(err)
  105. }
  106. // Reconstruct with all shards present
  107. err = r.Reconstruct(shards)
  108. if err != nil {
  109. t.Fatal(err)
  110. }
  111. // Reconstruct with 10 shards present
  112. shards[0] = nil
  113. shards[7] = nil
  114. shards[11] = nil
  115. err = r.Reconstruct(shards)
  116. if err != nil {
  117. t.Fatal(err)
  118. }
  119. ok, err := r.Verify(shards)
  120. if err != nil {
  121. t.Fatal(err)
  122. }
  123. if !ok {
  124. t.Fatal("Verification failed")
  125. }
  126. // Reconstruct with 9 shards present (should fail)
  127. shards[0] = nil
  128. shards[4] = nil
  129. shards[7] = nil
  130. shards[11] = nil
  131. err = r.Reconstruct(shards)
  132. if err != ErrTooFewShards {
  133. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  134. }
  135. err = r.Reconstruct(make([][]byte, 1))
  136. if err != ErrTooFewShards {
  137. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  138. }
  139. err = r.Reconstruct(make([][]byte, 13))
  140. if err != ErrShardNoData {
  141. t.Errorf("expected %v, got %v", ErrShardNoData, err)
  142. }
  143. }
  144. func TestVerify(t *testing.T) {
  145. testVerify(t)
  146. for _, o := range testOpts() {
  147. testVerify(t, o...)
  148. }
  149. }
  150. func testVerify(t *testing.T, o ...Option) {
  151. perShard := 33333
  152. r, err := New(10, 4, o...)
  153. if err != nil {
  154. t.Fatal(err)
  155. }
  156. shards := make([][]byte, 14)
  157. for s := range shards {
  158. shards[s] = make([]byte, perShard)
  159. }
  160. rand.Seed(0)
  161. for s := 0; s < 10; s++ {
  162. fillRandom(shards[s])
  163. }
  164. err = r.Encode(shards)
  165. if err != nil {
  166. t.Fatal(err)
  167. }
  168. ok, err := r.Verify(shards)
  169. if err != nil {
  170. t.Fatal(err)
  171. }
  172. if !ok {
  173. t.Fatal("Verification failed")
  174. }
  175. // Put in random data. Verification should fail
  176. fillRandom(shards[10])
  177. ok, err = r.Verify(shards)
  178. if err != nil {
  179. t.Fatal(err)
  180. }
  181. if ok {
  182. t.Fatal("Verification did not fail")
  183. }
  184. // Re-encode
  185. err = r.Encode(shards)
  186. if err != nil {
  187. t.Fatal(err)
  188. }
  189. // Fill a data segment with random data
  190. fillRandom(shards[0])
  191. ok, err = r.Verify(shards)
  192. if err != nil {
  193. t.Fatal(err)
  194. }
  195. if ok {
  196. t.Fatal("Verification did not fail")
  197. }
  198. _, err = r.Verify(make([][]byte, 1))
  199. if err != ErrTooFewShards {
  200. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  201. }
  202. _, err = r.Verify(make([][]byte, 14))
  203. if err != ErrShardNoData {
  204. t.Errorf("expected %v, got %v", ErrShardNoData, err)
  205. }
  206. }
  207. func TestOneEncode(t *testing.T) {
  208. codec, err := New(5, 5)
  209. if err != nil {
  210. t.Fatal(err)
  211. }
  212. shards := [][]byte{
  213. {0, 1},
  214. {4, 5},
  215. {2, 3},
  216. {6, 7},
  217. {8, 9},
  218. {0, 0},
  219. {0, 0},
  220. {0, 0},
  221. {0, 0},
  222. {0, 0},
  223. }
  224. codec.Encode(shards)
  225. if shards[5][0] != 12 || shards[5][1] != 13 {
  226. t.Fatal("shard 5 mismatch")
  227. }
  228. if shards[6][0] != 10 || shards[6][1] != 11 {
  229. t.Fatal("shard 6 mismatch")
  230. }
  231. if shards[7][0] != 14 || shards[7][1] != 15 {
  232. t.Fatal("shard 7 mismatch")
  233. }
  234. if shards[8][0] != 90 || shards[8][1] != 91 {
  235. t.Fatal("shard 8 mismatch")
  236. }
  237. if shards[9][0] != 94 || shards[9][1] != 95 {
  238. t.Fatal("shard 9 mismatch")
  239. }
  240. ok, err := codec.Verify(shards)
  241. if err != nil {
  242. t.Fatal(err)
  243. }
  244. if !ok {
  245. t.Fatal("did not verify")
  246. }
  247. shards[8][0]++
  248. ok, err = codec.Verify(shards)
  249. if err != nil {
  250. t.Fatal(err)
  251. }
  252. if ok {
  253. t.Fatal("verify did not fail as expected")
  254. }
  255. }
  256. func fillRandom(p []byte) {
  257. for i := 0; i < len(p); i += 7 {
  258. val := rand.Int63()
  259. for j := 0; i+j < len(p) && j < 7; j++ {
  260. p[i+j] = byte(val)
  261. val >>= 8
  262. }
  263. }
  264. }
  265. func benchmarkEncode(b *testing.B, dataShards, parityShards, shardSize int) {
  266. r, err := New(dataShards, parityShards)
  267. if err != nil {
  268. b.Fatal(err)
  269. }
  270. shards := make([][]byte, dataShards+parityShards)
  271. for s := range shards {
  272. shards[s] = make([]byte, shardSize)
  273. }
  274. rand.Seed(0)
  275. for s := 0; s < dataShards; s++ {
  276. fillRandom(shards[s])
  277. }
  278. b.SetBytes(int64(shardSize * dataShards))
  279. b.ResetTimer()
  280. for i := 0; i < b.N; i++ {
  281. err = r.Encode(shards)
  282. if err != nil {
  283. b.Fatal(err)
  284. }
  285. }
  286. }
  287. func BenchmarkEncode10x2x10000(b *testing.B) {
  288. benchmarkEncode(b, 10, 2, 10000)
  289. }
  290. func BenchmarkEncode100x20x10000(b *testing.B) {
  291. benchmarkEncode(b, 100, 20, 10000)
  292. }
  293. func BenchmarkEncode17x3x1M(b *testing.B) {
  294. benchmarkEncode(b, 17, 3, 1024*1024)
  295. }
  296. // Benchmark 10 data shards and 4 parity shards with 16MB each.
  297. func BenchmarkEncode10x4x16M(b *testing.B) {
  298. benchmarkEncode(b, 10, 4, 16*1024*1024)
  299. }
  300. // Benchmark 5 data shards and 2 parity shards with 1MB each.
  301. func BenchmarkEncode5x2x1M(b *testing.B) {
  302. benchmarkEncode(b, 5, 2, 1024*1024)
  303. }
  304. // Benchmark 1 data shards and 2 parity shards with 1MB each.
  305. func BenchmarkEncode10x2x1M(b *testing.B) {
  306. benchmarkEncode(b, 10, 2, 1024*1024)
  307. }
  308. // Benchmark 10 data shards and 4 parity shards with 1MB each.
  309. func BenchmarkEncode10x4x1M(b *testing.B) {
  310. benchmarkEncode(b, 10, 4, 1024*1024)
  311. }
  312. // Benchmark 50 data shards and 20 parity shards with 1MB each.
  313. func BenchmarkEncode50x20x1M(b *testing.B) {
  314. benchmarkEncode(b, 50, 20, 1024*1024)
  315. }
  316. // Benchmark 17 data shards and 3 parity shards with 16MB each.
  317. func BenchmarkEncode17x3x16M(b *testing.B) {
  318. benchmarkEncode(b, 17, 3, 16*1024*1024)
  319. }
  320. func benchmarkVerify(b *testing.B, dataShards, parityShards, shardSize int) {
  321. r, err := New(dataShards, parityShards)
  322. if err != nil {
  323. b.Fatal(err)
  324. }
  325. shards := make([][]byte, parityShards+dataShards)
  326. for s := range shards {
  327. shards[s] = make([]byte, shardSize)
  328. }
  329. rand.Seed(0)
  330. for s := 0; s < dataShards; s++ {
  331. fillRandom(shards[s])
  332. }
  333. err = r.Encode(shards)
  334. if err != nil {
  335. b.Fatal(err)
  336. }
  337. b.SetBytes(int64(shardSize * dataShards))
  338. b.ResetTimer()
  339. for i := 0; i < b.N; i++ {
  340. _, err = r.Verify(shards)
  341. if err != nil {
  342. b.Fatal(err)
  343. }
  344. }
  345. }
  346. // Benchmark 10 data slices with 2 parity slices holding 10000 bytes each
  347. func BenchmarkVerify10x2x10000(b *testing.B) {
  348. benchmarkVerify(b, 10, 2, 10000)
  349. }
  350. // Benchmark 50 data slices with 5 parity slices holding 100000 bytes each
  351. func BenchmarkVerify50x5x50000(b *testing.B) {
  352. benchmarkVerify(b, 50, 5, 100000)
  353. }
  354. // Benchmark 10 data slices with 2 parity slices holding 1MB bytes each
  355. func BenchmarkVerify10x2x1M(b *testing.B) {
  356. benchmarkVerify(b, 10, 2, 1024*1024)
  357. }
  358. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  359. func BenchmarkVerify5x2x1M(b *testing.B) {
  360. benchmarkVerify(b, 5, 2, 1024*1024)
  361. }
  362. // Benchmark 10 data slices with 4 parity slices holding 1MB bytes each
  363. func BenchmarkVerify10x4x1M(b *testing.B) {
  364. benchmarkVerify(b, 10, 4, 1024*1024)
  365. }
  366. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  367. func BenchmarkVerify50x20x1M(b *testing.B) {
  368. benchmarkVerify(b, 50, 20, 1024*1024)
  369. }
  370. // Benchmark 10 data slices with 4 parity slices holding 16MB bytes each
  371. func BenchmarkVerify10x4x16M(b *testing.B) {
  372. benchmarkVerify(b, 10, 4, 16*1024*1024)
  373. }
  374. func corruptRandom(shards [][]byte, dataShards, parityShards int) {
  375. shardsToCorrupt := rand.Intn(parityShards)
  376. for i := 1; i <= shardsToCorrupt; i++ {
  377. shards[rand.Intn(dataShards+parityShards)] = nil
  378. }
  379. }
  380. func benchmarkReconstruct(b *testing.B, dataShards, parityShards, shardSize int) {
  381. r, err := New(dataShards, parityShards)
  382. if err != nil {
  383. b.Fatal(err)
  384. }
  385. shards := make([][]byte, parityShards+dataShards)
  386. for s := range shards {
  387. shards[s] = make([]byte, shardSize)
  388. }
  389. rand.Seed(0)
  390. for s := 0; s < dataShards; s++ {
  391. fillRandom(shards[s])
  392. }
  393. err = r.Encode(shards)
  394. if err != nil {
  395. b.Fatal(err)
  396. }
  397. b.SetBytes(int64(shardSize * dataShards))
  398. b.ResetTimer()
  399. for i := 0; i < b.N; i++ {
  400. corruptRandom(shards, dataShards, parityShards)
  401. err = r.Reconstruct(shards)
  402. if err != nil {
  403. b.Fatal(err)
  404. }
  405. ok, err := r.Verify(shards)
  406. if err != nil {
  407. b.Fatal(err)
  408. }
  409. if !ok {
  410. b.Fatal("Verification failed")
  411. }
  412. }
  413. }
  414. // Benchmark 10 data slices with 2 parity slices holding 10000 bytes each
  415. func BenchmarkReconstruct10x2x10000(b *testing.B) {
  416. benchmarkReconstruct(b, 10, 2, 10000)
  417. }
  418. // Benchmark 50 data slices with 5 parity slices holding 100000 bytes each
  419. func BenchmarkReconstruct50x5x50000(b *testing.B) {
  420. benchmarkReconstruct(b, 50, 5, 100000)
  421. }
  422. // Benchmark 10 data slices with 2 parity slices holding 1MB bytes each
  423. func BenchmarkReconstruct10x2x1M(b *testing.B) {
  424. benchmarkReconstruct(b, 10, 2, 1024*1024)
  425. }
  426. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  427. func BenchmarkReconstruct5x2x1M(b *testing.B) {
  428. benchmarkReconstruct(b, 5, 2, 1024*1024)
  429. }
  430. // Benchmark 10 data slices with 4 parity slices holding 1MB bytes each
  431. func BenchmarkReconstruct10x4x1M(b *testing.B) {
  432. benchmarkReconstruct(b, 10, 4, 1024*1024)
  433. }
  434. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  435. func BenchmarkReconstruct50x20x1M(b *testing.B) {
  436. benchmarkReconstruct(b, 50, 20, 1024*1024)
  437. }
  438. // Benchmark 10 data slices with 4 parity slices holding 16MB bytes each
  439. func BenchmarkReconstruct10x4x16M(b *testing.B) {
  440. benchmarkReconstruct(b, 10, 4, 16*1024*1024)
  441. }
  442. func benchmarkReconstructP(b *testing.B, dataShards, parityShards, shardSize int) {
  443. r, err := New(dataShards, parityShards)
  444. if err != nil {
  445. b.Fatal(err)
  446. }
  447. b.SetBytes(int64(shardSize * dataShards))
  448. runtime.GOMAXPROCS(runtime.NumCPU())
  449. b.ResetTimer()
  450. b.RunParallel(func(pb *testing.PB) {
  451. shards := make([][]byte, parityShards+dataShards)
  452. for s := range shards {
  453. shards[s] = make([]byte, shardSize)
  454. }
  455. rand.Seed(0)
  456. for s := 0; s < dataShards; s++ {
  457. fillRandom(shards[s])
  458. }
  459. err = r.Encode(shards)
  460. if err != nil {
  461. b.Fatal(err)
  462. }
  463. for pb.Next() {
  464. corruptRandom(shards, dataShards, parityShards)
  465. err = r.Reconstruct(shards)
  466. if err != nil {
  467. b.Fatal(err)
  468. }
  469. ok, err := r.Verify(shards)
  470. if err != nil {
  471. b.Fatal(err)
  472. }
  473. if !ok {
  474. b.Fatal("Verification failed")
  475. }
  476. }
  477. })
  478. }
  479. // Benchmark 10 data slices with 2 parity slices holding 10000 bytes each
  480. func BenchmarkReconstructP10x2x10000(b *testing.B) {
  481. benchmarkReconstructP(b, 10, 2, 10000)
  482. }
  483. // Benchmark 50 data slices with 5 parity slices holding 100000 bytes each
  484. func BenchmarkReconstructP50x5x50000(b *testing.B) {
  485. benchmarkReconstructP(b, 50, 5, 100000)
  486. }
  487. // Benchmark 10 data slices with 2 parity slices holding 1MB bytes each
  488. func BenchmarkReconstructP10x2x1M(b *testing.B) {
  489. benchmarkReconstructP(b, 10, 2, 1024*1024)
  490. }
  491. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  492. func BenchmarkReconstructP5x2x1M(b *testing.B) {
  493. benchmarkReconstructP(b, 5, 2, 1024*1024)
  494. }
  495. // Benchmark 10 data slices with 4 parity slices holding 1MB bytes each
  496. func BenchmarkReconstructP10x4x1M(b *testing.B) {
  497. benchmarkReconstructP(b, 10, 4, 1024*1024)
  498. }
  499. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  500. func BenchmarkReconstructP50x20x1M(b *testing.B) {
  501. benchmarkReconstructP(b, 50, 20, 1024*1024)
  502. }
  503. // Benchmark 10 data slices with 4 parity slices holding 16MB bytes each
  504. func BenchmarkReconstructP10x4x16M(b *testing.B) {
  505. benchmarkReconstructP(b, 10, 4, 16*1024*1024)
  506. }
  507. func TestEncoderReconstruct(t *testing.T) {
  508. testEncoderReconstruct(t)
  509. for _, o := range testOpts() {
  510. testEncoderReconstruct(t, o...)
  511. }
  512. }
  513. func testEncoderReconstruct(t *testing.T, o ...Option) {
  514. // Create some sample data
  515. var data = make([]byte, 250000)
  516. fillRandom(data)
  517. // Create 5 data slices of 50000 elements each
  518. enc, err := New(5, 3, o...)
  519. if err != nil {
  520. t.Fatal(err)
  521. }
  522. shards, err := enc.Split(data)
  523. if err != nil {
  524. t.Fatal(err)
  525. }
  526. err = enc.Encode(shards)
  527. if err != nil {
  528. t.Fatal(err)
  529. }
  530. // Check that it verifies
  531. ok, err := enc.Verify(shards)
  532. if !ok || err != nil {
  533. t.Fatal("not ok:", ok, "err:", err)
  534. }
  535. // Delete a shard
  536. shards[0] = nil
  537. // Should reconstruct
  538. err = enc.Reconstruct(shards)
  539. if err != nil {
  540. t.Fatal(err)
  541. }
  542. // Check that it verifies
  543. ok, err = enc.Verify(shards)
  544. if !ok || err != nil {
  545. t.Fatal("not ok:", ok, "err:", err)
  546. }
  547. // Recover original bytes
  548. buf := new(bytes.Buffer)
  549. err = enc.Join(buf, shards, len(data))
  550. if err != nil {
  551. t.Fatal(err)
  552. }
  553. if !bytes.Equal(buf.Bytes(), data) {
  554. t.Fatal("recovered bytes do not match")
  555. }
  556. // Corrupt a shard
  557. shards[0] = nil
  558. shards[1][0], shards[1][500] = 75, 75
  559. // Should reconstruct (but with corrupted data)
  560. err = enc.Reconstruct(shards)
  561. if err != nil {
  562. t.Fatal(err)
  563. }
  564. // Check that it verifies
  565. ok, err = enc.Verify(shards)
  566. if ok || err != nil {
  567. t.Fatal("error or ok:", ok, "err:", err)
  568. }
  569. // Recovered data should not match original
  570. buf.Reset()
  571. err = enc.Join(buf, shards, len(data))
  572. if err != nil {
  573. t.Fatal(err)
  574. }
  575. if bytes.Equal(buf.Bytes(), data) {
  576. t.Fatal("corrupted data matches original")
  577. }
  578. }
  579. func TestSplitJoin(t *testing.T) {
  580. var data = make([]byte, 250000)
  581. rand.Seed(0)
  582. fillRandom(data)
  583. enc, _ := New(5, 3)
  584. shards, err := enc.Split(data)
  585. if err != nil {
  586. t.Fatal(err)
  587. }
  588. _, err = enc.Split([]byte{})
  589. if err != ErrShortData {
  590. t.Errorf("expected %v, got %v", ErrShortData, err)
  591. }
  592. buf := new(bytes.Buffer)
  593. err = enc.Join(buf, shards, 50)
  594. if err != nil {
  595. t.Fatal(err)
  596. }
  597. if !bytes.Equal(buf.Bytes(), data[:50]) {
  598. t.Fatal("recovered data does match original")
  599. }
  600. err = enc.Join(buf, [][]byte{}, 0)
  601. if err != ErrTooFewShards {
  602. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  603. }
  604. err = enc.Join(buf, shards, len(data)+1)
  605. if err != ErrShortData {
  606. t.Errorf("expected %v, got %v", ErrShortData, err)
  607. }
  608. shards[0] = nil
  609. err = enc.Join(buf, shards, len(data))
  610. if err != ErrReconstructRequired {
  611. t.Errorf("expected %v, got %v", ErrReconstructRequired, err)
  612. }
  613. }
  614. func TestCodeSomeShards(t *testing.T) {
  615. var data = make([]byte, 250000)
  616. fillRandom(data)
  617. enc, _ := New(5, 3)
  618. r := enc.(*reedSolomon) // need to access private methods
  619. shards, _ := enc.Split(data)
  620. old := runtime.GOMAXPROCS(1)
  621. r.codeSomeShards(r.parity, shards[:r.DataShards], shards[r.DataShards:], r.ParityShards, len(shards[0]))
  622. // hopefully more than 1 CPU
  623. runtime.GOMAXPROCS(runtime.NumCPU())
  624. r.codeSomeShards(r.parity, shards[:r.DataShards], shards[r.DataShards:], r.ParityShards, len(shards[0]))
  625. // reset MAXPROCS, otherwise testing complains
  626. runtime.GOMAXPROCS(old)
  627. }
  628. func TestAllMatrices(t *testing.T) {
  629. t.Skip("Skipping slow matrix check")
  630. for i := 1; i < 257; i++ {
  631. _, err := New(i, i)
  632. if err != nil {
  633. t.Fatal("creating matrix size", i, i, ":", err)
  634. }
  635. }
  636. }
  637. func TestNew(t *testing.T) {
  638. tests := []struct {
  639. data, parity int
  640. err error
  641. }{
  642. {127, 127, nil},
  643. {256, 256, ErrMaxShardNum},
  644. {0, 1, ErrInvShardNum},
  645. {1, 0, ErrInvShardNum},
  646. {257, 1, ErrMaxShardNum},
  647. // overflow causes r.Shards to be negative
  648. {256, int(^uint(0) >> 1), errInvalidRowSize},
  649. }
  650. for _, test := range tests {
  651. _, err := New(test.data, test.parity)
  652. if err != test.err {
  653. t.Errorf("New(%v, %v): expected %v, got %v", test.data, test.parity, test.err, err)
  654. }
  655. }
  656. }