github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/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) 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  	service.InitGossipServiceCustomDeliveryFactory(identity, peerEndpoint, nil, &mockDeliveryClientFactory{}, messageCryptoService, secAdv, nil)
   204  
   205  	// Successful path for JoinChain
   206  	blockBytes := mockConfigBlock()
   207  	if blockBytes == nil {
   208  		t.Fatalf("cscc invoke JoinChain failed because invalid block")
   209  	}
   210  	args := [][]byte{[]byte("JoinChain"), blockBytes}
   211  	sProp, _ := utils.MockSignedEndorserProposalOrPanic("", &pb.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
   212  	identityDeserializer.Msg = sProp.ProposalBytes
   213  	sProp.Signature = sProp.ProposalBytes
   214  
   215  	// Try fail path with nil block
   216  	res := stub.MockInvokeWithSignedProposal("2", [][]byte{[]byte("JoinChain"), nil}, sProp)
   217  	assert.Equal(t, res.Status, int32(shim.ERROR))
   218  
   219  	// Try fail path with block and nil payload header
   220  	payload, _ := proto.Marshal(&cb.Payload{})
   221  	env, _ := proto.Marshal(&cb.Envelope{
   222  		Payload: payload,
   223  	})
   224  	badBlock := &cb.Block{
   225  		Data: &cb.BlockData{
   226  			Data: [][]byte{env},
   227  		},
   228  	}
   229  	badBlockBytes := utils.MarshalOrPanic(badBlock)
   230  	res = stub.MockInvokeWithSignedProposal("2", [][]byte{[]byte("JoinChain"), badBlockBytes}, sProp)
   231  	assert.Equal(t, res.Status, int32(shim.ERROR))
   232  
   233  	// Now, continue with valid execution path
   234  	if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK {
   235  		t.Fatalf("cscc invoke JoinChain failed with: %v", res.Message)
   236  	}
   237  
   238  	// This call must fail
   239  	sProp.Signature = nil
   240  	res = stub.MockInvokeWithSignedProposal("3", args, sProp)
   241  	if res.Status == shim.OK {
   242  		t.Fatalf("cscc invoke JoinChain must fail : %v", res.Message)
   243  	}
   244  	assert.True(t, strings.HasPrefix(res.Message, "\"JoinChain\" request failed authorization check for channel"))
   245  	sProp.Signature = sProp.ProposalBytes
   246  
   247  	// Query the configuration block
   248  	//chainID := []byte{143, 222, 22, 192, 73, 145, 76, 110, 167, 154, 118, 66, 132, 204, 113, 168}
   249  	chainID, err := utils.GetChainIDFromBlockBytes(blockBytes)
   250  	if err != nil {
   251  		t.Fatalf("cscc invoke JoinChain failed with: %v", err)
   252  	}
   253  	args = [][]byte{[]byte("GetConfigBlock"), []byte(chainID)}
   254  	policyManagerGetter.Managers["mytestchainid"].(*policymocks.MockChannelPolicyManager).MockPolicy.(*policymocks.MockPolicy).Deserializer.(*policymocks.MockIdentityDeserializer).Msg = sProp.ProposalBytes
   255  	if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK {
   256  		t.Fatalf("cscc invoke GetConfigBlock failed with: %v", res.Message)
   257  	}
   258  
   259  	// get channels for the peer
   260  	args = [][]byte{[]byte(GetChannels)}
   261  	res = stub.MockInvokeWithSignedProposal("2", args, sProp)
   262  	if res.Status != shim.OK {
   263  		t.FailNow()
   264  	}
   265  
   266  	cqr := &pb.ChannelQueryResponse{}
   267  	err = proto.Unmarshal(res.Payload, cqr)
   268  	if err != nil {
   269  		t.FailNow()
   270  	}
   271  
   272  	// peer joined one channel so query should return an array with one channel
   273  	if len(cqr.GetChannels()) != 1 {
   274  		t.FailNow()
   275  	}
   276  }
   277  
   278  func TestPeerConfiger_SubmittingOrdererGenesis(t *testing.T) {
   279  	viper.Set("peer.fileSystemPath", "/tmp/hyperledgertest/")
   280  	os.Mkdir("/tmp/hyperledgertest", 0755)
   281  	defer os.RemoveAll("/tmp/hyperledgertest/")
   282  
   283  	e := new(PeerConfiger)
   284  	stub := shim.NewMockStub("PeerConfiger", e)
   285  
   286  	if res := stub.MockInit("1", nil); res.Status != shim.OK {
   287  		fmt.Println("Init failed", string(res.Message))
   288  		t.FailNow()
   289  	}
   290  
   291  	block, err := genesis.NewFactoryImpl(configtxtest.OrdererTemplate()).Block("testChainID")
   292  	assert.NoError(t, err)
   293  	blockBytes := utils.MarshalOrPanic(block)
   294  
   295  	// Failed path: wrong parameter type
   296  	args := [][]byte{[]byte("JoinChain"), []byte(blockBytes)}
   297  	if res := stub.MockInvoke("2", args); res.Status == shim.OK {
   298  		t.Fatalf("cscc invoke JoinChain should have failed with wrong genesis block.  args: %v", args)
   299  	} else {
   300  		assert.Contains(t, res.Message, "missing Application configuration group")
   301  	}
   302  
   303  }
   304  
   305  func mockConfigBlock() []byte {
   306  	var blockBytes []byte = nil
   307  	block, err := configtxtest.MakeGenesisBlock("mytestchainid")
   308  	if err == nil {
   309  		blockBytes = utils.MarshalOrPanic(block)
   310  	}
   311  	return blockBytes
   312  }