feed_test.gno

5.92 Kb ยท 255 lines
  1package static_test
  2
  3import (
  4	"errors"
  5	"testing"
  6
  7	"gno.land/p/demo/gnorkle/feed"
  8	"gno.land/p/demo/gnorkle/feeds/static"
  9	"gno.land/p/demo/gnorkle/gnorkle"
 10	"gno.land/p/demo/gnorkle/ingester"
 11	"gno.land/p/demo/gnorkle/message"
 12	"gno.land/p/demo/gnorkle/storage/simple"
 13	"gno.land/p/demo/uassert"
 14	"gno.land/p/demo/urequire"
 15)
 16
 17type mockIngester struct {
 18	canAutoCommit   bool
 19	ingestErr       error
 20	commitErr       error
 21	value           string
 22	providerAddress string
 23}
 24
 25func (i mockIngester) Type() ingester.Type {
 26	return ingester.Type(0)
 27}
 28
 29func (i *mockIngester) Ingest(value, providerAddress string) (bool, error) {
 30	if i.ingestErr != nil {
 31		return false, i.ingestErr
 32	}
 33
 34	i.value = value
 35	i.providerAddress = providerAddress
 36	return i.canAutoCommit, nil
 37}
 38
 39func (i *mockIngester) CommitValue(storage gnorkle.Storage, providerAddress string) error {
 40	if i.commitErr != nil {
 41		return i.commitErr
 42	}
 43
 44	return storage.Put(i.value)
 45}
 46
 47func TestNewSingleValueFeed(t *testing.T) {
 48	staticFeed := static.NewSingleValueFeed("1", "")
 49
 50	uassert.Equal(t, "1", staticFeed.ID())
 51	uassert.Equal(t, int(feed.TypeStatic), int(staticFeed.Type()))
 52}
 53
 54func TestFeed_Ingest(t *testing.T) {
 55	var undefinedFeed *static.Feed
 56	err := undefinedFeed.Ingest("", "", "")
 57	uassert.ErrorIs(t, err, feed.ErrUndefined)
 58
 59	tests := []struct {
 60		name               string
 61		ingester           *mockIngester
 62		verifyIsLocked     bool
 63		doCommit           bool
 64		funcType           message.FuncType
 65		msg                string
 66		providerAddress    string
 67		expFeedValueString string
 68		expErrText         string
 69		expIsActive        bool
 70	}{
 71		{
 72			name:        "func invalid error",
 73			ingester:    &mockIngester{},
 74			funcType:    message.FuncType("derp"),
 75			expErrText:  "invalid message function derp",
 76			expIsActive: true,
 77		},
 78		{
 79			name: "func ingest ingest error",
 80			ingester: &mockIngester{
 81				ingestErr: errors.New("ingest error"),
 82			},
 83			funcType:    message.FuncTypeIngest,
 84			expErrText:  "ingest error",
 85			expIsActive: true,
 86		},
 87		{
 88			name: "func ingest commit error",
 89			ingester: &mockIngester{
 90				commitErr:     errors.New("commit error"),
 91				canAutoCommit: true,
 92			},
 93			funcType:    message.FuncTypeIngest,
 94			expErrText:  "commit error",
 95			expIsActive: true,
 96		},
 97		{
 98			name: "func commit commit error",
 99			ingester: &mockIngester{
100				commitErr:     errors.New("commit error"),
101				canAutoCommit: true,
102			},
103			funcType:    message.FuncTypeCommit,
104			expErrText:  "commit error",
105			expIsActive: true,
106		},
107		{
108			name:            "only ingest",
109			ingester:        &mockIngester{},
110			funcType:        message.FuncTypeIngest,
111			msg:             "still active feed",
112			providerAddress: "gno1234",
113			expIsActive:     true,
114		},
115		{
116			name:               "ingest autocommit",
117			ingester:           &mockIngester{canAutoCommit: true},
118			funcType:           message.FuncTypeIngest,
119			msg:                "still active feed",
120			providerAddress:    "gno1234",
121			expFeedValueString: "still active feed",
122			verifyIsLocked:     true,
123		},
124		{
125			name:           "commit no value",
126			ingester:       &mockIngester{},
127			funcType:       message.FuncTypeCommit,
128			msg:            "shouldn't be stored",
129			verifyIsLocked: true,
130		},
131		{
132			name:               "ingest then commmit",
133			ingester:           &mockIngester{},
134			funcType:           message.FuncTypeIngest,
135			msg:                "blahblah",
136			doCommit:           true,
137			expFeedValueString: "blahblah",
138			verifyIsLocked:     true,
139		},
140	}
141
142	for _, tt := range tests {
143		t.Run(tt.name, func(t *testing.T) {
144			staticFeed := static.NewFeed(
145				"1",
146				"string",
147				tt.ingester,
148				simple.NewStorage(1),
149				nil,
150			)
151
152			var errText string
153			if err := staticFeed.Ingest(tt.funcType, tt.msg, tt.providerAddress); err != nil {
154				errText = err.Error()
155			}
156
157			urequire.Equal(t, tt.expErrText, errText)
158
159			if tt.doCommit {
160				err := staticFeed.Ingest(message.FuncTypeCommit, "", "")
161				urequire.NoError(t, err, "follow up commit failed")
162			}
163
164			if tt.verifyIsLocked {
165				errText = ""
166				if err := staticFeed.Ingest(tt.funcType, tt.msg, tt.providerAddress); err != nil {
167					errText = err.Error()
168				}
169
170				urequire.Equal(t, "feed locked", errText)
171			}
172
173			uassert.Equal(t, tt.providerAddress, tt.ingester.providerAddress)
174
175			feedValue, dataType, isLocked := staticFeed.Value()
176			uassert.Equal(t, tt.expFeedValueString, feedValue.String)
177			uassert.Equal(t, "string", dataType)
178			uassert.Equal(t, tt.verifyIsLocked, isLocked)
179			uassert.Equal(t, tt.expIsActive, staticFeed.IsActive())
180		})
181	}
182}
183
184type mockTask struct {
185	err   error
186	value string
187}
188
189func (t mockTask) MarshalJSON() ([]byte, error) {
190	if t.err != nil {
191		return nil, t.err
192	}
193
194	return []byte(`{"value":"` + t.value + `"}`), nil
195}
196
197func TestFeed_Tasks(t *testing.T) {
198	id := "99"
199	valueDataType := "int"
200
201	tests := []struct {
202		name       string
203		tasks      []feed.Task
204		expErrText string
205		expJSON    string
206	}{
207		{
208			name:    "no tasks",
209			expJSON: `{"id":"99","type":"0","value_type":"int","tasks":[]}`,
210		},
211		{
212			name: "marshal error",
213			tasks: []feed.Task{
214				mockTask{err: errors.New("marshal error")},
215			},
216			expErrText: "marshal error",
217		},
218		{
219			name: "one task",
220			tasks: []feed.Task{
221				mockTask{value: "single"},
222			},
223			expJSON: `{"id":"99","type":"0","value_type":"int","tasks":[{"value":"single"}]}`,
224		},
225		{
226			name: "two tasks",
227			tasks: []feed.Task{
228				mockTask{value: "first"},
229				mockTask{value: "second"},
230			},
231			expJSON: `{"id":"99","type":"0","value_type":"int","tasks":[{"value":"first"},{"value":"second"}]}`,
232		},
233	}
234
235	for _, tt := range tests {
236		t.Run(tt.name, func(t *testing.T) {
237			staticFeed := static.NewSingleValueFeed(
238				id,
239				valueDataType,
240				tt.tasks...,
241			)
242
243			urequire.Equal(t, len(tt.tasks), len(staticFeed.Tasks()))
244
245			var errText string
246			json, err := staticFeed.MarshalJSON()
247			if err != nil {
248				errText = err.Error()
249			}
250
251			urequire.Equal(t, tt.expErrText, errText)
252			urequire.Equal(t, tt.expJSON, string(json))
253		})
254	}
255}