github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/core/scc/cscc/configure_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 package cscc 17 18 import ( 19 "fmt" 20 "os" 21 "strings" 22 "testing" 23 "time" 24 25 "github.com/golang/protobuf/proto" 26 configtxtest "github.com/hyperledger/fabric/common/configtx/test" 27 "github.com/hyperledger/fabric/common/genesis" 28 "github.com/hyperledger/fabric/common/localmsp" 29 "github.com/hyperledger/fabric/common/mocks/scc" 30 "github.com/hyperledger/fabric/common/policies" 31 "github.com/hyperledger/fabric/core/chaincode" 32 "github.com/hyperledger/fabric/core/chaincode/shim" 33 "github.com/hyperledger/fabric/core/common/sysccprovider" 34 "github.com/hyperledger/fabric/core/deliverservice" 35 "github.com/hyperledger/fabric/core/deliverservice/blocksprovider" 36 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 37 "github.com/hyperledger/fabric/core/peer" 38 "github.com/hyperledger/fabric/core/policy" 39 policymocks "github.com/hyperledger/fabric/core/policy/mocks" 40 "github.com/hyperledger/fabric/gossip/api" 41 "github.com/hyperledger/fabric/gossip/service" 42 "github.com/hyperledger/fabric/msp/mgmt" 43 "github.com/hyperledger/fabric/msp/mgmt/testtools" 44 peergossip "github.com/hyperledger/fabric/peer/gossip" 45 "github.com/hyperledger/fabric/peer/gossip/mocks" 46 cb "github.com/hyperledger/fabric/protos/common" 47 pb "github.com/hyperledger/fabric/protos/peer" 48 "github.com/hyperledger/fabric/protos/utils" 49 "github.com/spf13/viper" 50 "github.com/stretchr/testify/assert" 51 ) 52 53 type mockDeliveryClient struct { 54 } 55 56 // StartDeliverForChannel dynamically starts delivery of new blocks from ordering service 57 // to channel peers. 58 func (ds *mockDeliveryClient) StartDeliverForChannel(chainID string, ledgerInfo blocksprovider.LedgerInfo, f func()) error { 59 return nil 60 } 61 62 // StopDeliverForChannel dynamically stops delivery of new blocks from ordering service 63 // to channel peers. 64 func (ds *mockDeliveryClient) StopDeliverForChannel(chainID string) error { 65 return nil 66 } 67 68 // Stop terminates delivery service and closes the connection 69 func (*mockDeliveryClient) Stop() { 70 71 } 72 73 type mockDeliveryClientFactory struct { 74 } 75 76 func (*mockDeliveryClientFactory) Service(g service.GossipService, endpoints []string, mcs api.MessageCryptoService) (deliverclient.DeliverService, error) { 77 return &mockDeliveryClient{}, nil 78 } 79 80 func TestMain(m *testing.M) { 81 msptesttools.LoadMSPSetupForTesting() 82 83 os.Exit(m.Run()) 84 } 85 86 func TestConfigerInit(t *testing.T) { 87 e := new(PeerConfiger) 88 stub := shim.NewMockStub("PeerConfiger", e) 89 90 if res := stub.MockInit("1", nil); res.Status != shim.OK { 91 fmt.Println("Init failed", string(res.Message)) 92 t.FailNow() 93 } 94 } 95 96 func TestConfigerInvokeInvalidParameters(t *testing.T) { 97 e := new(PeerConfiger) 98 stub := shim.NewMockStub("PeerConfiger", e) 99 100 res := stub.MockInit("1", nil) 101 assert.Equal(t, res.Status, int32(shim.OK), "Init failed") 102 103 res = stub.MockInvoke("2", nil) 104 assert.Equal(t, res.Status, int32(shim.ERROR), "CSCC invoke expected to fail having zero arguments") 105 assert.Equal(t, res.Message, "Incorrect number of arguments, 0") 106 107 args := [][]byte{[]byte("GetChannels")} 108 res = stub.MockInvokeWithSignedProposal("3", args, nil) 109 assert.Equal(t, res.Status, int32(shim.ERROR), "CSCC invoke expected to fail no signed proposal provided") 110 assert.Contains(t, res.Message, "failed authorization check") 111 112 args = [][]byte{[]byte("GetConfigBlock"), []byte("testChainID")} 113 res = stub.MockInvokeWithSignedProposal("4", args, nil) 114 assert.Equal(t, res.Status, int32(shim.ERROR), "CSCC invoke expected to fail no signed proposal provided") 115 assert.Contains(t, res.Message, "failed authorization check") 116 117 args = [][]byte{[]byte("fooFunction"), []byte("testChainID")} 118 res = stub.MockInvoke("5", args) 119 assert.Equal(t, res.Status, int32(shim.ERROR), "CSCC invoke expected wrong function name provided") 120 assert.Equal(t, res.Message, "Requested function fooFunction not found.") 121 } 122 123 func TestConfigerInvokeJoinChainMissingParams(t *testing.T) { 124 viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/") 125 os.Mkdir("/tmp/hyperledgertest", 0755) 126 defer os.RemoveAll("/tmp/hyperledgertest/") 127 128 e := new(PeerConfiger) 129 stub := shim.NewMockStub("PeerConfiger", e) 130 131 if res := stub.MockInit("1", nil); res.Status != shim.OK { 132 fmt.Println("Init failed", string(res.Message)) 133 t.FailNow() 134 } 135 136 // Failed path: expected to have at least one argument 137 args := [][]byte{[]byte("JoinChain")} 138 if res := stub.MockInvoke("2", args); res.Status == shim.OK { 139 t.Fatalf("cscc invoke JoinChain should have failed with invalid number of args: %v", args) 140 } 141 } 142 143 func TestConfigerInvokeJoinChainWrongParams(t *testing.T) { 144 viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/") 145 os.Mkdir("/tmp/hyperledgertest", 0755) 146 defer os.RemoveAll("/tmp/hyperledgertest/") 147 148 e := new(PeerConfiger) 149 stub := shim.NewMockStub("PeerConfiger", e) 150 151 if res := stub.MockInit("1", nil); res.Status != shim.OK { 152 fmt.Println("Init failed", string(res.Message)) 153 t.FailNow() 154 } 155 156 // Failed path: wrong parameter type 157 args := [][]byte{[]byte("JoinChain"), []byte("action")} 158 if res := stub.MockInvoke("2", args); res.Status == shim.OK { 159 t.Fatalf("cscc invoke JoinChain should have failed with null genesis block. args: %v", args) 160 } 161 } 162 163 func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) { 164 sysccprovider.RegisterSystemChaincodeProviderFactory(&scc.MocksccProviderFactory{}) 165 166 viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/") 167 viper.Set("chaincode.executetimeout", "3s") 168 os.Mkdir("/tmp/hyperledgertest", 0755) 169 170 peer.MockInitialize() 171 ledgermgmt.InitializeTestEnv() 172 defer ledgermgmt.CleanupTestEnv() 173 defer os.RemoveAll("/tmp/hyperledgertest/") 174 175 e := new(PeerConfiger) 176 stub := shim.NewMockStub("PeerConfiger", e) 177 178 peerEndpoint := "localhost:13611" 179 getPeerEndpoint := func() (*pb.PeerEndpoint, error) { 180 return &pb.PeerEndpoint{Id: &pb.PeerID{Name: "cscctestpeer"}, Address: peerEndpoint}, nil 181 } 182 ccStartupTimeout := time.Duration(30000) * time.Millisecond 183 chaincode.NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout) 184 185 // Init the policy checker 186 policyManagerGetter := &policymocks.MockChannelPolicyManagerGetter{ 187 Managers: map[string]policies.Manager{ 188 "mytestchainid": &policymocks.MockChannelPolicyManager{MockPolicy: &policymocks.MockPolicy{Deserializer: &policymocks.MockIdentityDeserializer{[]byte("Alice"), []byte("msg1")}}}, 189 }, 190 } 191 192 identityDeserializer := &policymocks.MockIdentityDeserializer{[]byte("Alice"), []byte("msg1")} 193 194 e.policyChecker = policy.NewPolicyChecker( 195 policyManagerGetter, 196 identityDeserializer, 197 &policymocks.MockMSPPrincipalGetter{Principal: []byte("Alice")}, 198 ) 199 200 identity, _ := mgmt.GetLocalSigningIdentityOrPanic().Serialize() 201 messageCryptoService := peergossip.NewMCS(&mocks.ChannelPolicyManagerGetter{}, localmsp.NewSigner(), mgmt.NewDeserializersManager()) 202 secAdv := peergossip.NewSecurityAdvisor(mgmt.NewDeserializersManager()) 203 err := service.InitGossipServiceCustomDeliveryFactory(identity, peerEndpoint, nil, &mockDeliveryClientFactory{}, messageCryptoService, secAdv, nil) 204 assert.NoError(t, err) 205 206 // Successful path for JoinChain 207 blockBytes := mockConfigBlock() 208 if blockBytes == nil { 209 t.Fatalf("cscc invoke JoinChain failed because invalid block") 210 } 211 args := [][]byte{[]byte("JoinChain"), blockBytes} 212 sProp, _ := utils.MockSignedEndorserProposalOrPanic("", &pb.ChaincodeSpec{}, []byte("Alice"), []byte("msg1")) 213 identityDeserializer.Msg = sProp.ProposalBytes 214 sProp.Signature = sProp.ProposalBytes 215 216 // Try fail path with nil block 217 res := stub.MockInvokeWithSignedProposal("2", [][]byte{[]byte("JoinChain"), nil}, sProp) 218 assert.Equal(t, res.Status, int32(shim.ERROR)) 219 220 // Try fail path with block and nil payload header 221 payload, _ := proto.Marshal(&cb.Payload{}) 222 env, _ := proto.Marshal(&cb.Envelope{ 223 Payload: payload, 224 }) 225 badBlock := &cb.Block{ 226 Data: &cb.BlockData{ 227 Data: [][]byte{env}, 228 }, 229 } 230 badBlockBytes := utils.MarshalOrPanic(badBlock) 231 res = stub.MockInvokeWithSignedProposal("2", [][]byte{[]byte("JoinChain"), badBlockBytes}, sProp) 232 assert.Equal(t, res.Status, int32(shim.ERROR)) 233 234 // Now, continue with valid execution path 235 if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK { 236 t.Fatalf("cscc invoke JoinChain failed with: %v", res.Message) 237 } 238 239 // This call must fail 240 sProp.Signature = nil 241 res = stub.MockInvokeWithSignedProposal("3", args, sProp) 242 if res.Status == shim.OK { 243 t.Fatalf("cscc invoke JoinChain must fail : %v", res.Message) 244 } 245 assert.True(t, strings.HasPrefix(res.Message, "\"JoinChain\" request failed authorization check for channel")) 246 sProp.Signature = sProp.ProposalBytes 247 248 // Query the configuration block 249 //chainID := []byte{143, 222, 22, 192, 73, 145, 76, 110, 167, 154, 118, 66, 132, 204, 113, 168} 250 chainID, err := utils.GetChainIDFromBlockBytes(blockBytes) 251 if err != nil { 252 t.Fatalf("cscc invoke JoinChain failed with: %v", err) 253 } 254 args = [][]byte{[]byte("GetConfigBlock"), []byte(chainID)} 255 policyManagerGetter.Managers["mytestchainid"].(*policymocks.MockChannelPolicyManager).MockPolicy.(*policymocks.MockPolicy).Deserializer.(*policymocks.MockIdentityDeserializer).Msg = sProp.ProposalBytes 256 if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK { 257 t.Fatalf("cscc invoke GetConfigBlock failed with: %v", res.Message) 258 } 259 260 // get channels for the peer 261 args = [][]byte{[]byte(GetChannels)} 262 res = stub.MockInvokeWithSignedProposal("2", args, sProp) 263 if res.Status != shim.OK { 264 t.FailNow() 265 } 266 267 cqr := &pb.ChannelQueryResponse{} 268 err = proto.Unmarshal(res.Payload, cqr) 269 if err != nil { 270 t.FailNow() 271 } 272 273 // peer joined one channel so query should return an array with one channel 274 if len(cqr.GetChannels()) != 1 { 275 t.FailNow() 276 } 277 } 278 279 func TestPeerConfiger_SubmittingOrdererGenesis(t *testing.T) { 280 viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/") 281 os.Mkdir("/tmp/hyperledgertest", 0755) 282 defer os.RemoveAll("/tmp/hyperledgertest/") 283 284 e := new(PeerConfiger) 285 stub := shim.NewMockStub("PeerConfiger", e) 286 287 if res := stub.MockInit("1", nil); res.Status != shim.OK { 288 fmt.Println("Init failed", string(res.Message)) 289 t.FailNow() 290 } 291 292 block, err := genesis.NewFactoryImpl(configtxtest.OrdererTemplate()).Block("testChainID") 293 assert.NoError(t, err) 294 blockBytes := utils.MarshalOrPanic(block) 295 296 // Failed path: wrong parameter type 297 args := [][]byte{[]byte("JoinChain"), []byte(blockBytes)} 298 if res := stub.MockInvoke("2", args); res.Status == shim.OK { 299 t.Fatalf("cscc invoke JoinChain should have failed with wrong genesis block. args: %v", args) 300 } else { 301 assert.Contains(t, res.Message, "missing Application configuration group") 302 } 303 304 } 305 306 func mockConfigBlock() []byte { 307 var blockBytes []byte = nil 308 block, err := configtxtest.MakeGenesisBlock("mytestchainid") 309 if err == nil { 310 blockBytes = utils.MarshalOrPanic(block) 311 } 312 return blockBytes 313 }