Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
325 lines
10 KiB
Go
325 lines
10 KiB
Go
package ec
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/storage/erasure_coding"
|
|
"github.com/seaweedfs/seaweedfs/weed/storage/needle"
|
|
"github.com/seaweedfs/seaweedfs/weed/util"
|
|
)
|
|
|
|
// TestEcShardMapRegister tests that EC shards are properly registered
|
|
func TestEcShardMapRegister(t *testing.T) {
|
|
ecShardMap := make(EcShardMap)
|
|
|
|
// Create test nodes with EC shards
|
|
node1 := newEcNode("dc1", "rack1", "node1", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{0, 1, 2, 3, 4, 5, 6})
|
|
node2 := newEcNode("dc1", "rack1", "node2", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{7, 8, 9, 10, 11, 12, 13})
|
|
|
|
ecShardMap.registerEcNode(node1, "c1")
|
|
ecShardMap.registerEcNode(node2, "c1")
|
|
|
|
// Verify volume 1 is registered
|
|
locations, found := ecShardMap[needle.VolumeId(1)]
|
|
if !found {
|
|
t.Fatal("Expected volume 1 to be registered")
|
|
}
|
|
|
|
// Check shard count
|
|
count := locations.shardCount()
|
|
if count != erasure_coding.TotalShardsCount {
|
|
t.Errorf("Expected %d shards, got %d", erasure_coding.TotalShardsCount, count)
|
|
}
|
|
|
|
// Verify shard distribution
|
|
for i := 0; i < 7; i++ {
|
|
if len(locations[i]) != 1 || locations[i][0].Info.Id != "node1" {
|
|
t.Errorf("Shard %d should be on node1", i)
|
|
}
|
|
}
|
|
for i := 7; i < erasure_coding.TotalShardsCount; i++ {
|
|
if len(locations[i]) != 1 || locations[i][0].Info.Id != "node2" {
|
|
t.Errorf("Shard %d should be on node2", i)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestEcShardMapShardCount tests shard counting
|
|
func TestEcShardMapShardCount(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
shardIds []erasure_coding.ShardId
|
|
expectedCount int
|
|
}{
|
|
{"all shards", []erasure_coding.ShardId{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 14},
|
|
{"data shards only", []erasure_coding.ShardId{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 10},
|
|
{"parity shards only", []erasure_coding.ShardId{10, 11, 12, 13}, 4},
|
|
{"missing some shards", []erasure_coding.ShardId{0, 1, 2, 3, 4, 5, 6, 7, 8}, 9},
|
|
{"single shard", []erasure_coding.ShardId{0}, 1},
|
|
{"no shards", []erasure_coding.ShardId{}, 0},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
locations := make(EcShardLocations, erasure_coding.MaxShardCount)
|
|
for _, shardId := range tc.shardIds {
|
|
locations[shardId] = []*EcNode{
|
|
newEcNode("dc1", "rack1", "node1", 100),
|
|
}
|
|
}
|
|
|
|
count := locations.shardCount()
|
|
if count != tc.expectedCount {
|
|
t.Errorf("Expected %d shards, got %d", tc.expectedCount, count)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestRebuildEcVolumesInsufficientShards tests that unrepairable volumes are skipped
|
|
func TestRebuildEcVolumesInsufficientShards(t *testing.T) {
|
|
var logBuffer bytes.Buffer
|
|
|
|
// Create a volume with insufficient shards (less than DataShardsCount)
|
|
node1 := newEcNode("dc1", "rack1", "node1", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{0, 1, 2, 3, 4}) // Only 5 shards
|
|
|
|
erb := &ecRebuilder{
|
|
env: &Env{},
|
|
ewg: util.NewErrorWaitGroup(10),
|
|
ecNodes: []*EcNode{node1},
|
|
writer: &logBuffer,
|
|
}
|
|
|
|
erb.rebuildEcVolumes("c1")
|
|
err := erb.ewg.Wait()
|
|
|
|
// Unrepairable volumes should be skipped (not cause an error)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error for unrepairable volume (should be skipped), got: %v", err)
|
|
}
|
|
// Verify the skip message was logged
|
|
if !strings.Contains(logBuffer.String(), "unrepairable") {
|
|
t.Errorf("Expected 'unrepairable' in log output, got: %s", logBuffer.String())
|
|
}
|
|
}
|
|
|
|
// TestRebuildEcVolumesCompleteVolume tests that complete volumes are skipped
|
|
func TestRebuildEcVolumesCompleteVolume(t *testing.T) {
|
|
var logBuffer bytes.Buffer
|
|
|
|
// Create a volume with all shards
|
|
node1 := newEcNode("dc1", "rack1", "node1", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13})
|
|
|
|
erb := &ecRebuilder{
|
|
env: &Env{},
|
|
ewg: util.NewErrorWaitGroup(10),
|
|
ecNodes: []*EcNode{node1},
|
|
writer: &logBuffer,
|
|
applyChanges: false,
|
|
}
|
|
|
|
erb.rebuildEcVolumes("c1")
|
|
err := erb.ewg.Wait()
|
|
|
|
if err != nil {
|
|
t.Fatalf("Expected no error for complete volume, got: %v", err)
|
|
}
|
|
|
|
// The function should return quickly without attempting rebuild
|
|
// since the volume is already complete
|
|
}
|
|
|
|
// TestRebuildEcVolumesInsufficientSpace tests error handling for insufficient disk space
|
|
func TestRebuildEcVolumesInsufficientSpace(t *testing.T) {
|
|
var logBuffer bytes.Buffer
|
|
|
|
// Create a volume with missing shards but insufficient free slots
|
|
// Node has 10 local shards, missing 4 shards (10,11,12,13), so needs 4 free slots
|
|
// Set free slots to 3 (insufficient)
|
|
node1 := newEcNode("dc1", "rack1", "node1", 3). // Only 3 free slots, need 4
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
|
|
|
|
erb := &ecRebuilder{
|
|
env: &Env{},
|
|
ewg: util.NewErrorWaitGroup(10),
|
|
ecNodes: []*EcNode{node1},
|
|
writer: &logBuffer,
|
|
applyChanges: false,
|
|
}
|
|
|
|
erb.rebuildEcVolumes("c1")
|
|
err := erb.ewg.Wait()
|
|
|
|
if err == nil {
|
|
t.Fatal("Expected error for insufficient disk space, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "no node has sufficient free slots") {
|
|
t.Errorf("Expected 'no node has sufficient free slots' in error message, got: %s", err.Error())
|
|
}
|
|
// Verify the enhanced error message includes diagnostic information
|
|
if !strings.Contains(err.Error(), "need") || !strings.Contains(err.Error(), "max available") {
|
|
t.Errorf("Expected diagnostic information in error message, got: %s", err.Error())
|
|
}
|
|
}
|
|
|
|
// TestMultipleNodesWithShards tests rebuild with shards distributed across multiple nodes
|
|
func TestMultipleNodesWithShards(t *testing.T) {
|
|
ecShardMap := make(EcShardMap)
|
|
|
|
// Create 3 nodes with different shards
|
|
node1 := newEcNode("dc1", "rack1", "node1", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{0, 1, 2, 3})
|
|
node2 := newEcNode("dc1", "rack1", "node2", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{4, 5, 6, 7})
|
|
node3 := newEcNode("dc1", "rack1", "node3", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{8, 9})
|
|
|
|
ecShardMap.registerEcNode(node1, "c1")
|
|
ecShardMap.registerEcNode(node2, "c1")
|
|
ecShardMap.registerEcNode(node3, "c1")
|
|
|
|
locations := ecShardMap[needle.VolumeId(1)]
|
|
count := locations.shardCount()
|
|
|
|
// We have 10 shards total, which is enough for data shards
|
|
if count != 10 {
|
|
t.Errorf("Expected 10 shards, got %d", count)
|
|
}
|
|
|
|
// Verify each shard is on the correct node
|
|
for i := 0; i < 4; i++ {
|
|
if len(locations[i]) != 1 || locations[i][0].Info.Id != "node1" {
|
|
t.Errorf("Shard %d should be on node1", i)
|
|
}
|
|
}
|
|
for i := 4; i < 8; i++ {
|
|
if len(locations[i]) != 1 || locations[i][0].Info.Id != "node2" {
|
|
t.Errorf("Shard %d should be on node2", i)
|
|
}
|
|
}
|
|
for i := 8; i < 10; i++ {
|
|
if len(locations[i]) != 1 || locations[i][0].Info.Id != "node3" {
|
|
t.Errorf("Shard %d should be on node3", i)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestDuplicateShards tests handling of duplicate shards on multiple nodes
|
|
func TestDuplicateShards(t *testing.T) {
|
|
ecShardMap := make(EcShardMap)
|
|
|
|
// Create 2 nodes with overlapping shards (both have shard 0)
|
|
node1 := newEcNode("dc1", "rack1", "node1", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{0, 1, 2, 3})
|
|
node2 := newEcNode("dc1", "rack1", "node2", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{0, 4, 5, 6}) // Duplicate shard 0
|
|
|
|
ecShardMap.registerEcNode(node1, "c1")
|
|
ecShardMap.registerEcNode(node2, "c1")
|
|
|
|
locations := ecShardMap[needle.VolumeId(1)]
|
|
|
|
// Shard 0 should be on both nodes
|
|
if len(locations[0]) != 2 {
|
|
t.Errorf("Expected shard 0 on 2 nodes, got %d", len(locations[0]))
|
|
}
|
|
|
|
// Verify both nodes are registered for shard 0
|
|
foundNode1 := false
|
|
foundNode2 := false
|
|
for _, node := range locations[0] {
|
|
if node.Info.Id == "node1" {
|
|
foundNode1 = true
|
|
}
|
|
if node.Info.Id == "node2" {
|
|
foundNode2 = true
|
|
}
|
|
}
|
|
if !foundNode1 || !foundNode2 {
|
|
t.Error("Both nodes should have shard 0")
|
|
}
|
|
|
|
// Shard count should be 7 (unique shards: 0, 1, 2, 3, 4, 5, 6)
|
|
count := locations.shardCount()
|
|
if count != 7 {
|
|
t.Errorf("Expected 7 unique shards, got %d", count)
|
|
}
|
|
}
|
|
|
|
// TestPrepareDataToRecoverTargetShardCount tests that prepareDataToRecover caps the shard reporting
|
|
func TestPrepareDataToRecoverTargetShardCount(t *testing.T) {
|
|
var logBuffer bytes.Buffer
|
|
|
|
// Create a node with 10 shards (0-9)
|
|
node1 := newEcNode("dc1", "rack1", "node1", 100).
|
|
addEcVolumeAndShardsForTest(1, "c1", []erasure_coding.ShardId{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
|
|
|
|
erb := &ecRebuilder{
|
|
env: &Env{},
|
|
ecNodes: []*EcNode{node1},
|
|
writer: &logBuffer,
|
|
}
|
|
|
|
locations := make(EcShardLocations, erasure_coding.MaxShardCount)
|
|
for i := 0; i < 10; i++ {
|
|
locations[i] = []*EcNode{node1}
|
|
}
|
|
|
|
// Shards 10-13 are missing, but 14-31 should NOT be reported
|
|
_, _, err := erb.prepareDataToRecover(node1, "c1", needle.VolumeId(1), locations)
|
|
if err != nil {
|
|
t.Fatalf("prepareDataToRecover failed: %v", err)
|
|
}
|
|
|
|
output := logBuffer.String()
|
|
lines := strings.Split(strings.TrimSpace(output), "\n")
|
|
|
|
// We expect "use existing shard 1.0" through "use existing shard 1.9" (10 lines)
|
|
// and "missing shard 1.10" through "missing shard 1.13" (4 lines)
|
|
// Total 14 lines expected. Shards 14-31 should be absent.
|
|
expectedLineCount := 14
|
|
if len(lines) != expectedLineCount {
|
|
t.Errorf("Expected %d lines of output, got %d. Output:\n%s", expectedLineCount, len(lines), output)
|
|
}
|
|
|
|
for i := 14; i < erasure_coding.MaxShardCount; i++ {
|
|
if strings.Contains(output, "shard 1."+strings.TrimSpace(string(rune('0'+i)))) ||
|
|
strings.Contains(output, "shard 1."+fmt.Sprintf("%d", i)) {
|
|
t.Errorf("Shard 1.%d should not be reported in output", i)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRebuilderVolumeIdMatches(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
rebuilderVolumeIds []needle.VolumeId
|
|
volumeId needle.VolumeId
|
|
want bool
|
|
}{
|
|
{"no target volume IDs (nil)", nil, needle.VolumeId(1234), true},
|
|
{"no target volume IDs", []needle.VolumeId{}, needle.VolumeId(5678), true},
|
|
{"volume ID matches", []needle.VolumeId{needle.VolumeId(123), needle.VolumeId(456), needle.VolumeId(789)}, needle.VolumeId(456), true},
|
|
{"volume ID mismatch", []needle.VolumeId{needle.VolumeId(123), needle.VolumeId(456), needle.VolumeId(789)}, needle.VolumeId(321), false},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
ecb := &ecRebuilder{
|
|
volumeIds: tc.rebuilderVolumeIds,
|
|
}
|
|
|
|
if got, want := ecb.matchesVolumeId(tc.volumeId), tc.want; got != want {
|
|
t.Errorf("Expected %v, got %v", want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|