gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/renter/siafile/rssubcode_test.go (about) 1 package siafile 2 3 import ( 4 "bytes" 5 "testing" 6 7 "gitlab.com/NebulousLabs/fastrand" 8 9 "gitlab.com/SiaPrime/SiaPrime/crypto" 10 ) 11 12 // TestPartialEncodeRecover checks that individual segments of an encoded piece 13 // can be recovered. 14 func TestPartialEncodeRecover(t *testing.T) { 15 segmentSize := crypto.SegmentSize 16 pieceSize := 4096 17 dataPieces := 10 18 parityPieces := 20 19 data := fastrand.Bytes(pieceSize * dataPieces) 20 originalData := make([]byte, len(data)) 21 copy(originalData, data) 22 // Create the erasure coder. 23 rsc, err := NewRSSubCode(dataPieces, parityPieces, uint64(segmentSize)) 24 if err != nil { 25 t.Fatal(err) 26 } 27 // Allocate space for the pieces. 28 pieces := make([][]byte, dataPieces) 29 for i := range pieces { 30 pieces[i] = make([]byte, pieceSize) 31 } 32 // Write the data to the pieces. 33 buf := bytes.NewBuffer(data) 34 for i := range pieces { 35 if buf.Len() < pieceSize { 36 t.Fatal("Buffer is empty") 37 } 38 pieces[i] = make([]byte, pieceSize) 39 copy(pieces[i], buf.Next(pieceSize)) 40 } 41 // Encode the pieces. 42 encodedPieces, err := rsc.EncodeShards(pieces) 43 if err != nil { 44 t.Fatal(err) 45 } 46 // Check that the parity shards have been created. 47 if len(encodedPieces) != rsc.NumPieces() { 48 t.Fatalf("encodedPieces should've length %v but was %v", rsc.NumPieces(), len(encodedPieces)) 49 } 50 // Every piece should have pieceSize. 51 for _, piece := range encodedPieces { 52 if len(piece) != pieceSize { 53 t.Fatalf("expecte len(piece) to be %v but was %v", pieceSize, len(piece)) 54 } 55 } 56 // Delete as many random pieces as possible. 57 for _, i := range fastrand.Perm(len(encodedPieces))[:parityPieces] { 58 encodedPieces[i] = nil 59 } 60 // Recover every segment individually. 61 dataOffset := 0 62 decodedSegmentSize := segmentSize * dataPieces 63 for segmentIndex := 0; segmentIndex < pieceSize/segmentSize; segmentIndex++ { 64 buf := new(bytes.Buffer) 65 segment := ExtractSegment(encodedPieces, segmentIndex, uint64(segmentSize)) 66 err = rsc.Recover(segment, uint64(segmentSize*rsc.MinPieces()), buf) 67 if err != nil { 68 t.Fatal(err) 69 } 70 if !bytes.Equal(buf.Bytes(), originalData[dataOffset:dataOffset+decodedSegmentSize]) { 71 t.Fatal("decoded bytes don't equal original segment") 72 } 73 dataOffset += decodedSegmentSize 74 } 75 // Recover all segments at once. 76 buf = new(bytes.Buffer) 77 err = rsc.Recover(encodedPieces, uint64(len(data)), buf) 78 if err != nil { 79 t.Fatal(err) 80 } 81 if !bytes.Equal(buf.Bytes(), originalData) { 82 t.Fatal("decoded bytes don't equal original data") 83 } 84 } 85 86 func BenchmarkRSSubCodeRecover(b *testing.B) { 87 segmentSize := crypto.SegmentSize 88 pieceSize := 4096 89 dataPieces := 10 90 parityPieces := 30 91 data := fastrand.Bytes(pieceSize * dataPieces) 92 originalData := make([]byte, len(data)) 93 copy(originalData, data) 94 // Create the erasure coder. 95 rsc, err := NewRSSubCode(dataPieces, parityPieces, uint64(segmentSize)) 96 if err != nil { 97 b.Fatal(err) 98 } 99 // Allocate space for the pieces. 100 pieces := make([][]byte, dataPieces) 101 for i := range pieces { 102 pieces[i] = make([]byte, pieceSize) 103 } 104 // Write the data to the pieces. 105 buf := bytes.NewBuffer(data) 106 for i := range pieces { 107 if buf.Len() < pieceSize { 108 b.Fatal("Buffer is empty") 109 } 110 pieces[i] = make([]byte, pieceSize) 111 copy(pieces[i], buf.Next(pieceSize)) 112 } 113 // Encode the pieces. 114 encodedPieces, err := rsc.EncodeShards(pieces) 115 if err != nil { 116 b.Fatal(err) 117 } 118 // Check that the parity shards have been created. 119 if len(encodedPieces) != rsc.NumPieces() { 120 b.Fatalf("encodedPieces should've length %v but was %v", rsc.NumPieces(), len(encodedPieces)) 121 } 122 // Every piece should have pieceSize. 123 for _, piece := range encodedPieces { 124 if len(piece) != pieceSize { 125 b.Fatalf("expecte len(piece) to be %v but was %v", pieceSize, len(piece)) 126 } 127 } 128 // Delete all data shards 129 for i := range encodedPieces[:dataPieces+1] { 130 encodedPieces[i] = nil 131 } 132 133 b.ReportAllocs() 134 b.ResetTimer() 135 b.SetBytes(int64(len(data))) 136 for i := 0; i < b.N; i++ { 137 buf.Reset() 138 err = rsc.Recover(encodedPieces, uint64(len(data)), buf) 139 if err != nil { 140 b.Fatal(err) 141 } 142 if !bytes.Equal(buf.Bytes(), originalData) { 143 b.Fatal("decoded bytes don't equal original data") 144 } 145 } 146 }