@@ -2240,3 +2240,110 @@ func TestReentrant(t *testing.T) {
22402240 }
22412241 }
22422242}
2243+
2244+ func TestRSReconstructSome (t * testing.T ) {
2245+ const (
2246+ dataShards = 3
2247+ parityShards = 2
2248+ sectorSize = 1 << 20 // 1 MiB
2249+ )
2250+ stripedSplit := func (data []byte , dataShards [][]byte ) {
2251+ const leafSize = 64
2252+ buf := bytes .NewBuffer (data )
2253+ for off := 0 ; buf .Len () > 0 ; off += leafSize {
2254+ for _ , shard := range dataShards {
2255+ copy (shard [off :], buf .Next (leafSize ))
2256+ }
2257+ }
2258+ }
2259+
2260+ // prepare random data
2261+ buf := make ([]byte , sectorSize * dataShards )
2262+ rand .Read (buf )
2263+
2264+ // prepare shards
2265+ shards := make ([][]byte , dataShards + parityShards )
2266+ for i := range shards {
2267+ shards [i ] = make ([]byte , sectorSize )
2268+ }
2269+
2270+ for i , o := range testOpts () {
2271+ toFill := []int {0 , 1 , 2 , 3 , 4 }
2272+ t .Run (fmt .Sprintf ("options %d" , i ), func (t * testing.T ) {
2273+ // Shuffle the indices to fill
2274+ rand .Shuffle (len (toFill ), func (i , j int ) {
2275+ toFill [i ], toFill [j ] = toFill [j ], toFill [i ]
2276+ })
2277+ stripedSplit (buf , shards [:dataShards ])
2278+ // encode shards
2279+ enc , err := New (dataShards , parityShards , o ... )
2280+ if err != nil {
2281+ t .Fatal (err )
2282+ }
2283+ err = enc .Encode (shards )
2284+ if err != nil {
2285+ t .Fatal (err )
2286+ }
2287+
2288+ for _ , required := range [][]bool {
2289+ {false , false , false , false , true },
2290+ {false , false , false , true , true },
2291+ {false , false , true , false , true },
2292+ {false , false , true , true , true },
2293+ {false , true , false , false , true },
2294+ {false , true , false , true , true },
2295+ {false , true , true , false , true },
2296+ {false , true , true , true , true },
2297+ {true , false , false , false , true },
2298+ {true , false , false , true , true },
2299+ {true , false , true , false , true },
2300+ {true , false , true , true , true },
2301+ {true , true , false , false , true },
2302+ {true , true , false , true , true },
2303+ {true , true , true , false , true },
2304+ {true , true , true , true , true },
2305+
2306+ {false , false , false , false , false },
2307+ {false , false , false , true , false },
2308+ {false , false , true , false , false },
2309+ {false , false , true , true , false },
2310+ {false , true , false , false , false },
2311+ {false , true , false , true , false },
2312+ {false , true , true , false , false },
2313+ {false , true , true , true , false },
2314+ {true , false , false , false , false },
2315+ {true , false , false , true , false },
2316+ {true , false , true , false , false },
2317+ {true , false , true , true , false },
2318+ {true , true , false , false , false },
2319+ {true , true , false , true , false },
2320+ {true , true , true , false , false },
2321+ {true , true , true , true , false },
2322+ } {
2323+ downloaded := make ([][]byte , len (shards ))
2324+ downloaded [toFill [0 ]] = append ([]byte {}, shards [toFill [0 ]]... )
2325+ downloaded [toFill [1 ]] = append ([]byte {}, shards [toFill [1 ]]... )
2326+ downloaded [toFill [2 ]] = append ([]byte {}, shards [toFill [2 ]]... )
2327+ err = enc .ReconstructSome (downloaded , required )
2328+ if err != nil {
2329+ t .Fatal (err )
2330+ }
2331+ for i , shard := range downloaded {
2332+ if shard == nil && required [i ] {
2333+ t .Errorf ("shard idx %d should not be nil" , i )
2334+ }
2335+ if ! required [i ] && shard == nil {
2336+ // Ignore, if it wasn't reconstructed
2337+ continue
2338+ }
2339+ if len (shard ) != sectorSize {
2340+ t .Errorf ("shard idx %d has wrong size: %d, want %d" , i , len (shard ), sectorSize )
2341+ }
2342+ if ! bytes .Equal (shard , shards [i ]) {
2343+ t .Errorf ("shard idx %d does not match original" , i )
2344+ }
2345+ }
2346+ }
2347+ })
2348+ }
2349+ }
0 commit comments