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  }