/* Copyright IBM Corp. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ package discovery import ( "testing" "github.com/golang/protobuf/proto" "github.com/hyperledger/fabric-protos-go/gossip" "github.com/hyperledger/fabric/gossip/protoext" "github.com/stretchr/testify/require" ) func TestShuffle(t *testing.T) { endorsers := make(Endorsers, 1000) for i := 0; i < len(endorsers); i++ { endorsers[i] = &Peer{ StateInfoMessage: stateInfoWithHeight(uint64(i)), } } isHeightAscending := func(endorsers Endorsers) bool { for i := 0; i < len(endorsers)-1; i++ { currHeight := endorsers[i].StateInfoMessage.GetStateInfo().Properties.LedgerHeight nextHeight := endorsers[i+1].StateInfoMessage.GetStateInfo().Properties.LedgerHeight if currHeight > nextHeight { return false } } return true } require.True(t, isHeightAscending(endorsers)) require.False(t, isHeightAscending(endorsers.Shuffle())) } func TestExclusionAndPriority(t *testing.T) { newPeer := func(i int) *Peer { si := stateInfoWithHeight(uint64(i)) am, _ := protoext.EnvelopeToGossipMessage(aliveMessage(i)) return &Peer{ StateInfoMessage: si, AliveMessage: am, } } excludeFirst := selectionFunc(func(p Peer) bool { return p.AliveMessage.GetAliveMsg().Timestamp.SeqNum == uint64(1) }) givenPeers := Endorsers{newPeer(3), newPeer(5), newPeer(1), newPeer(4), newPeer(2), newPeer(3)} require.Equal(t, []int{5, 4, 3, 3, 2}, heights(givenPeers.Filter(excludeFirst).Sort(PrioritiesByHeight))) } func TestExcludeEndpoints(t *testing.T) { secretEndpoint := &gossip.Secret{ Content: &gossip.Secret_InternalEndpoint{ InternalEndpoint: "s2", }, } secret, _ := proto.Marshal(secretEndpoint) am1 := aliveMessage(1) am2 := aliveMessage(2) am2.SecretEnvelope = &gossip.SecretEnvelope{ Payload: secret, } am3 := aliveMessage(3) g1, _ := protoext.EnvelopeToGossipMessage(am1) g2, _ := protoext.EnvelopeToGossipMessage(am2) g3, _ := protoext.EnvelopeToGossipMessage(am3) p1 := Peer{ AliveMessage: g1, } p2 := Peer{ AliveMessage: g2, } p3 := Peer{ AliveMessage: g3, } s := ExcludeHosts("p1", "s2") require.True(t, s.Exclude(p1)) require.True(t, s.Exclude(p2)) require.False(t, s.Exclude(p3)) s = NoExclusion require.False(t, s.Exclude(p1)) require.False(t, s.Exclude(p2)) require.False(t, s.Exclude(p3)) } func TestNoPriorities(t *testing.T) { s1 := stateInfoWithHeight(100) s2 := stateInfoWithHeight(200) p1 := Peer{ StateInfoMessage: s1, } p2 := Peer{ StateInfoMessage: s2, } require.Equal(t, Priority(0), NoPriorities.Compare(p1, p2)) } func TestPrioritiesByHeight(t *testing.T) { tests := []struct { name string expected Priority leftHeight uint64 rightHeight uint64 }{ { name: "Same heights", expected: 0, leftHeight: 100, rightHeight: 100, }, { name: "Right height bigger", expected: -1, leftHeight: 100, rightHeight: 200, }, { name: "Left height bigger", expected: 1, leftHeight: 200, rightHeight: 100, }, } for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { s1 := stateInfoWithHeight(test.leftHeight) s2 := stateInfoWithHeight(test.rightHeight) p1 := Peer{ StateInfoMessage: s1, } p2 := Peer{ StateInfoMessage: s2, } p := PrioritiesByHeight.Compare(p1, p2) require.Equal(t, test.expected, p) }) } } func stateInfoWithHeight(h uint64) *protoext.SignedGossipMessage { g := &gossip.GossipMessage{ Content: &gossip.GossipMessage_StateInfo{ StateInfo: &gossip.StateInfo{ Properties: &gossip.Properties{ LedgerHeight: h, }, Timestamp: &gossip.PeerTime{}, }, }, } sMsg, _ := protoext.NoopSign(g) return sMsg } func heights(endorsers Endorsers) []int { var res []int for _, e := range endorsers { res = append(res, int(e.StateInfoMessage.GetStateInfo().Properties.LedgerHeight)) } return res }