123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- package reedsolomon
- import (
- "bytes"
- "fmt"
- "math/rand"
- "testing"
- )
- const (
- kb = 1024
- mb = 1024 * 1024
- testNumIn = 10
- testNumOut = 4
- )
- const verifySize = 256 + 32 + 16 + 15
- func TestVerifyEncBase(t *testing.T) {
- d := 5
- p := 5
- vects := [][]byte{
- {0, 1},
- {4, 5},
- {2, 3},
- {6, 7},
- {8, 9},
- {0, 0},
- {0, 0},
- {0, 0},
- {0, 0},
- {0, 0},
- }
- em, err := genEncMatrixVand(d, p)
- if err != nil {
- t.Fatal(err)
- }
- g := em[d*d:]
- e := &encBase{data: d, parity: p, gen: g}
- err = e.Encode(vects)
- if err != nil {
- t.Fatal(err)
- }
- if vects[5][0] != 12 || vects[5][1] != 13 {
- t.Fatal("vect 5 mismatch")
- }
- if vects[6][0] != 10 || vects[6][1] != 11 {
- t.Fatal("vect 6 mismatch")
- }
- if vects[7][0] != 14 || vects[7][1] != 15 {
- t.Fatal("vect 7 mismatch")
- }
- if vects[8][0] != 90 || vects[8][1] != 91 {
- t.Fatal("vect 8 mismatch")
- }
- if vects[9][0] != 94 || vects[9][1] != 95 {
- t.Fatal("shard 9 mismatch")
- }
- }
- func fillRandom(v []byte) {
- for i := 0; i < len(v); i += 7 {
- val := rand.Int63()
- for j := 0; i+j < len(v) && j < 7; j++ {
- v[i+j] = byte(val)
- val >>= 8
- }
- }
- }
- func verifyEnc(t *testing.T, d, p int) {
- for i := 1; i <= verifySize; i++ {
- vects1 := make([][]byte, d+p)
- vects2 := make([][]byte, d+p)
- for j := 0; j < d+p; j++ {
- vects1[j] = make([]byte, i)
- vects2[j] = make([]byte, i)
- }
- for j := 0; j < d; j++ {
- rand.Seed(int64(j))
- fillRandom(vects1[j])
- copy(vects2[j], vects1[j])
- }
- e, err := New(d, p)
- if err != nil {
- t.Fatal(err)
- }
- err = e.Encode(vects1)
- if err != nil {
- t.Fatal(err)
- }
- em, err := genEncMatrixVand(d, p)
- if err != nil {
- t.Fatal(err)
- }
- g := em[d*d:]
- e2 := &encBase{data: d, parity: p, gen: g}
- err = e2.Encode(vects2)
- for k, v1 := range vects1 {
- if !bytes.Equal(v1, vects2[k]) {
- t.Fatalf("no match enc with encBase; vect: %d; size: %d", k, i)
- }
- }
- }
- }
- func TestVerifyEnc(t *testing.T) {
- verifyEnc(t, testNumIn, testNumOut)
- }
- func verifyReconst(t *testing.T, d, p int, lost []int) {
- for i := 1; i <= verifySize; i++ {
- vects1 := make([][]byte, d+p)
- vects2 := make([][]byte, d+p)
- for j := 0; j < d+p; j++ {
- vects1[j] = make([]byte, i)
- vects2[j] = make([]byte, i)
- }
- for j := 0; j < d; j++ {
- rand.Seed(int64(j))
- fillRandom(vects1[j])
- }
- e, err := New(d, p)
- if err != nil {
- t.Fatal(err)
- }
- err = e.Encode(vects1)
- if err != nil {
- t.Fatal(err)
- }
- for j := 0; j < d+p; j++ {
- copy(vects2[j], vects1[j])
- }
- for _, i := range lost {
- vects2[i] = nil
- }
- err = e.Reconstruct(vects2)
- if err != nil {
- t.Fatal(err)
- }
- for k, v1 := range vects1 {
- if !bytes.Equal(v1, vects2[k]) {
- t.Fatalf("no match reconst; vect: %d; size: %d", k, i)
- }
- }
- }
- }
- func TestVerifyReconst(t *testing.T) {
- lost := []int{0, 11, 3, 4}
- verifyReconst(t, testNumIn, testNumOut, lost)
- }
- func benchEnc(b *testing.B, d, p, size int) {
- vects := make([][]byte, d+p)
- for j := 0; j < d+p; j++ {
- vects[j] = make([]byte, size)
- }
- for j := 0; j < d; j++ {
- rand.Seed(int64(j))
- fillRandom(vects[j])
- }
- e, err := New(d, p)
- if err != nil {
- b.Fatal(err)
- }
- err = e.Encode(vects)
- if err != nil {
- b.Fatal(err)
- }
- b.SetBytes(int64(d * size))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- err = e.Encode(vects)
- if err != nil {
- b.Fatal(err)
- }
- }
- }
- func benchEncRun(f func(*testing.B, int, int, int), d, p int, size []int) func(*testing.B) {
- return func(b *testing.B) {
- for _, s := range size {
- b.Run(fmt.Sprintf("%d+%d_%d", d, p, s), func(b *testing.B) {
- f(b, d, p, s)
- })
- }
- }
- }
- func BenchmarkEnc(b *testing.B) {
- s1 := []int{1350}
- b.Run("", benchEncRun(benchEnc, 10, 3, s1))
- s2 := []int{1400, 4 * kb, 64 * kb, mb, 16 * mb}
- b.Run("", benchEncRun(benchEnc, testNumIn, testNumOut, s2))
- }
- func benchReconst(b *testing.B, d, p, size int, lost []int) {
- vects := make([][]byte, d+p)
- for j := 0; j < d+p; j++ {
- vects[j] = make([]byte, size)
- }
- for j := 0; j < d; j++ {
- rand.Seed(int64(j))
- fillRandom(vects[j])
- }
- e, err := New(d, p)
- if err != nil {
- b.Fatal(err)
- }
- err = e.Encode(vects)
- if err != nil {
- b.Fatal(err)
- }
- for _, i := range lost {
- vects[i] = nil
- }
- err = e.Reconstruct(vects)
- if err != nil {
- b.Fatal(err)
- }
- b.SetBytes(int64(d * size))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- for _, i := range lost {
- vects[i] = nil
- }
- err = e.Reconstruct(vects)
- if err != nil {
- b.Fatal(err)
- }
- }
- }
- func benchReconstRun(f func(*testing.B, int, int, int, []int), d, p int, size, lost []int) func(*testing.B) {
- return func(b *testing.B) {
- for _, s := range size {
- b.Run(fmt.Sprintf("%d+%d_%d", d, p, s), func(b *testing.B) {
- f(b, d, p, s, lost)
- })
- }
- }
- }
- // Reconstruct p vects
- func BenchmarkReconst(b *testing.B) {
- l1 := []int{2, 4, 5}
- s1 := []int{1350}
- b.Run("", benchReconstRun(benchReconst, 10, 3, s1, l1))
- l2 := []int{2, 4, 7, 9}
- s2 := []int{1400, 4 * kb, 64 * kb, mb, 16 * mb}
- b.Run("", benchReconstRun(benchReconst, testNumIn, testNumOut, s2, l2))
- }
- func benchReconstPos(b *testing.B, d, p, size int, has, dLost, pLost []int) {
- vects := make([][]byte, d+p)
- for j := 0; j < d+p; j++ {
- vects[j] = make([]byte, size)
- }
- for j := 0; j < d; j++ {
- rand.Seed(int64(j))
- fillRandom(vects[j])
- }
- e, err := New(d, p)
- if err != nil {
- b.Fatal(err)
- }
- err = e.Encode(vects)
- if err != nil {
- b.Fatal(err)
- }
- err = e.ReconstWithPos(vects, has, dLost, pLost)
- if err != nil {
- b.Fatal(err)
- }
- b.SetBytes(int64(d * size))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- err = e.ReconstWithPos(vects, has, dLost, pLost)
- if err != nil {
- b.Fatal(err)
- }
- }
- }
- func benchReconstPosRun(f func(*testing.B, int, int, int, []int, []int, []int), d, p int, size,
- has, dLost, pLost []int) func(*testing.B) {
- return func(b *testing.B) {
- for _, s := range size {
- b.Run(fmt.Sprintf("%dx%d_%d", d, p, s), func(b *testing.B) {
- f(b, d, p, s, has, dLost, pLost)
- })
- }
- }
- }
- // Reconstruct p vects with position
- func BenchmarkReconstWithPos(b *testing.B) {
- h1 := []int{0, 1, 3, 6, 7, 8, 9, 10, 11, 12}
- d1 := []int{2, 4, 5}
- p1 := []int{}
- s1 := []int{1350}
- b.Run("", benchReconstPosRun(benchReconstPos, 10, 3, s1, h1, d1, p1))
- h2 := []int{0, 1, 3, 5, 6, 8, 10, 11, 12, 13}
- d2 := []int{2, 4, 7, 9}
- p2 := []int{}
- s2 := []int{1400, 4 * kb, 64 * kb, mb, 16 * mb}
- b.Run("", benchReconstPosRun(benchReconstPos, testNumIn, testNumOut, s2, h2, d2, p2))
- }
|