Browse Source

fmt

pull/7445/head
chrislu 2 months ago
parent
commit
89da0c84d5
  1. 71
      weed/shell/command_ec_rebuild_test.go

71
weed/shell/command_ec_rebuild_test.go

@ -2,7 +2,6 @@ package shell
import ( import (
"bytes" "bytes"
"fmt"
"strings" "strings"
"testing" "testing"
@ -13,28 +12,28 @@ import (
// TestEcShardMapRegister tests that EC shards are properly registered // TestEcShardMapRegister tests that EC shards are properly registered
func TestEcShardMapRegister(t *testing.T) { func TestEcShardMapRegister(t *testing.T) {
ecShardMap := make(EcShardMap) ecShardMap := make(EcShardMap)
// Create test nodes with EC shards // Create test nodes with EC shards
node1 := newEcNode("dc1", "rack1", "node1", 100). node1 := newEcNode("dc1", "rack1", "node1", 100).
addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3, 4, 5, 6}) addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3, 4, 5, 6})
node2 := newEcNode("dc1", "rack1", "node2", 100). node2 := newEcNode("dc1", "rack1", "node2", 100).
addEcVolumeAndShardsForTest(1, "c1", []uint32{7, 8, 9, 10, 11, 12, 13}) addEcVolumeAndShardsForTest(1, "c1", []uint32{7, 8, 9, 10, 11, 12, 13})
ecShardMap.registerEcNode(node1, "c1") ecShardMap.registerEcNode(node1, "c1")
ecShardMap.registerEcNode(node2, "c1") ecShardMap.registerEcNode(node2, "c1")
// Verify volume 1 is registered // Verify volume 1 is registered
locations, found := ecShardMap[needle.VolumeId(1)] locations, found := ecShardMap[needle.VolumeId(1)]
if !found { if !found {
t.Fatal("Expected volume 1 to be registered") t.Fatal("Expected volume 1 to be registered")
} }
// Check shard count // Check shard count
count := locations.shardCount() count := locations.shardCount()
if count != erasure_coding.TotalShardsCount { if count != erasure_coding.TotalShardsCount {
t.Errorf("Expected %d shards, got %d", erasure_coding.TotalShardsCount, count) t.Errorf("Expected %d shards, got %d", erasure_coding.TotalShardsCount, count)
} }
// Verify shard distribution // Verify shard distribution
for i := 0; i < 7; i++ { for i := 0; i < 7; i++ {
if len(locations[i]) != 1 || locations[i][0].info.Id != "node1" { if len(locations[i]) != 1 || locations[i][0].info.Id != "node1" {
@ -62,7 +61,7 @@ func TestEcShardMapShardCount(t *testing.T) {
{"single shard", []uint32{0}, 1}, {"single shard", []uint32{0}, 1},
{"no shards", []uint32{}, 0}, {"no shards", []uint32{}, 0},
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
locations := make(EcShardLocations, erasure_coding.MaxShardCount) locations := make(EcShardLocations, erasure_coding.MaxShardCount)
@ -71,7 +70,7 @@ func TestEcShardMapShardCount(t *testing.T) {
newEcNode("dc1", "rack1", "node1", 100), newEcNode("dc1", "rack1", "node1", 100),
} }
} }
count := locations.shardCount() count := locations.shardCount()
if count != tc.expectedCount { if count != tc.expectedCount {
t.Errorf("Expected %d shards, got %d", tc.expectedCount, count) t.Errorf("Expected %d shards, got %d", tc.expectedCount, count)
@ -112,18 +111,18 @@ func TestEcRebuilderEcNodeWithMoreFreeSlots(t *testing.T) {
expectedNode: "node1", // Should return first one expectedNode: "node1", // Should return first one
}, },
} }
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
erb := &ecRebuilder{ erb := &ecRebuilder{
ecNodes: tc.nodes, ecNodes: tc.nodes,
} }
node := erb.ecNodeWithMoreFreeSlots() node := erb.ecNodeWithMoreFreeSlots()
if node == nil { if node == nil {
t.Fatal("Expected a node, got nil") t.Fatal("Expected a node, got nil")
} }
if node.info.Id != tc.expectedNode { if node.info.Id != tc.expectedNode {
t.Errorf("Expected node %s, got %s", tc.expectedNode, node.info.Id) t.Errorf("Expected node %s, got %s", tc.expectedNode, node.info.Id)
} }
@ -136,7 +135,7 @@ func TestEcRebuilderEcNodeWithMoreFreeSlotsEmpty(t *testing.T) {
erb := &ecRebuilder{ erb := &ecRebuilder{
ecNodes: []*EcNode{}, ecNodes: []*EcNode{},
} }
node := erb.ecNodeWithMoreFreeSlots() node := erb.ecNodeWithMoreFreeSlots()
if node != nil { if node != nil {
t.Errorf("Expected nil for empty node list, got %v", node) t.Errorf("Expected nil for empty node list, got %v", node)
@ -146,11 +145,11 @@ func TestEcRebuilderEcNodeWithMoreFreeSlotsEmpty(t *testing.T) {
// TestRebuildEcVolumesInsufficientShards tests error handling for unrepairable volumes // TestRebuildEcVolumesInsufficientShards tests error handling for unrepairable volumes
func TestRebuildEcVolumesInsufficientShards(t *testing.T) { func TestRebuildEcVolumesInsufficientShards(t *testing.T) {
var logBuffer bytes.Buffer var logBuffer bytes.Buffer
// Create a volume with insufficient shards (less than DataShardsCount) // Create a volume with insufficient shards (less than DataShardsCount)
node1 := newEcNode("dc1", "rack1", "node1", 100). node1 := newEcNode("dc1", "rack1", "node1", 100).
addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3, 4}) // Only 5 shards addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3, 4}) // Only 5 shards
erb := &ecRebuilder{ erb := &ecRebuilder{
commandEnv: &CommandEnv{ commandEnv: &CommandEnv{
env: make(map[string]string), env: make(map[string]string),
@ -159,12 +158,12 @@ func TestRebuildEcVolumesInsufficientShards(t *testing.T) {
ecNodes: []*EcNode{node1}, ecNodes: []*EcNode{node1},
writer: &logBuffer, writer: &logBuffer,
} }
err := erb.rebuildEcVolumes("c1") err := erb.rebuildEcVolumes("c1")
if err == nil { if err == nil {
t.Fatal("Expected error for insufficient shards, got nil") t.Fatal("Expected error for insufficient shards, got nil")
} }
if !strings.Contains(err.Error(), "unrepairable") { if !strings.Contains(err.Error(), "unrepairable") {
t.Errorf("Expected 'unrepairable' in error message, got: %s", err.Error()) t.Errorf("Expected 'unrepairable' in error message, got: %s", err.Error())
} }
@ -173,11 +172,11 @@ func TestRebuildEcVolumesInsufficientShards(t *testing.T) {
// TestRebuildEcVolumesCompleteVolume tests that complete volumes are skipped // TestRebuildEcVolumesCompleteVolume tests that complete volumes are skipped
func TestRebuildEcVolumesCompleteVolume(t *testing.T) { func TestRebuildEcVolumesCompleteVolume(t *testing.T) {
var logBuffer bytes.Buffer var logBuffer bytes.Buffer
// Create a volume with all shards // Create a volume with all shards
node1 := newEcNode("dc1", "rack1", "node1", 100). node1 := newEcNode("dc1", "rack1", "node1", 100).
addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}) addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13})
erb := &ecRebuilder{ erb := &ecRebuilder{
commandEnv: &CommandEnv{ commandEnv: &CommandEnv{
env: make(map[string]string), env: make(map[string]string),
@ -187,12 +186,12 @@ func TestRebuildEcVolumesCompleteVolume(t *testing.T) {
writer: &logBuffer, writer: &logBuffer,
applyChanges: false, applyChanges: false,
} }
err := erb.rebuildEcVolumes("c1") err := erb.rebuildEcVolumes("c1")
if err != nil { if err != nil {
t.Fatalf("Expected no error for complete volume, got: %v", err) t.Fatalf("Expected no error for complete volume, got: %v", err)
} }
// The function should return quickly without attempting rebuild // The function should return quickly without attempting rebuild
// since the volume is already complete // since the volume is already complete
} }
@ -200,11 +199,11 @@ func TestRebuildEcVolumesCompleteVolume(t *testing.T) {
// TestRebuildEcVolumesInsufficientSpace tests error handling for insufficient disk space // TestRebuildEcVolumesInsufficientSpace tests error handling for insufficient disk space
func TestRebuildEcVolumesInsufficientSpace(t *testing.T) { func TestRebuildEcVolumesInsufficientSpace(t *testing.T) {
var logBuffer bytes.Buffer var logBuffer bytes.Buffer
// Create a volume with missing shards but insufficient free slots // Create a volume with missing shards but insufficient free slots
node1 := newEcNode("dc1", "rack1", "node1", 5). // Only 5 free slots, need 14 node1 := newEcNode("dc1", "rack1", "node1", 5). // Only 5 free slots, need 14
addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
erb := &ecRebuilder{ erb := &ecRebuilder{
commandEnv: &CommandEnv{ commandEnv: &CommandEnv{
env: make(map[string]string), env: make(map[string]string),
@ -214,12 +213,12 @@ func TestRebuildEcVolumesInsufficientSpace(t *testing.T) {
writer: &logBuffer, writer: &logBuffer,
applyChanges: false, applyChanges: false,
} }
err := erb.rebuildEcVolumes("c1") err := erb.rebuildEcVolumes("c1")
if err == nil { if err == nil {
t.Fatal("Expected error for insufficient disk space, got nil") t.Fatal("Expected error for insufficient disk space, got nil")
} }
if !strings.Contains(err.Error(), "disk space is not enough") { if !strings.Contains(err.Error(), "disk space is not enough") {
t.Errorf("Expected 'disk space' in error message, got: %s", err.Error()) t.Errorf("Expected 'disk space' in error message, got: %s", err.Error())
} }
@ -228,7 +227,7 @@ func TestRebuildEcVolumesInsufficientSpace(t *testing.T) {
// TestMultipleNodesWithShards tests rebuild with shards distributed across multiple nodes // TestMultipleNodesWithShards tests rebuild with shards distributed across multiple nodes
func TestMultipleNodesWithShards(t *testing.T) { func TestMultipleNodesWithShards(t *testing.T) {
ecShardMap := make(EcShardMap) ecShardMap := make(EcShardMap)
// Create 3 nodes with different shards // Create 3 nodes with different shards
node1 := newEcNode("dc1", "rack1", "node1", 100). node1 := newEcNode("dc1", "rack1", "node1", 100).
addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3}) addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3})
@ -236,19 +235,19 @@ func TestMultipleNodesWithShards(t *testing.T) {
addEcVolumeAndShardsForTest(1, "c1", []uint32{4, 5, 6, 7}) addEcVolumeAndShardsForTest(1, "c1", []uint32{4, 5, 6, 7})
node3 := newEcNode("dc1", "rack1", "node3", 100). node3 := newEcNode("dc1", "rack1", "node3", 100).
addEcVolumeAndShardsForTest(1, "c1", []uint32{8, 9}) addEcVolumeAndShardsForTest(1, "c1", []uint32{8, 9})
ecShardMap.registerEcNode(node1, "c1") ecShardMap.registerEcNode(node1, "c1")
ecShardMap.registerEcNode(node2, "c1") ecShardMap.registerEcNode(node2, "c1")
ecShardMap.registerEcNode(node3, "c1") ecShardMap.registerEcNode(node3, "c1")
locations := ecShardMap[needle.VolumeId(1)] locations := ecShardMap[needle.VolumeId(1)]
count := locations.shardCount() count := locations.shardCount()
// We have 10 shards total, which is enough for data shards // We have 10 shards total, which is enough for data shards
if count != 10 { if count != 10 {
t.Errorf("Expected 10 shards, got %d", count) t.Errorf("Expected 10 shards, got %d", count)
} }
// Verify each shard is on the correct node // Verify each shard is on the correct node
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
if len(locations[i]) != 1 || locations[i][0].info.Id != "node1" { if len(locations[i]) != 1 || locations[i][0].info.Id != "node1" {
@ -270,23 +269,23 @@ func TestMultipleNodesWithShards(t *testing.T) {
// TestDuplicateShards tests handling of duplicate shards on multiple nodes // TestDuplicateShards tests handling of duplicate shards on multiple nodes
func TestDuplicateShards(t *testing.T) { func TestDuplicateShards(t *testing.T) {
ecShardMap := make(EcShardMap) ecShardMap := make(EcShardMap)
// Create 2 nodes with overlapping shards (both have shard 0) // Create 2 nodes with overlapping shards (both have shard 0)
node1 := newEcNode("dc1", "rack1", "node1", 100). node1 := newEcNode("dc1", "rack1", "node1", 100).
addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3}) addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 1, 2, 3})
node2 := newEcNode("dc1", "rack1", "node2", 100). node2 := newEcNode("dc1", "rack1", "node2", 100).
addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 4, 5, 6}) // Duplicate shard 0 addEcVolumeAndShardsForTest(1, "c1", []uint32{0, 4, 5, 6}) // Duplicate shard 0
ecShardMap.registerEcNode(node1, "c1") ecShardMap.registerEcNode(node1, "c1")
ecShardMap.registerEcNode(node2, "c1") ecShardMap.registerEcNode(node2, "c1")
locations := ecShardMap[needle.VolumeId(1)] locations := ecShardMap[needle.VolumeId(1)]
// Shard 0 should be on both nodes // Shard 0 should be on both nodes
if len(locations[0]) != 2 { if len(locations[0]) != 2 {
t.Errorf("Expected shard 0 on 2 nodes, got %d", len(locations[0])) t.Errorf("Expected shard 0 on 2 nodes, got %d", len(locations[0]))
} }
// Verify both nodes are registered for shard 0 // Verify both nodes are registered for shard 0
foundNode1 := false foundNode1 := false
foundNode2 := false foundNode2 := false
@ -301,7 +300,7 @@ func TestDuplicateShards(t *testing.T) {
if !foundNode1 || !foundNode2 { if !foundNode1 || !foundNode2 {
t.Error("Both nodes should have shard 0") t.Error("Both nodes should have shard 0")
} }
// Shard count should be 7 (unique shards: 0, 1, 2, 3, 4, 5, 6) // Shard count should be 7 (unique shards: 0, 1, 2, 3, 4, 5, 6)
count := locations.shardCount() count := locations.shardCount()
if count != 7 { if count != 7 {

Loading…
Cancel
Save