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}