prysm-pulse/beacon-chain/simulator/service_test.go

188 lines
4.6 KiB
Go

package simulator
import (
"context"
"fmt"
"io/ioutil"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
"github.com/prysmaticlabs/prysm/beacon-chain/types"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/database"
"github.com/prysmaticlabs/prysm/shared/p2p"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/sirupsen/logrus"
logTest "github.com/sirupsen/logrus/hooks/test"
)
func init() {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetOutput(ioutil.Discard)
}
type mockP2P struct{}
func (mp *mockP2P) Subscribe(msg interface{}, channel interface{}) event.Subscription {
return new(event.Feed).Subscribe(channel)
}
func (mp *mockP2P) Broadcast(msg interface{}) {}
func (mp *mockP2P) Send(msg interface{}, peer p2p.Peer) {}
type mockPOWChainService struct{}
func (mpow *mockPOWChainService) LatestBlockHash() common.Hash {
return common.BytesToHash([]byte{})
}
type mockChainService struct{}
func (mc *mockChainService) CurrentActiveState() *types.ActiveState {
return types.NewActiveState(&pb.ActiveState{}, make(map[*common.Hash]*types.VoteCache))
}
func (mc *mockChainService) CurrentCrystallizedState() *types.CrystallizedState {
return types.NewCrystallizedState(&pb.CrystallizedState{})
}
func TestLifecycle(t *testing.T) {
hook := logTest.NewGlobal()
db := database.NewKVStore()
cfg := &Config{
Delay: time.Second,
BlockRequestBuf: 0,
P2P: &mockP2P{},
Web3Service: &mockPOWChainService{},
ChainService: &mockChainService{},
BeaconDB: db,
Validator: false,
}
sim := NewSimulator(context.Background(), cfg)
sim.Start()
testutil.AssertLogsContain(t, hook, "Starting service")
sim.Stop()
testutil.AssertLogsContain(t, hook, "Stopping service")
// The context should have been canceled.
if sim.ctx.Err() == nil {
t.Error("context was not canceled")
}
}
func TestBroadcastBlockHash(t *testing.T) {
hook := logTest.NewGlobal()
db := database.NewKVStore()
cfg := &Config{
Delay: time.Second,
BlockRequestBuf: 0,
P2P: &mockP2P{},
Web3Service: &mockPOWChainService{},
ChainService: &mockChainService{},
BeaconDB: db,
Validator: false,
}
sim := NewSimulator(context.Background(), cfg)
delayChan := make(chan time.Time)
doneChan := make(chan struct{})
exitRoutine := make(chan bool)
go func() {
sim.run(delayChan, doneChan)
<-exitRoutine
}()
delayChan <- time.Time{}
doneChan <- struct{}{}
testutil.AssertLogsContain(t, hook, "Announcing block hash")
exitRoutine <- true
if len(sim.broadcastedBlockHashes) != 1 {
t.Error("Did not store the broadcasted block hash")
}
hook.Reset()
}
func TestBlockRequest(t *testing.T) {
hook := logTest.NewGlobal()
db := database.NewKVStore()
cfg := &Config{
Delay: time.Second,
BlockRequestBuf: 0,
P2P: &mockP2P{},
Web3Service: &mockPOWChainService{},
ChainService: &mockChainService{},
BeaconDB: db,
Validator: true,
}
sim := NewSimulator(context.Background(), cfg)
delayChan := make(chan time.Time)
doneChan := make(chan struct{})
exitRoutine := make(chan bool)
go func() {
sim.run(delayChan, doneChan)
<-exitRoutine
}()
block := types.NewBlock(&pb.BeaconBlock{ParentHash: make([]byte, 32)})
h, err := block.Hash()
if err != nil {
t.Fatal(err)
}
data := &pb.BeaconBlockRequest{
Hash: h[:],
}
msg := p2p.Message{
Peer: p2p.Peer{},
Data: data,
}
sim.broadcastedBlocks[h] = block
sim.blockRequestChan <- msg
doneChan <- struct{}{}
exitRoutine <- true
testutil.AssertLogsContain(t, hook, fmt.Sprintf("Responding to full block request for hash: 0x%x", h))
}
func TestLastSimulatedSession(t *testing.T) {
db := database.NewKVStore()
cfg := &Config{
Delay: time.Second,
BlockRequestBuf: 0,
P2P: &mockP2P{},
Web3Service: &mockPOWChainService{},
ChainService: &mockChainService{},
BeaconDB: db,
Validator: true,
}
sim := NewSimulator(context.Background(), cfg)
if err := db.Put([]byte("last-simulated-block"), []byte{}); err != nil {
t.Fatalf("Could not store last simulated block: %v", err)
}
if _, err := sim.lastSimulatedSessionBlock(); err != nil {
t.Errorf("could not fetch last simulated session block: %v", err)
}
}
func TestDefaultConfig(t *testing.T) {
if DefaultConfig().BlockRequestBuf != 100 {
t.Errorf("incorrect default config for block request buffer")
}
if DefaultConfig().Delay != time.Second*5 {
t.Errorf("incorrect default config for delay")
}
}