From 0c5a3095072cca2599a6a97b9ef1c6fce89ade4b Mon Sep 17 00:00:00 2001 From: Feng Ruohang Date: Tue, 3 Nov 2026 22:56:05 +0800 Subject: [PATCH] test(ilm): assert scanner refusal without claiming absence Keep the specialized scanner routing test aligned with the explicit lifecycle rejection result, and verify the addressed version and payload remain readable. This distinguishes refused expiry from an idempotent missing version. Signed-off-by: Feng Ruohang --- cmd/erasure-server-pool-consistency_test.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/cmd/erasure-server-pool-consistency_test.go b/cmd/erasure-server-pool-consistency_test.go index 0dec71fd5..8c94fb49b 100644 --- a/cmd/erasure-server-pool-consistency_test.go +++ b/cmd/erasure-server-pool-consistency_test.go @@ -522,10 +522,20 @@ func TestPoolsDeleteVersionSpecialCalls(t *testing.T) { opts := ObjectOptions{Versioned: true, VersionID: oi.VersionID, InclFreeVersions: !expiration, Expiration: ExpirationOptions{Expire: expiration}} _, err := z.DeleteObject(t.Context(), bucket, object, opts) if expiration { - // No lifecycle rule authorizes expiration. Preserve its existing - // version-not-found result, even with an unrelated unreadable pool. - if !isErrVersionNotFound(err) { - t.Errorf("expiration changed its scanner contract: %v", err) + // No rule authorizes expiration. Distinguish refusal from real + // absence, even with an unrelated unreadable pool, so a worker + // cannot acknowledge or replicate a purge that never happened. + if !errors.Is(err, errLifecycleNotApplicable) { + t.Errorf("expiration did not preserve its rejection: %v", err) + } + gr, err := z.serverPools[0].GetObjectNInfo(t.Context(), bucket, object, nil, nil, ObjectOptions{VersionID: oi.VersionID}) + if err != nil { + t.Fatal(err) + } + data, err := io.ReadAll(gr) + gr.Close() + if err != nil || string(data) != "payload" || gr.ObjInfo.VersionID != oi.VersionID { + t.Errorf("rejected expiration changed the stored version: %v", err) } } else if err != nil { t.Errorf("free-version cleanup was forced through all-pool resolution: %v", err)