github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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/localmsp" 28 "github.com/hyperledger/fabric/common/policies" 29 "github.com/hyperledger/fabric/core/chaincode" 30 "github.com/hyperledger/fabric/core/chaincode/shim" 31 "github.com/hyperledger/fabric/core/deliverservice" 32 "github.com/hyperledger/fabric/core/deliverservice/blocksprovider" 33 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 34 "github.com/hyperledger/fabric/core/peer" 35 "github.com/hyperledger/fabric/core/policy" 36 "github.com/hyperledger/fabric/gossip/api" 37 "github.com/hyperledger/fabric/gossip/service" 38 "github.com/hyperledger/fabric/msp/mgmt" 39 "github.com/hyperledger/fabric/msp/mgmt/testtools" 40 "github.com/hyperledger/fabric/peer/gossip/mcs" 41 "github.com/hyperledger/fabric/protos/common" 42 pb "github.com/hyperledger/fabric/protos/peer" 43 "github.com/hyperledger/fabric/protos/utils" 44 "github.com/spf13/viper" 45 "github.com/stretchr/testify/assert" 46 ) 47 48 type mockDeliveryClient struct { 49 } 50 51 // StartDeliverForChannel dynamically starts delivery of new blocks from ordering service 52 // to channel peers. 53 func (ds *mockDeliveryClient) StartDeliverForChannel(chainID string, ledgerInfo blocksprovider.LedgerInfo) error { 54 return nil 55 } 56 57 // StopDeliverForChannel dynamically stops delivery of new blocks from ordering service 58 // to channel peers. 59 func (ds *mockDeliveryClient) StopDeliverForChannel(chainID string) error { 60 return nil 61 } 62 63 // Stop terminates delivery service and closes the connection 64 func (*mockDeliveryClient) Stop() { 65 66 } 67 68 type mockDeliveryClientFactory struct { 69 } 70 71 func (*mockDeliveryClientFactory) Service(g service.GossipService, endpoints []string, mcs api.MessageCryptoService) (deliverclient.DeliverService, error) { 72 return &mockDeliveryClient{}, nil 73 } 74 75 func TestMain(m *testing.M) { 76 msptesttools.LoadMSPSetupForTesting() 77 78 os.Exit(m.Run()) 79 } 80 81 func TestConfigerInit(t *testing.T) { 82 e := new(PeerConfiger) 83 stub := shim.NewMockStub("PeerConfiger", e) 84 85 if res := stub.MockInit("1", nil); res.Status != shim.OK { 86 fmt.Println("Init failed", string(res.Message)) 87 t.FailNow() 88 } 89 } 90 91 func TestConfigerInvokeJoinChainMissingParams(t *testing.T) { 92 viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/") 93 os.Mkdir("/tmp/hyperledgertest", 0755) 94 defer os.RemoveAll("/tmp/hyperledgertest/") 95 96 e := new(PeerConfiger) 97 stub := shim.NewMockStub("PeerConfiger", e) 98 99 if res := stub.MockInit("1", nil); res.Status != shim.OK { 100 fmt.Println("Init failed", string(res.Message)) 101 t.FailNow() 102 } 103 104 // Failed path: Not enough parameters 105 args := [][]byte{[]byte("JoinChain")} 106 if res := stub.MockInvoke("2", args); res.Status == shim.OK { 107 t.Fatalf("cscc invoke JoinChain should have failed with invalid number of args: %v", args) 108 } 109 } 110 111 func TestConfigerInvokeJoinChainWrongParams(t *testing.T) { 112 viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/") 113 os.Mkdir("/tmp/hyperledgertest", 0755) 114 defer os.RemoveAll("/tmp/hyperledgertest/") 115 116 e := new(PeerConfiger) 117 stub := shim.NewMockStub("PeerConfiger", e) 118 119 if res := stub.MockInit("1", nil); res.Status != shim.OK { 120 fmt.Println("Init failed", string(res.Message)) 121 t.FailNow() 122 } 123 124 // Failed path: wrong parameter type 125 args := [][]byte{[]byte("JoinChain"), []byte("action")} 126 if res := stub.MockInvoke("2", args); res.Status == shim.OK { 127 t.Fatalf("cscc invoke JoinChain should have failed with null genesis block. args: %v", args) 128 } 129 } 130 131 func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) { 132 viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/") 133 viper.Set("chaincode.executetimeout", "3000") 134 os.Mkdir("/tmp/hyperledgertest", 0755) 135 136 peer.MockInitialize() 137 ledgermgmt.InitializeTestEnv() 138 defer ledgermgmt.CleanupTestEnv() 139 defer os.RemoveAll("/tmp/hyperledgerest/") 140 141 e := new(PeerConfiger) 142 stub := shim.NewMockStub("PeerConfiger", e) 143 144 peerEndpoint := "localhost:13611" 145 getPeerEndpoint := func() (*pb.PeerEndpoint, error) { 146 return &pb.PeerEndpoint{Id: &pb.PeerID{Name: "cscctestpeer"}, Address: peerEndpoint}, nil 147 } 148 ccStartupTimeout := time.Duration(30000) * time.Millisecond 149 chaincode.NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout) 150 151 // Init the policy checker 152 policyManagerGetter := &policy.MockChannelPolicyManagerGetter{ 153 Managers: map[string]policies.Manager{ 154 "mytestchainid": &policy.MockChannelPolicyManager{MockPolicy: &policy.MockPolicy{Deserializer: &policy.MockIdentityDeserializer{[]byte("Alice"), []byte("msg1")}}}, 155 }, 156 } 157 158 identityDeserializer := &policy.MockIdentityDeserializer{[]byte("Alice"), []byte("msg1")} 159 160 e.policyChecker = policy.NewPolicyChecker( 161 policyManagerGetter, 162 identityDeserializer, 163 &policy.MockMSPPrincipalGetter{Principal: []byte("Alice")}, 164 ) 165 166 identity, _ := mgmt.GetLocalSigningIdentityOrPanic().Serialize() 167 messageCryptoService := mcs.New(&mcs.MockChannelPolicyManagerGetter{}, localmsp.NewSigner(), mgmt.NewDeserializersManager()) 168 service.InitGossipServiceCustomDeliveryFactory(identity, peerEndpoint, nil, &mockDeliveryClientFactory{}, messageCryptoService) 169 170 // Successful path for JoinChain 171 blockBytes := mockConfigBlock() 172 if blockBytes == nil { 173 t.Fatalf("cscc invoke JoinChain failed because invalid block") 174 } 175 args := [][]byte{[]byte("JoinChain"), blockBytes} 176 sProp, _ := utils.MockSignedEndorserProposalOrPanic("", &pb.ChaincodeSpec{}, []byte("Alice"), []byte("msg1")) 177 identityDeserializer.Msg = sProp.ProposalBytes 178 sProp.Signature = sProp.ProposalBytes 179 if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK { 180 t.Fatalf("cscc invoke JoinChain failed with: %v", res.Message) 181 } 182 183 // This call must fail 184 sProp.Signature = nil 185 res := stub.MockInvokeWithSignedProposal("3", args, sProp) 186 if res.Status == shim.OK { 187 t.Fatalf("cscc invoke JoinChain must fail : %v", res.Message) 188 } 189 assert.True(t, strings.HasPrefix(res.Message, "\"JoinChain\" request failed authorization check for channel")) 190 sProp.Signature = sProp.ProposalBytes 191 192 // Query the configuration block 193 //chainID := []byte{143, 222, 22, 192, 73, 145, 76, 110, 167, 154, 118, 66, 132, 204, 113, 168} 194 chainID, err := getChainID(blockBytes) 195 if err != nil { 196 t.Fatalf("cscc invoke JoinChain failed with: %v", err) 197 } 198 args = [][]byte{[]byte("GetConfigBlock"), []byte(chainID)} 199 policyManagerGetter.Managers["mytestchainid"].(*policy.MockChannelPolicyManager).MockPolicy.(*policy.MockPolicy).Deserializer.(*policy.MockIdentityDeserializer).Msg = sProp.ProposalBytes 200 if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK { 201 t.Fatalf("cscc invoke GetConfigBlock failed with: %v", res.Message) 202 } 203 204 // get channels for the peer 205 args = [][]byte{[]byte(GetChannels)} 206 res = stub.MockInvokeWithSignedProposal("2", args, sProp) 207 if res.Status != shim.OK { 208 t.FailNow() 209 } 210 211 cqr := &pb.ChannelQueryResponse{} 212 err = proto.Unmarshal(res.Payload, cqr) 213 if err != nil { 214 t.FailNow() 215 } 216 217 // peer joined one channel so query should return an array with one channel 218 if len(cqr.GetChannels()) != 1 { 219 t.FailNow() 220 } 221 } 222 223 func TestConfigerInvokeUpdateConfigBlock(t *testing.T) { 224 e := new(PeerConfiger) 225 stub := shim.NewMockStub("PeerConfiger", e) 226 227 // Init the policy checker 228 policyManagerGetter := &policy.MockChannelPolicyManagerGetter{ 229 Managers: map[string]policies.Manager{ 230 "mytestchainid": &policy.MockChannelPolicyManager{MockPolicy: &policy.MockPolicy{Deserializer: &policy.MockIdentityDeserializer{[]byte("Alice"), []byte("msg1")}}}, 231 }, 232 } 233 234 identityDeserializer := &policy.MockIdentityDeserializer{[]byte("Alice"), []byte("msg1")} 235 236 e.policyChecker = policy.NewPolicyChecker( 237 policyManagerGetter, 238 identityDeserializer, 239 &policy.MockMSPPrincipalGetter{Principal: []byte("Alice")}, 240 ) 241 242 sProp, _ := utils.MockSignedEndorserProposalOrPanic("", &pb.ChaincodeSpec{}, []byte("Alice"), []byte("msg1")) 243 identityDeserializer.Msg = sProp.ProposalBytes 244 sProp.Signature = sProp.ProposalBytes 245 policyManagerGetter.Managers["mytestchainid"].(*policy.MockChannelPolicyManager).MockPolicy.(*policy.MockPolicy).Deserializer.(*policy.MockIdentityDeserializer).Msg = sProp.ProposalBytes 246 247 // Failed path: Not enough parameters 248 args := [][]byte{[]byte("UpdateConfigBlock")} 249 if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status == shim.OK { 250 t.Fatalf("cscc invoke UpdateConfigBlock should have failed with invalid number of args: %v", args) 251 } 252 253 // Failed path: wrong parameter type 254 args = [][]byte{[]byte("UpdateConfigBlock"), []byte("action")} 255 if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status == shim.OK { 256 t.Fatalf("cscc invoke UpdateConfigBlock should have failed with null genesis block - args: %v", args) 257 } 258 259 // Successful path for UpdateConfigBlock 260 blockBytes := mockConfigBlock() 261 if blockBytes == nil { 262 t.Fatalf("cscc invoke UpdateConfigBlock failed because invalid block") 263 } 264 args = [][]byte{[]byte("UpdateConfigBlock"), blockBytes} 265 if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK { 266 t.Fatalf("cscc invoke UpdateConfigBlock failed with: %v", res.Message) 267 } 268 269 // Query the configuration block 270 //chainID := []byte{143, 222, 22, 192, 73, 145, 76, 110, 167, 154, 118, 66, 132, 204, 113, 168} 271 chainID, err := getChainID(blockBytes) 272 if err != nil { 273 t.Fatalf("cscc invoke UpdateConfigBlock failed with: %v", err) 274 } 275 args = [][]byte{[]byte("GetConfigBlock"), []byte(chainID)} 276 if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK { 277 t.Fatalf("cscc invoke GetConfigBlock failed with: %v", err) 278 } 279 280 } 281 282 func mockConfigBlock() []byte { 283 var blockBytes []byte 284 block, err := configtxtest.MakeGenesisBlock("mytestchainid") 285 if err != nil { 286 blockBytes = nil 287 } else { 288 blockBytes = utils.MarshalOrPanic(block) 289 } 290 return blockBytes 291 } 292 293 func getChainID(blockBytes []byte) (string, error) { 294 block := &common.Block{} 295 if err := proto.Unmarshal(blockBytes, block); err != nil { 296 return "", err 297 } 298 envelope := &common.Envelope{} 299 if err := proto.Unmarshal(block.Data.Data[0], envelope); err != nil { 300 return "", err 301 } 302 payload := &common.Payload{} 303 if err := proto.Unmarshal(envelope.Payload, payload); err != nil { 304 return "", err 305 } 306 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 307 if err != nil { 308 return "", err 309 } 310 fmt.Printf("Channel id: %v\n", chdr.ChannelId) 311 return chdr.ChannelId, nil 312 }