@agoric/cosmos 0.34.2-dev-ecf2d8e.0 → 0.35.0-other-dev-70beeb7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/app/app.go +103 -14
- package/app/const.go +6 -0
- package/cmd/agd/main.go +11 -133
- package/cmd/libdaemon/main.go +53 -67
- package/daemon/cmd/root.go +24 -55
- package/daemon/main.go +1 -3
- package/git-revision.txt +1 -1
- package/package.json +3 -3
- package/proto/agoric/vstorage/query.proto +1 -53
- package/vm/controller.go +18 -8
- package/x/lien/lien.go +4 -6
- package/x/lien/lien_test.go +15 -19
- package/x/swingset/abci.go +2 -3
- package/x/swingset/swingset.go +2 -4
- package/x/swingset/types/default-params.go +1 -1
- package/x/swingset/types/msgs.pb.go +16 -16
- package/x/vbank/vbank.go +10 -11
- package/x/vbank/vbank_test.go +5 -5
- package/x/vibc/ibc.go +11 -12
- package/x/vibc/keeper/keeper.go +15 -1
- package/x/vibc/types/expected_keepers.go +1 -2
- package/x/vstorage/keeper/grpc_query.go +0 -221
- package/x/vstorage/keeper/querier.go +11 -31
- package/x/vstorage/types/path_keys.go +10 -22
- package/x/vstorage/types/path_keys_test.go +18 -84
- package/x/vstorage/types/query.pb.go +36 -646
- package/x/vstorage/types/query.pb.gw.go +0 -119
- package/x/vstorage/vstorage.go +15 -16
- package/x/vstorage/vstorage_test.go +4 -4
- package/cmd/agd/agvm.go +0 -42
- package/vm/client.go +0 -113
- package/vm/client_test.go +0 -184
- package/vm/jsonrpcconn/jsonrpcconn.go +0 -160
- package/vm/jsonrpcconn/jsonrpcconn_test.go +0 -126
- package/vm/server.go +0 -23
- package/x/vstorage/README.md +0 -95
- package/x/vstorage/capdata/capdata.go +0 -298
- package/x/vstorage/capdata/capdata_test.go +0 -352
- package/x/vstorage/keeper/keeper_grpc_test.go +0 -300
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
package capdata
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"encoding/json"
|
|
5
|
-
"fmt"
|
|
6
|
-
"reflect"
|
|
7
|
-
"strings"
|
|
8
|
-
"testing"
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
func ptr[T any](v T) *T {
|
|
12
|
-
return &v
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
func mustJsonMarshal(val any) string {
|
|
16
|
-
jsonText, err := JsonMarshal(val)
|
|
17
|
-
if err != nil {
|
|
18
|
-
panic(err)
|
|
19
|
-
}
|
|
20
|
-
return string(jsonText)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
func mustJsonUnmarshal(jsonText string, ptr any) {
|
|
24
|
-
if err := json.Unmarshal([]byte(jsonText), ptr); err != nil {
|
|
25
|
-
panic(err)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
func prefixBigint(bigint *CapdataBigint) interface{} {
|
|
30
|
-
return fmt.Sprintf("bigint:%s", bigint.Normalized)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
func remotableToString(r *CapdataRemotable) interface{} {
|
|
34
|
-
iface := ""
|
|
35
|
-
if r.Iface != nil {
|
|
36
|
-
iface = *r.Iface
|
|
37
|
-
}
|
|
38
|
-
return fmt.Sprintf("remotable:%s{%s}", iface, r.Id)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
func Test_JsonMarshal(t *testing.T) {
|
|
42
|
-
type testCase struct {
|
|
43
|
-
input string
|
|
44
|
-
expected string
|
|
45
|
-
errContains *string
|
|
46
|
-
}
|
|
47
|
-
testCases := []testCase{
|
|
48
|
-
{
|
|
49
|
-
input: "<>&\u2028\u2029",
|
|
50
|
-
expected: `"<>&\u2028\u2029"`,
|
|
51
|
-
},
|
|
52
|
-
}
|
|
53
|
-
for _, desc := range testCases {
|
|
54
|
-
label := fmt.Sprintf("%q", desc.input)
|
|
55
|
-
result, err := JsonMarshal(desc.input)
|
|
56
|
-
if desc.errContains == nil {
|
|
57
|
-
if err != nil {
|
|
58
|
-
t.Errorf("%s: got unexpected error %v", label, err)
|
|
59
|
-
} else if string(result) != desc.expected {
|
|
60
|
-
t.Errorf("%s: wrong result: %#q", label, result)
|
|
61
|
-
}
|
|
62
|
-
} else if err == nil {
|
|
63
|
-
t.Errorf("%s: got no error, want error %q", label, *desc.errContains)
|
|
64
|
-
} else if !strings.Contains(err.Error(), *desc.errContains) {
|
|
65
|
-
t.Errorf("%s: got error %v, want error %q", label, err, *desc.errContains)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
func Test_DecodeSerializedCapdata(t *testing.T) {
|
|
71
|
-
type testCase struct {
|
|
72
|
-
format string
|
|
73
|
-
label string
|
|
74
|
-
body string
|
|
75
|
-
slots []interface{}
|
|
76
|
-
expected string
|
|
77
|
-
errContains *string
|
|
78
|
-
transformations CapdataValueTransformations
|
|
79
|
-
}
|
|
80
|
-
testCases := []testCase{
|
|
81
|
-
// JSON
|
|
82
|
-
// cf. https://github.com/endojs/endo/blob/209b612e0a267239f33cd607e94ccd179d3ba248/packages/marshal/test/test-marshal-capdata.js#L11
|
|
83
|
-
{body: `[1, 2]`},
|
|
84
|
-
{body: `{ "foo": 1 }`},
|
|
85
|
-
{body: `{}`},
|
|
86
|
-
{body: `{ "a": 1, "b": 2 }`},
|
|
87
|
-
{body: `{ "a": 1, "b": { "c": 3 } }`},
|
|
88
|
-
{body: `true`},
|
|
89
|
-
{body: `1`},
|
|
90
|
-
{body: `"abc"`},
|
|
91
|
-
{body: `null`},
|
|
92
|
-
|
|
93
|
-
// transformation of non-JSON values
|
|
94
|
-
{format: "smallcaps", label: "bigint",
|
|
95
|
-
body: `"+98765432101234567890"`,
|
|
96
|
-
expected: `"bigint:98765432101234567890"`,
|
|
97
|
-
transformations: CapdataValueTransformations{Bigint: prefixBigint},
|
|
98
|
-
},
|
|
99
|
-
{format: "legacy", label: "bigint",
|
|
100
|
-
body: `{ "@qclass": "bigint", "digits": "98765432101234567890" }`,
|
|
101
|
-
expected: `"bigint:98765432101234567890"`,
|
|
102
|
-
transformations: CapdataValueTransformations{Bigint: prefixBigint},
|
|
103
|
-
},
|
|
104
|
-
{format: "smallcaps", label: "remotables",
|
|
105
|
-
body: `["$0.Foo", "$0"]`,
|
|
106
|
-
slots: []interface{}{"a"},
|
|
107
|
-
expected: `["remotable:Foo{a}","remotable:Foo{a}"]`,
|
|
108
|
-
transformations: CapdataValueTransformations{Remotable: remotableToString},
|
|
109
|
-
},
|
|
110
|
-
{format: "legacy", label: "remotables",
|
|
111
|
-
body: `[{"@qclass":"slot","index":0,"iface":"Foo"}, {"@qclass":"slot","index":0}]`,
|
|
112
|
-
slots: []interface{}{"a"},
|
|
113
|
-
expected: `["remotable:Foo{a}","remotable:Foo{a}"]`,
|
|
114
|
-
transformations: CapdataValueTransformations{Remotable: remotableToString},
|
|
115
|
-
},
|
|
116
|
-
{format: "smallcaps", label: "escaped string",
|
|
117
|
-
body: `"!#escaped"`,
|
|
118
|
-
expected: `"#escaped"`,
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
// unimplemented
|
|
122
|
-
{format: "smallcaps",
|
|
123
|
-
body: `"#undefined"`,
|
|
124
|
-
errContains: ptr("not implemented"),
|
|
125
|
-
},
|
|
126
|
-
{format: "legacy", label: "undefined",
|
|
127
|
-
body: `{"@qclass":"undefined"}`,
|
|
128
|
-
errContains: ptr("not implemented"),
|
|
129
|
-
},
|
|
130
|
-
{format: "smallcaps",
|
|
131
|
-
body: `"#NaN"`,
|
|
132
|
-
errContains: ptr("not implemented"),
|
|
133
|
-
},
|
|
134
|
-
{format: "legacy", label: "NaN",
|
|
135
|
-
body: `{"@qclass":"NaN"}`,
|
|
136
|
-
errContains: ptr("not implemented"),
|
|
137
|
-
},
|
|
138
|
-
{format: "smallcaps",
|
|
139
|
-
body: `"#Infinity"`,
|
|
140
|
-
errContains: ptr("not implemented"),
|
|
141
|
-
},
|
|
142
|
-
{format: "legacy", label: "Infinity",
|
|
143
|
-
body: `{"@qclass":"Infinity"}`,
|
|
144
|
-
errContains: ptr("not implemented"),
|
|
145
|
-
},
|
|
146
|
-
{format: "smallcaps",
|
|
147
|
-
body: `"#-Infinity"`,
|
|
148
|
-
errContains: ptr("not implemented"),
|
|
149
|
-
},
|
|
150
|
-
{format: "legacy", label: "-Infinity",
|
|
151
|
-
body: `{"@qclass":"-Infinity"}`,
|
|
152
|
-
errContains: ptr("not implemented"),
|
|
153
|
-
},
|
|
154
|
-
{format: "smallcaps", label: "symbol",
|
|
155
|
-
body: `"%foo"`,
|
|
156
|
-
errContains: ptr("not implemented"),
|
|
157
|
-
},
|
|
158
|
-
{format: "legacy", label: "symbol",
|
|
159
|
-
body: `{"@qclass":"symbol"}`,
|
|
160
|
-
errContains: ptr("not implemented"),
|
|
161
|
-
},
|
|
162
|
-
{format: "smallcaps", label: "tagged",
|
|
163
|
-
body: `{"#tag":"foo","payload":"bar"}`,
|
|
164
|
-
errContains: ptr("not implemented: #tag"),
|
|
165
|
-
},
|
|
166
|
-
{format: "legacy", label: "tagged",
|
|
167
|
-
body: `{"@qclass":"tagged","tag":"foo","payload":"bar"}`,
|
|
168
|
-
errContains: ptr("not implemented"),
|
|
169
|
-
},
|
|
170
|
-
{format: "smallcaps", label: "error",
|
|
171
|
-
body: `{"#error":"","name":"Error"}`,
|
|
172
|
-
errContains: ptr("not implemented: #error"),
|
|
173
|
-
},
|
|
174
|
-
{format: "legacy", label: "error",
|
|
175
|
-
body: `{"@qclass":"error","message":"foo","name":"bar"}`,
|
|
176
|
-
errContains: ptr("not implemented"),
|
|
177
|
-
},
|
|
178
|
-
{format: "smallcaps", label: "promise",
|
|
179
|
-
body: `"&0"`,
|
|
180
|
-
slots: []interface{}{"a"},
|
|
181
|
-
errContains: ptr("not implemented"),
|
|
182
|
-
},
|
|
183
|
-
{format: "legacy", label: "error",
|
|
184
|
-
body: `{"@qclass":"hilbert","original":"foo"}`,
|
|
185
|
-
errContains: ptr("not implemented"),
|
|
186
|
-
},
|
|
187
|
-
|
|
188
|
-
// missing transformations
|
|
189
|
-
{format: "smallcaps", label: "untransformed bigint",
|
|
190
|
-
body: `"+98765432101234567890"`,
|
|
191
|
-
errContains: ptr("untransformed bigint"),
|
|
192
|
-
},
|
|
193
|
-
{format: "legacy", label: "untransformed bigint",
|
|
194
|
-
body: `{ "@qclass": "bigint", "digits": "98765432101234567890" }`,
|
|
195
|
-
errContains: ptr("untransformed bigint"),
|
|
196
|
-
},
|
|
197
|
-
{format: "smallcaps", label: "untransformed remotable",
|
|
198
|
-
body: `["$0.Foo", "$0"]`,
|
|
199
|
-
slots: []interface{}{"a"},
|
|
200
|
-
errContains: ptr("untransformed remotable"),
|
|
201
|
-
},
|
|
202
|
-
{format: "legacy", label: "untransformed remotable",
|
|
203
|
-
body: `[{"@qclass":"slot","index":0,"iface":"Foo"}, {"@qclass":"slot","index":0}]`,
|
|
204
|
-
slots: []interface{}{"a"},
|
|
205
|
-
errContains: ptr("untransformed remotable"),
|
|
206
|
-
},
|
|
207
|
-
|
|
208
|
-
// invalid data
|
|
209
|
-
{format: "smallcaps", label: "iface mismatch",
|
|
210
|
-
body: `["$0.Foo", "$0."]`,
|
|
211
|
-
slots: []interface{}{"a"},
|
|
212
|
-
errContains: ptr("iface mismatch"),
|
|
213
|
-
},
|
|
214
|
-
{format: "legacy", label: "iface mismatch",
|
|
215
|
-
body: `[{"@qclass":"slot","index":0,"iface":"Foo"}, {"@qclass":"slot","index":0,"iface":""}]`,
|
|
216
|
-
slots: []interface{}{"a"},
|
|
217
|
-
errContains: ptr("iface mismatch"),
|
|
218
|
-
},
|
|
219
|
-
{format: "smallcaps", label: "invalid slot index (out of bounds)",
|
|
220
|
-
body: `"$0.Foo"`,
|
|
221
|
-
errContains: ptr("invalid slot index"),
|
|
222
|
-
},
|
|
223
|
-
{format: "legacy", label: "invalid slot index (out of bounds)",
|
|
224
|
-
body: `{"@qclass":"slot","index":0}`,
|
|
225
|
-
errContains: ptr("invalid slot index"),
|
|
226
|
-
},
|
|
227
|
-
{format: "smallcaps", label: "invalid slot index (bad format)",
|
|
228
|
-
body: `"$x.Foo"`,
|
|
229
|
-
slots: []interface{}{"a"},
|
|
230
|
-
errContains: ptr("invalid slot index"),
|
|
231
|
-
},
|
|
232
|
-
{format: "legacy", label: "invalid slot index (missing)",
|
|
233
|
-
body: `{"@qclass":"slot"}`,
|
|
234
|
-
slots: []interface{}{"a"},
|
|
235
|
-
errContains: ptr("invalid slot index"),
|
|
236
|
-
},
|
|
237
|
-
{format: "legacy", label: "invalid slot index (null)",
|
|
238
|
-
body: `{"@qclass":"slot","index":null}`,
|
|
239
|
-
slots: []interface{}{"a"},
|
|
240
|
-
errContains: ptr("invalid slot index"),
|
|
241
|
-
},
|
|
242
|
-
{format: "legacy", label: "invalid slot index (string)",
|
|
243
|
-
body: `{"@qclass":"slot","index":"0"}`,
|
|
244
|
-
slots: []interface{}{"a"},
|
|
245
|
-
errContains: ptr("invalid slot index"),
|
|
246
|
-
},
|
|
247
|
-
{format: "legacy", label: "invalid slot index (non-integer)",
|
|
248
|
-
body: `{"@qclass":"slot","index":0.1}`,
|
|
249
|
-
slots: []interface{}{"a"},
|
|
250
|
-
errContains: ptr("invalid slot index"),
|
|
251
|
-
},
|
|
252
|
-
{format: "legacy", label: "invalid slot index (negative)",
|
|
253
|
-
body: `{"@qclass":"slot","index":-1}`,
|
|
254
|
-
slots: []interface{}{"a"},
|
|
255
|
-
errContains: ptr("invalid slot index"),
|
|
256
|
-
},
|
|
257
|
-
{format: "legacy", label: "invalid slot iface (number)",
|
|
258
|
-
body: `{"@qclass":"slot","index":0,"iface":0}`,
|
|
259
|
-
slots: []interface{}{"a"},
|
|
260
|
-
errContains: ptr("invalid slot iface"),
|
|
261
|
-
},
|
|
262
|
-
{format: "smallcaps", label: "unrecognized record type",
|
|
263
|
-
body: `{"#foo":0}`,
|
|
264
|
-
errContains: ptr("unrecognized record type"),
|
|
265
|
-
},
|
|
266
|
-
{format: "legacy", label: "invalid @qclass (null)",
|
|
267
|
-
body: `{"@qclass":null}`,
|
|
268
|
-
errContains: ptr("invalid @qclass"),
|
|
269
|
-
},
|
|
270
|
-
{format: "legacy", label: "invalid @qclass (number)",
|
|
271
|
-
body: `{"@qclass":1}`,
|
|
272
|
-
errContains: ptr("invalid @qclass"),
|
|
273
|
-
},
|
|
274
|
-
{format: "legacy", label: "invalid @qclass (number)",
|
|
275
|
-
body: `{"@qclass":1}`,
|
|
276
|
-
errContains: ptr("invalid @qclass"),
|
|
277
|
-
},
|
|
278
|
-
{format: "legacy", label: "unrecognized @qclass",
|
|
279
|
-
body: `{"@qclass":"foo"}`,
|
|
280
|
-
errContains: ptr("unrecognized @qclass"),
|
|
281
|
-
},
|
|
282
|
-
{format: "smallcaps", label: "invalid copyRecord key",
|
|
283
|
-
body: `{"+0":0}`,
|
|
284
|
-
errContains: ptr("invalid copyRecord key"),
|
|
285
|
-
},
|
|
286
|
-
{format: "smallcaps", label: "invalid bigint (`--`)",
|
|
287
|
-
body: `"--"`,
|
|
288
|
-
errContains: ptr("invalid bigint"),
|
|
289
|
-
},
|
|
290
|
-
{format: "smallcaps", label: "invalid bigint (`+0x`)",
|
|
291
|
-
body: `"+0x"`,
|
|
292
|
-
errContains: ptr("invalid bigint"),
|
|
293
|
-
},
|
|
294
|
-
{format: "legacy", label: "invalid bigint (no digits)",
|
|
295
|
-
body: `{"@qclass":"bigint"}`,
|
|
296
|
-
errContains: ptr("invalid bigint"),
|
|
297
|
-
},
|
|
298
|
-
{format: "legacy", label: "invalid bigint (null digits)",
|
|
299
|
-
body: `{"@qclass":"bigint","digits":null}`,
|
|
300
|
-
errContains: ptr("invalid bigint"),
|
|
301
|
-
},
|
|
302
|
-
{format: "legacy", label: "invalid bigint (`7up`)",
|
|
303
|
-
body: `{"@qclass":"bigint","digits":"7up"}`,
|
|
304
|
-
errContains: ptr("invalid bigint"),
|
|
305
|
-
},
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
for _, desc := range testCases {
|
|
309
|
-
slots := desc.slots
|
|
310
|
-
if slots == nil {
|
|
311
|
-
slots = []interface{}{}
|
|
312
|
-
}
|
|
313
|
-
var expected interface{}
|
|
314
|
-
if desc.expected != "" {
|
|
315
|
-
mustJsonUnmarshal(desc.expected, &expected)
|
|
316
|
-
} else {
|
|
317
|
-
mustJsonUnmarshal(desc.body, &expected)
|
|
318
|
-
}
|
|
319
|
-
for _, format := range []string{"smallcaps", "legacy"} {
|
|
320
|
-
if desc.format != "" && desc.format != format {
|
|
321
|
-
continue
|
|
322
|
-
}
|
|
323
|
-
label := fmt.Sprintf("%s %s", format, desc.label)
|
|
324
|
-
if desc.label == "" {
|
|
325
|
-
label = fmt.Sprintf("%s %s", format, desc.body)
|
|
326
|
-
}
|
|
327
|
-
capdata := Capdata{desc.body, slots}
|
|
328
|
-
if format == "smallcaps" {
|
|
329
|
-
capdata.Body = "#" + capdata.Body
|
|
330
|
-
}
|
|
331
|
-
intermediate, err := DecodeSerializedCapdata(mustJsonMarshal(capdata), desc.transformations)
|
|
332
|
-
// Replace each Remotable with its representation before comparing.
|
|
333
|
-
var got interface{}
|
|
334
|
-
mustJsonUnmarshal(mustJsonMarshal(intermediate), &got)
|
|
335
|
-
if desc.errContains == nil {
|
|
336
|
-
if err != nil {
|
|
337
|
-
t.Errorf("%s: got unexpected error %v", label, err)
|
|
338
|
-
} else if !reflect.DeepEqual(got, expected) {
|
|
339
|
-
result, err := JsonMarshal(got)
|
|
340
|
-
if err != nil {
|
|
341
|
-
panic(fmt.Errorf("%s: %v", label, err))
|
|
342
|
-
}
|
|
343
|
-
t.Errorf("%s: wrong result: %s", label, result)
|
|
344
|
-
}
|
|
345
|
-
} else if err == nil {
|
|
346
|
-
t.Errorf("%s: got no error, want error %q", label, *desc.errContains)
|
|
347
|
-
} else if !strings.Contains(err.Error(), *desc.errContains) {
|
|
348
|
-
t.Errorf("%s: got error %v, want error %q", label, err, *desc.errContains)
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
package keeper
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"fmt"
|
|
5
|
-
"reflect"
|
|
6
|
-
"strings"
|
|
7
|
-
"testing"
|
|
8
|
-
|
|
9
|
-
grpcCodes "google.golang.org/grpc/codes"
|
|
10
|
-
grpcStatus "google.golang.org/grpc/status"
|
|
11
|
-
|
|
12
|
-
agoric "github.com/Agoric/agoric-sdk/golang/cosmos/types"
|
|
13
|
-
"github.com/Agoric/agoric-sdk/golang/cosmos/x/vstorage/capdata"
|
|
14
|
-
"github.com/Agoric/agoric-sdk/golang/cosmos/x/vstorage/types"
|
|
15
|
-
|
|
16
|
-
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
func ptr[T any](v T) *T {
|
|
20
|
-
return &v
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
func mustJsonMarshal(val any) string {
|
|
24
|
-
jsonText, err := capdata.JsonMarshal(val)
|
|
25
|
-
if err != nil {
|
|
26
|
-
panic(err)
|
|
27
|
-
}
|
|
28
|
-
return string(jsonText)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
func mustMarshalStreamCell(blockHeight string, values []string) string {
|
|
32
|
-
cell := map[string]any{
|
|
33
|
-
"blockHeight": blockHeight,
|
|
34
|
-
"values": values,
|
|
35
|
-
}
|
|
36
|
-
return mustJsonMarshal(cell)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
func TestCapData(t *testing.T) {
|
|
40
|
-
testKit := makeTestKit()
|
|
41
|
-
ctx, keeper := testKit.ctx, testKit.vstorageKeeper
|
|
42
|
-
querier := Querier{keeper}
|
|
43
|
-
|
|
44
|
-
type testCase struct {
|
|
45
|
-
label string
|
|
46
|
-
data *string
|
|
47
|
-
request types.QueryCapDataRequest
|
|
48
|
-
expected types.QueryCapDataResponse
|
|
49
|
-
errCode grpcCodes.Code
|
|
50
|
-
errContains *string
|
|
51
|
-
}
|
|
52
|
-
testCases := []testCase{}
|
|
53
|
-
|
|
54
|
-
// Test simple cases (various kinds of bad data up to simple flat JSON-compatible CapData).
|
|
55
|
-
decodableSmallcaps := `{"body":"#true","slots":[]}`
|
|
56
|
-
decodableLegacy := `{"body":"true","slots":[]}`
|
|
57
|
-
testCases = append(testCases, []testCase{
|
|
58
|
-
{label: "no data",
|
|
59
|
-
data: nil,
|
|
60
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
61
|
-
errCode: grpcCodes.FailedPrecondition,
|
|
62
|
-
errContains: ptr("no data"),
|
|
63
|
-
},
|
|
64
|
-
{label: "zero-length data",
|
|
65
|
-
data: ptr(""),
|
|
66
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
67
|
-
errCode: grpcCodes.FailedPrecondition,
|
|
68
|
-
errContains: ptr("JSON"),
|
|
69
|
-
},
|
|
70
|
-
{label: "cell with empty string",
|
|
71
|
-
data: ptr(mustMarshalStreamCell("1", []string{decodableSmallcaps, "", decodableLegacy})),
|
|
72
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
73
|
-
errCode: grpcCodes.FailedPrecondition,
|
|
74
|
-
errContains: ptr("JSON"),
|
|
75
|
-
},
|
|
76
|
-
{label: "non-JSON data",
|
|
77
|
-
data: ptr("foo"),
|
|
78
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
79
|
-
errCode: grpcCodes.FailedPrecondition,
|
|
80
|
-
errContains: ptr("invalid"),
|
|
81
|
-
},
|
|
82
|
-
{label: "cell with non-JSON",
|
|
83
|
-
data: ptr(mustMarshalStreamCell("1", []string{decodableSmallcaps, "foo", decodableLegacy})),
|
|
84
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
85
|
-
errCode: grpcCodes.FailedPrecondition,
|
|
86
|
-
errContains: ptr("invalid"),
|
|
87
|
-
},
|
|
88
|
-
{label: "lone non-CapData",
|
|
89
|
-
data: ptr("{}"),
|
|
90
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
91
|
-
errCode: grpcCodes.FailedPrecondition,
|
|
92
|
-
errContains: ptr("invalid CapData"),
|
|
93
|
-
},
|
|
94
|
-
{label: "cell with non-CapData",
|
|
95
|
-
data: ptr(mustMarshalStreamCell("1", []string{decodableSmallcaps, "{}", decodableLegacy})),
|
|
96
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
97
|
-
errCode: grpcCodes.FailedPrecondition,
|
|
98
|
-
errContains: ptr("invalid CapData"),
|
|
99
|
-
},
|
|
100
|
-
{label: "lone smallcaps CapData",
|
|
101
|
-
data: ptr(decodableSmallcaps),
|
|
102
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
103
|
-
expected: types.QueryCapDataResponse{Value: `true`},
|
|
104
|
-
},
|
|
105
|
-
{label: "cell with smallcaps CapData",
|
|
106
|
-
data: ptr(mustMarshalStreamCell("1", []string{decodableSmallcaps})),
|
|
107
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
108
|
-
expected: types.QueryCapDataResponse{BlockHeight: "1", Value: `true`},
|
|
109
|
-
},
|
|
110
|
-
{label: "lone legacy CapData",
|
|
111
|
-
data: ptr(decodableLegacy),
|
|
112
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
113
|
-
expected: types.QueryCapDataResponse{Value: `true`},
|
|
114
|
-
},
|
|
115
|
-
{label: "cell with legacy CapData",
|
|
116
|
-
data: ptr(mustMarshalStreamCell("1", []string{decodableLegacy})),
|
|
117
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
118
|
-
expected: types.QueryCapDataResponse{BlockHeight: "1", Value: `true`},
|
|
119
|
-
},
|
|
120
|
-
}...)
|
|
121
|
-
|
|
122
|
-
// Test option validation.
|
|
123
|
-
testCases = append(testCases, []testCase{
|
|
124
|
-
{label: "explicit JSON Lines",
|
|
125
|
-
data: ptr(decodableSmallcaps),
|
|
126
|
-
request: types.QueryCapDataRequest{MediaType: "JSON Lines", RemotableValueFormat: "string"},
|
|
127
|
-
expected: types.QueryCapDataResponse{Value: `true`},
|
|
128
|
-
},
|
|
129
|
-
{label: "invalid media type",
|
|
130
|
-
data: ptr(decodableSmallcaps),
|
|
131
|
-
request: types.QueryCapDataRequest{MediaType: "JSONLines", RemotableValueFormat: "string"},
|
|
132
|
-
errCode: grpcCodes.InvalidArgument,
|
|
133
|
-
errContains: ptr("media_type"),
|
|
134
|
-
},
|
|
135
|
-
{label: "invalid item format",
|
|
136
|
-
data: ptr(decodableSmallcaps),
|
|
137
|
-
request: types.QueryCapDataRequest{ItemFormat: "deep", RemotableValueFormat: "string"},
|
|
138
|
-
errCode: grpcCodes.InvalidArgument,
|
|
139
|
-
errContains: ptr("item_format"),
|
|
140
|
-
},
|
|
141
|
-
{label: "missing remotable value format",
|
|
142
|
-
data: ptr(decodableSmallcaps),
|
|
143
|
-
request: types.QueryCapDataRequest{},
|
|
144
|
-
errCode: grpcCodes.InvalidArgument,
|
|
145
|
-
errContains: ptr("remotable_value_format"),
|
|
146
|
-
},
|
|
147
|
-
{label: "invalid remotable value format",
|
|
148
|
-
data: ptr(decodableSmallcaps),
|
|
149
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "foo"},
|
|
150
|
-
errCode: grpcCodes.InvalidArgument,
|
|
151
|
-
errContains: ptr("remotable_value_format"),
|
|
152
|
-
},
|
|
153
|
-
}...)
|
|
154
|
-
|
|
155
|
-
// Test formatting options against sufficiently complex CapData,
|
|
156
|
-
// deriving legacy encoding from smallcaps encoding to ensure equivalence
|
|
157
|
-
// and deriving expectations from marshalling to avoid spurious mismatches
|
|
158
|
-
// from Go's unpredictable field ordering (e.g., `{"a":0,"b":1}` vs. `{"b":1,"a":0}`).
|
|
159
|
-
slots := []any{"a"}
|
|
160
|
-
deepSmallcapsBody := `{"arr":[{"bigint":"+42","remotable":"$0.Alleged: Foo brand","ref2":"$0"}]}`
|
|
161
|
-
deepLegacyBody := deepSmallcapsBody
|
|
162
|
-
legacyFromSmallcaps := [][2]string{
|
|
163
|
-
[2]string{`"+42"`, `{"@qclass":"bigint","digits":"42"}`},
|
|
164
|
-
[2]string{`"$0.Alleged: Foo brand"`, `{"@qclass":"slot","index":0,"iface":"Alleged: Foo brand"}`},
|
|
165
|
-
[2]string{`"$0"`, `{"@qclass":"slot","index":0}`},
|
|
166
|
-
}
|
|
167
|
-
for _, pair := range legacyFromSmallcaps {
|
|
168
|
-
deepLegacyBody = strings.Replace(deepLegacyBody, pair[0], pair[1], -1)
|
|
169
|
-
}
|
|
170
|
-
cell := mustMarshalStreamCell("1", []string{
|
|
171
|
-
mustJsonMarshal(map[string]any{"body": "#" + deepSmallcapsBody, "slots": slots}),
|
|
172
|
-
mustJsonMarshal(map[string]any{"body": deepLegacyBody, "slots": slots}),
|
|
173
|
-
})
|
|
174
|
-
mustMarshalTwoLines := func(val any) string {
|
|
175
|
-
line := mustJsonMarshal(val)
|
|
176
|
-
return fmt.Sprintf("%s\n%s", line, line)
|
|
177
|
-
}
|
|
178
|
-
testCases = append(testCases, testCase{label: "remotables as strings",
|
|
179
|
-
data: ptr(cell),
|
|
180
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
181
|
-
expected: types.QueryCapDataResponse{
|
|
182
|
-
BlockHeight: "1",
|
|
183
|
-
Value: mustMarshalTwoLines(map[string]any{
|
|
184
|
-
"arr": []any{
|
|
185
|
-
map[string]any{
|
|
186
|
-
"bigint": "42",
|
|
187
|
-
"remotable": "[Alleged: Foo brand <a>]",
|
|
188
|
-
"ref2": "[Alleged: Foo brand <a>]",
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
}),
|
|
192
|
-
},
|
|
193
|
-
})
|
|
194
|
-
testCases = append(testCases, testCase{label: "remotables as strings, flat",
|
|
195
|
-
data: ptr(cell),
|
|
196
|
-
request: types.QueryCapDataRequest{ItemFormat: "flat", RemotableValueFormat: "string"},
|
|
197
|
-
expected: types.QueryCapDataResponse{
|
|
198
|
-
BlockHeight: "1",
|
|
199
|
-
Value: mustMarshalTwoLines(map[string]any{
|
|
200
|
-
"arr-0-bigint": "42",
|
|
201
|
-
"arr-0-remotable": "[Alleged: Foo brand <a>]",
|
|
202
|
-
"arr-0-ref2": "[Alleged: Foo brand <a>]",
|
|
203
|
-
}),
|
|
204
|
-
},
|
|
205
|
-
})
|
|
206
|
-
testCases = append(testCases, testCase{label: "remotables as objects",
|
|
207
|
-
data: ptr(cell),
|
|
208
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "object"},
|
|
209
|
-
expected: types.QueryCapDataResponse{
|
|
210
|
-
BlockHeight: "1",
|
|
211
|
-
Value: mustMarshalTwoLines(map[string]any{
|
|
212
|
-
"arr": []any{
|
|
213
|
-
map[string]any{
|
|
214
|
-
"bigint": "42",
|
|
215
|
-
"remotable": map[string]any{"id": "a", "allegedName": "Foo brand"},
|
|
216
|
-
"ref2": map[string]any{"id": "a", "allegedName": "Foo brand"},
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
}),
|
|
220
|
-
},
|
|
221
|
-
})
|
|
222
|
-
testCases = append(testCases, testCase{label: "remotables as objects, flat",
|
|
223
|
-
data: ptr(cell),
|
|
224
|
-
request: types.QueryCapDataRequest{ItemFormat: "flat", RemotableValueFormat: "object"},
|
|
225
|
-
expected: types.QueryCapDataResponse{
|
|
226
|
-
BlockHeight: "1",
|
|
227
|
-
Value: mustMarshalTwoLines(map[string]any{
|
|
228
|
-
"arr-0-bigint": "42",
|
|
229
|
-
"arr-0-remotable-id": "a",
|
|
230
|
-
"arr-0-remotable-allegedName": "Foo brand",
|
|
231
|
-
"arr-0-ref2-id": "a",
|
|
232
|
-
"arr-0-ref2-allegedName": "Foo brand",
|
|
233
|
-
}),
|
|
234
|
-
},
|
|
235
|
-
})
|
|
236
|
-
|
|
237
|
-
// Test errors from CapData that includes unsupported values.
|
|
238
|
-
expectNotImplemented := func(label, capdataBody string, slots []any) testCase {
|
|
239
|
-
if slots == nil {
|
|
240
|
-
slots = []any{}
|
|
241
|
-
}
|
|
242
|
-
serialized := mustJsonMarshal(map[string]any{
|
|
243
|
-
"body": capdataBody,
|
|
244
|
-
"slots": slots,
|
|
245
|
-
})
|
|
246
|
-
return testCase{
|
|
247
|
-
label: label,
|
|
248
|
-
data: ptr(serialized),
|
|
249
|
-
request: types.QueryCapDataRequest{RemotableValueFormat: "string"},
|
|
250
|
-
errCode: grpcCodes.FailedPrecondition,
|
|
251
|
-
errContains: ptr("not implemented"),
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
testCases = append(testCases, []testCase{
|
|
255
|
-
expectNotImplemented("smallcaps undefined", `#"#undefined"`, nil),
|
|
256
|
-
expectNotImplemented("smallcaps NaN", `#"#NaN"`, nil),
|
|
257
|
-
expectNotImplemented("smallcaps infinity", `#"#Infinity"`, nil),
|
|
258
|
-
expectNotImplemented("smallcaps negative infinity", `#"#-Infinity"`, nil),
|
|
259
|
-
expectNotImplemented("smallcaps symbol", `#"%foo"`, nil),
|
|
260
|
-
expectNotImplemented("smallcaps promise", `#"&0"`, []any{"a"}),
|
|
261
|
-
expectNotImplemented("smallcaps tagged", `#{"#tag":"copySet","payload":[]}`, nil),
|
|
262
|
-
expectNotImplemented("smallcaps error", `#{"#error":"foo","name":"Error"}`, nil),
|
|
263
|
-
expectNotImplemented("legacy undefined", `{"@qclass":"undefined"}`, nil),
|
|
264
|
-
expectNotImplemented("legacy NaN", `{"@qclass":"NaN"}`, nil),
|
|
265
|
-
expectNotImplemented("legacy infinity", `{"@qclass":"Infinity"}`, nil),
|
|
266
|
-
expectNotImplemented("legacy negative infinity", `{"@qclass":"-Infinity"}`, nil),
|
|
267
|
-
expectNotImplemented("legacy symbol", `{"@qclass":"symbol","name":"foo"}`, nil),
|
|
268
|
-
expectNotImplemented("smallcaps tagged", `{"@qclass":"tagged","tag":"copySet","payload":[]}`, nil),
|
|
269
|
-
expectNotImplemented("smallcaps error", `{"@qclass":"error","message":"foo","name":"Error"}`, nil),
|
|
270
|
-
expectNotImplemented("smallcaps Hilbert Hotel", `{"@qclass":"hilbert","original":"foo"}`, nil),
|
|
271
|
-
}...)
|
|
272
|
-
for _, desc := range testCases {
|
|
273
|
-
desc.request.Path = "key"
|
|
274
|
-
if desc.data == nil {
|
|
275
|
-
keeper.SetStorage(ctx, agoric.NewKVEntryWithNoValue(desc.request.Path))
|
|
276
|
-
} else {
|
|
277
|
-
keeper.SetStorage(ctx, agoric.NewKVEntry(desc.request.Path, *desc.data))
|
|
278
|
-
}
|
|
279
|
-
resp, err := querier.CapData(sdk.WrapSDKContext(ctx), &desc.request)
|
|
280
|
-
if desc.errCode == grpcCodes.OK {
|
|
281
|
-
if err != nil {
|
|
282
|
-
t.Errorf("%s: got unexpected error %v", desc.label, err)
|
|
283
|
-
} else if reflect.DeepEqual(resp, &desc.expected) {
|
|
284
|
-
continue
|
|
285
|
-
}
|
|
286
|
-
if resp.Value != desc.expected.Value {
|
|
287
|
-
lines := strings.Split(resp.Value, "\n")
|
|
288
|
-
t.Errorf("%s: wrong result value lines: %#q", desc.label, lines)
|
|
289
|
-
} else {
|
|
290
|
-
t.Errorf("%s: wrong result: %#v", desc.label, resp)
|
|
291
|
-
}
|
|
292
|
-
} else if err == nil {
|
|
293
|
-
t.Errorf("%s: got no error, want error %q", desc.label, *desc.errContains)
|
|
294
|
-
} else if code := grpcStatus.Code(err); code != desc.errCode {
|
|
295
|
-
t.Errorf("%s: got error code %q, want %q", desc.label, code, desc.errCode)
|
|
296
|
-
} else if desc.errContains != nil && !strings.Contains(err.Error(), *desc.errContains) {
|
|
297
|
-
t.Errorf("%s: got error %v, want error %q", desc.label, err, *desc.errContains)
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|