Skip to content

Commit c64264b

Browse files
committed
[FAB-4057] Improve UT coverage for QSCC
This CR refactors the existing unit tests and adds new unit tests, improving the coverage from 62.5% to 88.7%. Change-Id: If2c110a6c5af7d4c8528b91ba3bb16717450e4e7 Signed-off-by: Will Lahti <[email protected]>
1 parent 52f1942 commit c64264b

File tree

2 files changed

+188
-126
lines changed

2 files changed

+188
-126
lines changed

core/scc/qscc/query.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"strconv"
2222

2323
"github.com/hyperledger/fabric/common/flogging"
24-
"github.com/op/go-logging"
2524

2625
"github.com/hyperledger/fabric/common/policies"
2726
"github.com/hyperledger/fabric/core/chaincode/shim"
@@ -93,9 +92,8 @@ func (e *LedgerQuerier) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
9392
if targetLedger == nil {
9493
return shim.Error(fmt.Sprintf("Invalid chain ID, %s", cid))
9594
}
96-
if qscclogger.IsEnabledFor(logging.DEBUG) {
97-
qscclogger.Debugf("Invoke function: %s on chain: %s", fname, cid)
98-
}
95+
96+
qscclogger.Debugf("Invoke function: %s on chain: %s", fname, cid)
9997

10098
// Handle ACL:
10199
// 1. get the signed proposal

core/scc/qscc/query_test.go

+186-122
Original file line numberDiff line numberDiff line change
@@ -24,188 +24,252 @@ import (
2424

2525
"strings"
2626

27+
"github.com/hyperledger/fabric/common/ledger/testutil"
2728
"github.com/hyperledger/fabric/common/policies"
2829
"github.com/hyperledger/fabric/core/chaincode/shim"
2930
"github.com/hyperledger/fabric/core/peer"
3031
"github.com/hyperledger/fabric/core/policy"
32+
"github.com/hyperledger/fabric/protos/common"
3133
peer2 "github.com/hyperledger/fabric/protos/peer"
3234
"github.com/hyperledger/fabric/protos/utils"
3335
"github.com/stretchr/testify/assert"
3436
)
3537

