record_test.gno
6.41 Kb ยท 337 lines
1package datastore
2
3import (
4 "testing"
5
6 "gno.land/p/demo/uassert"
7 "gno.land/p/demo/urequire"
8)
9
10var (
11 _ Record = (*record)(nil)
12 _ Recordset = (*recordset)(nil)
13)
14
15func TestRecordDefaults(t *testing.T) {
16 // Arrange
17 storage := NewStorage("foo")
18
19 // Act
20 r := storage.NewRecord()
21
22 // Assert
23 uassert.Equal(t, uint64(0), r.ID())
24 uassert.Equal(t, "0000000", r.Key())
25 uassert.Equal(t, "Foo", r.Type())
26 uassert.Equal(t, nil, r.Fields())
27 uassert.True(t, r.IsEmpty())
28}
29
30func TestRecordHasField(t *testing.T) {
31 storage := NewStorage("foo")
32 storage.Schema().AddField("foo", nil)
33
34 r := storage.NewRecord()
35
36 uassert.True(t, r.HasField("foo"))
37 uassert.False(t, r.HasField("undefined"))
38}
39
40func TestRecordSet(t *testing.T) {
41 cases := []struct {
42 name string
43 options []SchemaOption
44 field string
45 fieldsCount int
46 value int
47 err error
48 }{
49 {
50 name: "first new field",
51 field: "test",
52 fieldsCount: 1,
53 value: 42,
54 },
55 {
56 name: "new extra field",
57 options: []SchemaOption{
58 WithField("foo"),
59 WithField("bar"),
60 },
61 field: "test",
62 fieldsCount: 3,
63 value: 42,
64 },
65 {
66 name: "existing field",
67 options: []SchemaOption{
68 WithField("test"),
69 },
70 field: "test",
71 fieldsCount: 1,
72 value: 42,
73 },
74 {
75 name: "undefined field",
76 options: []SchemaOption{Strict()},
77 field: "test",
78 fieldsCount: 1,
79 value: 42,
80 err: ErrUndefinedField,
81 },
82 }
83
84 for _, tc := range cases {
85 t.Run(tc.name, func(t *testing.T) {
86 // Arrange
87 s := NewSchema("Foo", tc.options...)
88 storage := NewStorage("foo", WithSchema(s))
89 r := storage.NewRecord()
90
91 // Act
92 err := r.Set(tc.field, tc.value)
93
94 // Assert
95 if tc.err != nil {
96 urequire.ErrorIs(t, err, tc.err)
97 return
98 }
99
100 urequire.NoError(t, err)
101 uassert.True(t, r.HasField("test"))
102 uassert.False(t, r.IsEmpty())
103 uassert.Equal(t, tc.fieldsCount, len(r.Fields()))
104 })
105 }
106}
107
108func TestRecordGet(t *testing.T) {
109 storage := NewStorage("foo")
110 r := storage.NewRecord()
111 r.Set("foo", "bar")
112 r.Set("test", 42)
113
114 v, found := r.Get("test")
115 urequire.True(t, found, "get setted value")
116
117 got, ok := v.(int)
118 urequire.True(t, ok, "setted value type")
119 uassert.Equal(t, 42, got)
120
121 _, found = r.Get("unknown")
122 uassert.False(t, found)
123}
124
125func TestRecordSave(t *testing.T) {
126 index := NewIndex("name", func(r Record) string {
127 return r.MustGet("name").(string)
128 }).Unique().CaseInsensitive()
129
130 storage := NewStorage("foo", WithIndex(index))
131 cases := []struct {
132 name string
133 id uint64
134 fieldValue, key string
135 storageSize int
136 setup func(Storage) Record
137 }{
138 {
139 name: "create first record",
140 id: 1,
141 key: "0000001",
142 fieldValue: "foo",
143 storageSize: 1,
144 setup: func(s Storage) Record { return s.NewRecord() },
145 },
146 {
147 name: "create second record",
148 id: 2,
149 key: "0000002",
150 fieldValue: "bar",
151 storageSize: 2,
152 setup: func(s Storage) Record { return s.NewRecord() },
153 },
154 {
155 name: "update second record",
156 id: 2,
157 key: "0000002",
158 fieldValue: "baz",
159 storageSize: 2,
160 setup: func(s Storage) Record {
161 r, _ := storage.Get(index.Name(), "bar")
162 return r
163 },
164 },
165 }
166
167 for _, tc := range cases {
168 t.Run(tc.name, func(t *testing.T) {
169 r := tc.setup(storage)
170 r.Set("name", tc.fieldValue)
171
172 _, found := storage.Get(index.Name(), tc.fieldValue)
173 urequire.False(t, found, "record not found")
174 urequire.True(t, r.Save(), "save success")
175 uassert.Equal(t, tc.storageSize, storage.Size())
176
177 r, found = storage.Get(index.Name(), tc.fieldValue)
178 urequire.True(t, found, "record found")
179 uassert.Equal(t, tc.id, r.ID())
180 uassert.Equal(t, tc.key, r.Key())
181 uassert.Equal(t, tc.fieldValue, r.MustGet("name"))
182 })
183 }
184}
185
186func TestRecordsetIterate(t *testing.T) {
187 cases := []struct {
188 name string
189 recordIDs []uint64
190 setup func(*Storage)
191 }{
192 {
193 name: "single record",
194 recordIDs: []uint64{1},
195 setup: func(s *Storage) {
196 s.NewRecord().Save()
197 },
198 },
199 {
200 name: "two records",
201 recordIDs: []uint64{1, 2},
202 setup: func(s *Storage) {
203 s.NewRecord().Save()
204 s.NewRecord().Save()
205 },
206 },
207 {
208 name: "empty recordset",
209 },
210 }
211
212 for _, tc := range cases {
213 t.Run(tc.name, func(t *testing.T) {
214 // Arrange
215 storage := NewStorage("foo")
216 if tc.setup != nil {
217 tc.setup(&storage)
218 }
219
220 var (
221 records []Record
222 rs = storage.MustQuery()
223 )
224
225 // Act
226 rs.Iterate(func(r Record) bool {
227 records = append(records, r)
228 return false
229 })
230
231 // Assert
232 urequire.Equal(t, len(tc.recordIDs), len(records), "results count")
233 for i, r := range records {
234 uassert.Equal(t, tc.recordIDs[i], r.ID())
235 }
236 })
237 }
238}
239
240func TestRecordsetReverseIterate(t *testing.T) {
241 cases := []struct {
242 name string
243 recordIDs []uint64
244 setup func(*Storage)
245 }{
246 {
247 name: "single record",
248 recordIDs: []uint64{1},
249 setup: func(s *Storage) {
250 s.NewRecord().Save()
251 },
252 },
253 {
254 name: "two records",
255 recordIDs: []uint64{2, 1},
256 setup: func(s *Storage) {
257 s.NewRecord().Save()
258 s.NewRecord().Save()
259 },
260 },
261 {
262 name: "empty recordser",
263 },
264 }
265
266 for _, tc := range cases {
267 t.Run(tc.name, func(t *testing.T) {
268 // Arrange
269 storage := NewStorage("foo")
270 if tc.setup != nil {
271 tc.setup(&storage)
272 }
273
274 var (
275 records []Record
276 rs = storage.MustQuery()
277 )
278
279 // Act
280 rs.ReverseIterate(func(r Record) bool {
281 records = append(records, r)
282 return false
283 })
284
285 // Assert
286 urequire.Equal(t, len(tc.recordIDs), len(records), "results count")
287 for i, r := range records {
288 uassert.Equal(t, tc.recordIDs[i], r.ID())
289 }
290 })
291 }
292}
293
294func TestRecordsetSize(t *testing.T) {
295 cases := []struct {
296 name string
297 size int
298 setup func(*Storage)
299 }{
300 {
301 name: "single record",
302 size: 1,
303 setup: func(s *Storage) {
304 s.NewRecord().Save()
305 },
306 },
307 {
308 name: "two records",
309 size: 2,
310 setup: func(s *Storage) {
311 s.NewRecord().Save()
312 s.NewRecord().Save()
313 },
314 },
315 {
316 name: "empty recordser",
317 },
318 }
319
320 for _, tc := range cases {
321 t.Run(tc.name, func(t *testing.T) {
322 // Arrange
323 storage := NewStorage("foo")
324 if tc.setup != nil {
325 tc.setup(&storage)
326 }
327
328 rs := storage.MustQuery()
329
330 // Act
331 size := rs.Size()
332
333 // Assert
334 uassert.Equal(t, tc.size, size)
335 })
336 }
337}