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  }