-
Notifications
You must be signed in to change notification settings - Fork 9
/
map_test.go
126 lines (106 loc) · 3.61 KB
/
map_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package collections
import (
"testing"
"cosmossdk.io/store"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestUpstreamIterAssertions(t *testing.T) {
// ugly but asserts upstream behavior
sk, ctx, _ := deps()
kv := ctx.KVStore(sk)
kv.Set([]byte("hi"), []byte{})
i := kv.Iterator(nil, nil)
err := i.Close()
require.NoError(t, err)
require.NoError(t, i.Close())
}
type MapImpl[K, V any] interface {
Delete(ctx sdk.Context, k K) error
Get(ctx sdk.Context, k K) (v V, err error)
GetOr(ctx sdk.Context, key K, def V) (v V)
GetStore(ctx sdk.Context) store.KVStore
Insert(ctx sdk.Context, k K, v V)
Iterate(ctx sdk.Context, rng Ranger[K]) Iterator[K, V]
}
func TestMap(t *testing.T) {
sk, ctx, _ := deps()
RunTestMap(t, ctx, NewMap[string, string](sk, 0, StringKeyEncoder, stringValue{}))
sk, ctx, _ = deps()
RunTestMap(t, ctx, NewMapTransient[string, string](sk, 1, StringKeyEncoder, stringValue{}))
}
func TestMapGetOrDefault(t *testing.T) {
sk, ctx, _ := deps()
RunTestMapGetOrDefault(t, ctx, NewMap[string, string](sk, 2, StringKeyEncoder, stringValue{}))
RunTestMapGetOrDefault(t, ctx, NewMapTransient[string, string](sk, 3, StringKeyEncoder, stringValue{}))
}
func TestMapIterate(t *testing.T) {
sk, ctx, _ := deps()
RunTestMapIterate(t, ctx, NewMap[string, string](sk, 0, StringKeyEncoder, stringValue{}))
RunTestMapIterate(t, ctx, NewMapTransient[string, string](sk, 1, StringKeyEncoder, stringValue{}))
}
func RunTestMap(t *testing.T, ctx sdk.Context, m MapImpl[string, string]) {
key := "id"
expected := "test"
// test insert and get
m.Insert(ctx, key, expected)
got, err := m.Get(ctx, key)
require.NoError(t, err)
require.Equal(t, expected, got)
// test delete and get error
err = m.Delete(ctx, key)
require.NoError(t, err)
_, err = m.Get(ctx, key)
require.ErrorIs(t, err, ErrNotFound)
require.ErrorContains(t, err, "test string") // assert value name is correctly reported
require.ErrorContains(t, err, "id") // assert key is correctly reported
// test delete errors not exist
err = m.Delete(ctx, key)
require.ErrorIs(t, err, ErrNotFound)
require.ErrorContains(t, err, "test string")
require.ErrorContains(t, err, "id") // assert key is correctly reported
}
func RunTestMapGetOrDefault(t *testing.T, ctx sdk.Context, m MapImpl[string, string]) {
assert.EqualValues(t, "default", m.GetOr(ctx, "foo", "default"))
m.Insert(ctx, "foo", "not-default")
assert.EqualValues(t, "not-default", m.GetOr(ctx, "foo", "default"))
}
func RunTestMapIterate(t *testing.T, ctx sdk.Context, m MapImpl[string, string]) {
kv := func(o string) KeyValue[string, string] {
return KeyValue[string, string]{
Key: o,
Value: o,
}
}
expectedObjs := []KeyValue[string, string]{
kv("a"), kv("aa"), kv("b"), kv("bb"),
}
m.Insert(ctx, "a", "a")
m.Insert(ctx, "aa", "aa")
m.Insert(ctx, "b", "b")
m.Insert(ctx, "bb", "bb")
// test iteration ascending
iter := m.Iterate(ctx, Range[string]{})
defer iter.Close()
for i, o := range iter.KeyValues() {
require.Equal(t, expectedObjs[i], o)
}
// test iteration descending
reverseIter := m.Iterate(ctx, Range[string]{}.Descending())
defer reverseIter.Close()
for i, o := range reverseIter.KeyValues() {
require.Equal(t, expectedObjs[len(expectedObjs)-1-i], o)
}
// test key iteration
keyIter := m.Iterate(ctx, Range[string]{})
defer keyIter.Close()
for i, o := range keyIter.Keys() {
require.Equal(t, expectedObjs[i].Key, o)
}
valIter := m.Iterate(ctx, Range[string]{})
defer valIter.Close()
for i, o := range valIter.Values() {
require.Equal(t, expectedObjs[i].Value, o)
}
}