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 }