node_test.go 3.03 KB
Newer Older
1 2 3 4 5 6 7
package syncnode

import (
	"context"
	"testing"
	"time"

8 9 10 11 12
	"github.com/stretchr/testify/require"

	"github.com/ethereum/go-ethereum/log"

	"github.com/ethereum-optimism/optimism/op-node/rollup/event"
13 14
	"github.com/ethereum-optimism/optimism/op-service/eth"
	"github.com/ethereum-optimism/optimism/op-service/testlog"
15
	"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/superevents"
16 17 18 19
	"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
)

func TestEventResponse(t *testing.T) {
20
	chainID := eth.ChainIDFromUInt64(1)
21 22 23 24
	logger := testlog.Logger(t, log.LvlInfo)
	syncCtrl := &mockSyncControl{}
	backend := &mockBackend{}

25 26 27 28 29 30 31 32 33 34
	ex := event.NewGlobalSynchronous(context.Background())
	eventSys := event.NewSystem(logger, ex)

	mon := &eventMonitor{}
	eventSys.Register("monitor", mon, event.DefaultRegisterOpts())

	node := NewManagedNode(logger, chainID, syncCtrl, backend, false)
	eventSys.Register("node", node, event.DefaultRegisterOpts())

	emitter := eventSys.Register("test", nil, event.DefaultRegisterOpts())
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

	crossUnsafe := 0
	crossSafe := 0
	finalized := 0

	nodeExhausted := 0

	// the node will call UpdateCrossUnsafe when a cross-unsafe event is received from the database
	syncCtrl.updateCrossUnsafeFn = func(ctx context.Context, id eth.BlockID) error {
		crossUnsafe++
		return nil
	}
	// the node will call UpdateCrossSafe when a cross-safe event is received from the database
	syncCtrl.updateCrossSafeFn = func(ctx context.Context, derived eth.BlockID, derivedFrom eth.BlockID) error {
		crossSafe++
		return nil
	}
	// the node will call UpdateFinalized when a finalized event is received from the database
	syncCtrl.updateFinalizedFn = func(ctx context.Context, id eth.BlockID) error {
		finalized++
		return nil
	}

	// the node will call ProvideL1 when the node is exhausted and needs a new L1 derivation source
	syncCtrl.provideL1Fn = func(ctx context.Context, nextL1 eth.BlockRef) error {
		nodeExhausted++
		return nil
	}
63

64 65 66 67 68 69 70
	// TODO(#13595): rework node-reset, and include testing for it here

	node.Start()

	// send events and continue to do so until at least one of each type has been received
	require.Eventually(t, func() bool {
		// send in one event of each type
71 72 73 74
		emitter.Emit(superevents.CrossUnsafeUpdateEvent{ChainID: chainID})
		emitter.Emit(superevents.CrossSafeUpdateEvent{ChainID: chainID})
		emitter.Emit(superevents.FinalizedL2UpdateEvent{ChainID: chainID})

75 76 77 78 79 80 81
		syncCtrl.subscribeEvents.Send(&types.ManagedEvent{
			UnsafeBlock: &eth.BlockRef{Number: 1}})
		syncCtrl.subscribeEvents.Send(&types.ManagedEvent{
			DerivationUpdate: &types.DerivedBlockRefPair{DerivedFrom: eth.BlockRef{Number: 1}, Derived: eth.BlockRef{Number: 2}}})
		syncCtrl.subscribeEvents.Send(&types.ManagedEvent{
			ExhaustL1: &types.DerivedBlockRefPair{DerivedFrom: eth.BlockRef{Number: 1}, Derived: eth.BlockRef{Number: 2}}})

82 83
		require.NoError(t, ex.Drain())

84 85 86
		return crossUnsafe >= 1 &&
			crossSafe >= 1 &&
			finalized >= 1 &&
87 88
			mon.receivedLocalUnsafe >= 1 &&
			mon.localDerived >= 1 &&
89 90 91
			nodeExhausted >= 1
	}, 4*time.Second, 250*time.Millisecond)
}