reedsolomon_test.go 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357
  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. "fmt"
  11. "math/rand"
  12. "runtime"
  13. "sync"
  14. "testing"
  15. )
  16. func isIncreasingAndContainsDataRow(indices []int) bool {
  17. cols := len(indices)
  18. for i := 0; i < cols-1; i++ {
  19. if indices[i] >= indices[i+1] {
  20. return false
  21. }
  22. }
  23. // Data rows are in the upper square portion of the matrix.
  24. return indices[0] < cols
  25. }
  26. func incrementIndices(indices []int, indexBound int) (valid bool) {
  27. for i := len(indices) - 1; i >= 0; i-- {
  28. indices[i]++
  29. if indices[i] < indexBound {
  30. break
  31. }
  32. if i == 0 {
  33. return false
  34. }
  35. indices[i] = 0
  36. }
  37. return true
  38. }
  39. func incrementIndicesUntilIncreasingAndContainsDataRow(
  40. indices []int, maxIndex int) bool {
  41. for {
  42. valid := incrementIndices(indices, maxIndex)
  43. if !valid {
  44. return false
  45. }
  46. if isIncreasingAndContainsDataRow(indices) {
  47. return true
  48. }
  49. }
  50. }
  51. func findSingularSubMatrix(m matrix) (matrix, error) {
  52. rows := len(m)
  53. cols := len(m[0])
  54. rowIndices := make([]int, cols)
  55. for incrementIndicesUntilIncreasingAndContainsDataRow(rowIndices, rows) {
  56. subMatrix, _ := newMatrix(cols, cols)
  57. for i, r := range rowIndices {
  58. for c := 0; c < cols; c++ {
  59. subMatrix[i][c] = m[r][c]
  60. }
  61. }
  62. _, err := subMatrix.Invert()
  63. if err == errSingular {
  64. return subMatrix, nil
  65. } else if err != nil {
  66. return nil, err
  67. }
  68. }
  69. return nil, nil
  70. }
  71. func TestBuildMatrixPAR1Singular(t *testing.T) {
  72. totalShards := 8
  73. dataShards := 4
  74. m, err := buildMatrixPAR1(dataShards, totalShards)
  75. if err != nil {
  76. t.Fatal(err)
  77. }
  78. singularSubMatrix, err := findSingularSubMatrix(m)
  79. if err != nil {
  80. t.Fatal(err)
  81. }
  82. if singularSubMatrix == nil {
  83. t.Fatal("No singular sub-matrix found")
  84. }
  85. t.Logf("matrix %s has singular sub-matrix %s", m, singularSubMatrix)
  86. }
  87. func testOpts() [][]Option {
  88. if testing.Short() {
  89. return [][]Option{
  90. {WithPAR1Matrix()}, {WithCauchyMatrix()},
  91. }
  92. }
  93. opts := [][]Option{
  94. {WithPAR1Matrix()}, {WithCauchyMatrix()},
  95. {WithMaxGoroutines(1), WithMinSplitSize(500), withSSE3(false), withAVX2(false)},
  96. {WithMaxGoroutines(5000), WithMinSplitSize(50), withSSE3(false), withAVX2(false)},
  97. {WithMaxGoroutines(5000), WithMinSplitSize(500000), withSSE3(false), withAVX2(false)},
  98. {WithMaxGoroutines(1), WithMinSplitSize(500000), withSSE3(false), withAVX2(false)},
  99. {WithAutoGoroutines(50000), WithMinSplitSize(500)},
  100. }
  101. for _, o := range opts[:] {
  102. if defaultOptions.useSSSE3 {
  103. n := make([]Option, len(o), len(o)+1)
  104. copy(n, o)
  105. n = append(n, withSSE3(true))
  106. opts = append(opts, n)
  107. }
  108. if defaultOptions.useAVX2 {
  109. n := make([]Option, len(o), len(o)+1)
  110. copy(n, o)
  111. n = append(n, withAVX2(true))
  112. opts = append(opts, n)
  113. }
  114. }
  115. return opts
  116. }
  117. func TestEncoding(t *testing.T) {
  118. testEncoding(t)
  119. for i, o := range testOpts() {
  120. t.Run(fmt.Sprintf("options %d", i), func(t *testing.T) {
  121. testEncoding(t, o...)
  122. })
  123. }
  124. }
  125. func testEncoding(t *testing.T, o ...Option) {
  126. perShard := 50000
  127. r, err := New(10, 3, o...)
  128. if err != nil {
  129. t.Fatal(err)
  130. }
  131. shards := make([][]byte, 13)
  132. for s := range shards {
  133. shards[s] = make([]byte, perShard)
  134. }
  135. rand.Seed(0)
  136. for s := 0; s < 13; s++ {
  137. fillRandom(shards[s])
  138. }
  139. err = r.Encode(shards)
  140. if err != nil {
  141. t.Fatal(err)
  142. }
  143. ok, err := r.Verify(shards)
  144. if err != nil {
  145. t.Fatal(err)
  146. }
  147. if !ok {
  148. t.Fatal("Verification failed")
  149. }
  150. err = r.Encode(make([][]byte, 1))
  151. if err != ErrTooFewShards {
  152. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  153. }
  154. badShards := make([][]byte, 13)
  155. badShards[0] = make([]byte, 1)
  156. err = r.Encode(badShards)
  157. if err != ErrShardSize {
  158. t.Errorf("expected %v, got %v", ErrShardSize, err)
  159. }
  160. }
  161. func TestUpdate(t *testing.T) {
  162. testEncoding(t)
  163. for i, o := range testOpts() {
  164. t.Run(fmt.Sprintf("options %d", i), func(t *testing.T) {
  165. testUpdate(t, o...)
  166. })
  167. }
  168. }
  169. func testUpdate(t *testing.T, o ...Option) {
  170. perShard := 50000
  171. r, err := New(10, 3, o...)
  172. if err != nil {
  173. t.Fatal(err)
  174. }
  175. shards := make([][]byte, 13)
  176. for s := range shards {
  177. shards[s] = make([]byte, perShard)
  178. }
  179. rand.Seed(0)
  180. for s := 0; s < 13; s++ {
  181. fillRandom(shards[s])
  182. }
  183. err = r.Encode(shards)
  184. if err != nil {
  185. t.Fatal(err)
  186. }
  187. ok, err := r.Verify(shards)
  188. if err != nil {
  189. t.Fatal(err)
  190. }
  191. if !ok {
  192. t.Fatal("Verification failed")
  193. }
  194. newdatashards := make([][]byte, 10)
  195. for s := 0; s < 10; s++ {
  196. newdatashards[s] = make([]byte, perShard)
  197. fillRandom(newdatashards[s])
  198. err = r.Update(shards, newdatashards)
  199. if err != nil {
  200. t.Fatal(err)
  201. }
  202. shards[s] = newdatashards[s]
  203. ok, err := r.Verify(shards)
  204. if err != nil {
  205. t.Fatal(err)
  206. }
  207. if !ok {
  208. t.Fatal("Verification failed")
  209. }
  210. newdatashards[s] = nil
  211. }
  212. for s := 0; s < 9; s++ {
  213. newdatashards[s] = make([]byte, perShard)
  214. newdatashards[s+1] = make([]byte, perShard)
  215. fillRandom(newdatashards[s])
  216. fillRandom(newdatashards[s+1])
  217. err = r.Update(shards, newdatashards)
  218. if err != nil {
  219. t.Fatal(err)
  220. }
  221. shards[s] = newdatashards[s]
  222. shards[s+1] = newdatashards[s+1]
  223. ok, err := r.Verify(shards)
  224. if err != nil {
  225. t.Fatal(err)
  226. }
  227. if !ok {
  228. t.Fatal("Verification failed")
  229. }
  230. newdatashards[s] = nil
  231. newdatashards[s+1] = nil
  232. }
  233. for newNum := 1; newNum <= 10; newNum++ {
  234. for s := 0; s <= 10-newNum; s++ {
  235. for i := 0; i < newNum; i++ {
  236. newdatashards[s+i] = make([]byte, perShard)
  237. fillRandom(newdatashards[s+i])
  238. }
  239. err = r.Update(shards, newdatashards)
  240. if err != nil {
  241. t.Fatal(err)
  242. }
  243. for i := 0; i < newNum; i++ {
  244. shards[s+i] = newdatashards[s+i]
  245. }
  246. ok, err := r.Verify(shards)
  247. if err != nil {
  248. t.Fatal(err)
  249. }
  250. if !ok {
  251. t.Fatal("Verification failed")
  252. }
  253. for i := 0; i < newNum; i++ {
  254. newdatashards[s+i] = nil
  255. }
  256. }
  257. }
  258. }
  259. func TestReconstruct(t *testing.T) {
  260. testReconstruct(t)
  261. for i, o := range testOpts() {
  262. t.Run(fmt.Sprintf("options %d", i), func(t *testing.T) {
  263. testReconstruct(t, o...)
  264. })
  265. }
  266. }
  267. func testReconstruct(t *testing.T, o ...Option) {
  268. perShard := 50000
  269. r, err := New(10, 3, o...)
  270. if err != nil {
  271. t.Fatal(err)
  272. }
  273. shards := make([][]byte, 13)
  274. for s := range shards {
  275. shards[s] = make([]byte, perShard)
  276. }
  277. rand.Seed(0)
  278. for s := 0; s < 13; s++ {
  279. fillRandom(shards[s])
  280. }
  281. err = r.Encode(shards)
  282. if err != nil {
  283. t.Fatal(err)
  284. }
  285. // Reconstruct with all shards present
  286. err = r.Reconstruct(shards)
  287. if err != nil {
  288. t.Fatal(err)
  289. }
  290. // Reconstruct with 10 shards present. Use pre-allocated memory for one of them.
  291. shards[0] = nil
  292. shards[7] = nil
  293. shard11 := shards[11]
  294. shards[11] = shard11[:0]
  295. fillRandom(shard11)
  296. err = r.Reconstruct(shards)
  297. if err != nil {
  298. t.Fatal(err)
  299. }
  300. ok, err := r.Verify(shards)
  301. if err != nil {
  302. t.Fatal(err)
  303. }
  304. if !ok {
  305. t.Fatal("Verification failed")
  306. }
  307. if &shard11[0] != &shards[11][0] {
  308. t.Errorf("Shard was not reconstructed into pre-allocated memory")
  309. }
  310. // Reconstruct with 9 shards present (should fail)
  311. shards[0] = nil
  312. shards[4] = nil
  313. shards[7] = nil
  314. shards[11] = nil
  315. err = r.Reconstruct(shards)
  316. if err != ErrTooFewShards {
  317. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  318. }
  319. err = r.Reconstruct(make([][]byte, 1))
  320. if err != ErrTooFewShards {
  321. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  322. }
  323. err = r.Reconstruct(make([][]byte, 13))
  324. if err != ErrShardNoData {
  325. t.Errorf("expected %v, got %v", ErrShardNoData, err)
  326. }
  327. }
  328. func TestReconstructData(t *testing.T) {
  329. testReconstructData(t)
  330. for i, o := range testOpts() {
  331. t.Run(fmt.Sprintf("options %d", i), func(t *testing.T) {
  332. testReconstruct(t, o...)
  333. })
  334. }
  335. }
  336. func testReconstructData(t *testing.T, o ...Option) {
  337. perShard := 100000
  338. r, err := New(8, 5, o...)
  339. if err != nil {
  340. t.Fatal(err)
  341. }
  342. shards := make([][]byte, 13)
  343. for s := range shards {
  344. shards[s] = make([]byte, perShard)
  345. }
  346. rand.Seed(0)
  347. for s := 0; s < 13; s++ {
  348. fillRandom(shards[s])
  349. }
  350. err = r.Encode(shards)
  351. if err != nil {
  352. t.Fatal(err)
  353. }
  354. // Reconstruct with all shards present
  355. err = r.ReconstructData(shards)
  356. if err != nil {
  357. t.Fatal(err)
  358. }
  359. // Reconstruct with 10 shards present. Use pre-allocated memory for one of them.
  360. shards[0] = nil
  361. shards[2] = nil
  362. shard4 := shards[4]
  363. shards[4] = shard4[:0]
  364. fillRandom(shard4)
  365. err = r.ReconstructData(shards)
  366. if err != nil {
  367. t.Fatal(err)
  368. }
  369. // Since all parity shards are available, verification will succeed
  370. ok, err := r.Verify(shards)
  371. if err != nil {
  372. t.Fatal(err)
  373. }
  374. if !ok {
  375. t.Fatal("Verification failed")
  376. }
  377. if &shard4[0] != &shards[4][0] {
  378. t.Errorf("Shard was not reconstructed into pre-allocated memory")
  379. }
  380. // Reconstruct with 6 data and 4 parity shards
  381. shards[0] = nil
  382. shards[2] = nil
  383. shards[12] = nil
  384. err = r.ReconstructData(shards)
  385. if err != nil {
  386. t.Fatal(err)
  387. }
  388. // Verification will fail now due to absence of a parity block
  389. _, err = r.Verify(shards)
  390. if err != ErrShardSize {
  391. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  392. }
  393. // Reconstruct with 7 data and 1 parity shards
  394. shards[0] = nil
  395. shards[9] = nil
  396. shards[10] = nil
  397. shards[11] = nil
  398. shards[12] = nil
  399. err = r.ReconstructData(shards)
  400. if err != nil {
  401. t.Fatal(err)
  402. }
  403. _, err = r.Verify(shards)
  404. if err != ErrShardSize {
  405. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  406. }
  407. // Reconstruct with 6 data and 1 parity shards (should fail)
  408. shards[0] = nil
  409. shards[1] = nil
  410. shards[9] = nil
  411. shards[10] = nil
  412. shards[11] = nil
  413. shards[12] = nil
  414. err = r.ReconstructData(shards)
  415. if err != ErrTooFewShards {
  416. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  417. }
  418. err = r.ReconstructData(make([][]byte, 1))
  419. if err != ErrTooFewShards {
  420. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  421. }
  422. err = r.ReconstructData(make([][]byte, 13))
  423. if err != ErrShardNoData {
  424. t.Errorf("expected %v, got %v", ErrShardNoData, err)
  425. }
  426. }
  427. func TestReconstructPAR1Singular(t *testing.T) {
  428. perShard := 50
  429. r, err := New(4, 4, WithPAR1Matrix())
  430. if err != nil {
  431. t.Fatal(err)
  432. }
  433. shards := make([][]byte, 8)
  434. for s := range shards {
  435. shards[s] = make([]byte, perShard)
  436. }
  437. rand.Seed(0)
  438. for s := 0; s < 8; s++ {
  439. fillRandom(shards[s])
  440. }
  441. err = r.Encode(shards)
  442. if err != nil {
  443. t.Fatal(err)
  444. }
  445. // Reconstruct with only the last data shard present, and the
  446. // first, second, and fourth parity shard present (based on
  447. // the result of TestBuildMatrixPAR1Singular). This should
  448. // fail.
  449. shards[0] = nil
  450. shards[1] = nil
  451. shards[2] = nil
  452. shards[6] = nil
  453. err = r.Reconstruct(shards)
  454. if err != errSingular {
  455. t.Fatal(err)
  456. t.Errorf("expected %v, got %v", errSingular, err)
  457. }
  458. }
  459. func TestVerify(t *testing.T) {
  460. testVerify(t)
  461. for i, o := range testOpts() {
  462. t.Run(fmt.Sprintf("options %d", i), func(t *testing.T) {
  463. testVerify(t, o...)
  464. })
  465. }
  466. }
  467. func testVerify(t *testing.T, o ...Option) {
  468. perShard := 33333
  469. r, err := New(10, 4, o...)
  470. if err != nil {
  471. t.Fatal(err)
  472. }
  473. shards := make([][]byte, 14)
  474. for s := range shards {
  475. shards[s] = make([]byte, perShard)
  476. }
  477. rand.Seed(0)
  478. for s := 0; s < 10; s++ {
  479. fillRandom(shards[s])
  480. }
  481. err = r.Encode(shards)
  482. if err != nil {
  483. t.Fatal(err)
  484. }
  485. ok, err := r.Verify(shards)
  486. if err != nil {
  487. t.Fatal(err)
  488. }
  489. if !ok {
  490. t.Fatal("Verification failed")
  491. }
  492. // Put in random data. Verification should fail
  493. fillRandom(shards[10])
  494. ok, err = r.Verify(shards)
  495. if err != nil {
  496. t.Fatal(err)
  497. }
  498. if ok {
  499. t.Fatal("Verification did not fail")
  500. }
  501. // Re-encode
  502. err = r.Encode(shards)
  503. if err != nil {
  504. t.Fatal(err)
  505. }
  506. // Fill a data segment with random data
  507. fillRandom(shards[0])
  508. ok, err = r.Verify(shards)
  509. if err != nil {
  510. t.Fatal(err)
  511. }
  512. if ok {
  513. t.Fatal("Verification did not fail")
  514. }
  515. _, err = r.Verify(make([][]byte, 1))
  516. if err != ErrTooFewShards {
  517. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  518. }
  519. _, err = r.Verify(make([][]byte, 14))
  520. if err != ErrShardNoData {
  521. t.Errorf("expected %v, got %v", ErrShardNoData, err)
  522. }
  523. }
  524. func TestOneEncode(t *testing.T) {
  525. codec, err := New(5, 5)
  526. if err != nil {
  527. t.Fatal(err)
  528. }
  529. shards := [][]byte{
  530. {0, 1},
  531. {4, 5},
  532. {2, 3},
  533. {6, 7},
  534. {8, 9},
  535. {0, 0},
  536. {0, 0},
  537. {0, 0},
  538. {0, 0},
  539. {0, 0},
  540. }
  541. codec.Encode(shards)
  542. if shards[5][0] != 12 || shards[5][1] != 13 {
  543. t.Fatal("shard 5 mismatch")
  544. }
  545. if shards[6][0] != 10 || shards[6][1] != 11 {
  546. t.Fatal("shard 6 mismatch")
  547. }
  548. if shards[7][0] != 14 || shards[7][1] != 15 {
  549. t.Fatal("shard 7 mismatch")
  550. }
  551. if shards[8][0] != 90 || shards[8][1] != 91 {
  552. t.Fatal("shard 8 mismatch")
  553. }
  554. if shards[9][0] != 94 || shards[9][1] != 95 {
  555. t.Fatal("shard 9 mismatch")
  556. }
  557. ok, err := codec.Verify(shards)
  558. if err != nil {
  559. t.Fatal(err)
  560. }
  561. if !ok {
  562. t.Fatal("did not verify")
  563. }
  564. shards[8][0]++
  565. ok, err = codec.Verify(shards)
  566. if err != nil {
  567. t.Fatal(err)
  568. }
  569. if ok {
  570. t.Fatal("verify did not fail as expected")
  571. }
  572. }
  573. func fillRandom(p []byte) {
  574. for i := 0; i < len(p); i += 7 {
  575. val := rand.Int63()
  576. for j := 0; i+j < len(p) && j < 7; j++ {
  577. p[i+j] = byte(val)
  578. val >>= 8
  579. }
  580. }
  581. }
  582. func benchmarkEncode(b *testing.B, dataShards, parityShards, shardSize int) {
  583. r, err := New(dataShards, parityShards, WithAutoGoroutines(shardSize))
  584. if err != nil {
  585. b.Fatal(err)
  586. }
  587. shards := make([][]byte, dataShards+parityShards)
  588. for s := range shards {
  589. shards[s] = make([]byte, shardSize)
  590. }
  591. rand.Seed(0)
  592. for s := 0; s < dataShards; s++ {
  593. fillRandom(shards[s])
  594. }
  595. b.SetBytes(int64(shardSize * dataShards))
  596. b.ResetTimer()
  597. for i := 0; i < b.N; i++ {
  598. err = r.Encode(shards)
  599. if err != nil {
  600. b.Fatal(err)
  601. }
  602. }
  603. }
  604. func BenchmarkEncode10x2x10000(b *testing.B) {
  605. benchmarkEncode(b, 10, 2, 10000)
  606. }
  607. func BenchmarkEncode100x20x10000(b *testing.B) {
  608. benchmarkEncode(b, 100, 20, 10000)
  609. }
  610. func BenchmarkEncode17x3x1M(b *testing.B) {
  611. benchmarkEncode(b, 17, 3, 1024*1024)
  612. }
  613. // Benchmark 10 data shards and 4 parity shards with 16MB each.
  614. func BenchmarkEncode10x4x16M(b *testing.B) {
  615. benchmarkEncode(b, 10, 4, 16*1024*1024)
  616. }
  617. // Benchmark 5 data shards and 2 parity shards with 1MB each.
  618. func BenchmarkEncode5x2x1M(b *testing.B) {
  619. benchmarkEncode(b, 5, 2, 1024*1024)
  620. }
  621. // Benchmark 1 data shards and 2 parity shards with 1MB each.
  622. func BenchmarkEncode10x2x1M(b *testing.B) {
  623. benchmarkEncode(b, 10, 2, 1024*1024)
  624. }
  625. // Benchmark 10 data shards and 4 parity shards with 1MB each.
  626. func BenchmarkEncode10x4x1M(b *testing.B) {
  627. benchmarkEncode(b, 10, 4, 1024*1024)
  628. }
  629. // Benchmark 50 data shards and 20 parity shards with 1MB each.
  630. func BenchmarkEncode50x20x1M(b *testing.B) {
  631. benchmarkEncode(b, 50, 20, 1024*1024)
  632. }
  633. // Benchmark 17 data shards and 3 parity shards with 16MB each.
  634. func BenchmarkEncode17x3x16M(b *testing.B) {
  635. benchmarkEncode(b, 17, 3, 16*1024*1024)
  636. }
  637. func benchmarkVerify(b *testing.B, dataShards, parityShards, shardSize int) {
  638. r, err := New(dataShards, parityShards, WithAutoGoroutines(shardSize))
  639. if err != nil {
  640. b.Fatal(err)
  641. }
  642. shards := make([][]byte, parityShards+dataShards)
  643. for s := range shards {
  644. shards[s] = make([]byte, shardSize)
  645. }
  646. rand.Seed(0)
  647. for s := 0; s < dataShards; s++ {
  648. fillRandom(shards[s])
  649. }
  650. err = r.Encode(shards)
  651. if err != nil {
  652. b.Fatal(err)
  653. }
  654. b.SetBytes(int64(shardSize * dataShards))
  655. b.ResetTimer()
  656. for i := 0; i < b.N; i++ {
  657. _, err = r.Verify(shards)
  658. if err != nil {
  659. b.Fatal(err)
  660. }
  661. }
  662. }
  663. // Benchmark 10 data slices with 2 parity slices holding 10000 bytes each
  664. func BenchmarkVerify10x2x10000(b *testing.B) {
  665. benchmarkVerify(b, 10, 2, 10000)
  666. }
  667. // Benchmark 50 data slices with 5 parity slices holding 100000 bytes each
  668. func BenchmarkVerify50x5x50000(b *testing.B) {
  669. benchmarkVerify(b, 50, 5, 100000)
  670. }
  671. // Benchmark 10 data slices with 2 parity slices holding 1MB bytes each
  672. func BenchmarkVerify10x2x1M(b *testing.B) {
  673. benchmarkVerify(b, 10, 2, 1024*1024)
  674. }
  675. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  676. func BenchmarkVerify5x2x1M(b *testing.B) {
  677. benchmarkVerify(b, 5, 2, 1024*1024)
  678. }
  679. // Benchmark 10 data slices with 4 parity slices holding 1MB bytes each
  680. func BenchmarkVerify10x4x1M(b *testing.B) {
  681. benchmarkVerify(b, 10, 4, 1024*1024)
  682. }
  683. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  684. func BenchmarkVerify50x20x1M(b *testing.B) {
  685. benchmarkVerify(b, 50, 20, 1024*1024)
  686. }
  687. // Benchmark 10 data slices with 4 parity slices holding 16MB bytes each
  688. func BenchmarkVerify10x4x16M(b *testing.B) {
  689. benchmarkVerify(b, 10, 4, 16*1024*1024)
  690. }
  691. func corruptRandom(shards [][]byte, dataShards, parityShards int) {
  692. shardsToCorrupt := rand.Intn(parityShards)
  693. for i := 1; i <= shardsToCorrupt; i++ {
  694. shards[rand.Intn(dataShards+parityShards)] = nil
  695. }
  696. }
  697. func benchmarkReconstruct(b *testing.B, dataShards, parityShards, shardSize int) {
  698. r, err := New(dataShards, parityShards, WithAutoGoroutines(shardSize))
  699. if err != nil {
  700. b.Fatal(err)
  701. }
  702. shards := make([][]byte, parityShards+dataShards)
  703. for s := range shards {
  704. shards[s] = make([]byte, shardSize)
  705. }
  706. rand.Seed(0)
  707. for s := 0; s < dataShards; s++ {
  708. fillRandom(shards[s])
  709. }
  710. err = r.Encode(shards)
  711. if err != nil {
  712. b.Fatal(err)
  713. }
  714. b.SetBytes(int64(shardSize * dataShards))
  715. b.ResetTimer()
  716. for i := 0; i < b.N; i++ {
  717. corruptRandom(shards, dataShards, parityShards)
  718. err = r.Reconstruct(shards)
  719. if err != nil {
  720. b.Fatal(err)
  721. }
  722. ok, err := r.Verify(shards)
  723. if err != nil {
  724. b.Fatal(err)
  725. }
  726. if !ok {
  727. b.Fatal("Verification failed")
  728. }
  729. }
  730. }
  731. // Benchmark 10 data slices with 2 parity slices holding 10000 bytes each
  732. func BenchmarkReconstruct10x2x10000(b *testing.B) {
  733. benchmarkReconstruct(b, 10, 2, 10000)
  734. }
  735. // Benchmark 50 data slices with 5 parity slices holding 100000 bytes each
  736. func BenchmarkReconstruct50x5x50000(b *testing.B) {
  737. benchmarkReconstruct(b, 50, 5, 100000)
  738. }
  739. // Benchmark 10 data slices with 2 parity slices holding 1MB bytes each
  740. func BenchmarkReconstruct10x2x1M(b *testing.B) {
  741. benchmarkReconstruct(b, 10, 2, 1024*1024)
  742. }
  743. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  744. func BenchmarkReconstruct5x2x1M(b *testing.B) {
  745. benchmarkReconstruct(b, 5, 2, 1024*1024)
  746. }
  747. // Benchmark 10 data slices with 4 parity slices holding 1MB bytes each
  748. func BenchmarkReconstruct10x4x1M(b *testing.B) {
  749. benchmarkReconstruct(b, 10, 4, 1024*1024)
  750. }
  751. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  752. func BenchmarkReconstruct50x20x1M(b *testing.B) {
  753. benchmarkReconstruct(b, 50, 20, 1024*1024)
  754. }
  755. // Benchmark 10 data slices with 4 parity slices holding 16MB bytes each
  756. func BenchmarkReconstruct10x4x16M(b *testing.B) {
  757. benchmarkReconstruct(b, 10, 4, 16*1024*1024)
  758. }
  759. func corruptRandomData(shards [][]byte, dataShards, parityShards int) {
  760. shardsToCorrupt := rand.Intn(parityShards)
  761. for i := 1; i <= shardsToCorrupt; i++ {
  762. shards[rand.Intn(dataShards)] = nil
  763. }
  764. }
  765. func benchmarkReconstructData(b *testing.B, dataShards, parityShards, shardSize int) {
  766. r, err := New(dataShards, parityShards, WithAutoGoroutines(shardSize))
  767. if err != nil {
  768. b.Fatal(err)
  769. }
  770. shards := make([][]byte, parityShards+dataShards)
  771. for s := range shards {
  772. shards[s] = make([]byte, shardSize)
  773. }
  774. rand.Seed(0)
  775. for s := 0; s < dataShards; s++ {
  776. fillRandom(shards[s])
  777. }
  778. err = r.Encode(shards)
  779. if err != nil {
  780. b.Fatal(err)
  781. }
  782. b.SetBytes(int64(shardSize * dataShards))
  783. b.ResetTimer()
  784. for i := 0; i < b.N; i++ {
  785. corruptRandomData(shards, dataShards, parityShards)
  786. err = r.ReconstructData(shards)
  787. if err != nil {
  788. b.Fatal(err)
  789. }
  790. }
  791. }
  792. // Benchmark 10 data slices with 2 parity slices holding 10000 bytes each
  793. func BenchmarkReconstructData10x2x10000(b *testing.B) {
  794. benchmarkReconstructData(b, 10, 2, 10000)
  795. }
  796. // Benchmark 50 data slices with 5 parity slices holding 100000 bytes each
  797. func BenchmarkReconstructData50x5x50000(b *testing.B) {
  798. benchmarkReconstructData(b, 50, 5, 100000)
  799. }
  800. // Benchmark 10 data slices with 2 parity slices holding 1MB bytes each
  801. func BenchmarkReconstructData10x2x1M(b *testing.B) {
  802. benchmarkReconstructData(b, 10, 2, 1024*1024)
  803. }
  804. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  805. func BenchmarkReconstructData5x2x1M(b *testing.B) {
  806. benchmarkReconstructData(b, 5, 2, 1024*1024)
  807. }
  808. // Benchmark 10 data slices with 4 parity slices holding 1MB bytes each
  809. func BenchmarkReconstructData10x4x1M(b *testing.B) {
  810. benchmarkReconstructData(b, 10, 4, 1024*1024)
  811. }
  812. // Benchmark 5 data slices with 2 parity slices holding 1MB bytes each
  813. func BenchmarkReconstructData50x20x1M(b *testing.B) {
  814. benchmarkReconstructData(b, 50, 20, 1024*1024)
  815. }
  816. // Benchmark 10 data slices with 4 parity slices holding 16MB bytes each
  817. func BenchmarkReconstructData10x4x16M(b *testing.B) {
  818. benchmarkReconstructData(b, 10, 4, 16*1024*1024)
  819. }
  820. func benchmarkReconstructP(b *testing.B, dataShards, parityShards, shardSize int) {
  821. r, err := New(dataShards, parityShards, WithAutoGoroutines(shardSize))
  822. if err != nil {
  823. b.Fatal(err)
  824. }
  825. b.SetBytes(int64(shardSize * dataShards))
  826. runtime.GOMAXPROCS(runtime.NumCPU())
  827. b.ResetTimer()
  828. b.RunParallel(func(pb *testing.PB) {
  829. shards := make([][]byte, parityShards+dataShards)
  830. for s := range shards {
  831. shards[s] = make([]byte, shardSize)
  832. }
  833. rand.Seed(0)
  834. for s := 0; s < dataShards; s++ {
  835. fillRandom(shards[s])
  836. }
  837. err = r.Encode(shards)
  838. if err != nil {
  839. b.Fatal(err)
  840. }
  841. for pb.Next() {
  842. corruptRandom(shards, dataShards, parityShards)
  843. err = r.Reconstruct(shards)
  844. if err != nil {
  845. b.Fatal(err)
  846. }
  847. ok, err := r.Verify(shards)
  848. if err != nil {
  849. b.Fatal(err)
  850. }
  851. if !ok {
  852. b.Fatal("Verification failed")
  853. }
  854. }
  855. })
  856. }
  857. // Benchmark 10 data slices with 2 parity slices holding 10000 bytes each
  858. func BenchmarkReconstructP10x2x10000(b *testing.B) {
  859. benchmarkReconstructP(b, 10, 2, 10000)
  860. }
  861. // Benchmark 10 data slices with 5 parity slices holding 20000 bytes each
  862. func BenchmarkReconstructP10x5x20000(b *testing.B) {
  863. benchmarkReconstructP(b, 10, 5, 20000)
  864. }
  865. func TestEncoderReconstruct(t *testing.T) {
  866. testEncoderReconstruct(t)
  867. for _, o := range testOpts() {
  868. testEncoderReconstruct(t, o...)
  869. }
  870. }
  871. func testEncoderReconstruct(t *testing.T, o ...Option) {
  872. // Create some sample data
  873. var data = make([]byte, 250000)
  874. fillRandom(data)
  875. // Create 5 data slices of 50000 elements each
  876. enc, err := New(5, 3, o...)
  877. if err != nil {
  878. t.Fatal(err)
  879. }
  880. shards, err := enc.Split(data)
  881. if err != nil {
  882. t.Fatal(err)
  883. }
  884. err = enc.Encode(shards)
  885. if err != nil {
  886. t.Fatal(err)
  887. }
  888. // Check that it verifies
  889. ok, err := enc.Verify(shards)
  890. if !ok || err != nil {
  891. t.Fatal("not ok:", ok, "err:", err)
  892. }
  893. // Delete a shard
  894. shards[0] = nil
  895. // Should reconstruct
  896. err = enc.Reconstruct(shards)
  897. if err != nil {
  898. t.Fatal(err)
  899. }
  900. // Check that it verifies
  901. ok, err = enc.Verify(shards)
  902. if !ok || err != nil {
  903. t.Fatal("not ok:", ok, "err:", err)
  904. }
  905. // Recover original bytes
  906. buf := new(bytes.Buffer)
  907. err = enc.Join(buf, shards, len(data))
  908. if err != nil {
  909. t.Fatal(err)
  910. }
  911. if !bytes.Equal(buf.Bytes(), data) {
  912. t.Fatal("recovered bytes do not match")
  913. }
  914. // Corrupt a shard
  915. shards[0] = nil
  916. shards[1][0], shards[1][500] = 75, 75
  917. // Should reconstruct (but with corrupted data)
  918. err = enc.Reconstruct(shards)
  919. if err != nil {
  920. t.Fatal(err)
  921. }
  922. // Check that it verifies
  923. ok, err = enc.Verify(shards)
  924. if ok || err != nil {
  925. t.Fatal("error or ok:", ok, "err:", err)
  926. }
  927. // Recovered data should not match original
  928. buf.Reset()
  929. err = enc.Join(buf, shards, len(data))
  930. if err != nil {
  931. t.Fatal(err)
  932. }
  933. if bytes.Equal(buf.Bytes(), data) {
  934. t.Fatal("corrupted data matches original")
  935. }
  936. }
  937. func TestSplitJoin(t *testing.T) {
  938. var data = make([]byte, 250000)
  939. rand.Seed(0)
  940. fillRandom(data)
  941. enc, _ := New(5, 3)
  942. shards, err := enc.Split(data)
  943. if err != nil {
  944. t.Fatal(err)
  945. }
  946. _, err = enc.Split([]byte{})
  947. if err != ErrShortData {
  948. t.Errorf("expected %v, got %v", ErrShortData, err)
  949. }
  950. buf := new(bytes.Buffer)
  951. err = enc.Join(buf, shards, 50)
  952. if err != nil {
  953. t.Fatal(err)
  954. }
  955. if !bytes.Equal(buf.Bytes(), data[:50]) {
  956. t.Fatal("recovered data does match original")
  957. }
  958. err = enc.Join(buf, [][]byte{}, 0)
  959. if err != ErrTooFewShards {
  960. t.Errorf("expected %v, got %v", ErrTooFewShards, err)
  961. }
  962. err = enc.Join(buf, shards, len(data)+1)
  963. if err != ErrShortData {
  964. t.Errorf("expected %v, got %v", ErrShortData, err)
  965. }
  966. shards[0] = nil
  967. err = enc.Join(buf, shards, len(data))
  968. if err != ErrReconstructRequired {
  969. t.Errorf("expected %v, got %v", ErrReconstructRequired, err)
  970. }
  971. }
  972. func TestCodeSomeShards(t *testing.T) {
  973. var data = make([]byte, 250000)
  974. fillRandom(data)
  975. enc, _ := New(5, 3)
  976. r := enc.(*reedSolomon) // need to access private methods
  977. shards, _ := enc.Split(data)
  978. old := runtime.GOMAXPROCS(1)
  979. r.codeSomeShards(r.parity, shards[:r.DataShards], shards[r.DataShards:], r.ParityShards, len(shards[0]))
  980. // hopefully more than 1 CPU
  981. runtime.GOMAXPROCS(runtime.NumCPU())
  982. r.codeSomeShards(r.parity, shards[:r.DataShards], shards[r.DataShards:], r.ParityShards, len(shards[0]))
  983. // reset MAXPROCS, otherwise testing complains
  984. runtime.GOMAXPROCS(old)
  985. }
  986. func TestStandardMatrices(t *testing.T) {
  987. t.Skip("Skipping slow matrix check (~2 min)")
  988. var wg sync.WaitGroup
  989. wg.Add(256 - 1)
  990. for i := 1; i < 256; i++ {
  991. go func(i int) {
  992. // i == n.o. datashards
  993. defer wg.Done()
  994. var shards = make([][]byte, 255)
  995. for p := range shards {
  996. v := byte(i)
  997. shards[p] = []byte{v}
  998. }
  999. rng := rand.New(rand.NewSource(0))
  1000. for j := 1; j < 256; j++ {
  1001. // j == n.o. parity shards
  1002. if i+j > 255 {
  1003. continue
  1004. }
  1005. sh := shards[:i+j]
  1006. r, err := New(i, j, WithCauchyMatrix())
  1007. if err != nil {
  1008. // We are not supposed to write to t from goroutines.
  1009. t.Fatal("creating matrix size", i, j, ":", err)
  1010. }
  1011. err = r.Encode(sh)
  1012. if err != nil {
  1013. t.Fatal("encoding", i, j, ":", err)
  1014. }
  1015. for k := 0; k < j; k++ {
  1016. // Remove random shard.
  1017. r := int(rng.Int63n(int64(i + j)))
  1018. sh[r] = sh[r][:0]
  1019. }
  1020. err = r.Reconstruct(sh)
  1021. if err != nil {
  1022. t.Fatal("reconstructing", i, j, ":", err)
  1023. }
  1024. ok, err := r.Verify(sh)
  1025. if err != nil {
  1026. t.Fatal("verifying", i, j, ":", err)
  1027. }
  1028. if !ok {
  1029. t.Fatal(i, j, ok)
  1030. }
  1031. for k := range sh {
  1032. if k == i {
  1033. // Only check data shards
  1034. break
  1035. }
  1036. if sh[k][0] != byte(i) {
  1037. t.Fatal("does not match", i, j, k, sh[0], sh[k])
  1038. }
  1039. }
  1040. }
  1041. }(i)
  1042. }
  1043. wg.Wait()
  1044. }
  1045. func TestCauchyMatrices(t *testing.T) {
  1046. if testing.Short() || runtime.GOMAXPROCS(0) < 4 {
  1047. // Runtime ~15s.
  1048. t.Skip("Skipping slow matrix check")
  1049. }
  1050. var wg sync.WaitGroup
  1051. wg.Add(256 - 1)
  1052. for i := 1; i < 256; i++ {
  1053. go func(i int) {
  1054. // i == n.o. datashards
  1055. defer wg.Done()
  1056. var shards = make([][]byte, 255)
  1057. for p := range shards {
  1058. v := byte(i)
  1059. shards[p] = []byte{v}
  1060. }
  1061. rng := rand.New(rand.NewSource(0))
  1062. for j := 1; j < 256; j++ {
  1063. // j == n.o. parity shards
  1064. if i+j > 255 {
  1065. continue
  1066. }
  1067. sh := shards[:i+j]
  1068. r, err := New(i, j, WithCauchyMatrix())
  1069. if err != nil {
  1070. // We are not supposed to write to t from goroutines.
  1071. t.Fatal("creating matrix size", i, j, ":", err)
  1072. }
  1073. err = r.Encode(sh)
  1074. if err != nil {
  1075. t.Fatal("encoding", i, j, ":", err)
  1076. }
  1077. for k := 0; k < j; k++ {
  1078. // Remove random shard.
  1079. r := int(rng.Int63n(int64(i + j)))
  1080. sh[r] = sh[r][:0]
  1081. }
  1082. err = r.Reconstruct(sh)
  1083. if err != nil {
  1084. t.Fatal("reconstructing", i, j, ":", err)
  1085. }
  1086. ok, err := r.Verify(sh)
  1087. if err != nil {
  1088. t.Fatal("verifying", i, j, ":", err)
  1089. }
  1090. if !ok {
  1091. t.Fatal(i, j, ok)
  1092. }
  1093. for k := range sh {
  1094. if k == i {
  1095. // Only check data shards
  1096. break
  1097. }
  1098. if sh[k][0] != byte(i) {
  1099. t.Fatal("does not match", i, j, k, sh[0], sh[k])
  1100. }
  1101. }
  1102. }
  1103. }(i)
  1104. }
  1105. wg.Wait()
  1106. }
  1107. func TestPar1Matrices(t *testing.T) {
  1108. if testing.Short() || runtime.GOMAXPROCS(0) < 4 {
  1109. // Runtime ~15s.
  1110. t.Skip("Skipping slow matrix check")
  1111. }
  1112. var wg sync.WaitGroup
  1113. wg.Add(256 - 1)
  1114. for i := 1; i < 256; i++ {
  1115. go func(i int) {
  1116. // i == n.o. datashards
  1117. defer wg.Done()
  1118. var shards = make([][]byte, 255)
  1119. for p := range shards {
  1120. v := byte(i)
  1121. shards[p] = []byte{v}
  1122. }
  1123. rng := rand.New(rand.NewSource(0))
  1124. for j := 1; j < 256; j++ {
  1125. // j == n.o. parity shards
  1126. if i+j > 255 {
  1127. continue
  1128. }
  1129. sh := shards[:i+j]
  1130. r, err := New(i, j, WithPAR1Matrix())
  1131. if err != nil {
  1132. // We are not supposed to write to t from goroutines.
  1133. t.Fatal("creating matrix size", i, j, ":", err)
  1134. }
  1135. err = r.Encode(sh)
  1136. if err != nil {
  1137. t.Fatal("encoding", i, j, ":", err)
  1138. }
  1139. for k := 0; k < j; k++ {
  1140. // Remove random shard.
  1141. r := int(rng.Int63n(int64(i + j)))
  1142. sh[r] = sh[r][:0]
  1143. }
  1144. err = r.Reconstruct(sh)
  1145. if err != nil {
  1146. if err == errSingular {
  1147. t.Logf("Singular: %d (data), %d (parity)", i, j)
  1148. for p := range sh {
  1149. if len(sh[p]) == 0 {
  1150. shards[p] = []byte{byte(i)}
  1151. }
  1152. }
  1153. continue
  1154. }
  1155. t.Fatal("reconstructing", i, j, ":", err)
  1156. }
  1157. ok, err := r.Verify(sh)
  1158. if err != nil {
  1159. t.Fatal("verifying", i, j, ":", err)
  1160. }
  1161. if !ok {
  1162. t.Fatal(i, j, ok)
  1163. }
  1164. for k := range sh {
  1165. if k == i {
  1166. // Only check data shards
  1167. break
  1168. }
  1169. if sh[k][0] != byte(i) {
  1170. t.Fatal("does not match", i, j, k, sh[0], sh[k])
  1171. }
  1172. }
  1173. }
  1174. }(i)
  1175. }
  1176. wg.Wait()
  1177. }
  1178. func TestNew(t *testing.T) {
  1179. tests := []struct {
  1180. data, parity int
  1181. err error
  1182. }{
  1183. {127, 127, nil},
  1184. {128, 128, nil},
  1185. {255, 1, nil},
  1186. {256, 256, ErrMaxShardNum},
  1187. {0, 1, ErrInvShardNum},
  1188. {1, 0, ErrInvShardNum},
  1189. {256, 1, ErrMaxShardNum},
  1190. // overflow causes r.Shards to be negative
  1191. {256, int(^uint(0) >> 1), errInvalidRowSize},
  1192. }
  1193. for _, test := range tests {
  1194. _, err := New(test.data, test.parity)
  1195. if err != test.err {
  1196. t.Errorf("New(%v, %v): expected %v, got %v", test.data, test.parity, test.err, err)
  1197. }
  1198. }
  1199. }