Files
seaweedfs/weed/shell/command_s3_lifecycle_run_shard_test.go
T
Chris LuandGitHub 4ce027c2f3 fix(shell): restore s3.lifecycle.run-shard for CI/integration-test compatibility (#9475)
fix(shell): restore s3.lifecycle.run-shard as a dailyrun.Run wrapper

PR #9466 deleted weed/shell/command_s3_lifecycle_run_shard.go on the
premise that it was a debug-only tool. It wasn't: the s3tests CI
workflow (.github/workflows/s3tests.yml) and the test/s3/lifecycle/
integration tests invoke it via `weed shell` to drive lifecycle
expirations on demand. Both started failing with
"unknown command: s3.lifecycle.run-shard".

This PR restores the command with the same flag set so existing
callers (CI scripts and integration tests) work unchanged. The
implementation no longer drives the streaming dispatcher.Pipeline +
scheduler.BucketBootstrapper (deleted) — instead it does one bounded
dailyrun.Run pass through the same daily-replay code path the
production worker exercises. The walker fires for walker-bound
rules just like in the worker.

Obsolete streaming flags (-dispatch / -checkpoint / -refresh /
-bootstrap-interval) are accepted-but-ignored so existing scripts
don't need to drop them.
2026-05-12 18:29:18 -07:00

93 lines
2.1 KiB
Go

package shell
import (
"reflect"
"testing"
)
func TestParseShardsSpec_Range(t *testing.T) {
got, err := parseShardsSpec("3-7")
if err != nil {
t.Fatalf("err: %v", err)
}
want := []int{3, 4, 5, 6, 7}
if !reflect.DeepEqual(got, want) {
t.Fatalf("got %v, want %v", got, want)
}
}
func TestParseShardsSpec_Set(t *testing.T) {
got, err := parseShardsSpec("0,3,7")
if err != nil {
t.Fatalf("err: %v", err)
}
want := []int{0, 3, 7}
if !reflect.DeepEqual(got, want) {
t.Fatalf("got %v, want %v", got, want)
}
}
func TestParseShardsSpec_DedupSort(t *testing.T) {
got, err := parseShardsSpec("7,3,3,0")
if err != nil {
t.Fatalf("err: %v", err)
}
want := []int{0, 3, 7}
if !reflect.DeepEqual(got, want) {
t.Fatalf("got %v, want %v", got, want)
}
}
func TestParseShardsSpec_OutOfRange(t *testing.T) {
if _, err := parseShardsSpec("16"); err == nil {
t.Fatal("expected out-of-range error for 16")
}
if _, err := parseShardsSpec("-1"); err == nil {
t.Fatal("expected out-of-range error for -1")
}
if _, err := parseShardsSpec("0-16"); err == nil {
t.Fatal("expected out-of-range error for 0-16")
}
}
func TestParseShardsSpec_BadRange(t *testing.T) {
if _, err := parseShardsSpec("7-3"); err == nil {
t.Fatal("expected lo>hi error")
}
}
func TestResolveShardSelection_Mutex(t *testing.T) {
if _, err := resolveShardSelection(0, "1,2"); err == nil {
t.Fatal("expected mutex error when both -shard and -shards set")
}
if _, err := resolveShardSelection(-1, ""); err == nil {
t.Fatal("expected error when neither set")
}
}
func TestResolveShardSelection_SingleShard(t *testing.T) {
got, err := resolveShardSelection(5, "")
if err != nil {
t.Fatalf("err: %v", err)
}
if !reflect.DeepEqual(got, []int{5}) {
t.Fatalf("got %v, want [5]", got)
}
}
func TestFormatShardLabel(t *testing.T) {
cases := []struct {
in []int
want string
}{
{[]int{5}, "5"},
{[]int{0, 1, 2, 3}, "0-3"},
{[]int{0, 2, 5}, "0,2,5"},
}
for _, tc := range cases {
if got := formatShardLabel(tc.in); got != tc.want {
t.Errorf("formatShardLabel(%v)=%q, want %q", tc.in, got, tc.want)
}
}
}