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}