Skip to content

Commit b5ced55

Browse files
committed
[FAB-9691] Extract PendingQueryResult
Extract and explicitly unit test this object. Change-Id: I2585b2582ab5bfbd6a6f6c5791323e7de05835be Signed-off-by: Matthew Sykes <sykesmat@us.ibm.com>
1 parent aa2cc94 commit b5ced55

6 files changed

+101
-34
lines changed

core/chaincode/handler.go

+7-30
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,12 @@ type TransactionContext struct {
4949

5050
// tracks open iterators used for range queries
5151
queryIteratorMap map[string]commonledger.ResultsIterator
52-
pendingQueryResults map[string]*pendingQueryResult
52+
pendingQueryResults map[string]*PendingQueryResult
5353

5454
txsimulator ledger.TxSimulator
5555
historyQueryExecutor ledger.HistoryQueryExecutor
5656
}
5757

58-
type pendingQueryResult struct {
59-
batch []*pb.QueryResultBytes
60-
count int
61-
}
62-
6358
type stateHandlers map[pb.ChaincodeMessage_Type]func(*pb.ChaincodeMessage)
6459

6560
// internal interface to scope dependencies on ChaincodeSupport
@@ -206,7 +201,7 @@ func (h *Handler) initializeQueryContext(txContext *TransactionContext, queryID
206201
h.Lock()
207202
defer h.Unlock()
208203
txContext.queryIteratorMap[queryID] = queryIterator
209-
txContext.pendingQueryResults[queryID] = &pendingQueryResult{batch: make([]*pb.QueryResultBytes, 0)}
204+
txContext.pendingQueryResults[queryID] = &PendingQueryResult{batch: make([]*pb.QueryResultBytes, 0)}
210205
}
211206

