Files
seaweedfs/weed/s3api/s3lifecycle/reader/event_predicates_test.go
T
Chris LuandGitHub ad77362be3 test(s3/lifecycle): bundle reader + scheduler helper coverage (#9412)
* test(s3/lifecycle): bundle reader + scheduler helper coverage

Bundles direct tests for previously-uncovered helpers in two
packages. Bumps reader 73.2% → 79.2% and scheduler 71.6% → 73.6%.

Reader Event predicates (4):
- IsCreate: NewEntry-only event classifies as create
- IsDelete: OldEntry-only event classifies as delete
- both entries (update): neither IsCreate nor IsDelete (strict
  exclusivity so router routes updates through their own path)
- no entries (degenerate): neither (so a metadata-only filer event
  with no payload doesn't trigger spurious dispatches)

Reader LogStartup (4): exercises both shape branches (single-shard
ShardID vs ShardPredicate), the explicit-StartTsNs override path, and
the Cursor.MinTsNs fallback when StartTsNs=0. Side-effect-only
function; tests pin compile-time shape and visit each code path.

Scheduler pipelineFanout.InjectEvent (5):
- nil event silently absorbed (no follow-up panic in receiving
  pipeline)
- unknown shard returns nil (forward-compat for future shard-mapping
  gaps)
- known shard succeeds
- ctx cancellation propagates when underlying pipeline's buffer fills
- routes to the correct pipeline among multiple, with cross-pipeline
  isolation proven via per-pipeline buffer state

* test(s3/lifecycle): rename canceled to canceledCtx in fanout test

Per gemini review on #9412: a bare 'canceled' identifier reads like
a bool. Rename to canceledCtx so the type is obvious at the call site.
2026-05-09 22:02:09 -07:00

48 lines
1.5 KiB
Go

package reader
import (
"testing"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/stretchr/testify/assert"
)
// IsCreate / IsDelete are the small but routing-critical predicates
// the dispatcher uses to decide which match path applies. Both were
// previously exercised only through end-to-end Tick/Match tests; pin
// them directly here.
func TestEventIsCreate_PopulatedNewEntryNoOldEntry(t *testing.T) {
e := &Event{NewEntry: &filer_pb.Entry{Name: "k"}}
assert.True(t, e.IsCreate())
assert.False(t, e.IsDelete())
}
func TestEventIsDelete_PopulatedOldEntryNoNewEntry(t *testing.T) {
e := &Event{OldEntry: &filer_pb.Entry{Name: "k"}}
assert.True(t, e.IsDelete())
assert.False(t, e.IsCreate())
}
func TestEventBothEntries_NeitherCreateNorDelete(t *testing.T) {
// An update event carries both old and new; the predicates are
// strict (one or the other, not both) so the router can route
// updates through the dedicated path rather than treating them
// as creates or deletes.
e := &Event{
OldEntry: &filer_pb.Entry{Name: "k"},
NewEntry: &filer_pb.Entry{Name: "k"},
}
assert.False(t, e.IsCreate(), "update event must not classify as create")
assert.False(t, e.IsDelete(), "update event must not classify as delete")
}
func TestEventNoEntries_NeitherCreateNorDelete(t *testing.T) {
// A degenerate event with neither side populated must not classify
// as either; otherwise a metadata-only filer event with no bucket
// payload could trigger spurious dispatches.
e := &Event{}
assert.False(t, e.IsCreate())
assert.False(t, e.IsDelete())
}