Skip to content

Commit 6860e67

Browse files
authored
State list serializer test (#32)
state list serializer test
1 parent 6b596ec commit 6860e67

File tree

11 files changed

+97
-59
lines changed

11 files changed

+97
-59
lines changed

.github/workflows/go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
- name: Set up Go
1212
uses: actions/setup-go@v1
1313
with:
14-
go-version: '1.16'
14+
go-version: '1.18'
1515

1616
- name: Check out code
1717
uses: actions/checkout@v2

.github/workflows/golangci-lint.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,23 @@ on:
44
tags:
55
- v*
66
branches:
7-
- master
87
- main
98
pull_request:
109
jobs:
1110
golangci:
1211
name: lint
1312
strategy:
1413
matrix:
15-
go-version: [ 1.17.x, 1.18.x ]
14+
go-version: [ 1.18.x ]
1615
os: [ ubuntu-latest ]
1716
runs-on: ${{ matrix.os }}
1817
steps:
1918
- uses: actions/checkout@v2
2019
- name: golangci-lint
21-
uses: golangci/golangci-lint-action@v2
20+
uses: golangci/golangci-lint-action@v3
2221
with:
2322
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
24-
version: v1.49
23+
version: v1.52
2524

2625
# Optional: working directory, useful for monorepos
2726
# working-directory: somedir

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/hyperledger-labs/cckit
22

3-
go 1.17
3+
go 1.18
44

55
require (
66
github.com/btcsuite/btcutil v1.0.2

go.sum

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,6 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
407407
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
408408
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
409409
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
410-
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
411410
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
412411
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 h1:J27LZFQBFoihqXoegpscI10HpjZ7B5WQLLKL2FZXQKw=
413412
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

serialize/serializer_test.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818

1919
func TestState(t *testing.T) {
2020
RegisterFailHandler(Fail)
21-
RunSpecs(t, "State suite")
21+
RunSpecs(t, "Serializer suite")
2222
}
2323

2424
var (
@@ -36,7 +36,6 @@ var (
3636
)
3737

3838
var _ = Describe(`Generic serializer`, func() {
39-
4039
serializer := serialize.DefaultSerializer
4140

4241
Context(`Bool`, func() {
@@ -104,7 +103,6 @@ var _ = Describe(`Generic serializer`, func() {
104103
})
105104

106105
Context(`Proto`, func() {
107-
108106
var serializedProto1 []byte
109107
It(`serialize`, func() {
110108
serializedProto1, err = serializer.ToBytesFrom(ProtoToSerialize)
@@ -125,10 +123,9 @@ var _ = Describe(`Generic serializer`, func() {
125123
})
126124

127125
var _ = Describe(`Prefer JSON serializer`, func() {
128-
129126
serializer := serialize.PreferJSONSerializer
130-
131127
var serializedProtoAsJSON []byte
128+
132129
It(`serialize (snake_case)`, func() {
133130
serializedProtoAsJSON, err = serializer.ToBytesFrom(ProtoToSerialize)
134131
Expect(err).NotTo(HaveOccurred())

state/mapping/mapping_test.go

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package mapping_test
22

33
import (
4+
"reflect"
45
"strconv"
56
"strings"
67
"testing"
78
"time"
89

9-
"github.com/golang/protobuf/proto"
1010
"github.com/golang/protobuf/ptypes"
1111
. "github.com/onsi/ginkgo"
1212
. "github.com/onsi/gomega"
13+
"google.golang.org/protobuf/proto"
1314

1415
identitytestdata "github.com/hyperledger-labs/cckit/identity/testdata"
1516
"github.com/hyperledger-labs/cckit/serialize"
@@ -27,16 +28,15 @@ func TestState(t *testing.T) {
2728
RunSpecs(t, "State suite")
2829
}
2930

30-
var (
31-
compositeIDCC, complexIDCC, sliceIDCC, indexesCC, configCC *testcc.MockStub
31+
var _ = Describe(`State mapping in chaincode with default serializer`, func() {
3232

33-
Owner = identitytestdata.Certificates[0].MustIdentity(`SOME_MSP`)
34-
)
35-
var _ = Describe(`State mapping in chaincode`, func() {
36-
37-
BeforeSuite(func() {
33+
var (
34+
compositeIDCC, complexIDCC, sliceIDCC, indexesCC, configCC *testcc.MockStub
35+
Owner = identitytestdata.Certificates[0].MustIdentity(`SOME_MSP`)
36+
)
3837

39-
compositeIDCC = testcc.NewMockStub(`proto`, testdata.NewCompositeIdCC())
38+
Describe(`init chaincodes`, func() {
39+
compositeIDCC = testcc.NewMockStub(`proto`, testdata.NewCompositeIdCC(serialize.DefaultSerializer))
4040
compositeIDCC.From(Owner).Init()
4141

4242
complexIDCC = testcc.NewMockStub(`complex_id`, testdata.NewComplexIdCC())
@@ -60,7 +60,8 @@ var _ = Describe(`State mapping in chaincode`, func() {
6060
It("Allow to get mapping data by namespace", func() {
6161
mapping, err := testdata.EntityWithCompositeIdStateMapping.GetByNamespace(testdata.EntityCompositeIdNamespace)
6262
Expect(err).NotTo(HaveOccurred())
63-
Expect(mapping.Schema()).To(BeEquivalentTo(&schema.EntityWithCompositeId{}))
63+
Expect(reflect.TypeOf(mapping.Schema()).String()).To(
64+
Equal(reflect.TypeOf(&schema.EntityWithCompositeId{}).String()))
6465

6566
key, err := mapping.PrimaryKey(&schema.EntityWithCompositeId{
6667
IdFirstPart: create1.IdFirstPart,
@@ -76,33 +77,33 @@ var _ = Describe(`State mapping in chaincode`, func() {
7677

7778
It("Allow to add data to chaincode state", func(done Done) {
7879
events, closer := compositeIDCC.EventSubscription()
79-
expectcc.ResponseOk(compositeIDCC.Invoke(`create`, create1))
80+
expectcc.ResponseOk(compositeIDCC.Invoke(testdata.CreateFunc, create1))
8081

8182
expectcc.EventStringerEqual(<-events,
8283
`CreateEntityWithCompositeId`, create1, compositeIDCC.Serializer)
8384

84-
expectcc.ResponseOk(compositeIDCC.Invoke(`create`, create2))
85-
expectcc.ResponseOk(compositeIDCC.Invoke(`create`, create3))
85+
expectcc.ResponseOk(compositeIDCC.Invoke(testdata.CreateFunc, create2))
86+
expectcc.ResponseOk(compositeIDCC.Invoke(testdata.CreateFunc, create3))
8687

8788
_ = closer()
8889
close(done)
8990
})
9091

9192
It("Disallow to insert entries with same primary key", func() {
92-
expectcc.ResponseError(compositeIDCC.Invoke(`create`, create1), state.ErrKeyAlreadyExists)
93+
expectcc.ResponseError(compositeIDCC.Invoke(testdata.CreateFunc, create1), state.ErrKeyAlreadyExists)
9394
})
9495

9596
It("Allow to get entry list", func() {
9697
// default serializer should serialize proto to / from binary representation
97-
entities := expectcc.PayloadIs(compositeIDCC.Query(`list`),
98+
entities := expectcc.PayloadIs(compositeIDCC.Query(testdata.ListFunc),
9899
&schema.EntityWithCompositeIdList{}, serialize.DefaultSerializer).(*schema.EntityWithCompositeIdList)
99100
Expect(len(entities.Items)).To(Equal(3))
100101
Expect(entities.Items[0].Name).To(Equal(create1.Name))
101102
Expect(entities.Items[0].Value).To(BeNumerically("==", create1.Value))
102103
})
103104

104105
It("Allow to get entry raw protobuf", func() {
105-
dataFromCC := compositeIDCC.Query(`get`,
106+
dataFromCC := compositeIDCC.Query(testdata.GetFunc,
106107
&schema.EntityCompositeId{
107108
IdFirstPart: create1.IdFirstPart,
108109
IdSecondPart: create1.IdSecondPart,
@@ -122,7 +123,7 @@ var _ = Describe(`State mapping in chaincode`, func() {
122123
})
123124

124125
It("Allow update data in chaincode state", func() {
125-
expectcc.ResponseOk(compositeIDCC.Invoke(`update`, &schema.UpdateEntityWithCompositeId{
126+
expectcc.ResponseOk(compositeIDCC.Invoke(testdata.UpdateFunc, &schema.UpdateEntityWithCompositeId{
126127
IdFirstPart: create1.IdFirstPart,
127128
IdSecondPart: create1.IdSecondPart,
128129
IdThirdPart: create1.IdThirdPart,
@@ -131,7 +132,7 @@ var _ = Describe(`State mapping in chaincode`, func() {
131132
}))
132133

133134
entityFromCC := expectcc.PayloadIs(
134-
compositeIDCC.Query(`get`, &schema.EntityCompositeId{
135+
compositeIDCC.Query(testdata.GetFunc, &schema.EntityCompositeId{
135136
IdFirstPart: create1.IdFirstPart,
136137
IdSecondPart: create1.IdSecondPart,
137138
IdThirdPart: create1.IdThirdPart,
@@ -150,22 +151,21 @@ var _ = Describe(`State mapping in chaincode`, func() {
150151
IdThirdPart: create1.IdThirdPart,
151152
}
152153

153-
expectcc.ResponseOk(compositeIDCC.Invoke(`delete`, toDelete))
154+
expectcc.ResponseOk(compositeIDCC.Invoke(testdata.DeleteFunc, toDelete))
154155
ee := expectcc.PayloadIs(
155-
compositeIDCC.Invoke(`list`),
156+
compositeIDCC.Invoke(testdata.ListFunc),
156157
&schema.EntityWithCompositeIdList{}, compositeIDCC.Serializer).(*schema.EntityWithCompositeIdList)
157158

158159
Expect(len(ee.Items)).To(Equal(2))
159-
expectcc.ResponseError(compositeIDCC.Invoke(`get`, toDelete), state.ErrKeyNotFound)
160+
expectcc.ResponseError(compositeIDCC.Invoke(testdata.GetFunc, toDelete), state.ErrKeyNotFound)
160161
})
161162

162163
It("Allow to insert entry once more time", func() {
163-
expectcc.ResponseOk(compositeIDCC.Invoke(`create`, create1))
164+
expectcc.ResponseOk(compositeIDCC.Invoke(testdata.CreateFunc, create1))
164165
})
165166
})
166167

167168
Describe(`Entity with complex id`, func() {
168-
169169
ent1 := testdata.CreateEntityWithComplextId[0]
170170

171171
It("Allow to add data to chaincode state", func() {
@@ -391,3 +391,30 @@ var _ = Describe(`State mapping in chaincode`, func() {
391391

392392
})
393393
})
394+
395+
var _ = Describe(`State mapping in chaincode with JSON serializer`, func() {
396+
397+
var (
398+
compositeIDCC *testcc.MockStub
399+
Owner = identitytestdata.Certificates[0].MustIdentity(`SOME_MSP`)
400+
)
401+
402+
Describe("init chaincode", func() {
403+
compositeIDCC = testcc.NewMockStub(`proto`, testdata.NewCompositeIdCC(serialize.PreferJSONSerializer))
404+
compositeIDCC.Serializer = serialize.PreferJSONSerializer // need to set for correct invoking
405+
compositeIDCC.From(Owner).Init()
406+
})
407+
408+
It("Allow to add data to chaincode state", func() {
409+
expectcc.ResponseOk(compositeIDCC.Invoke(testdata.CreateFunc, testdata.CreateEntityWithCompositeId[0]))
410+
})
411+
412+
It("Allow to get entry list", func() {
413+
res := compositeIDCC.Query(testdata.ListFunc)
414+
Expect(string(res.Payload)[0:1]).To(Equal(`{`)) // json serialized
415+
entities := expectcc.JSONPayloadIs(res, &schema.EntityWithCompositeIdList{}).(*schema.EntityWithCompositeIdList)
416+
Expect(len(entities.Items)).To(Equal(1))
417+
Expect(entities.Items[0].Name).To(Equal(testdata.CreateEntityWithCompositeId[0].Name))
418+
Expect(entities.Items[0].Value).To(BeNumerically("==", testdata.CreateEntityWithCompositeId[0].Value))
419+
})
420+
})

state/mapping/testdata/cc_composite_id.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"github.com/hyperledger-labs/cckit/extensions/owner"
66
"github.com/hyperledger-labs/cckit/router"
77
"github.com/hyperledger-labs/cckit/router/param/defparam"
8+
"github.com/hyperledger-labs/cckit/serialize"
89
"github.com/hyperledger-labs/cckit/state"
910
"github.com/hyperledger-labs/cckit/state/mapping"
1011
"github.com/hyperledger-labs/cckit/state/mapping/testdata/schema"
@@ -20,9 +21,8 @@ var (
2021
mapping.List(&schema.EntityWithCompositeIdList{}))
2122
)
2223

23-
func NewCompositeIdCC() *router.Chaincode {
24-
r := router.New("composite_id")
25-
24+
func NewCompositeIdCC(serializer serialize.Serializer) *router.Chaincode {
25+
r := router.New("composite_id", router.WithSerializer(serializer))
2626
r.Use(mapping.MapStates(EntityWithCompositeIdStateMapping))
2727

2828
r.Use(mapping.MapEvents(mapping.EventMappings{}.
@@ -33,11 +33,11 @@ func NewCompositeIdCC() *router.Chaincode {
3333
debug.AddHandlers(r, "debug", owner.Only)
3434

3535
r.
36-
Query("list", queryListComposite).
37-
Query("get", queryByIdComposite, defparam.Proto(&schema.EntityCompositeId{})).
38-
Invoke("create", invokeCreateComposite, defparam.Proto(&schema.CreateEntityWithCompositeId{})).
39-
Invoke("update", invokeUpdateComposite, defparam.Proto(&schema.UpdateEntityWithCompositeId{})).
40-
Invoke("delete", invokeDeleteComposite, defparam.Proto(&schema.EntityCompositeId{}))
36+
Query(ListFunc, queryListComposite).
37+
Query(GetFunc, queryByIdComposite, defparam.Proto(&schema.EntityCompositeId{})).
38+
Invoke(CreateFunc, invokeCreateComposite, defparam.Proto(&schema.CreateEntityWithCompositeId{})).
39+
Invoke(UpdateFunc, invokeUpdateComposite, defparam.Proto(&schema.UpdateEntityWithCompositeId{})).
40+
Invoke(DeleteFunc, invokeDeleteComposite, defparam.Proto(&schema.EntityCompositeId{}))
4141

4242
return router.NewChaincode(r)
4343
}

state/mapping/testdata/funcs.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package testdata
2+
3+
const (
4+
CreateFunc = `create`
5+
ListFunc = `list`
6+
GetFunc = `get`
7+
UpdateFunc = `update`
8+
DeleteFunc = `delete`
9+
)

state/state.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func (s *Impl) Exists(entry interface{}) (bool, error) {
218218
// List data from state using objectType prefix in composite key, trying to convert to target interface.
219219
// Keys - additional components of composite key
220220
func (s *Impl) List(namespace interface{}, target ...interface{}) (interface{}, error) {
221-
stateList, err := NewStateList(target...)
221+
stateList, err := NewList(target...)
222222
if err != nil {
223223
return nil, err
224224
}
@@ -267,7 +267,7 @@ func (s *Impl) normalizeAndTransformKey(namespace interface{}) (Key, Key, error)
267267
func (s *Impl) ListPaginated(
268268
namespace interface{}, pageSize int32, bookmark string, target ...interface{}) (
269269
interface{}, *pb.QueryResponseMetadata, error) {
270-
stateList, err := NewStateList(target...)
270+
stateList, err := NewList(target...)
271271
if err != nil {
272272
return nil, nil, err
273273
}
@@ -469,7 +469,7 @@ func (s *Impl) ExistsPrivate(collection string, entry interface{}) (bool, error)
469469
// If usePrivateDataIterator is true, used private state for iterate over objects
470470
// if false, used public state for iterate over keys and GetPrivateData for each key
471471
func (s *Impl) ListPrivate(collection string, usePrivateDataIterator bool, namespace interface{}, target ...interface{}) (interface{}, error) {
472-
stateList, err := NewStateList(target...)
472+
stateList, err := NewList(target...)
473473
if err != nil {
474474
return nil, err
475475
}

state/state_list.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@ import (
1313
)
1414

1515
type (
16-
StateList struct {
17-
itemTarget interface{}
18-
listTarget interface{}
19-
list []interface{}
16+
List struct {
17+
itemTarget interface{} // type of item
18+
listTarget interface{} // type of item list
19+
list []interface{} // actual lost
2020
}
2121
)
2222

23-
func NewStateList(config ...interface{}) (sl *StateList, err error) {
23+
// ListItemsField name of field with items in listTarget proto structure setting
24+
const ListItemsField = `Items`
25+
26+
func NewList(config ...interface{}) (*List, error) {
2427
var (
2528
itemTarget, listTarget interface{}
2629
)
@@ -31,10 +34,11 @@ func NewStateList(config ...interface{}) (sl *StateList, err error) {
3134
listTarget = config[1]
3235
}
3336

34-
return &StateList{itemTarget: itemTarget, listTarget: listTarget}, nil
37+
return &List{itemTarget: itemTarget, listTarget: listTarget}, nil
3538
}
3639

37-
func (sl *StateList) Fill(
40+
// Fill state list from iterator
41+
func (sl *List) Fill(
3842
iter shim.StateQueryIteratorInterface, fromBytesConverter serialize.FromBytesConverter) (list interface{}, err error) {
3943
for iter.HasNext() {
4044
kv, err := iter.Next()
@@ -50,13 +54,12 @@ func (sl *StateList) Fill(
5054
return sl.Get()
5155
}
5256

53-
func (sl *StateList) Get() (list interface{}, err error) {
54-
55-
// custom list proto.Message
57+
func (sl *List) Get() (list interface{}, err error) {
58+
// list type is proto.Message, with predefined Items field
5659
if _, isListProto := sl.listTarget.(proto.Message); isListProto {
57-
58-
customList := proto.Clone(sl.listTarget.(proto.Message))
60+
customList := proto.Clone(sl.listTarget.(proto.Message)) // create copy of list type proto message
5961
items := reflect.ValueOf(customList).Elem().FieldByName(`Items`)
62+
6063
for _, v := range sl.list {
6164
items.Set(reflect.Append(items, reflect.ValueOf(v)))
6265
}
@@ -79,6 +82,6 @@ func (sl *StateList) Get() (list interface{}, err error) {
7982
return sl.list, nil
8083
}
8184

82-
func (sl *StateList) AddElementToList(elem interface{}) {
85+
func (sl *List) AddElementToList(elem interface{}) {
8386
sl.list = append(sl.list, elem)
8487
}

0 commit comments

Comments
 (0)