Skip to content

Commit 58cde22

Browse files
authored
chore(pkg): add kvlist validator (#498)
Signed-off-by: Michele Meloni <[email protected]>
1 parent f36775d commit 58cde22

File tree

3 files changed

+111
-3
lines changed

3 files changed

+111
-3
lines changed

pkg/api/schema/kvlist.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
Copyright 2019-2020 vChain, Inc.
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+
17+
package schema
18+
19+
import (
20+
"encoding/base64"
21+
"errors"
22+
)
23+
24+
// Validate checks for duplicated keys values that are not supported at the moment.
25+
func (l KVList) Validate() error {
26+
if len(l.GetKVs()) == 0 {
27+
return errors.New("empty set")
28+
}
29+
m := make(map[string]struct{}, len(l.GetKVs()))
30+
for _, k := range l.GetKVs() {
31+
b64k := base64.StdEncoding.EncodeToString(k.Key)
32+
if _, ok := m[b64k]; ok {
33+
return errors.New("duplicate keys are not supported in single batch transaction")
34+
}
35+
m[b64k] = struct{}{}
36+
}
37+
return nil
38+
}

pkg/api/schema/kvlist_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
Copyright 2019-2020 vChain, Inc.
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+
17+
package schema
18+
19+
import (
20+
"github.com/stretchr/testify/assert"
21+
"testing"
22+
)
23+
24+
func TestKVList_Validate(t *testing.T) {
25+
kv := &KVList{
26+
KVs: []*KeyValue{
27+
{
28+
Key: []byte("key1"),
29+
Value: []byte("val1"),
30+
},
31+
{
32+
Key: []byte("key2"),
33+
Value: []byte("val2"),
34+
},
35+
{
36+
Key: []byte("key3"),
37+
Value: []byte("val3"),
38+
},
39+
},
40+
}
41+
err := kv.Validate()
42+
assert.NoError(t, err)
43+
}
44+
45+
func TestKVList_ValidateDuplicateKeys(t *testing.T) {
46+
kv := &KVList{
47+
KVs: []*KeyValue{
48+
{
49+
Key: []byte("key1"),
50+
Value: []byte("val1"),
51+
},
52+
{
53+
Key: []byte("key1"),
54+
Value: []byte("val2"),
55+
},
56+
{
57+
Key: []byte("key3"),
58+
Value: []byte("val3"),
59+
},
60+
},
61+
}
62+
err := kv.Validate()
63+
assert.Errorf(t, err, "duplicate keys are not supported in single batch transaction")
64+
}
65+
func TestKVList_ValidateEmptySet(t *testing.T) {
66+
kv := &KVList{
67+
KVs: []*KeyValue{},
68+
}
69+
err := kv.Validate()
70+
assert.Errorf(t, err, "empty set")
71+
}

pkg/store/store.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"bytes"
2121
"context"
2222
"crypto/sha256"
23-
"errors"
2423
"math"
2524
"sync"
2625

@@ -130,8 +129,8 @@ func (t *Store) CurrentRoot() (root *schema.Root, err error) {
130129

131130
// SetBatch adds many entries at once
132131
func (t *Store) SetBatch(list schema.KVList, options ...WriteOption) (index *schema.Index, err error) {
133-
if len(list.GetKVs()) == 0 {
134-
return nil, errors.New("Empty set")
132+
if err = list.Validate(); err != nil {
133+
return nil, err
135134
}
136135
opts := makeWriteOptions(options...)
137136
txn := t.db.NewTransactionAt(math.MaxUint64, true)

0 commit comments

Comments
 (0)