github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/common/synchronization/engine_suite_test.go (about)

     1  package synchronization
     2  
     3  import (
     4  	"io"
     5  	"testing"
     6  
     7  	"github.com/rs/zerolog"
     8  	"github.com/stretchr/testify/mock"
     9  	"github.com/stretchr/testify/require"
    10  	"github.com/stretchr/testify/suite"
    11  
    12  	mockconsensus "github.com/onflow/flow-go/engine/consensus/mock"
    13  	"github.com/onflow/flow-go/model/flow"
    14  	"github.com/onflow/flow-go/model/flow/filter"
    15  	"github.com/onflow/flow-go/module/id"
    16  	"github.com/onflow/flow-go/module/metrics"
    17  	module "github.com/onflow/flow-go/module/mock"
    18  	netint "github.com/onflow/flow-go/network"
    19  	"github.com/onflow/flow-go/network/channels"
    20  	"github.com/onflow/flow-go/network/mocknetwork"
    21  	"github.com/onflow/flow-go/network/p2p/cache"
    22  	protocolint "github.com/onflow/flow-go/state/protocol"
    23  	protocolEvents "github.com/onflow/flow-go/state/protocol/events"
    24  	protocol "github.com/onflow/flow-go/state/protocol/mock"
    25  	storerr "github.com/onflow/flow-go/storage"
    26  	storage "github.com/onflow/flow-go/storage/mock"
    27  	"github.com/onflow/flow-go/utils/unittest"
    28  )
    29  
    30  func TestSyncEngine(t *testing.T) {
    31  	suite.Run(t, new(SyncSuite))
    32  }
    33  
    34  type SyncSuite struct {
    35  	suite.Suite
    36  	myID         flow.Identifier
    37  	participants flow.IdentityList
    38  	head         *flow.Header
    39  	heights      map[uint64]*flow.Block
    40  	blockIDs     map[flow.Identifier]*flow.Block
    41  	net          *mocknetwork.Network
    42  	con          *mocknetwork.Conduit
    43  	me           *module.Local
    44  	state        *protocol.State
    45  	snapshot     *protocol.Snapshot
    46  	blocks       *storage.Blocks
    47  	comp         *mockconsensus.Compliance
    48  	core         *module.SyncCore
    49  	e            *Engine
    50  }
    51  
    52  func (ss *SyncSuite) SetupTest() {
    53  	// generate own ID
    54  	ss.participants = unittest.IdentityListFixture(3, unittest.WithRole(flow.RoleConsensus))
    55  	keys := unittest.NetworkingKeys(len(ss.participants))
    56  
    57  	for i, p := range ss.participants {
    58  		p.NetworkPubKey = keys[i].PublicKey()
    59  	}
    60  	ss.myID = ss.participants[0].NodeID
    61  
    62  	// generate a header for the final state
    63  	header := unittest.BlockHeaderFixture()
    64  	ss.head = header
    65  
    66  	// create maps to enable block returns
    67  	ss.heights = make(map[uint64]*flow.Block)
    68  	ss.blockIDs = make(map[flow.Identifier]*flow.Block)
    69  
    70  	// set up the network module mock
    71  	ss.net = &mocknetwork.Network{}
    72  	ss.net.On("Register", mock.Anything, mock.Anything).Return(
    73  		func(channel channels.Channel, engine netint.MessageProcessor) netint.Conduit {
    74  			return ss.con
    75  		},
    76  		nil,
    77  	)
    78  
    79  	// set up the network conduit mock
    80  	ss.con = &mocknetwork.Conduit{}
    81  
    82  	// set up the local module mock
    83  	ss.me = &module.Local{}
    84  	ss.me.On("NodeID").Return(
    85  		func() flow.Identifier {
    86  			return ss.myID
    87  		},
    88  	)
    89  
    90  	// set up the protocol state mock
    91  	ss.state = &protocol.State{}
    92  	ss.state.On("Final").Return(
    93  		func() protocolint.Snapshot {
    94  			return ss.snapshot
    95  		},
    96  	)
    97  	ss.state.On("AtBlockID", mock.Anything).Return(
    98  		func(blockID flow.Identifier) protocolint.Snapshot {
    99  			if ss.head.ID() == blockID {
   100  				return ss.snapshot
   101  			} else {
   102  				return unittest.StateSnapshotForUnknownBlock()
   103  			}
   104  		},
   105  	).Maybe()
   106  
   107  	// set up the snapshot mock
   108  	ss.snapshot = &protocol.Snapshot{}
   109  	ss.snapshot.On("Head").Return(
   110  		func() *flow.Header {
   111  			return ss.head
   112  		},
   113  		nil,
   114  	)
   115  	ss.snapshot.On("Identities", mock.Anything).Return(
   116  		func(selector flow.IdentityFilter[flow.Identity]) flow.IdentityList {
   117  			return ss.participants.Filter(selector)
   118  		},
   119  		nil,
   120  	)
   121  
   122  	// set up blocks storage mock
   123  	ss.blocks = &storage.Blocks{}
   124  	ss.blocks.On("ByHeight", mock.Anything).Return(
   125  		func(height uint64) *flow.Block {
   126  			return ss.heights[height]
   127  		},
   128  		func(height uint64) error {
   129  			_, enabled := ss.heights[height]
   130  			if !enabled {
   131  				return storerr.ErrNotFound
   132  			}
   133  			return nil
   134  		},
   135  	)
   136  	ss.blocks.On("ByID", mock.Anything).Return(
   137  		func(blockID flow.Identifier) *flow.Block {
   138  			return ss.blockIDs[blockID]
   139  		},
   140  		func(blockID flow.Identifier) error {
   141  			_, enabled := ss.blockIDs[blockID]
   142  			if !enabled {
   143  				return storerr.ErrNotFound
   144  			}
   145  			return nil
   146  		},
   147  	)
   148  
   149  	// set up compliance engine mock
   150  	ss.comp = mockconsensus.NewCompliance(ss.T())
   151  	ss.comp.On("Process", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe()
   152  
   153  	// set up sync core
   154  	ss.core = &module.SyncCore{}
   155  
   156  	// initialize the engine
   157  	log := zerolog.New(io.Discard)
   158  	metrics := metrics.NewNoopCollector()
   159  
   160  	idCache, err := cache.NewProtocolStateIDCache(log, ss.state, protocolEvents.NewDistributor())
   161  	require.NoError(ss.T(), err, "could not create protocol state identity cache")
   162  	spamConfig, err := NewSpamDetectionConfig()
   163  	require.NoError(ss.T(), err, "could not create spam detection config")
   164  	e, err := New(log, metrics, ss.net, ss.me, ss.state, ss.blocks, ss.comp, ss.core,
   165  		id.NewIdentityFilterIdentifierProvider(
   166  			filter.And(
   167  				filter.HasRole[flow.Identity](flow.RoleConsensus),
   168  				filter.Not(filter.HasNodeID[flow.Identity](ss.me.NodeID())),
   169  			),
   170  			idCache,
   171  		),
   172  		spamConfig)
   173  	require.NoError(ss.T(), err, "should pass engine initialization")
   174  	ss.e = e
   175  }