mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-21 06:36:54 +00:00
test(s3/lifecycle): integration coverage for ExpirationDate (past)
Rules with Expiration{Date: <past>} route through ScanAtDate in the
engine (decideMode's ActionKindExpirationDate case) — a separate
compile + dispatch branch from the EventDriven delay-group path the
Days-based tests exercise.
Past date + in-prefix object → must expire. Out-of-prefix object →
must remain. Object also backdated as defense-in-depth so the
assertion doesn't depend on whether the dispatcher consults
MinTriggerAge for date kinds.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
// ExpirationDate (date-based, not Days) integration scenario.
|
||||
package lifecycle
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestLifecycleExpirationDateInThePast: an Expiration{Date: <past>} rule
|
||||
// routes through the engine's ScanAtDate mode rather than the
|
||||
// EventDriven delay-group path. The worker's dispatcher must still fire
|
||||
// when the date has already passed at the time the worker runs. Pinning
|
||||
// this path because most tests use Days-based rules; ScanAtDate is a
|
||||
// separate compile + dispatch branch (engine.decideMode case
|
||||
// ActionKindExpirationDate) that wouldn't be exercised otherwise.
|
||||
func TestLifecycleExpirationDateInThePast(t *testing.T) {
|
||||
c := s3Client(t)
|
||||
fc, fcClose := filerClient(t)
|
||||
defer fcClose()
|
||||
|
||||
bucket := uniqueBucket("expdate")
|
||||
mustCreateBucket(t, c, bucket)
|
||||
|
||||
// Date in the past: AWS rejects ExpirationDate in the future from
|
||||
// being processed early but a past date is the natural integration
|
||||
// test — every object hit by the rule is immediately eligible.
|
||||
pastDate := time.Now().Add(-7 * 24 * time.Hour).UTC().Truncate(24 * time.Hour)
|
||||
_, err := c.PutBucketLifecycleConfiguration(context.Background(), &s3.PutBucketLifecycleConfigurationInput{
|
||||
Bucket: aws.String(bucket),
|
||||
LifecycleConfiguration: &types.BucketLifecycleConfiguration{
|
||||
Rules: []types.LifecycleRule{{
|
||||
ID: aws.String("expire-by-date"),
|
||||
Status: types.ExpirationStatusEnabled,
|
||||
Filter: &types.LifecycleRuleFilter{Prefix: aws.String("d/")},
|
||||
Expiration: &types.LifecycleExpiration{
|
||||
Date: aws.Time(pastDate),
|
||||
},
|
||||
}},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
const oldKey = "d/in-prefix.txt"
|
||||
const otherKey = "other/skip.txt"
|
||||
putObject(t, c, bucket, oldKey, "old")
|
||||
putObject(t, c, bucket, otherKey, "other")
|
||||
|
||||
// Backdate oldKey too — defense-in-depth so the test doesn't
|
||||
// depend on whether the worker also considers MinTriggerAge for
|
||||
// date kinds; a fresh object with a past date should still expire,
|
||||
// but aging it locks the assertion either way.
|
||||
backdateMtime(t, fc, bucket, oldKey, 30)
|
||||
|
||||
out := runLifecycleShard(t)
|
||||
t.Logf("shell output:\n%s", out)
|
||||
|
||||
require.Eventuallyf(t, func() bool {
|
||||
_, err := c.HeadObject(context.Background(), &s3.HeadObjectInput{
|
||||
Bucket: aws.String(bucket), Key: aws.String(oldKey),
|
||||
})
|
||||
return isS3NotFound(err)
|
||||
}, 30*time.Second, 500*time.Millisecond, "%s/%s must be expired by past-date rule", bucket, oldKey)
|
||||
|
||||
// Out-of-prefix object stays — the rule's Filter.Prefix gates this.
|
||||
_, err = c.HeadObject(context.Background(), &s3.HeadObjectInput{
|
||||
Bucket: aws.String(bucket), Key: aws.String(otherKey),
|
||||
})
|
||||
require.NoError(t, err, "object outside the rule's prefix must remain")
|
||||
}
|
||||
Reference in New Issue
Block a user