36-
func TestInit(t *testing.T) {
37-
viper.Set("peer.fileSystemPath", "/var/hyperledger/test1/")
38-
defer os.RemoveAll("/var/hyperledger/test1/")
38+
func setupTestLedger(chainid string, path string) (*shim.MockStub, error) {
39+
viper.Set("peer.fileSystemPath", path)
3940
peer.MockInitialize()
40-
peer.MockCreateChain("mytestchainid1")
41-
42-
e := new(LedgerQuerier)
43-
stub := shim.NewMockStub("LedgerQuerier", e)
41+
peer.MockCreateChain(chainid)
4442

43+
lq := new(LedgerQuerier)
44+
stub := shim.NewMockStub("LedgerQuerier", lq)
4545
if res := stub.MockInit("1", nil); res.Status != shim.OK {
46-
fmt.Println("Init failed", string(res.Message))
47-
t.FailNow()
46+
return nil, fmt.Errorf("Init failed for test ledger [%s] with message: %s", chainid, string(res.Message))
4847
}
48+
return stub, nil
4949
}
5050

5151
func TestQueryGetChainInfo(t *testing.T) {
52-
viper.Set("peer.fileSystemPath", "/var/hyperledger/test2/")
53-
defer os.RemoveAll("/var/hyperledger/test2/")
54-
peer.MockInitialize()
55-
peer.MockCreateChain("mytestchainid2")
52+
chainid := "mytestchainid1"
53+
path := "/var/hyperledger/test1/"
54+
stub, err := setupTestLedger(chainid, path)
55+
defer os.RemoveAll(path)
56+
if err != nil {
57+
t.Fatalf(err.Error())
58+
}
5659

57-
e := new(LedgerQuerier)
58-
stub := shim.NewMockStub("LedgerQuerier", e)
60+
args := [][]byte{[]byte(GetChainInfo), []byte(chainid)}
61+
res := stub.MockInvoke("1", args)
62+
assert.Equal(t, int32(shim.OK), res.Status, "GetChainInfo failed with err: %s", res.Message)
5963

60-
if res := stub.MockInit("1", nil); res.Status != shim.OK {
61-
fmt.Println("Init failed", string(res.Message))
62-
t.FailNow()
63-
}
64+
args = [][]byte{[]byte(GetChainInfo)}
65+
res = stub.MockInvoke("2", args)
66+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo should have failed because no channel id was provided")
6467

65-
args := [][]byte{[]byte(GetChainInfo), []byte("mytestchainid2")}
66-
if res := stub.MockInvoke("2", args); res.Status != shim.OK {
67-
t.Fatalf("qscc GetChainInfo failed with err: %s", res.Message)
68-
}
68+
args = [][]byte{[]byte(GetChainInfo), []byte("fakechainid")}
69+
res = stub.MockInvoke("3", args)
70+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo should have failed because the channel id does not exist")
6971
}
7072

7173
func TestQueryGetTransactionByID(t *testing.T) {
72-
viper.Set("peer.fileSystemPath", "/var/hyperledger/test3/")
73-
defer os.RemoveAll("/var/hyperledger/test3/")
74-
peer.MockInitialize()
75-
peer.MockCreateChain("mytestchainid3")
76-
77-
e := new(LedgerQuerier)
78-
stub := shim.NewMockStub("LedgerQuerier", e)
79-
80-
if res := stub.MockInit("1", nil); res.Status != shim.OK {
81-
fmt.Println("Init failed", string(res.Message))
82-
t.FailNow()
74+
chainid := "mytestchainid2"
75+
path := "/var/hyperledger/test2/"
76+
stub, err := setupTestLedger(chainid, path)
77+
defer os.RemoveAll(path)
78+
if err != nil {
79+
t.Fatalf(err.Error())
8380
}
8481

85-
args := [][]byte{[]byte(GetTransactionByID), []byte("mytestchainid3"), []byte("1")}
86-
if res := stub.MockInvoke("2", args); res.Status == shim.OK {
87-
t.Fatal("qscc getTransactionByID should have failed with invalid txid: 2")
88-
}
89-
}
90-
91-
func TestQueryWithWrongParameters(t *testing.T) {
92-
viper.Set("peer.fileSystemPath", "/var/hyperledger/test4/")
93-
defer os.RemoveAll("/var/hyperledger/test4/")
94-
peer.MockInitialize()
95-
peer.MockCreateChain("mytestchainid4")
96-
97-
e := new(LedgerQuerier)
98-
stub := shim.NewMockStub("LedgerQuerier", e)
82+
args := [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte("1")}
83+
res := stub.MockInvoke("1", args)
84+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetTransactionByID should have failed with invalid txid: 1")
9985

100-
if res := stub.MockInit("1", nil); res.Status != shim.OK {
101-
fmt.Println("Init failed", string(res.Message))
102-
t.FailNow()
103-
}
86+
args = [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte(nil)}
87+
res = stub.MockInvoke("2", args)
88+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetTransactionByID should have failed with invalid txid: nil")
10489

10590
// Test with wrong number of parameters
106-
args := [][]byte{[]byte(GetTransactionByID), []byte("mytestchainid4")}
107-
if res := stub.MockInvoke("2", args); res.Status == shim.OK {
108-
t.Fatal("qscc getTransactionByID should have failed with invalid txid: 2")
109-
}
91+
args = [][]byte{[]byte(GetTransactionByID), []byte(chainid)}
92+
res = stub.MockInvoke("3", args)
93+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetTransactionByID should have failed due to incorrect number of arguments")
11094
}
11195

11296
func TestQueryGetBlockByNumber(t *testing.T) {
113-
//t.Skip()
114-
viper.Set("peer.fileSystemPath", "/var/hyperledger/test5/")
115-
defer os.RemoveAll("/var/hyperledger/test5/")
116-
peer.MockInitialize()
117-
peer.MockCreateChain("mytestchainid5")
118-
119-
e := new(LedgerQuerier)
120-
stub := shim.NewMockStub("LedgerQuerier", e)
121-
122-
if res := stub.MockInit("1", nil); res.Status != shim.OK {
123-
fmt.Println("Init failed", string(res.Message))
124-
t.FailNow()
97+
chainid := "mytestchainid3"
98+
path := "/var/hyperledger/test3/"
99+
stub, err := setupTestLedger(chainid, path)
100+
defer os.RemoveAll(path)
101+
if err != nil {
102+
t.Fatalf(err.Error())
125103
}
104+
126105
// block number 0 (genesis block) would already be present in the ledger
127-
args := [][]byte{[]byte(GetBlockByNumber), []byte("mytestchainid5"), []byte("1")}
128-
if res := stub.MockInvoke("2", args); res.Status == shim.OK {
129-
t.Fatal("qscc GetBlockByNumber should have failed with invalid number: 1")
130-
}
106+
args := [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("0")}
107+
res := stub.MockInvoke("1", args)
108+
assert.Equal(t, int32(shim.OK), res.Status, "GetBlockByNumber should have succeeded for block number: 0")
109+
110+
// block number 1 should not be present in the ledger
111+
args = [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("1")}
112+
res = stub.MockInvoke("2", args)
113+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByNumber should have failed with invalid number: 1")
114+
115+
// block number cannot be nil
116+
args = [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte(nil)}
117+
res = stub.MockInvoke("3", args)
118+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByNumber should have failed with nil block number")
131119
}
132120

133121
func TestQueryGetBlockByHash(t *testing.T) {
134-
viper.Set("peer.fileSystemPath", "/var/hyperledger/test6/")
135-
defer os.RemoveAll("/var/hyperledger/test6/")
136-
peer.MockInitialize()
137-
peer.MockCreateChain("mytestchainid6")
138-
139-
e := new(LedgerQuerier)
140-
stub := shim.NewMockStub("LedgerQuerier", e)
141-
142-
if res := stub.MockInit("1", nil); res.Status != shim.OK {
143-
fmt.Println("Init failed", string(res.Message))
144-
t.FailNow()
122+
chainid := "mytestchainid4"
123+
path := "/var/hyperledger/test4/"
124+
stub, err := setupTestLedger(chainid, path)
125+
defer os.RemoveAll(path)
126+
if err != nil {
127+
t.Fatalf(err.Error())
145128
}
146129

147-
args := [][]byte{[]byte(GetBlockByHash), []byte("mytestchainid6"), []byte("0")}
148-
if res := stub.MockInvoke("2", args); res.Status == shim.OK {
149-
t.Fatal("qscc GetBlockByHash should have failed with invalid hash: 0")
150-
}
130+
args := [][]byte{[]byte(GetBlockByHash), []byte(chainid), []byte("0")}
131+
res := stub.MockInvoke("1", args)
132+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByHash should have failed with invalid hash: 0")
133+
134+
args = [][]byte{[]byte(GetBlockByHash), []byte(chainid), []byte(nil)}
135+
res = stub.MockInvoke("2", args)
136+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByHash should have failed with nil hash")
151137
}
152138

153139
func TestQueryGetBlockByTxID(t *testing.T) {
154-
viper.Set("peer.fileSystemPath", "/var/hyperledger/test8/")
155-
defer os.RemoveAll("/var/hyperledger/test8/")
156-
peer.MockInitialize()
157-
peer.MockCreateChain("mytestchainid8")
158-
159-
e := new(LedgerQuerier)
160-
stub := shim.NewMockStub("LedgerQuerier", e)
161-
162-
txID := ""
163-
164-
if res := stub.MockInit("1", nil); res.Status != shim.OK {
165-
fmt.Println("Init failed", string(res.Message))
166-
t.FailNow()
140+
chainid := "mytestchainid5"
141+
path := "/var/hyperledger/test5/"
142+
stub, err := setupTestLedger(chainid, path)
143+
defer os.RemoveAll(path)
144+
if err != nil {
145+
t.Fatalf(err.Error())
167146
}
168147

169-
args := [][]byte{[]byte(GetBlockByTxID), []byte("mytestchainid8"), []byte(txID)}
170-
if res := stub.MockInvoke("2", args); res.Status == shim.OK {
171-
t.Fatalf("qscc GetBlockByTxID should have failed with invalid txID: %s", txID)
172-
}
148+
args := [][]byte{[]byte(GetBlockByTxID), []byte(chainid), []byte("")}
149+
res := stub.MockInvoke("1", args)
150+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlockByTxID should have failed with blank txId.")
173151
}
174152

175153
func TestFailingAccessControl(t *testing.T) {
176-
viper.Set("peer.fileSystemPath", "/var/hyperledger/test9/")
177-
defer os.RemoveAll("/var/hyperledger/test9/")
178-
peer.MockInitialize()
179-
peer.MockCreateChain("mytestchainid9")
180-
154+
chainid := "mytestchainid6"
155+
path := "/var/hyperledger/test6/"
156+
_, err := setupTestLedger(chainid, path)
157+
defer os.RemoveAll(path)
158+
if err != nil {
159+
t.Fatalf(err.Error())
160+
}
181161
e := new(LedgerQuerier)
182162
// Init the policy checker to have a failure
183163
policyManagerGetter := &policy.MockChannelPolicyManagerGetter{
184164
Managers: map[string]policies.Manager{
185-
"mytestchainid9": &policy.MockChannelPolicyManager{MockPolicy: &policy.MockPolicy{Deserializer: &policy.MockIdentityDeserializer{[]byte("Alice"), []byte("msg1")}}},
165+
chainid: &policy.MockChannelPolicyManager{MockPolicy: &policy.MockPolicy{Deserializer: &policy.MockIdentityDeserializer{[]byte("Alice"), []byte("msg1")}}},
186166
},
187167
}
188-
189168
e.policyChecker = policy.NewPolicyChecker(
190169
policyManagerGetter,
191170
&policy.MockIdentityDeserializer{[]byte("Alice"), []byte("msg1")},
192171
&policy.MockMSPPrincipalGetter{Principal: []byte("Alice")},
193172
)
194-
195173
stub := shim.NewMockStub("LedgerQuerier", e)
196174

197-
args := [][]byte{[]byte(GetChainInfo), []byte("mytestchainid9")}
198-
sProp, _ := utils.MockSignedEndorserProposalOrPanic("mytestchainid9", &peer2.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
199-
policyManagerGetter.Managers["mytestchainid9"].(*policy.MockChannelPolicyManager).MockPolicy.(*policy.MockPolicy).Deserializer.(*policy.MockIdentityDeserializer).Msg = sProp.ProposalBytes
175+
args := [][]byte{[]byte(GetChainInfo), []byte(chainid)}
176+
sProp, _ := utils.MockSignedEndorserProposalOrPanic(chainid, &peer2.ChaincodeSpec{}, []byte("Alice"), []byte("msg1"))
177+
policyManagerGetter.Managers[chainid].(*policy.MockChannelPolicyManager).MockPolicy.(*policy.MockPolicy).Deserializer.(*policy.MockIdentityDeserializer).Msg = sProp.ProposalBytes
200178
sProp.Signature = sProp.ProposalBytes
201-
if res := stub.MockInvokeWithSignedProposal("2", args, sProp); res.Status != shim.OK {
202-
t.Fatalf("qscc GetChainInfo failed with err: %s", res.Message)
179+
res := stub.MockInvokeWithSignedProposal("2", args, sProp)
180+
assert.Equal(t, int32(shim.OK), res.Status, "GetChainInfo failed with err: %s", res.Message)
181+
182+
sProp, _ = utils.MockSignedEndorserProposalOrPanic(chainid, &peer2.ChaincodeSpec{}, []byte("Bob"), []byte("msg2"))
183+
res = stub.MockInvokeWithSignedProposal("3", args, sProp)
184+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetChainInfo must fail: %s", res.Message)
185+
assert.True(t, strings.HasPrefix(res.Message, "Authorization request failed"))
186+
}
187+
188+
func TestQueryNonexistentFunction(t *testing.T) {
189+
chainid := "mytestchainid7"
190+
path := "/var/hyperledger/test7/"
191+
stub, err := setupTestLedger(chainid, path)
192+
defer os.RemoveAll(path)
193+
if err != nil {
194+
t.Fatalf(err.Error())
203195
}
204196

205-
sProp, _ = utils.MockSignedEndorserProposalOrPanic("mytestchainid9", &peer2.ChaincodeSpec{}, []byte("Bob"), []byte("msg2"))
206-
res := stub.MockInvokeWithSignedProposal("3", args, sProp)
207-
if res.Status == shim.OK {
208-
t.Fatalf("qscc GetChainInfo must fail: %s", res.Message)
197+
args := [][]byte{[]byte("GetBlocks"), []byte(chainid), []byte("arg1")}
198+
res := stub.MockInvoke("1", args)
199+
assert.Equal(t, int32(shim.ERROR), res.Status, "GetBlocks should have failed because the function does not exist")
200+
}
201+
202+
// TestQueryGeneratedBlock tests various queries for a newly generated block
203+
// that contains two transactions
204+
func TestQueryGeneratedBlock(t *testing.T) {
205+
chainid := "mytestchainid8"
206+
path := "/var/hyperledger/test8/"
207+
stub, err := setupTestLedger(chainid, path)
208+
defer os.RemoveAll(path)
209+
if err != nil {
210+
t.Fatalf(err.Error())
209211
}
210-
assert.True(t, strings.HasPrefix(res.Message, "Authorization request failed"))
212+
213+
block1 := addBlockForTesting(t, chainid)
214+
215+
// block number 1 should now exist
216+
args := [][]byte{[]byte(GetBlockByNumber), []byte(chainid), []byte("1")}
217+
res := stub.MockInvoke("1", args)
218+
assert.Equal(t, int32(shim.OK), res.Status, "GetBlockByNumber should have succeeded for block number 1")
219+
220+
// block number 1
221+
args = [][]byte{[]byte(GetBlockByHash), []byte(chainid), []byte(block1.Header.Hash())}
222+
res = stub.MockInvoke("2", args)
223+
assert.Equal(t, int32(shim.OK), res.Status, "GetBlockByHash should have succeeded for block 1 hash")
224+
225+
// drill into the block to find the transaction ids it contains
226+
for _, d := range block1.Data.Data {
227+
ebytes := d
228+
if ebytes != nil {
229+
if env, err := utils.GetEnvelopeFromBlock(ebytes); err != nil {
230+
t.Fatalf("error getting envelope from block: %s", err)
231+
} else if env != nil {
232+
payload, err := utils.GetPayload(env)
233+
if err != nil {
234+
t.Fatalf("error extracting payload from envelope: %s", err)
235+
}
236+
chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
237+
if err != nil {
238+
t.Fatalf(err.Error())
239+
}
240+
if common.HeaderType(chdr.Type) == common.HeaderType_ENDORSER_TRANSACTION {
241+
args = [][]byte{[]byte(GetBlockByTxID), []byte(chainid), []byte(chdr.TxId)}
242+
res = stub.MockInvoke("3", args)
243+
assert.Equal(t, int32(shim.OK), res.Status, "GetBlockByTxId should have succeeded for txid: %s", chdr.TxId)
244+
245+
args = [][]byte{[]byte(GetTransactionByID), []byte(chainid), []byte(chdr.TxId)}
246+
res = stub.MockInvoke("4", args)
247+
assert.Equal(t, int32(shim.OK), res.Status, "GetTransactionById should have succeeded for txid: %s", chdr.TxId)
248+
}
249+
}
250+
}
251+
}
252+
}
253+
254+
func addBlockForTesting(t *testing.T, chainid string) *common.Block {
255+
bg, _ := testutil.NewBlockGenerator(t, chainid, false)
256+
ledger := peer.GetLedger(chainid)
257+
defer ledger.Close()
258+
259+
simulator, _ := ledger.NewTxSimulator()
260+
simulator.SetState("ns1", "key1", []byte("value1"))
261+
simulator.SetState("ns1", "key2", []byte("value2"))
262+
simulator.SetState("ns1", "key3", []byte("value3"))
263+
simulator.Done()
264+
simRes1, _ := simulator.GetTxSimulationResults()
265+
simulator, _ = ledger.NewTxSimulator()
266+
simulator.SetState("ns2", "key4", []byte("value4"))
267+
simulator.SetState("ns2", "key5", []byte("value5"))
268+
simulator.SetState("ns2", "key6", []byte("value6"))
269+
simulator.Done()
270+
simRes2, _ := simulator.GetTxSimulationResults()
271+
block1 := bg.NextBlock([][]byte{simRes1, simRes2})
272+
ledger.Commit(block1)
273+
274+
return block1
211275
}

0 commit comments

Comments
 (0)