rollup_sync_test.go 3.19 KB
Newer Older
1 2 3 4 5
package dial

import (
	"context"
	"errors"
6
	"log/slog"
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
	"testing"
	"time"

	"github.com/ethereum-optimism/optimism/op-service/eth"
	"github.com/ethereum-optimism/optimism/op-service/testlog"
	"github.com/ethereum-optimism/optimism/op-service/testutils"
	"github.com/stretchr/testify/require"
)

func TestWaitRollupSync(t *testing.T) {
	bctx := context.Background()
	hasInfoLevel := testlog.NewLevelFilter(slog.LevelInfo)
	const target = 42

	t.Run("sync-error", func(t *testing.T) {
		lgr, logs := testlog.CaptureLogger(t, slog.LevelInfo)
		rollup := new(testutils.MockRollupClient)
		syncErr := errors.New("test sync error")
		rollup.ExpectSyncStatus(nil, syncErr)

		err := WaitRollupSync(bctx, lgr, rollup, 0, 0)
		require.ErrorIs(t, err, syncErr)
		require.Nil(t, logs.FindLog(hasInfoLevel), "expected no logs")
		rollup.AssertExpectations(t)
	})

	t.Run("at-target", func(t *testing.T) {
		lgr, logs := testlog.CaptureLogger(t, slog.LevelDebug)
		rollup := new(testutils.MockRollupClient)
		rollup.ExpectSyncStatus(&eth.SyncStatus{
			CurrentL1: eth.L1BlockRef{Number: target},
		}, nil)

		err := WaitRollupSync(bctx, lgr, rollup, target, 0)
		require.NoError(t, err)
		require.NotNil(t, logs.FindLog(hasInfoLevel,
			testlog.NewMessageContainsFilter("target reached")))
		rollup.AssertExpectations(t)
	})

	t.Run("beyond-target", func(t *testing.T) {
		lgr, logs := testlog.CaptureLogger(t, slog.LevelDebug)
		rollup := new(testutils.MockRollupClient)
		rollup.ExpectSyncStatus(&eth.SyncStatus{
			CurrentL1: eth.L1BlockRef{Number: target + 12},
		}, nil)

		err := WaitRollupSync(bctx, lgr, rollup, target, 0)
		require.NoError(t, err)
		require.NotNil(t, logs.FindLog(hasInfoLevel,
			testlog.NewMessageContainsFilter("target reached")))
		rollup.AssertExpectations(t)
	})

	t.Run("few-blocks-before-target", func(t *testing.T) {
		lgr, logs := testlog.CaptureLogger(t, slog.LevelDebug)
		rollup := new(testutils.MockRollupClient)
		const gap = 7
		for i := -gap; i <= 0; i++ {
			rollup.ExpectSyncStatus(&eth.SyncStatus{
				CurrentL1: eth.L1BlockRef{Number: uint64(target + i)},
			}, nil)
		}

		err := WaitRollupSync(bctx, lgr, rollup, target, 0)
		require.NoError(t, err)
		require.NotNil(t, logs.FindLog(hasInfoLevel,
			testlog.NewMessageContainsFilter("target reached")))
		require.Len(t, logs.FindLogs(hasInfoLevel,
			testlog.NewMessageContainsFilter("retrying")), gap)
		rollup.AssertExpectations(t)
	})

	t.Run("ctx-timeout", func(t *testing.T) {
		lgr, logs := testlog.CaptureLogger(t, slog.LevelDebug)
		rollup := new(testutils.MockRollupClient)
		rollup.ExpectSyncStatus(&eth.SyncStatus{
			CurrentL1: eth.L1BlockRef{Number: uint64(target - 1)},
		}, nil)

		ctx, cancel := context.WithCancel(bctx)
		// We can already cancel the context because the mock ignores the
		// cancelled context.
		cancel()
		// need real duration or the timer races with the cancelled context
		err := WaitRollupSync(ctx, lgr, rollup, target, time.Second)
		require.ErrorIs(t, err, context.Canceled)
		require.NotNil(t, logs.FindLogs(hasInfoLevel,
			testlog.NewMessageContainsFilter("retrying")))
		require.NotNil(t, logs.FindLog(
			testlog.NewLevelFilter(slog.LevelWarn),
			testlog.NewMessageContainsFilter("timed out")))
		rollup.AssertExpectations(t)
	})
}