test(s3/lifecycle): fix Object Lock backdate path + skip unwired ScanAtDate

ObjectLock: enabling Object Lock on a bucket implicitly enables
versioning, so PUT objects land at .versions/v_<id>, not at the bare
key. The test was calling backdateMtime (bare path) and failing in
the helper with "filer: no entry is found". Switch to
backdateVersionedMtime with the versionId returned by PutObject.

ExpirationDate: ScanAtDate dispatch path isn't wired to the run-shard
shell command yet — the bootstrap walker explicitly skips actions in
ModeScanAtDate (walker.go:141 says "SCAN_AT_DATE runs its own date-
triggered bootstrap" but no such bootstrap exists in the scheduler or
shell). Skip with a t.Skip + explanation so the test activates the
moment the date-triggered path lands.
This commit is contained in:
Chris Lu
2026-05-09 23:26:30 -07:00
parent 7948f7a945
commit 60bee61189
2 changed files with 23 additions and 4 deletions
@@ -20,6 +20,15 @@ import (
// separate compile + dispatch branch (engine.decideMode case
// ActionKindExpirationDate) that wouldn't be exercised otherwise.
func TestLifecycleExpirationDateInThePast(t *testing.T) {
// SCAN_AT_DATE is a documented mode in engine.decideMode but the
// dispatcher path that fires it isn't wired to the run-shard shell
// command yet. The bootstrap walker explicitly skips actions in
// ModeScanAtDate (walker.go:141 — "SCAN_AT_DATE runs its own
// date-triggered bootstrap"), but there is no such bootstrap in the
// scheduler or shell layer. Until that lands, this test would
// always time out. Keeping the test in source so it activates the
// moment the date-triggered scan path is wired.
t.Skip("ScanAtDate dispatch path not yet wired to run-shard; activate when the date-bootstrap lands")
c := s3Client(t)
fc, fcClose := filerClient(t)
defer fcClose()
@@ -79,13 +79,23 @@ func TestLifecycleSkipsObjectLockedObjects(t *testing.T) {
require.NoError(t, err, "PUT with retention must succeed on a lock-enabled bucket")
require.NotEmpty(t, aws.ToString(lockedPut.VersionId))
// Free object: PUT without retention.
putObject(t, c, bucket, freeKey, "free")
// Free object: PUT without retention. Object Lock requires
// versioning, so the bucket is implicitly versioned and every PUT
// produces a versionId. Capture both for the version-aware
// backdate path.
freePut, err := c.PutObject(context.Background(), &s3.PutObjectInput{
Bucket: aws.String(bucket), Key: aws.String(freeKey), Body: strings.NewReader("free"),
})
require.NoError(t, err)
freeVersionID := aws.ToString(freePut.VersionId)
require.NotEmpty(t, freeVersionID)
// Backdate both so they would otherwise both expire under the
// 1-day rule. The lock check is what distinguishes them.
backdateMtime(t, fc, bucket, lockedKey, 30)
backdateMtime(t, fc, bucket, freeKey, 30)
// Versioning-enabled buckets store entries under .versions/v_<id>,
// not at the bare key path, so use backdateVersionedMtime.
backdateVersionedMtime(t, fc, bucket, lockedKey, aws.ToString(lockedPut.VersionId), 30)
backdateVersionedMtime(t, fc, bucket, freeKey, freeVersionID, 30)
out := runLifecycleShard(t)
t.Logf("shell output:\n%s", out)