From c5d7147ab0bc661085e7668ce1fd577404b27e3d Mon Sep 17 00:00:00 2001 From: bitromortac Date: Mon, 22 Jun 2026 10:10:00 +0200 Subject: [PATCH] itest: add channel events pruning test Add an integration test to verify the safety pruning behavior under various conditions. --- itest/channel_events_test.go | 73 ++++++++++++++++++++++++++++++++++++ itest/test_context.go | 11 ++++-- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/itest/channel_events_test.go b/itest/channel_events_test.go index 4def9f6..b1befbd 100644 --- a/itest/channel_events_test.go +++ b/itest/channel_events_test.go @@ -360,3 +360,76 @@ func TestForwardingDowntime(t *testing.T) { return ok }, "expected bob self-pair after reconnect") } + +// TestChannelEventsPruning verifies that starting Faraday with low size limits +// (e.g. max-events=1 and retention=2s) executes live background pruning +// successfully and bounds the database size correctly. +func TestChannelEventsPruning(t *testing.T) { + c := newTestContext( + t, "--chanevents.max-events=1", "--chanevents.retention=2s", + ) + defer c.stop() + + ctx := context.Background() + + // We will start by opening a channel from alice to bob. + var aliceChannelAmt = btcutil.Amount(500000) + + err := c.aliceClient.Client.Connect( + ctx, c.bobPubkey, "localhost:10012", true, + ) + require.NoError(c.t, err, "could not connect nodes") + + aliceChannel, _ := c.openChannel( + c.aliceClient.Client, c.bobPubkey, aliceChannelAmt, + ) + + // Use a far-future end time so the query window never excludes a stored + // event on a slow host. A tight wall-clock window here would make the + // counts below racy. + endTime := time.Now().Add(time.Hour).Unix() + + // We deliberately do not assert on the initial event count here: opening + // a channel records several events, but the 2-second background prune can + // fire before we observe them on a slow host, so any such pre-prune + // assertion would be flaky. The eventuallyf checks below verify the + // pruning behaviour directly instead. + + // Wait for the live background pruning ticker to bound the table to the + // max-events ceiling. We assert at most one event rather than exactly + // one: the size limit keeps a single event, but the 2-second retention + // limit then ages it out since no new events follow the channel open, + // so the steady state is zero or one. + var eventsAfter *frdrpc.ChannelEventsResponse + c.eventuallyf(func() bool { + var err error + eventsAfter, err = c.faradayClient.GetChannelEvents( + ctx, &frdrpc.ChannelEventsRequest{ + ChanPoint: aliceChannel.String(), + EndTime: endTime, + }, + ) + if err != nil { + return false + } + return len(eventsAfter.Events) <= 1 + }, "expected channel events to be pruned down to at most one in the "+ + "background") + + // No further events follow the channel open, so once the remaining + // event ages past the 2-second retention window the age-based prune + // removes it too, draining the table to zero. + c.eventuallyf(func() bool { + eventsAfter, err := c.faradayClient.GetChannelEvents( + ctx, &frdrpc.ChannelEventsRequest{ + ChanPoint: aliceChannel.String(), + EndTime: endTime, + }, + ) + if err != nil { + return false + } + return len(eventsAfter.Events) == 0 + }, "expected channel events to be pruned down to zero once all events "+ + "age out of the retention window") +} diff --git a/itest/test_context.go b/itest/test_context.go index 70d4e32..2f34a2f 100644 --- a/itest/test_context.go +++ b/itest/test_context.go @@ -68,7 +68,7 @@ type testContext struct { } // newTestContext returns a new context instance. -func newTestContext(t *testing.T) *testContext { +func newTestContext(t *testing.T, extraFaradayArgs ...string) *testContext { var err error ctx := &testContext{ @@ -123,7 +123,7 @@ func newTestContext(t *testing.T) *testContext { require.NoError(t, err) // Start faraday. - ctx.startFaraday() + ctx.startFaraday(extraFaradayArgs...) // Wait for faraday's channel events monitor to finish its initial // chain-sync. @@ -564,10 +564,13 @@ func (c *testContext) waitForMempoolTxCount(txCount int, msg string) { // startFaraday starts faraday, connecting to our test context's alice lnd node. // It returns process start errors and an error channel for errors that occur // after the start. -func (c *testContext) startFaraday() { +func (c *testContext) startFaraday(extraArgs ...string) { + args := append([]string{}, faradayArgs...) + args = append(args, extraArgs...) + // Start loop client daemon. c.faradayCmd = exec.Command( - faradayCmd, faradayArgs..., + faradayCmd, args..., ) attachPrefixStdout(c.faradayCmd, "faraday")