212207
func (h *Handler) getQueryIterator(txContext *TransactionContext, queryID string) commonledger.ResultsIterator {
@@ -668,44 +663,26 @@ func getQueryResponse(h *Handler, txContext *TransactionContext, iter commonledg
668663
return nil, err
669664
case queryResult == nil:
670665
// nil response from iterator indicates end of query results
671-
batch := pendingQueryResults.cut()
666+
batch := pendingQueryResults.Cut()
672667
h.cleanupQueryContext(txContext, iterID)
673668
return &pb.QueryResponse{Results: batch, HasMore: false, Id: iterID}, nil
674-
case pendingQueryResults.count == maxResultLimit:
669+
case pendingQueryResults.Size() == maxResultLimit:
675670
// max number of results queued up, cut batch, then add current result to pending batch
676-
batch := pendingQueryResults.cut()
677-
if err := pendingQueryResults.add(queryResult); err != nil {
671+
batch := pendingQueryResults.Cut()
672+
if err := pendingQueryResults.Add(queryResult); err != nil {
678673
h.cleanupQueryContext(txContext, iterID)
679674
return nil, err
680675
}
681676
return &pb.QueryResponse{Results: batch, HasMore: true, Id: iterID}, nil
682677
default:
683-
if err := pendingQueryResults.add(queryResult); err != nil {
678+
if err := pendingQueryResults.Add(queryResult); err != nil {
684679
h.cleanupQueryContext(txContext, iterID)
685680
return nil, err
686681
}
687682
}
688683
}
689684
}
690685

691-
func (p *pendingQueryResult) cut() []*pb.QueryResultBytes {
692-
batch := p.batch
693-
p.batch = nil
694-
p.count = 0
695-
return batch
696-
}
697-
698-
func (p *pendingQueryResult) add(queryResult commonledger.QueryResult) error {
699-
queryResultBytes, err := proto.Marshal(queryResult.(proto.Message))
700-
if err != nil {
701-
chaincodeLogger.Errorf("Failed to get encode query result as bytes")
702-
return err
703-
}
704-
p.batch = append(p.batch, &pb.QueryResultBytes{ResultBytes: queryResultBytes})
705-
p.count = len(p.batch)
706-
return nil
707-
}
708-
709686
// Handles query to ledger for query state next
710687
func (h *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) {
711688
go func() {

core/chaincode/handler_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func TestGetQueryResponse(t *testing.T) {
5151
handler := &Handler{}
5252
TransactionContext := &TransactionContext{
5353
queryIteratorMap: make(map[string]ledger.ResultsIterator),
54-
pendingQueryResults: make(map[string]*pendingQueryResult),
54+
pendingQueryResults: make(map[string]*PendingQueryResult),
5555
}
5656
queryID := "test"
5757
t.Run(fmt.Sprintf("%d", tc.expectedResultCount), func(t *testing.T) {
@@ -65,7 +65,6 @@ func TestGetQueryResponse(t *testing.T) {
6565
totalResultCount := 0
6666
for hasMoreCount := 0; hasMoreCount <= tc.expectedHasMoreCount; hasMoreCount++ {
6767
queryResponse, _ := getQueryResponse(handler, TransactionContext, resultsIterator, queryID)
68-
assert.NotNil(t, queryResponse.GetResults())
6968
if queryResponse.GetHasMore() {
7069
t.Logf("Got %d results and more are expected.", len(queryResponse.GetResults()))
7170
} else {
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package chaincode
8+
9+
import (
10+
"github.com/golang/protobuf/proto"
11+
commonledger "github.com/hyperledger/fabric/common/ledger"
12+
pb "github.com/hyperledger/fabric/protos/peer"
13+
)
14+
15+
type PendingQueryResult struct {
16+
batch []*pb.QueryResultBytes
17+
}
18+
19+
func (p *PendingQueryResult) Cut() []*pb.QueryResultBytes {
20+
batch := p.batch
21+
p.batch = nil
22+
return batch
23+
}
24+
25+
func (p *PendingQueryResult) Add(queryResult commonledger.QueryResult) error {
26+
queryResultBytes, err := proto.Marshal(queryResult.(proto.Message))
27+
if err != nil {
28+
chaincodeLogger.Errorf("failed to marshal query result: %s", err)
29+
return err
30+
}
31+
p.batch = append(p.batch, &pb.QueryResultBytes{ResultBytes: queryResultBytes})
32+
return nil
33+
}
34+
35+
func (p *PendingQueryResult) Size() int {
36+
return len(p.batch)
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package chaincode_test
8+
9+
import (
10+
"fmt"
11+
"testing"
12+
13+
"github.com/golang/protobuf/proto"
14+
"github.com/hyperledger/fabric/core/chaincode"
15+
"github.com/hyperledger/fabric/protos/ledger/queryresult"
16+
"github.com/pkg/errors"
17+
"github.com/stretchr/testify/assert"
18+
)
19+
20+
func TestPendingQueryResult(t *testing.T) {
21+
pqr := chaincode.PendingQueryResult{}
22+
assert.Equal(t, 0, pqr.Size())
23+
assert.Nil(t, pqr.Cut())
24+
25+
for i := 1; i <= 5; i++ {
26+
kv := &queryresult.KV{Key: fmt.Sprintf("key-%d", i)}
27+
err := pqr.Add(kv)
28+
assert.NoError(t, err)
29+
assert.Equal(t, i, pqr.Size())
30+
}
31+
32+
results := pqr.Cut()
33+
assert.Len(t, results, 5)
34+
assert.Equal(t, 0, pqr.Size())
35+
for i, bytes := range results {
36+
var kv queryresult.KV
37+
err := proto.Unmarshal(bytes.ResultBytes, &kv)
38+
assert.NoError(t, err)
39+
assert.Equal(t, kv.Key, fmt.Sprintf("key-%d", i+1))
40+
}
41+
}
42+
43+
func TestPendingQueryResultBadQueryResult(t *testing.T) {
44+
pqr := chaincode.PendingQueryResult{}
45+
err := pqr.Add(brokenProto{})
46+
assert.EqualError(t, err, "marshal-failed")
47+
}
48+
49+
type brokenProto struct{}
50+
51+
func (brokenProto) Reset() {}
52+
func (brokenProto) String() string { return "" }
53+
func (brokenProto) ProtoMessage() {}
54+
func (brokenProto) Marshal() ([]byte, error) { return nil, errors.New("marshal-failed") }

core/chaincode/transaction_contexts.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (c *TransactionContexts) Create(ctx context.Context, chainID, txID string,
5252
proposal: prop,
5353
responseNotifier: make(chan *pb.ChaincodeMessage, 1),
5454
queryIteratorMap: map[string]commonledger.ResultsIterator{},
55-
pendingQueryResults: map[string]*pendingQueryResult{},
55+
pendingQueryResults: map[string]*PendingQueryResult{},
5656
txsimulator: getTxSimulator(ctx),
5757
historyQueryExecutor: getHistoryQueryExecutor(ctx),
5858
}

core/chaincode/transaction_contexts_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ var _ = Describe("TransactionContexts", func() {
5353
Expect(txContext.responseNotifier).NotTo(BeNil())
5454
Expect(txContext.responseNotifier).NotTo(BeClosed())
5555
Expect(txContext.queryIteratorMap).To(Equal(map[string]commonledger.ResultsIterator{}))
56-
Expect(txContext.pendingQueryResults).To(Equal(map[string]*pendingQueryResult{}))
56+
Expect(txContext.pendingQueryResults).To(Equal(map[string]*PendingQueryResult{}))
5757
Expect(txContext.txsimulator).To(Equal(fakeTxSimulator))
5858
Expect(txContext.historyQueryExecutor).To(Equal(fakeHistoryQueryExecutor))
5959
})

0 commit comments

Comments
 (0)