1
2
3
4
5
6
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
package dial
import (
"context"
"errors"
"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"
"golang.org/x/exp/slog"
)
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(ð.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(ð.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(ð.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(ð.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)
})
}