github.com/Hnampk/fabric@v2.1.1+incompatible/gossip/privdata/distributor_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package privdata 8 9 import ( 10 "errors" 11 "fmt" 12 "testing" 13 14 proto "github.com/hyperledger/fabric-protos-go/gossip" 15 "github.com/hyperledger/fabric-protos-go/peer" 16 "github.com/hyperledger/fabric-protos-go/transientstore" 17 "github.com/hyperledger/fabric/core/common/privdata" 18 "github.com/hyperledger/fabric/gossip/api" 19 gcommon "github.com/hyperledger/fabric/gossip/common" 20 "github.com/hyperledger/fabric/gossip/discovery" 21 "github.com/hyperledger/fabric/gossip/filter" 22 gossip2 "github.com/hyperledger/fabric/gossip/gossip" 23 "github.com/hyperledger/fabric/gossip/metrics" 24 "github.com/hyperledger/fabric/gossip/metrics/mocks" 25 mocks2 "github.com/hyperledger/fabric/gossip/privdata/mocks" 26 "github.com/hyperledger/fabric/gossip/protoext" 27 "github.com/hyperledger/fabric/protoutil" 28 "github.com/stretchr/testify/assert" 29 "github.com/stretchr/testify/mock" 30 ) 31 32 func Setup(mock *mocks2.CollectionAccessPolicy, requiredPeerCount int, maxPeerCount int, 33 accessFilter privdata.Filter, orgs map[string]struct{}, memberOnlyRead bool) { 34 mock.On("AccessFilter").Return(accessFilter) 35 mock.On("RequiredPeerCount").Return(requiredPeerCount) 36 mock.On("MaximumPeerCount").Return(maxPeerCount) 37 mock.On("MemberOrgs").Return(orgs) 38 mock.On("IsMemberOnlyRead").Return(memberOnlyRead) 39 } 40 41 type gossipMock struct { 42 err error 43 mock.Mock 44 api.PeerSignature 45 } 46 47 func (g *gossipMock) IdentityInfo() api.PeerIdentitySet { 48 return g.Called().Get(0).(api.PeerIdentitySet) 49 } 50 51 func (g *gossipMock) PeersOfChannel(channelID gcommon.ChannelID) []discovery.NetworkMember { 52 return g.Called(channelID).Get(0).([]discovery.NetworkMember) 53 } 54 55 func (g *gossipMock) SendByCriteria(message *protoext.SignedGossipMessage, criteria gossip2.SendCriteria) error { 56 args := g.Called(message, criteria) 57 if args.Get(0) != nil { 58 return args.Get(0).(error) 59 } 60 return nil 61 } 62 63 func (g *gossipMock) PeerFilter(channel gcommon.ChannelID, messagePredicate api.SubChannelSelectionCriteria) (filter.RoutingFilter, error) { 64 if g.err != nil { 65 return nil, g.err 66 } 67 return func(member discovery.NetworkMember) bool { 68 return messagePredicate(g.PeerSignature) 69 }, nil 70 } 71 72 func TestDistributor(t *testing.T) { 73 channelID := "test" 74 75 g := &gossipMock{ 76 Mock: mock.Mock{}, 77 PeerSignature: api.PeerSignature{ 78 Signature: []byte{3, 4, 5}, 79 Message: []byte{6, 7, 8}, 80 PeerIdentity: []byte{0, 1, 2}, 81 }, 82 } 83 sendings := make(chan struct { 84 *proto.PrivatePayload 85 gossip2.SendCriteria 86 }, 8) 87 88 g.On("PeersOfChannel", gcommon.ChannelID(channelID)).Return([]discovery.NetworkMember{ 89 {PKIid: gcommon.PKIidType{1}}, 90 {PKIid: gcommon.PKIidType{2}}, 91 }) 92 93 g.On("IdentityInfo").Return(api.PeerIdentitySet{ 94 { 95 PKIId: gcommon.PKIidType{1}, 96 Organization: api.OrgIdentityType("org1"), 97 }, 98 { 99 PKIId: gcommon.PKIidType{2}, 100 Organization: api.OrgIdentityType("org2"), 101 }, 102 }) 103 104 g.On("SendByCriteria", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { 105 msg := args.Get(0).(*protoext.SignedGossipMessage) 106 sendCriteria := args.Get(1).(gossip2.SendCriteria) 107 sendings <- struct { 108 *proto.PrivatePayload 109 gossip2.SendCriteria 110 }{ 111 PrivatePayload: msg.GetPrivateData().Payload, 112 SendCriteria: sendCriteria, 113 } 114 }).Return(nil) 115 accessFactoryMock := &mocks2.CollectionAccessFactory{} 116 c1ColConfig := &peer.CollectionConfig{ 117 Payload: &peer.CollectionConfig_StaticCollectionConfig{ 118 StaticCollectionConfig: &peer.StaticCollectionConfig{ 119 Name: "c1", 120 RequiredPeerCount: 1, 121 MaximumPeerCount: 1, 122 }, 123 }, 124 } 125 126 c2ColConfig := &peer.CollectionConfig{ 127 Payload: &peer.CollectionConfig_StaticCollectionConfig{ 128 StaticCollectionConfig: &peer.StaticCollectionConfig{ 129 Name: "c2", 130 RequiredPeerCount: 1, 131 MaximumPeerCount: 1, 132 }, 133 }, 134 } 135 136 policyMock := &mocks2.CollectionAccessPolicy{} 137 Setup(policyMock, 1, 2, func(_ protoutil.SignedData) bool { 138 return true 139 }, map[string]struct{}{ 140 "org1": {}, 141 "org2": {}, 142 }, false) 143 144 accessFactoryMock.On("AccessPolicy", c1ColConfig, channelID).Return(policyMock, nil) 145 accessFactoryMock.On("AccessPolicy", c2ColConfig, channelID).Return(policyMock, nil) 146 147 testMetricProvider := mocks.TestUtilConstructMetricProvider() 148 metrics := metrics.NewGossipMetrics(testMetricProvider.FakeProvider).PrivdataMetrics 149 150 d := NewDistributor(channelID, g, accessFactoryMock, metrics, 0) 151 pdFactory := &pvtDataFactory{} 152 pvtData := pdFactory.addRWSet().addNSRWSet("ns1", "c1", "c2").addRWSet().addNSRWSet("ns2", "c1", "c2").create() 153 err := d.Distribute("tx1", &transientstore.TxPvtReadWriteSetWithConfigInfo{ 154 PvtRwset: pvtData[0].WriteSet, 155 CollectionConfigs: map[string]*peer.CollectionConfigPackage{ 156 "ns1": { 157 Config: []*peer.CollectionConfig{c1ColConfig, c2ColConfig}, 158 }, 159 }, 160 }, 0) 161 assert.NoError(t, err) 162 err = d.Distribute("tx2", &transientstore.TxPvtReadWriteSetWithConfigInfo{ 163 PvtRwset: pvtData[1].WriteSet, 164 CollectionConfigs: map[string]*peer.CollectionConfigPackage{ 165 "ns2": { 166 Config: []*peer.CollectionConfig{c1ColConfig, c2ColConfig}, 167 }, 168 }, 169 }, 0) 170 assert.NoError(t, err) 171 172 expectedMaxCount := map[string]int{} 173 expectedMinAck := map[string]int{} 174 175 i := 0 176 assert.Len(t, sendings, 8) 177 for dis := range sendings { 178 key := fmt.Sprintf("%s~%s", dis.PrivatePayload.Namespace, dis.PrivatePayload.CollectionName) 179 expectedMaxCount[key] += dis.SendCriteria.MaxPeers 180 expectedMinAck[key] += dis.SendCriteria.MinAck 181 i++ 182 if i == 8 { 183 break 184 } 185 } 186 187 // Ensure MaxPeers is maxInternalPeers which is 2 188 assert.Equal(t, 2, expectedMaxCount["ns1~c1"]) 189 assert.Equal(t, 2, expectedMaxCount["ns2~c2"]) 190 191 // and MinAck is minInternalPeers which is 1 192 assert.Equal(t, 1, expectedMinAck["ns1~c1"]) 193 assert.Equal(t, 1, expectedMinAck["ns2~c2"]) 194 195 // Channel is empty after we read 8 times from it 196 assert.Len(t, sendings, 0) 197 198 // Bad path: dependencies (gossip and others) don't work properly 199 g.err = errors.New("failed obtaining filter") 200 err = d.Distribute("tx1", &transientstore.TxPvtReadWriteSetWithConfigInfo{ 201 PvtRwset: pvtData[0].WriteSet, 202 CollectionConfigs: map[string]*peer.CollectionConfigPackage{ 203 "ns1": { 204 Config: []*peer.CollectionConfig{c1ColConfig, c2ColConfig}, 205 }, 206 }, 207 }, 0) 208 assert.Error(t, err) 209 assert.Contains(t, err.Error(), "failed obtaining filter") 210 211 g.Mock = mock.Mock{} 212 g.On("SendByCriteria", mock.Anything, mock.Anything).Return(errors.New("failed sending")) 213 g.On("PeersOfChannel", gcommon.ChannelID(channelID)).Return([]discovery.NetworkMember{ 214 {PKIid: gcommon.PKIidType{1}}, 215 }) 216 217 g.On("IdentityInfo").Return(api.PeerIdentitySet{ 218 { 219 PKIId: gcommon.PKIidType{1}, 220 Organization: api.OrgIdentityType("org1"), 221 }, 222 }) 223 224 g.err = nil 225 err = d.Distribute("tx1", &transientstore.TxPvtReadWriteSetWithConfigInfo{ 226 PvtRwset: pvtData[0].WriteSet, 227 CollectionConfigs: map[string]*peer.CollectionConfigPackage{ 228 "ns1": { 229 Config: []*peer.CollectionConfig{c1ColConfig, c2ColConfig}, 230 }, 231 }, 232 }, 0) 233 assert.Error(t, err) 234 assert.Contains(t, err.Error(), "Failed disseminating 2 out of 2 private dissemination plans") 235 236 assert.Equal(t, 237 []string{"channel", channelID}, 238 testMetricProvider.FakeSendDuration.WithArgsForCall(0), 239 ) 240 assert.True(t, testMetricProvider.FakeSendDuration.ObserveArgsForCall(0) > 0) 241 }