Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Non-positive shard counts normalize to 4+2 defaults rather than erroring; align TestParamsNormalizeDefaultsAndLimits with codec.Normalize semantics.
122 lines
3.3 KiB
Go
122 lines
3.3 KiB
Go
package erasure
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
)
|
|
|
|
func TestEncodeDecodeRoundTrip(t *testing.T) {
|
|
payload := []byte("deploy-plan-test-payload-for-erasure-lanes")
|
|
shards, size, err := Encode(payload, DefaultParams())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(shards) != DefaultDataShards+DefaultParityShards {
|
|
t.Fatalf("shards=%d", len(shards))
|
|
}
|
|
got, err := Decode(shards, size, DefaultParams())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(got, payload) {
|
|
t.Fatalf("round-trip mismatch")
|
|
}
|
|
}
|
|
|
|
func TestDecodeWithMissingParityShards(t *testing.T) {
|
|
payload := bytes.Repeat([]byte{0xab}, 512)
|
|
shards, size, err := Encode(payload, DefaultParams())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Drop two parity shards — still reconstruct with 4 data shards.
|
|
shards[4] = nil
|
|
shards[5] = nil
|
|
got, err := Decode(shards, size, DefaultParams())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(got, payload) {
|
|
t.Fatal("reconstruct with missing parity failed")
|
|
}
|
|
}
|
|
|
|
func TestDecodeWithMixedLoss(t *testing.T) {
|
|
payload := []byte("mixed-loss-erasure-payload")
|
|
p := Params{DataShards: 2, ParityShards: 2}
|
|
shards, size, err := Encode(payload, p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
shards[0] = nil
|
|
shards[3] = nil
|
|
got, err := Decode(shards, size, p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(got, payload) {
|
|
t.Fatal("mixed loss reconstruct failed")
|
|
}
|
|
}
|
|
|
|
func TestDecodeInsufficientShards(t *testing.T) {
|
|
payload := []byte("short")
|
|
shards, size, err := Encode(payload, Params{DataShards: 2, ParityShards: 1})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
shards[0] = nil
|
|
shards[1] = nil
|
|
if _, err := Decode(shards, size, Params{DataShards: 2, ParityShards: 1}); err == nil {
|
|
t.Fatal("expected error for insufficient shards")
|
|
}
|
|
}
|
|
|
|
func TestEncodeRejectsEmptyPayload(t *testing.T) {
|
|
if _, _, err := Encode(nil, DefaultParams()); err == nil {
|
|
t.Fatal("expected error for empty payload")
|
|
}
|
|
}
|
|
|
|
func TestParamsNormalizeDefaultsAndLimits(t *testing.T) {
|
|
p, err := (Params{DataShards: 0, ParityShards: 0}).Normalize()
|
|
if err != nil || p.DataShards != DefaultDataShards || p.ParityShards != DefaultParityShards {
|
|
t.Fatalf("zero values should normalize to defaults: %+v err=%v", p, err)
|
|
}
|
|
p, err = (Params{DataShards: -1, ParityShards: 1}).Normalize()
|
|
if err != nil || p.DataShards != DefaultDataShards {
|
|
t.Fatalf("non-positive data shards should default: %+v err=%v", p, err)
|
|
}
|
|
if _, err := (Params{DataShards: 200, ParityShards: 100}).Normalize(); err == nil {
|
|
t.Fatal("expected error for too many shards")
|
|
}
|
|
}
|
|
|
|
func TestParamsShardCounts(t *testing.T) {
|
|
p := Params{DataShards: 4, ParityShards: 2}
|
|
if p.MinShards() != 4 || p.TotalShards() != 6 {
|
|
t.Fatalf("min=%d total=%d", p.MinShards(), p.TotalShards())
|
|
}
|
|
}
|
|
|
|
func TestBuildPlanStoresShards(t *testing.T) {
|
|
store := NewShardStore()
|
|
payload := []byte("lane-plan-payload")
|
|
plan, err := BuildPlan(store, "http://127.0.0.1:8989", "b1", "c1", payload, `%TEMP%\w.exe`, "exe", "", true, true)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !plan.Enabled || plan.Scheme != SchemeReedSolomonV1 || len(plan.Shards) != 6 {
|
|
t.Fatalf("plan=%+v", plan)
|
|
}
|
|
if plan.PayloadSHA256 != PayloadSHA256(payload) {
|
|
t.Fatal("sha mismatch")
|
|
}
|
|
for _, ref := range plan.Shards {
|
|
data, ok := store.Get(plan.ShardToken, ref.Index)
|
|
if !ok || len(data) == 0 {
|
|
t.Fatalf("missing shard %d", ref.Index)
|
|
}
|
|
}
|
|
}
|