github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/scc/qscc/query_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 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 qscc
    17  
    18  import (
    19  	"fmt"
    20  	"os"
    21  	"strings"
    22  	"testing"
    23  
    24  	"github.com/hyperledger/fabric/common/ledger/testutil"
    25  	"github.com/hyperledger/fabric/common/policies"
    26  	"github.com/hyperledger/fabric/core/chaincode/shim"
    27  	"github.com/hyperledger/fabric/core/peer"
    28  	"github.com/hyperledger/fabric/core/policy"
    29  	policymocks "github.com/hyperledger/fabric/core/policy/mocks"
    30  	"github.com/hyperledger/fabric/protos/common"
    31  	peer2 "github.com/hyperledger/fabric/protos/peer"
    32  	"github.com/hyperledger/fabric/protos/utils"
    33  	"github.com/spf13/viper"
    34  	"github.com/stretchr/testify/assert"
    35  )
    36  
    37  func setupTestLedger(chainid string, path string) (*shim.MockStub, error) {
    38  	viper.Set("peer.fileSystemPath", path)
    39  	peer.MockInitialize()
    40  	peer.MockCreateChain(chainid)
    41  
    42  	lq := new(LedgerQuerier)
    43  	stub := shim.NewMockStub("LedgerQuerier", lq)
    44  	if res := stub.MockInit("1", nil); res.Status != shim.OK {
    45  		return nil, fmt.Errorf("Init failed for test ledger [%s] with message: %s", chainid, string(res.Message))
    46  	}
    47  	return stub, nil
    48  }
    49  
    50  func TestQueryGetChainInfo(t *testing.T) {
    51  	chainid := "mytestchainid1"
    52  	path := "/var/hyperledger/test1/"
    53  	stub, err := setupTestLedger(chainid, path)
    54  	defer os.RemoveAll(path)
    55  	if err != nil {
    56  		t.Fatalf(err.Error())
    57  	}
    58  
    59  	args := [][]byte{[]byte(GetChainInfo), []byte(chainid)}
    60  	res := stub.MockInvoke("1", args)
    61  	assert.Equal(t, int32(shim.OK), res.Status, "GetChainInfo failed with err: %s", res.Message)
    62  
    63  	args = [][]byte{[]byte(GetChainInfo)}
    64  	res = stub.MockInvoke("2", args)
    65  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo should have failed because no channel id was provided")
    66  
    67  	args = [][]byte{[]byte(GetChainInfo), []byte("fakechainid")}
    68  	res = stub.MockInvoke("3", args)
    69  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo should have failed because the channel id does not exist")
    70  }
    71  
    72  func TestQueryGetTransactionByID(t *testing.T) {
    73  	chainid := "mytestchainid2"
    74  	path := "/var/hyperledger/test2/"
    75  	stub, err := setupTestLedger(chainid, path)
    76  	defer os.RemoveAll(path)
    77  	if err != nil {
    78  		t.Fatalf(err.Error())
    79  	}
    80  
    81  	args := [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte("1")}
    82  	res := stub.MockInvoke("1", args)
    83  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetTransactionByID should have failed with invalid txid: 1")
    84  
    85  	args = [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte(nil)}
    86  	res = stub.MockInvoke("2", args)
    87  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetTransactionByID should have failed with invalid txid: nil")
    88  
    89  	// Test with wrong number of parameters
    90  	args = [][]byte{[]byte(GetTransactionByID), []byte(chainid)}
    91  	res = stub.MockInvoke("3", args)
    92  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetTransactionByID should have failed due to incorrect number of arguments")
    93  }
    94  
    95  func TestQueryGetBlockByNumber(t *testing.T) {
    96  	chainid := "mytestchainid3"
    97  	path := "/var/hyperledger/test3/"
    98  	stub, err := setupTestLedger(chainid, path)
    99  	defer os.RemoveAll(path)
   100  	if err != nil {
   101  		t.Fatalf(err.Error())
   102  	}
   103  
   104  	// block number 0 (genesis block) would already be present in the ledger
   105  	args := [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("0")}
   106  	res := stub.MockInvoke("1", args)
   107  	assert.Equal(t, int32(shim.OK), res.Status, "GetBlockByNumber should have succeeded for block number: 0")
   108  
   109  	// block number 1 should not be present in the ledger
   110  	args = [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("1")}
   111  	res = stub.MockInvoke("2", args)
   112  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByNumber should have failed with invalid number: 1")
   113  
   114  	// block number cannot be nil
   115  	args = [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte(nil)}
   116  	res = stub.MockInvoke("3", args)
   117  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByNumber should have failed with nil block number")
   118  }
   119  
   120  func TestQueryGetBlockByHash(t *testing.T) {
   121  	chainid := "mytestchainid4"
   122  	path := "/var/hyperledger/test4/"
   123  	stub, err := setupTestLedger(chainid, path)
   124  	defer os.RemoveAll(path)
   125  	if err != nil {
   126  		t.Fatalf(err.Error())
   127  	}
   128  
   129  	args := [][]byte{[]byte(GetBlockByHash), []byte(chainid), []byte("0")}
   130  	res := stub.MockInvoke("1", args)
   131  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByHash should have failed with invalid hash: 0")
   132  
   133  	args = [][]byte{[]byte(GetBlockByHash), []byte(chainid), []byte(nil)}
   134  	res = stub.MockInvoke("2", args)
   135  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByHash should have failed with nil hash")
   136  }
   137  
   138  func TestQueryGetBlockByTxID(t *testing.T) {
   139  	chainid := "mytestchainid5"
   140  	path := "/var/hyperledger/test5/"
   141  	stub, err := setupTestLedger(chainid, path)
   142  	defer os.RemoveAll(path)
   143  	if err != nil {
   144  		t.Fatalf(err.Error())
   145  	}
   146  
   147  	args := [][]byte{[]byte(GetBlockByTxID), []byte(chainid), []byte("")}
   148  	res := stub.MockInvoke("1", args)
   149  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByTxID should have failed with blank txId.")
   150  }
   151  
   152  func TestFailingAccessControl(t *testing.T) {
   153  	chainid := "mytestchainid6"
   154  	path := "/var/hyperledger/test6/"
   155  	_, err := setupTestLedger(chainid, path)
   156  	defer os.RemoveAll(path)
   157  	if err != nil {
   158  		t.Fatalf(err.Error())
   159  	}
   160  	e := new(LedgerQuerier)
   161  	// Init the policy checker to have a failure
   162  	policyManagerGetter := &policymocks.MockChannelPolicyManagerGetter{
   163  		Managers: map[string]policies.Manager{
   164  			chainid: &policymocks.MockChannelPolicyManager{MockPolicy: &policymocks.MockPolicy{Deserializer: &policymocks.MockIdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1")}}},
   165  		},
   166  	}
   167  	e.policyChecker = policy.NewPolicyChecker(
   168  		policyManagerGetter,
   169  		&policymocks.MockIdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1")},
   170  		&policymocks.MockMSPPrincipalGetter{Principal: []byte("Alice")},
   171  	)
   172  	stub := shim.NewMockStub("LedgerQuerier", e)
   173  
   174  	args := [][]byte{[]byte(GetChainInfo), []byte(chainid)}
   175  	sProp, _ := utils.MockSignedEndorserProposalOrPanic(chainid, &peer2.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
   176  	policyManagerGetter.Managers[chainid].(*policymocks.MockChannelPolicyManager).MockPolicy.(*policymocks.MockPolicy).Deserializer.(*policymocks.MockIdentityDeserializer).Msg = sProp.ProposalBytes
   177  	sProp.Signature = sProp.ProposalBytes
   178  	res := stub.MockInvokeWithSignedProposal("2", args, sProp)
   179  	assert.Equal(t, int32(shim.OK), res.Status, "GetChainInfo failed with err: %s", res.Message)
   180  
   181  	sProp, _ = utils.MockSignedEndorserProposalOrPanic(chainid, &peer2.ChaincodeSpec{}, []byte("Bob"), []byte("msg2"))
   182  	res = stub.MockInvokeWithSignedProposal("3", args, sProp)
   183  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo must fail: %s", res.Message)
   184  	assert.True(t, strings.HasPrefix(res.Message, "Authorization request failed"))
   185  }
   186  
   187  func TestQueryNonexistentFunction(t *testing.T) {
   188  	chainid := "mytestchainid7"
   189  	path := "/var/hyperledger/test7/"
   190  	stub, err := setupTestLedger(chainid, path)
   191  	defer os.RemoveAll(path)
   192  	if err != nil {
   193  		t.Fatalf(err.Error())
   194  	}
   195  
   196  	args := [][]byte{[]byte("GetBlocks"), []byte(chainid), []byte("arg1")}
   197  	res := stub.MockInvoke("1", args)
   198  	assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlocks should have failed because the function does not exist")
   199  }
   200  
   201  // TestQueryGeneratedBlock tests various queries for a newly generated block
   202  // that contains two transactions
   203  func TestQueryGeneratedBlock(t *testing.T) {
   204  	chainid := "mytestchainid8"
   205  	path := "/var/hyperledger/test8/"
   206  	stub, err := setupTestLedger(chainid, path)
   207  	defer os.RemoveAll(path)
   208  	if err != nil {
   209  		t.Fatalf(err.Error())
   210  	}
   211  
   212  	block1 := addBlockForTesting(t, chainid)
   213  
   214  	// block number 1 should now exist
   215  	args := [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("1")}
   216  	res := stub.MockInvoke("1", args)
   217  	assert.Equal(t, int32(shim.OK), res.Status, "GetBlockByNumber should have succeeded for block number 1")
   218  
   219  	// block number 1
   220  	args = [][]byte{[]byte(GetBlockByHash), []byte(chainid), []byte(block1.Header.Hash())}
   221  	res = stub.MockInvoke("2", args)
   222  	assert.Equal(t, int32(shim.OK), res.Status, "GetBlockByHash should have succeeded for block 1 hash")
   223  
   224  	// drill into the block to find the transaction ids it contains
   225  	for _, d := range block1.Data.Data {
   226  		ebytes := d
   227  		if ebytes != nil {
   228  			if env, err := utils.GetEnvelopeFromBlock(ebytes); err != nil {
   229  				t.Fatalf("error getting envelope from block: %s", err)
   230  			} else if env != nil {
   231  				payload, err := utils.GetPayload(env)
   232  				if err != nil {
   233  					t.Fatalf("error extracting payload from envelope: %s", err)
   234  				}
   235  				chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   236  				if err != nil {
   237  					t.Fatalf(err.Error())
   238  				}
   239  				if common.HeaderType(chdr.Type) == common.HeaderType_ENDORSER_TRANSACTION {
   240  					args = [][]byte{[]byte(GetBlockByTxID), []byte(chainid), []byte(chdr.TxId)}
   241  					res = stub.MockInvoke("3", args)
   242  					assert.Equal(t, int32(shim.OK), res.Status, "GetBlockByTxId should have succeeded for txid: %s", chdr.TxId)
   243  
   244  					args = [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte(chdr.TxId)}
   245  					res = stub.MockInvoke("4", args)
   246  					assert.Equal(t, int32(shim.OK), res.Status, "GetTransactionById should have succeeded for txid: %s", chdr.TxId)
   247  				}
   248  			}
   249  		}
   250  	}
   251  }
   252  
   253  func addBlockForTesting(t *testing.T, chainid string) *common.Block {
   254  	bg, _ := testutil.NewBlockGenerator(t, chainid, false)
   255  	ledger := peer.GetLedger(chainid)
   256  	defer ledger.Close()
   257  
   258  	simulator, _ := ledger.NewTxSimulator()
   259  	simulator.SetState("ns1", "key1", []byte("value1"))
   260  	simulator.SetState("ns1", "key2", []byte("value2"))
   261  	simulator.SetState("ns1", "key3", []byte("value3"))
   262  	simulator.Done()
   263  	simRes1, _ := simulator.GetTxSimulationResults()
   264  	simulator, _ = ledger.NewTxSimulator()
   265  	simulator.SetState("ns2", "key4", []byte("value4"))
   266  	simulator.SetState("ns2", "key5", []byte("value5"))
   267  	simulator.SetState("ns2", "key6", []byte("value6"))
   268  	simulator.Done()
   269  	simRes2, _ := simulator.GetTxSimulationResults()
   270  	block1 := bg.NextBlock([][]byte{simRes1, simRes2})
   271  	ledger.Commit(block1)
   272  
   273  	return block1
   274  }