mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-05-29 21:20:21 +00:00
Bind non-authoritative inventory, restart primary-truth rebasing, and sparse replica readiness retention into the heartbeat/master seam, and package the bounded finish-line checkpoint with explicit claims, non-claims, and proof commands. Made-with: Cursor
115 lines
3.1 KiB
Go
115 lines
3.1 KiB
Go
package weed_server
|
|
|
|
import (
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/pb/volume_server_pb"
|
|
"github.com/seaweedfs/seaweedfs/weed/storage"
|
|
)
|
|
|
|
func TestMaintenanceMode(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
pb *volume_server_pb.VolumeServerState
|
|
want bool
|
|
wantCheckErr string
|
|
}{
|
|
{
|
|
name: "non-initialized state",
|
|
pb: nil,
|
|
want: false,
|
|
wantCheckErr: "",
|
|
},
|
|
{
|
|
name: "maintenance mode disabled",
|
|
pb: &volume_server_pb.VolumeServerState{
|
|
Maintenance: false,
|
|
},
|
|
want: false,
|
|
wantCheckErr: "",
|
|
},
|
|
{
|
|
name: "maintenance mode enabled",
|
|
pb: &volume_server_pb.VolumeServerState{
|
|
Maintenance: true,
|
|
},
|
|
want: true,
|
|
wantCheckErr: "volume server test_1234 is in maintenance mode",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
vs := VolumeServer{
|
|
store: &storage.Store{
|
|
Id: "test_1234",
|
|
State: storage.NewStateFromProto("/some/path.pb", tc.pb),
|
|
},
|
|
}
|
|
|
|
if got, want := vs.MaintenanceMode(), tc.want; got != want {
|
|
t.Errorf("MaintenanceMode() returned %v, want %v", got, want)
|
|
}
|
|
|
|
err, wantErrStr := vs.CheckMaintenanceMode(), tc.wantCheckErr
|
|
if err != nil {
|
|
if wantErrStr == "" {
|
|
t.Errorf("CheckMaintenanceMode() returned error %v, want nil", err)
|
|
}
|
|
if errStr := err.Error(); errStr != wantErrStr {
|
|
t.Errorf("CheckMaintenanceMode() returned error %q, want %q", errStr, wantErrStr)
|
|
}
|
|
} else {
|
|
if wantErrStr != "" {
|
|
t.Errorf("CheckMaintenanceMode() returned no error, want %q", wantErrStr)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCollectBlockVolumeHeartbeat_IncludesInventoryAuthority(t *testing.T) {
|
|
vs := &VolumeServer{
|
|
store: &storage.Store{},
|
|
blockService: &BlockService{
|
|
blockStore: storage.NewBlockVolumeStore(),
|
|
blockInventoryAuthoritative: false,
|
|
},
|
|
}
|
|
|
|
hb := vs.collectBlockVolumeHeartbeat("127.0.0.1", 18080, "dc1", "rack1")
|
|
if hb.BlockVolumeInventoryAuthoritative == nil {
|
|
t.Fatal("expected block inventory authority bit to be present")
|
|
}
|
|
if hb.GetBlockVolumeInventoryAuthoritative() {
|
|
t.Fatal("expected non-authoritative block inventory bit on test heartbeat")
|
|
}
|
|
if !hb.HasNoBlockVolumes {
|
|
t.Fatal("expected empty heartbeat to report has_no_block_volumes")
|
|
}
|
|
}
|
|
|
|
func TestStartBlockService_ScanFailureEmitsNonAuthoritativeInventory(t *testing.T) {
|
|
missingDir := filepath.Join(t.TempDir(), "missing-block-dir")
|
|
bs := StartBlockService("127.0.0.1:3260", missingDir, "", "", NVMeConfig{})
|
|
if bs == nil {
|
|
t.Fatal("expected block service even when startup scan fails")
|
|
}
|
|
if bs.BlockInventoryAuthoritative() {
|
|
t.Fatal("startup scan failure should leave block inventory non-authoritative")
|
|
}
|
|
|
|
vs := &VolumeServer{
|
|
store: &storage.Store{},
|
|
blockService: bs,
|
|
}
|
|
hb := vs.collectBlockVolumeHeartbeat("127.0.0.1", 18080, "dc1", "rack1")
|
|
if hb.BlockVolumeInventoryAuthoritative == nil {
|
|
t.Fatal("expected inventory authority bit on startup-scan-failure heartbeat")
|
|
}
|
|
if hb.GetBlockVolumeInventoryAuthoritative() {
|
|
t.Fatal("startup-scan-failure heartbeat should be non-authoritative")
|
|
}
|
|
}
|