Merge pull request #3205 from SebastianJ/coverage-consensus
[coverage] [consensus] Additional unit tests / coveragepull/3209/head
commit
af38bc655d
@ -0,0 +1,69 @@ |
||||
package consensus |
||||
|
||||
import ( |
||||
"sync/atomic" |
||||
"testing" |
||||
|
||||
msg_pb "github.com/harmony-one/harmony/api/proto/message" |
||||
nodeconfig "github.com/harmony-one/harmony/internal/configs/node" |
||||
"github.com/harmony-one/harmony/test/helpers" |
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestMessageSenderInitialization(t *testing.T) { |
||||
hostData := helpers.Hosts[0] |
||||
host, _, err := helpers.GenerateHost(hostData.IP, hostData.Port) |
||||
assert.NoError(t, err) |
||||
|
||||
messageSender := NewMessageSender(host) |
||||
expectedMessageSender := &MessageSender{blockNum: 0, host: host, retryTimes: int(phaseDuration.Seconds()) / RetryIntervalInSec} |
||||
assert.Equal(t, expectedMessageSender.host, messageSender.host) |
||||
assert.Equal(t, expectedMessageSender.retryTimes, messageSender.retryTimes) |
||||
assert.Equal(t, uint64(0), messageSender.blockNum) |
||||
|
||||
assert.Equal(t, 0, numberOfMessagesToRetry(messageSender)) |
||||
} |
||||
|
||||
func TestMessageSenderReset(t *testing.T) { |
||||
hostData := helpers.Hosts[0] |
||||
host, _, err := helpers.GenerateHost(hostData.IP, hostData.Port) |
||||
assert.NoError(t, err) |
||||
|
||||
messageSender := NewMessageSender(host) |
||||
assert.Equal(t, uint64(0), messageSender.blockNum) |
||||
assert.Equal(t, 0, numberOfMessagesToRetry(messageSender)) |
||||
|
||||
groups := []nodeconfig.GroupID{ |
||||
"hmy/testnet/0.0.1/client/beacon", |
||||
"hmy/testnet/0.0.1/node/beacon", |
||||
} |
||||
p2pMsg := []byte{0} |
||||
msgType := msg_pb.MessageType_ANNOUNCE |
||||
msgRetry := MessageRetry{blockNum: 1, groups: groups, p2pMsg: p2pMsg, msgType: msgType, retryCount: 0} |
||||
atomic.StoreUint32(&msgRetry.isActive, 1) |
||||
messageSender.messagesToRetry.Store(msgType, &msgRetry) |
||||
assert.Equal(t, 1, numberOfMessagesToRetry(messageSender)) |
||||
|
||||
messageSender.Reset(1) |
||||
assert.Equal(t, uint64(1), messageSender.blockNum) |
||||
assert.Equal(t, 0, numberOfMessagesToRetry(messageSender)) |
||||
|
||||
msgType = msg_pb.MessageType_COMMITTED |
||||
msgRetry = MessageRetry{blockNum: 2, groups: groups, p2pMsg: p2pMsg, msgType: msgType, retryCount: 0} |
||||
atomic.StoreUint32(&msgRetry.isActive, 1) |
||||
messageSender.messagesToRetry.Store(msgType, &msgRetry) |
||||
|
||||
messageSender.Reset(2) |
||||
assert.Equal(t, uint64(2), messageSender.blockNum) |
||||
assert.Equal(t, 1, numberOfMessagesToRetry(messageSender)) |
||||
} |
||||
|
||||
func numberOfMessagesToRetry(messageSender *MessageSender) int { |
||||
messagesToRetryCount := 0 |
||||
messageSender.messagesToRetry.Range(func(_, _ interface{}) bool { |
||||
messagesToRetryCount++ |
||||
return true |
||||
}) |
||||
|
||||
return messagesToRetryCount |
||||
} |
@ -1,37 +1,126 @@ |
||||
package consensus |
||||
|
||||
import ( |
||||
"sync" |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/harmony-one/abool" |
||||
"github.com/harmony-one/harmony/consensus/quorum" |
||||
"github.com/harmony-one/harmony/crypto/bls" |
||||
"github.com/harmony-one/harmony/internal/utils" |
||||
"github.com/harmony-one/harmony/multibls" |
||||
"github.com/harmony-one/harmony/p2p" |
||||
"github.com/harmony-one/harmony/shard" |
||||
"github.com/harmony-one/harmony/staking/slash" |
||||
"github.com/harmony-one/harmony/test/helpers" |
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestNew(test *testing.T) { |
||||
leader := p2p.Peer{IP: "127.0.0.1", Port: "9902"} |
||||
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") |
||||
host, err := p2p.NewHost(&leader, priKey) |
||||
if err != nil { |
||||
test.Fatalf("newhost failure: %v", err) |
||||
func TestConsensusInitialization(t *testing.T) { |
||||
host, multiBLSPrivateKey, consensus, decider, err := GenerateConsensusForTesting() |
||||
assert.NoError(t, err) |
||||
|
||||
peer := host.GetSelfPeer() |
||||
|
||||
messageSender := &MessageSender{host: host, retryTimes: int(phaseDuration.Seconds()) / RetryIntervalInSec} |
||||
fbtLog := NewFBFTLog() |
||||
state := State{mode: Normal} |
||||
|
||||
timeouts := createTimeout() |
||||
expectedTimeouts := make(map[TimeoutType]time.Duration) |
||||
expectedTimeouts[timeoutConsensus] = phaseDuration |
||||
expectedTimeouts[timeoutViewChange] = viewChangeDuration |
||||
expectedTimeouts[timeoutBootstrap] = bootstrapDuration |
||||
|
||||
assert.Equal(t, decider, consensus.Decider) |
||||
assert.Equal(t, host, consensus.host) |
||||
assert.Equal(t, messageSender, consensus.msgSender) |
||||
assert.IsType(t, make(chan struct{}), consensus.BlockNumLowChan) |
||||
|
||||
// FBFTLog
|
||||
assert.Equal(t, fbtLog, consensus.FBFTLog) |
||||
assert.Equal(t, maxLogSize, consensus.FBFTLog.maxLogSize) |
||||
|
||||
assert.Equal(t, FBFTAnnounce, consensus.phase) |
||||
|
||||
// State / consensus.current
|
||||
assert.Equal(t, state.mode, consensus.current.mode) |
||||
assert.Equal(t, state.viewID, consensus.current.viewID) |
||||
|
||||
// FBFT timeout
|
||||
assert.IsType(t, make(map[TimeoutType]*utils.Timeout), consensus.consensusTimeout) |
||||
for timeoutType, timeout := range expectedTimeouts { |
||||
duration := consensus.consensusTimeout[timeoutType].Duration() |
||||
assert.Equal(t, timeouts[timeoutType].Duration().Nanoseconds(), duration.Nanoseconds()) |
||||
assert.Equal(t, timeout.Nanoseconds(), duration.Nanoseconds()) |
||||
} |
||||
decider := quorum.NewDecider( |
||||
quorum.SuperMajorityVote, shard.BeaconChainShardID, |
||||
) |
||||
consensus, err := New( |
||||
host, shard.BeaconChainShardID, leader, multibls.GetPrivateKeys(bls.RandPrivateKey()), decider, |
||||
) |
||||
|
||||
// Validators sync.Map
|
||||
assert.IsType(t, sync.Map{}, consensus.validators) |
||||
assert.NotEmpty(t, consensus.validators) |
||||
|
||||
validatorLength := 0 |
||||
consensus.validators.Range(func(_, _ interface{}) bool { |
||||
validatorLength++ |
||||
return true |
||||
}) |
||||
|
||||
assert.Equal(t, 1, validatorLength) |
||||
retrievedPeer, loadedOk := consensus.validators.Load(peer.ConsensusPubKey.SerializeToHexStr()) |
||||
assert.Equal(t, true, loadedOk) |
||||
assert.Equal(t, retrievedPeer, peer) |
||||
|
||||
// MultiBLS
|
||||
assert.Equal(t, multiBLSPrivateKey, consensus.priKey) |
||||
assert.Equal(t, multiBLSPrivateKey.GetPublicKeys(), consensus.GetPublicKeys()) |
||||
|
||||
// Misc
|
||||
assert.Equal(t, uint64(0), consensus.viewID) |
||||
assert.Equal(t, uint32(shard.BeaconChainShardID), consensus.ShardID) |
||||
|
||||
assert.IsType(t, make(chan []byte), consensus.MsgChan) |
||||
assert.NotNil(t, consensus.MsgChan) |
||||
|
||||
assert.IsType(t, make(chan struct{}), consensus.syncReadyChan) |
||||
assert.NotNil(t, consensus.syncReadyChan) |
||||
|
||||
assert.IsType(t, make(chan struct{}), consensus.syncNotReadyChan) |
||||
assert.NotNil(t, consensus.syncNotReadyChan) |
||||
|
||||
assert.IsType(t, make(chan slash.Record), consensus.SlashChan) |
||||
assert.NotNil(t, consensus.SlashChan) |
||||
|
||||
assert.IsType(t, make(chan uint64), consensus.commitFinishChan) |
||||
assert.NotNil(t, consensus.commitFinishChan) |
||||
|
||||
assert.IsType(t, make(chan struct{}), consensus.ReadySignal) |
||||
assert.NotNil(t, consensus.ReadySignal) |
||||
|
||||
assert.IsType(t, make(chan [vdfAndSeedSize]byte), consensus.RndChannel) |
||||
assert.NotNil(t, consensus.RndChannel) |
||||
|
||||
assert.IsType(t, abool.NewBool(false), consensus.IgnoreViewIDCheck) |
||||
assert.NotNil(t, consensus.IgnoreViewIDCheck) |
||||
} |
||||
|
||||
// GenerateConsensusForTesting - helper method to generate a basic consensus
|
||||
func GenerateConsensusForTesting() (p2p.Host, multibls.PrivateKeys, *Consensus, quorum.Decider, error) { |
||||
hostData := helpers.Hosts[0] |
||||
host, _, err := helpers.GenerateHost(hostData.IP, hostData.Port) |
||||
if err != nil { |
||||
test.Fatalf("Cannot craeate consensus: %v", err) |
||||
} |
||||
if consensus.viewID != 0 { |
||||
test.Errorf("Consensus Id is initialized to the wrong value: %d", consensus.viewID) |
||||
return nil, nil, nil, nil, err |
||||
} |
||||
|
||||
if consensus.ReadySignal == nil { |
||||
test.Error("Consensus ReadySignal should be initialized") |
||||
peer := host.GetSelfPeer() |
||||
|
||||
decider := quorum.NewDecider(quorum.SuperMajorityVote, shard.BeaconChainShardID) |
||||
multiBLSPrivateKey := multibls.GetPrivateKeys(bls.RandPrivateKey()) |
||||
|
||||
consensus, err := New(host, shard.BeaconChainShardID, peer, multiBLSPrivateKey, decider) |
||||
if err != nil { |
||||
return nil, nil, nil, nil, err |
||||
} |
||||
|
||||
return host, multiBLSPrivateKey, consensus, decider, nil |
||||
} |
||||
|
@ -0,0 +1,45 @@ |
||||
package consensus |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestModeStrings(t *testing.T) { |
||||
modes := []Mode{ |
||||
Normal, |
||||
ViewChanging, |
||||
Syncing, |
||||
Listening, |
||||
} |
||||
|
||||
expectations := make(map[Mode]string) |
||||
expectations[Normal] = "Normal" |
||||
expectations[ViewChanging] = "ViewChanging" |
||||
expectations[Syncing] = "Syncing" |
||||
expectations[Listening] = "Listening" |
||||
|
||||
for _, mode := range modes { |
||||
expected := expectations[mode] |
||||
assert.Equal(t, expected, mode.String()) |
||||
} |
||||
} |
||||
|
||||
func TestPhaseStrings(t *testing.T) { |
||||
phases := []FBFTPhase{ |
||||
FBFTAnnounce, |
||||
FBFTPrepare, |
||||
FBFTCommit, |
||||
} |
||||
|
||||
expectations := make(map[FBFTPhase]string) |
||||
expectations[FBFTAnnounce] = "Announce" |
||||
expectations[FBFTPrepare] = "Prepare" |
||||
expectations[FBFTCommit] = "Commit" |
||||
|
||||
for _, phase := range phases { |
||||
expected := expectations[phase] |
||||
assert.Equal(t, expected, phase.String()) |
||||
} |
||||
} |
@ -0,0 +1,60 @@ |
||||
package quorum |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"github.com/harmony-one/bls/ffi/go/bls" |
||||
harmony_bls "github.com/harmony-one/harmony/crypto/bls" |
||||
"github.com/harmony-one/harmony/shard" |
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestPhaseStrings(t *testing.T) { |
||||
phases := []Phase{ |
||||
Prepare, |
||||
Commit, |
||||
ViewChange, |
||||
} |
||||
|
||||
expectations := make(map[Phase]string) |
||||
expectations[Prepare] = "Prepare" |
||||
expectations[Commit] = "Commit" |
||||
expectations[ViewChange] = "viewChange" |
||||
|
||||
for _, phase := range phases { |
||||
expected := expectations[phase] |
||||
assert.Equal(t, expected, phase.String()) |
||||
} |
||||
} |
||||
|
||||
func TestPolicyStrings(t *testing.T) { |
||||
policies := []Policy{ |
||||
SuperMajorityVote, |
||||
SuperMajorityStake, |
||||
} |
||||
|
||||
expectations := make(map[Policy]string) |
||||
expectations[SuperMajorityVote] = "SuperMajorityVote" |
||||
expectations[SuperMajorityStake] = "SuperMajorityStake" |
||||
|
||||
for _, policy := range policies { |
||||
expected := expectations[policy] |
||||
assert.Equal(t, expected, policy.String()) |
||||
} |
||||
} |
||||
|
||||
func TestAddingQuoromParticipants(t *testing.T) { |
||||
decider := NewDecider(SuperMajorityVote, shard.BeaconChainShardID) |
||||
|
||||
assert.Equal(t, int64(0), decider.ParticipantsCount()) |
||||
|
||||
blsKeys := []*bls.PublicKey{} |
||||
keyCount := int64(5) |
||||
for i := int64(0); i < keyCount; i++ { |
||||
blsKey := harmony_bls.RandPrivateKey() |
||||
blsKeys = append(blsKeys, blsKey.GetPublicKey()) |
||||
} |
||||
|
||||
decider.UpdateParticipants(blsKeys) |
||||
assert.Equal(t, keyCount, decider.ParticipantsCount()) |
||||
} |
@ -0,0 +1,148 @@ |
||||
package consensus |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"github.com/harmony-one/bls/ffi/go/bls" |
||||
harmony_bls "github.com/harmony-one/harmony/crypto/bls" |
||||
"github.com/harmony-one/harmony/shard" |
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestBasicViewChanging(t *testing.T) { |
||||
_, _, consensus, _, err := GenerateConsensusForTesting() |
||||
assert.NoError(t, err) |
||||
|
||||
state := State{mode: Normal} |
||||
|
||||
// Change Mode
|
||||
assert.Equal(t, state.mode, consensus.current.mode) |
||||
assert.Equal(t, state.Mode(), consensus.current.Mode()) |
||||
|
||||
consensus.current.SetMode(ViewChanging) |
||||
assert.Equal(t, ViewChanging, consensus.current.mode) |
||||
assert.Equal(t, ViewChanging, consensus.current.Mode()) |
||||
|
||||
// Change ViewID
|
||||
assert.Equal(t, state.viewID, consensus.current.viewID) |
||||
assert.Equal(t, state.ViewID(), consensus.current.ViewID()) |
||||
assert.Equal(t, state.GetViewID(), consensus.current.GetViewID()) // Why are there two methods to retrieve the ViewID?
|
||||
|
||||
newViewID := consensus.current.ViewID() + 1 |
||||
consensus.current.SetViewID(newViewID) |
||||
assert.Equal(t, newViewID, consensus.current.viewID) |
||||
assert.Equal(t, newViewID, consensus.current.ViewID()) |
||||
assert.Equal(t, newViewID, consensus.current.GetViewID()) |
||||
} |
||||
|
||||
func TestPhaseSwitching(t *testing.T) { |
||||
type phaseSwitch struct { |
||||
start FBFTPhase |
||||
end FBFTPhase |
||||
} |
||||
|
||||
phases := []FBFTPhase{FBFTAnnounce, FBFTPrepare, FBFTCommit} |
||||
|
||||
_, _, consensus, _, err := GenerateConsensusForTesting() |
||||
assert.NoError(t, err) |
||||
|
||||
assert.Equal(t, FBFTAnnounce, consensus.phase) // It's a new consensus, we should be at the FBFTAnnounce phase
|
||||
|
||||
override := false |
||||
|
||||
switches := []phaseSwitch{ |
||||
{start: FBFTAnnounce, end: FBFTPrepare}, |
||||
{start: FBFTPrepare, end: FBFTCommit}, |
||||
{start: FBFTCommit, end: FBFTAnnounce}, |
||||
} |
||||
|
||||
for _, sw := range switches { |
||||
testPhaseGroupSwitching(t, consensus, phases, sw.start, sw.end, override) |
||||
} |
||||
|
||||
override = true |
||||
|
||||
for _, sw := range switches { |
||||
testPhaseGroupSwitching(t, consensus, phases, sw.start, sw.end, override) |
||||
} |
||||
|
||||
switches = []phaseSwitch{ |
||||
{start: FBFTAnnounce, end: FBFTCommit}, |
||||
{start: FBFTPrepare, end: FBFTAnnounce}, |
||||
{start: FBFTCommit, end: FBFTPrepare}, |
||||
} |
||||
|
||||
for _, sw := range switches { |
||||
testPhaseGroupSwitching(t, consensus, phases, sw.start, sw.end, override) |
||||
} |
||||
} |
||||
|
||||
func testPhaseGroupSwitching(t *testing.T, consensus *Consensus, phases []FBFTPhase, startPhase FBFTPhase, desiredPhase FBFTPhase, override bool) { |
||||
phaseMapping := make(map[FBFTPhase]bool) |
||||
|
||||
if override { |
||||
for range phases { |
||||
consensus.switchPhase(desiredPhase, override) |
||||
assert.Equal(t, desiredPhase, consensus.phase) |
||||
} |
||||
|
||||
assert.Equal(t, desiredPhase, consensus.phase) |
||||
|
||||
return |
||||
} |
||||
|
||||
phaseMapping[FBFTAnnounce] = false |
||||
phaseMapping[FBFTPrepare] = false |
||||
phaseMapping[FBFTCommit] = false |
||||
phaseMapping[startPhase] = false |
||||
phaseMapping[desiredPhase] = true |
||||
|
||||
assert.Equal(t, startPhase, consensus.phase) |
||||
|
||||
for _, phase := range phases { |
||||
consensus.switchPhase(desiredPhase, override) |
||||
expected := phaseMapping[phase] |
||||
assert.Equal(t, expected, (phase == consensus.phase)) |
||||
} |
||||
|
||||
assert.Equal(t, desiredPhase, consensus.phase) |
||||
} |
||||
|
||||
func TestGetNextLeaderKeyShouldFailForStandardGeneratedConsensus(t *testing.T) { |
||||
_, _, consensus, _, err := GenerateConsensusForTesting() |
||||
assert.NoError(t, err) |
||||
|
||||
// The below results in: "panic: runtime error: integer divide by zero"
|
||||
// This happens because there's no check for if there are any participants or not in https://github.com/harmony-one/harmony/blob/main/consensus/quorum/quorum.go#L188-L197
|
||||
assert.Panics(t, func() { consensus.GetNextLeaderKey() }) |
||||
} |
||||
|
||||
func TestGetNextLeaderKeyShouldSucceed(t *testing.T) { |
||||
_, _, consensus, _, err := GenerateConsensusForTesting() |
||||
assert.NoError(t, err) |
||||
|
||||
assert.Equal(t, int64(0), consensus.Decider.ParticipantsCount()) |
||||
|
||||
blsKeys := []*bls.PublicKey{} |
||||
wrappedBLSKeys := []*shard.BLSPublicKeyWrapper{} |
||||
|
||||
keyCount := int64(5) |
||||
for i := int64(0); i < keyCount; i++ { |
||||
blsKey := harmony_bls.RandPrivateKey() |
||||
blsPubKey := blsKey.GetPublicKey() |
||||
bytes := shard.BLSPublicKey{} |
||||
bytes.FromLibBLSPublicKey(blsPubKey) |
||||
wrapped := &shard.BLSPublicKeyWrapper{Object: blsPubKey, Bytes: bytes} |
||||
|
||||
blsKeys = append(blsKeys, blsPubKey) |
||||
wrappedBLSKeys = append(wrappedBLSKeys, wrapped) |
||||
} |
||||
|
||||
consensus.Decider.UpdateParticipants(blsKeys) |
||||
assert.Equal(t, keyCount, consensus.Decider.ParticipantsCount()) |
||||
|
||||
consensus.LeaderPubKey = wrappedBLSKeys[0] |
||||
nextKey := consensus.GetNextLeaderKey() |
||||
|
||||
assert.Equal(t, nextKey, wrappedBLSKeys[1]) |
||||
} |
@ -0,0 +1,48 @@ |
||||
package p2ptests |
||||
|
||||
import ( |
||||
"strings" |
||||
"testing" |
||||
|
||||
"github.com/harmony-one/harmony/p2p" |
||||
"github.com/harmony-one/harmony/test/helpers" |
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestMultiAddressParsing(t *testing.T) { |
||||
t.Parallel() |
||||
|
||||
multiAddresses, err := p2p.StringsToAddrs(helpers.Bootnodes) |
||||
assert.NoError(t, err) |
||||
assert.Equal(t, len(helpers.Bootnodes), len(multiAddresses)) |
||||
|
||||
for index, multiAddress := range multiAddresses { |
||||
assert.Equal(t, multiAddress.String(), helpers.Bootnodes[index]) |
||||
} |
||||
} |
||||
|
||||
func TestAddressListConversionToString(t *testing.T) { |
||||
t.Parallel() |
||||
|
||||
multiAddresses, err := p2p.StringsToAddrs(helpers.Bootnodes) |
||||
assert.NoError(t, err) |
||||
assert.Equal(t, len(helpers.Bootnodes), len(multiAddresses)) |
||||
|
||||
expected := strings.Join(helpers.Bootnodes[:], ",") |
||||
var addressList p2p.AddrList = multiAddresses |
||||
assert.Equal(t, expected, addressList.String()) |
||||
} |
||||
|
||||
func TestAddressListConversionFromString(t *testing.T) { |
||||
t.Parallel() |
||||
|
||||
multiAddresses, err := p2p.StringsToAddrs(helpers.Bootnodes) |
||||
assert.NoError(t, err) |
||||
assert.Equal(t, len(helpers.Bootnodes), len(multiAddresses)) |
||||
|
||||
addressString := strings.Join(helpers.Bootnodes[:], ",") |
||||
var addressList p2p.AddrList = multiAddresses |
||||
addressList.Set(addressString) |
||||
assert.Equal(t, len(addressList), len(multiAddresses)) |
||||
assert.Equal(t, addressList[0], multiAddresses[0]) |
||||
} |
@ -0,0 +1,83 @@ |
||||
package p2ptests |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"github.com/harmony-one/harmony/test/helpers" |
||||
"github.com/stretchr/testify/assert" |
||||
) |
||||
|
||||
func TestHostSetup(t *testing.T) { |
||||
t.Parallel() |
||||
|
||||
hostData := helpers.Hosts[0] |
||||
host, pubKey, err := helpers.GenerateHost(hostData.IP, hostData.Port) |
||||
assert.NoError(t, err) |
||||
|
||||
peer := host.GetSelfPeer() |
||||
|
||||
assert.Equal(t, hostData.IP, peer.IP) |
||||
assert.Equal(t, hostData.Port, peer.Port) |
||||
assert.Equal(t, pubKey, peer.ConsensusPubKey) |
||||
assert.NotEmpty(t, peer.PeerID) |
||||
assert.Equal(t, peer.PeerID, host.GetID()) |
||||
assert.Empty(t, peer.Addrs) |
||||
} |
||||
|
||||
func TestAddPeer(t *testing.T) { |
||||
t.Parallel() |
||||
|
||||
hostData := helpers.Hosts[0] |
||||
host, _, err := helpers.GenerateHost(hostData.IP, hostData.Port) |
||||
assert.NoError(t, err) |
||||
assert.NotEmpty(t, host.GetID()) |
||||
|
||||
discoveredHostData := helpers.Hosts[1] |
||||
discoveredHost, _, err := helpers.GenerateHost(discoveredHostData.IP, discoveredHostData.Port) |
||||
assert.NoError(t, err) |
||||
assert.NotEmpty(t, discoveredHost.GetID()) |
||||
|
||||
discoveredPeer := discoveredHost.GetSelfPeer() |
||||
|
||||
assert.Empty(t, host.GetP2PHost().Peerstore().Addrs(discoveredHost.GetSelfPeer().PeerID)) |
||||
|
||||
err = host.AddPeer(&discoveredPeer) |
||||
assert.NoError(t, err) |
||||
|
||||
assert.NotEmpty(t, host.GetP2PHost().Peerstore().Addrs(discoveredHost.GetSelfPeer().PeerID)) |
||||
assert.Equal(t, 2, host.GetPeerCount()) |
||||
} |
||||
|
||||
/*func TestTopicJoining(t *testing.T) { |
||||
t.Parallel() |
||||
|
||||
hostData := hosts[0] |
||||
host, _, err := createNode(hostData.IP, hostData.Port) |
||||
assert.NoError(t, err) |
||||
assert.NotEmpty(t, host.GetID()) |
||||
|
||||
for _, topicName := range topics { |
||||
topic, err := host.GetOrJoin(topicName) |
||||
assert.NoError(t, err) |
||||
assert.NotNil(t, topic) |
||||
} |
||||
}*/ |
||||
|
||||
func TestConnectionToInvalidPeer(t *testing.T) { |
||||
t.Parallel() |
||||
|
||||
hostData := helpers.Hosts[0] |
||||
host, _, err := helpers.GenerateHost(hostData.IP, hostData.Port) |
||||
assert.NoError(t, err) |
||||
assert.NotEmpty(t, host.GetID()) |
||||
|
||||
discoveredHostData := helpers.Hosts[1] |
||||
discoveredHost, _, err := helpers.GenerateHost(discoveredHostData.IP, discoveredHostData.Port) |
||||
assert.NoError(t, err) |
||||
assert.NotEmpty(t, discoveredHost.GetID()) |
||||
|
||||
discoveredPeer := discoveredHost.GetSelfPeer() |
||||
|
||||
err = host.ConnectHostPeer(discoveredPeer) |
||||
assert.Error(t, err) |
||||
} |
@ -0,0 +1,87 @@ |
||||
package helpers |
||||
|
||||
import ( |
||||
"github.com/harmony-one/bls/ffi/go/bls" |
||||
harmony_bls "github.com/harmony-one/harmony/crypto/bls" |
||||
"github.com/harmony-one/harmony/p2p" |
||||
libp2p_crypto "github.com/libp2p/go-libp2p-crypto" |
||||
"github.com/pkg/errors" |
||||
) |
||||
|
||||
// Host - struct for representing a host (IP / Port)
|
||||
type Host struct { |
||||
IP string |
||||
Port string |
||||
} |
||||
|
||||
var ( |
||||
// Hosts - host combinations
|
||||
Hosts []Host |
||||
// Topics - p2p topics
|
||||
Topics []string |
||||
// Bootnodes - p2p bootnodes
|
||||
Bootnodes []string |
||||
) |
||||
|
||||
func init() { |
||||
Hosts = []Host{ |
||||
{IP: "127.0.0.1", Port: "9000"}, |
||||
{IP: "8.8.8.8", Port: "9001"}, |
||||
} |
||||
|
||||
Topics = []string{ |
||||
"hmy/testnet/0.0.1/client/beacon", |
||||
"hmy/testnet/0.0.1/node/beacon", |
||||
"hmy/testnet/0.0.1/node/shard/1", |
||||
"hmy/testnet/0.0.1/node/shard/2", |
||||
"hmy/testnet/0.0.1/node/shard/3", |
||||
} |
||||
|
||||
Bootnodes = []string{ |
||||
"/ip4/54.86.126.90/tcp/9850/p2p/Qmdfjtk6hPoyrH1zVD9PEH4zfWLo38dP2mDvvKXfh3tnEv", |
||||
"/ip4/52.40.84.2/tcp/9850/p2p/QmbPVwrqWsTYXq1RxGWcxx9SWaTUCfoo1wA6wmdbduWe29", |
||||
} |
||||
} |
||||
|
||||
// GenerateHost - test helper to generate a new host
|
||||
func GenerateHost(address string, port string) (p2p.Host, *bls.PublicKey, error) { |
||||
nodePrivateKey, _, err := GeneratePrivateKey() |
||||
if err != nil { |
||||
return nil, nil, errors.New("failed to generate private key for node") |
||||
} |
||||
|
||||
peer, err := GeneratePeer(address, port) |
||||
if err != nil { |
||||
return nil, nil, err |
||||
} |
||||
|
||||
host, err := p2p.NewHost(&peer, nodePrivateKey) |
||||
if err != nil { |
||||
return nil, nil, err |
||||
} |
||||
|
||||
return host, peer.ConsensusPubKey, nil |
||||
} |
||||
|
||||
// GeneratePeer - test helper to generate a new peer
|
||||
func GeneratePeer(address string, port string) (p2p.Peer, error) { |
||||
peerPrivateKey := harmony_bls.RandPrivateKey() |
||||
peerPublicKey := peerPrivateKey.GetPublicKey() |
||||
if peerPrivateKey == nil || peerPublicKey == nil { |
||||
return p2p.Peer{}, errors.New("failed to generate bls key for peer") |
||||
} |
||||
|
||||
peer := p2p.Peer{IP: address, Port: port, ConsensusPubKey: peerPublicKey} |
||||
|
||||
return peer, nil |
||||
} |
||||
|
||||
// GeneratePrivateKey - test helper to generate a new private key to be used for p2p
|
||||
func GeneratePrivateKey() (privateKey libp2p_crypto.PrivKey, publicKey libp2p_crypto.PubKey, err error) { |
||||
privateKey, publicKey, err = libp2p_crypto.GenerateKeyPair(libp2p_crypto.RSA, 2048) |
||||
if err != nil { |
||||
return nil, nil, err |
||||
} |
||||
|
||||
return privateKey, publicKey, nil |
||||
} |
Loading…
Reference in new issue