@agoric/cosmos 0.34.2-dev-5dc325b.0 → 0.35.0-getting-started-dev-26244e8.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 +73 -0
- package/app/app.go +4 -5
- 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 -6
- 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 +9 -11
- package/x/vstorage/keeper/grpc_query.go +0 -221
- 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 -140
- 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,298 +0,0 @@
|
|
|
1
|
-
package capdata
|
|
2
|
-
|
|
3
|
-
import (
|
|
4
|
-
"bytes"
|
|
5
|
-
"encoding/json"
|
|
6
|
-
"fmt"
|
|
7
|
-
"regexp"
|
|
8
|
-
"strconv"
|
|
9
|
-
"strings"
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
// JsonMarshal returns JSON text representing its input,
|
|
13
|
-
// without special replacement of "<", ">", "&", U+2028, or U+2029.
|
|
14
|
-
func JsonMarshal(val any) ([]byte, error) {
|
|
15
|
-
buf := &bytes.Buffer{}
|
|
16
|
-
encoder := json.NewEncoder(buf)
|
|
17
|
-
encoder.SetEscapeHTML(false)
|
|
18
|
-
if err := encoder.Encode(val); err != nil {
|
|
19
|
-
return nil, err
|
|
20
|
-
}
|
|
21
|
-
// Return without a trailing line feed.
|
|
22
|
-
lineTerminatedJson := buf.Bytes()
|
|
23
|
-
return bytes.TrimSuffix(lineTerminatedJson, []byte("\n")), nil
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// cf. https://github.com/endojs/endo/tree/master/packages/marshal
|
|
27
|
-
|
|
28
|
-
type Capdata struct {
|
|
29
|
-
Body string `json:"body"`
|
|
30
|
-
Slots []interface{} `json:"slots"`
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
var validBigint = regexp.MustCompile(`^-?(?:0|[1-9][0-9]*)$`)
|
|
34
|
-
|
|
35
|
-
type CapdataBigint struct {
|
|
36
|
-
Normalized string
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
type CapdataRemotable struct {
|
|
40
|
-
Id interface{}
|
|
41
|
-
Iface *string
|
|
42
|
-
Representation interface{}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
func NewCapdataBigint(str string) *CapdataBigint {
|
|
46
|
-
if !validBigint.MatchString(str) {
|
|
47
|
-
return nil
|
|
48
|
-
}
|
|
49
|
-
bigint := CapdataBigint{str}
|
|
50
|
-
return &bigint
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
func (r *CapdataRemotable) MarshalJSON() ([]byte, error) {
|
|
54
|
-
return JsonMarshal(r.Representation)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
type CapdataValueTransformations struct {
|
|
58
|
-
Bigint func(*CapdataBigint) interface{}
|
|
59
|
-
Remotable func(*CapdataRemotable) interface{}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// upsertCapdataRemotable either adds a new CapdataRemotable to `remotables` at the specified
|
|
63
|
-
// slot index or updates the iface of the value that is already there, ensuring lack of iface name
|
|
64
|
-
// inconsistency (iteration order is not guaranteed to correspond with JSON text like it does in
|
|
65
|
-
// JavaScript, so we must accept encountering the "first" reference to a slot late
|
|
66
|
-
// and must therefore also defer transformations).
|
|
67
|
-
func upsertCapdataRemotable(remotables map[uint64]*CapdataRemotable, slotIndex uint64, id interface{}, iface *string) (*CapdataRemotable, error) {
|
|
68
|
-
r := remotables[slotIndex]
|
|
69
|
-
if r == nil {
|
|
70
|
-
r = new(CapdataRemotable)
|
|
71
|
-
r.Id = id
|
|
72
|
-
r.Iface = iface
|
|
73
|
-
remotables[slotIndex] = r
|
|
74
|
-
} else if iface != nil {
|
|
75
|
-
if r.Iface != nil && *iface != *r.Iface {
|
|
76
|
-
return nil, fmt.Errorf("slot iface mismatch: %q", *iface)
|
|
77
|
-
}
|
|
78
|
-
r.Iface = iface
|
|
79
|
-
}
|
|
80
|
-
return r, nil
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// decodeCapdataLegacyValue decodes the non-smallcaps encoding of
|
|
84
|
-
// https://github.com/endojs/endo/blob/master/packages/marshal/src/encodeToCapData.js
|
|
85
|
-
func decodeCapdataLegacyValue(
|
|
86
|
-
encoded interface{},
|
|
87
|
-
slots []interface{},
|
|
88
|
-
remotables map[uint64]*CapdataRemotable,
|
|
89
|
-
transformations CapdataValueTransformations,
|
|
90
|
-
) (interface{}, error) {
|
|
91
|
-
if arr, ok := encoded.([]interface{}); ok {
|
|
92
|
-
for i, v := range arr {
|
|
93
|
-
decoded, err := decodeCapdataLegacyValue(v, slots, remotables, transformations)
|
|
94
|
-
if err != nil {
|
|
95
|
-
return nil, err
|
|
96
|
-
}
|
|
97
|
-
arr[i] = decoded
|
|
98
|
-
}
|
|
99
|
-
return arr, nil
|
|
100
|
-
} else if obj, ok := encoded.(map[string]interface{}); ok {
|
|
101
|
-
if qclassVal, ok := obj["@qclass"]; ok {
|
|
102
|
-
qclass, ok := qclassVal.(string)
|
|
103
|
-
if !ok {
|
|
104
|
-
return nil, fmt.Errorf("invalid @qclass: %q", qclassVal)
|
|
105
|
-
}
|
|
106
|
-
switch qclass {
|
|
107
|
-
case "bigint":
|
|
108
|
-
var bigint *CapdataBigint
|
|
109
|
-
digitsVal := obj["digits"]
|
|
110
|
-
if digitsStr, ok := digitsVal.(string); ok {
|
|
111
|
-
bigint = NewCapdataBigint(digitsStr)
|
|
112
|
-
}
|
|
113
|
-
if bigint == nil {
|
|
114
|
-
return nil, fmt.Errorf("invalid bigint: %q", digitsVal)
|
|
115
|
-
}
|
|
116
|
-
if transformations.Bigint == nil {
|
|
117
|
-
return nil, fmt.Errorf("untransformed bigint")
|
|
118
|
-
}
|
|
119
|
-
return transformations.Bigint(bigint), nil
|
|
120
|
-
case "slot":
|
|
121
|
-
var iface *string
|
|
122
|
-
slotIndexVal, ifaceVal := obj["index"], obj["iface"]
|
|
123
|
-
slotIndexNum, ok := slotIndexVal.(float64)
|
|
124
|
-
slotIndex := uint64(slotIndexNum)
|
|
125
|
-
if !ok || float64(slotIndex) != slotIndexNum || slotIndex >= uint64(len(slots)) {
|
|
126
|
-
return nil, fmt.Errorf("invalid slot index: %q", slotIndexVal)
|
|
127
|
-
}
|
|
128
|
-
if ifaceStr, ok := ifaceVal.(string); ok {
|
|
129
|
-
iface = &ifaceStr
|
|
130
|
-
} else if ifaceVal != nil {
|
|
131
|
-
return nil, fmt.Errorf("invalid slot iface: %q", ifaceVal)
|
|
132
|
-
}
|
|
133
|
-
return upsertCapdataRemotable(remotables, slotIndex, slots[slotIndex], iface)
|
|
134
|
-
case "hilbert":
|
|
135
|
-
fallthrough
|
|
136
|
-
case "undefined":
|
|
137
|
-
fallthrough
|
|
138
|
-
case "NaN":
|
|
139
|
-
fallthrough
|
|
140
|
-
case "Infinity":
|
|
141
|
-
fallthrough
|
|
142
|
-
case "symbol":
|
|
143
|
-
fallthrough
|
|
144
|
-
case "tagged":
|
|
145
|
-
fallthrough
|
|
146
|
-
case "error":
|
|
147
|
-
fallthrough
|
|
148
|
-
case "-Infinity":
|
|
149
|
-
return nil, fmt.Errorf("not implemented: @qclass %q", qclass)
|
|
150
|
-
default:
|
|
151
|
-
return nil, fmt.Errorf("unrecognized @qclass: %q", qclass)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
for k, v := range obj {
|
|
155
|
-
decoded, err := decodeCapdataLegacyValue(v, slots, remotables, transformations)
|
|
156
|
-
if err != nil {
|
|
157
|
-
return nil, err
|
|
158
|
-
}
|
|
159
|
-
obj[k] = decoded
|
|
160
|
-
}
|
|
161
|
-
return obj, nil
|
|
162
|
-
} else {
|
|
163
|
-
return encoded, nil
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// decodeCapdataSmallcapsValue decodes the "smallcaps" encoding from
|
|
168
|
-
// https://github.com/endojs/endo/blob/master/packages/marshal/src/encodeToSmallcaps.js
|
|
169
|
-
func decodeCapdataSmallcapsValue(
|
|
170
|
-
encoded interface{},
|
|
171
|
-
slots []interface{},
|
|
172
|
-
remotables map[uint64]*CapdataRemotable,
|
|
173
|
-
transformations CapdataValueTransformations,
|
|
174
|
-
) (interface{}, error) {
|
|
175
|
-
if arr, ok := encoded.([]interface{}); ok {
|
|
176
|
-
for i, v := range arr {
|
|
177
|
-
decoded, err := decodeCapdataSmallcapsValue(v, slots, remotables, transformations)
|
|
178
|
-
if err != nil {
|
|
179
|
-
return nil, err
|
|
180
|
-
}
|
|
181
|
-
arr[i] = decoded
|
|
182
|
-
}
|
|
183
|
-
return arr, nil
|
|
184
|
-
} else if encodedObj, ok := encoded.(map[string]interface{}); ok {
|
|
185
|
-
if _, ok := encodedObj["#tag"]; ok {
|
|
186
|
-
return nil, fmt.Errorf("not implemented: #tag")
|
|
187
|
-
}
|
|
188
|
-
if _, ok := encodedObj["#error"]; ok {
|
|
189
|
-
return nil, fmt.Errorf("not implemented: #error")
|
|
190
|
-
}
|
|
191
|
-
// We need a distinct output map to avoid reprocessing already-decoded keys.
|
|
192
|
-
decodedObj := make(map[string]interface{}, len(encodedObj))
|
|
193
|
-
for encodedK, v := range encodedObj {
|
|
194
|
-
if strings.HasPrefix(encodedK, "#") {
|
|
195
|
-
return nil, fmt.Errorf("unrecognized record type: %q", encodedK)
|
|
196
|
-
}
|
|
197
|
-
decodedK, err := decodeCapdataSmallcapsValue(encodedK, slots, remotables, CapdataValueTransformations{})
|
|
198
|
-
k, ok := decodedK.(string)
|
|
199
|
-
if err != nil || !ok {
|
|
200
|
-
return nil, fmt.Errorf("invalid copyRecord key: %q", encodedK)
|
|
201
|
-
}
|
|
202
|
-
decoded, err := decodeCapdataSmallcapsValue(v, slots, remotables, transformations)
|
|
203
|
-
if err != nil {
|
|
204
|
-
return nil, err
|
|
205
|
-
}
|
|
206
|
-
decodedObj[k] = decoded
|
|
207
|
-
}
|
|
208
|
-
return decodedObj, nil
|
|
209
|
-
} else if str, ok := encoded.(string); ok {
|
|
210
|
-
if len(str) == 0 {
|
|
211
|
-
return str, nil
|
|
212
|
-
}
|
|
213
|
-
switch str[0] {
|
|
214
|
-
case '!':
|
|
215
|
-
return str[1:], nil
|
|
216
|
-
case '+':
|
|
217
|
-
// Normalize to no leading "+".
|
|
218
|
-
str = str[1:]
|
|
219
|
-
fallthrough
|
|
220
|
-
case '-':
|
|
221
|
-
bigint := NewCapdataBigint(str)
|
|
222
|
-
if bigint == nil {
|
|
223
|
-
return nil, fmt.Errorf("invalid bigint: %q", encoded.(string))
|
|
224
|
-
}
|
|
225
|
-
if transformations.Bigint == nil {
|
|
226
|
-
return nil, fmt.Errorf("untransformed bigint")
|
|
227
|
-
}
|
|
228
|
-
return transformations.Bigint(bigint), nil
|
|
229
|
-
case '$':
|
|
230
|
-
var slotIndexStr string
|
|
231
|
-
var iface *string
|
|
232
|
-
if dotIndex := strings.IndexByte(str, '.'); dotIndex >= 0 {
|
|
233
|
-
slotIndexStr = str[1:dotIndex]
|
|
234
|
-
ifaceStr := str[dotIndex+1:]
|
|
235
|
-
iface = &ifaceStr
|
|
236
|
-
} else {
|
|
237
|
-
slotIndexStr = str[1:]
|
|
238
|
-
}
|
|
239
|
-
slotIndex, err := strconv.ParseUint(slotIndexStr, 10, 0)
|
|
240
|
-
if err != nil || slotIndex >= uint64(len(slots)) {
|
|
241
|
-
return nil, fmt.Errorf("invalid slot index: %q", str)
|
|
242
|
-
}
|
|
243
|
-
r, err := upsertCapdataRemotable(remotables, slotIndex, slots[slotIndex], iface)
|
|
244
|
-
if err != nil {
|
|
245
|
-
return nil, fmt.Errorf("slot iface mismatch: %q", str)
|
|
246
|
-
}
|
|
247
|
-
return r, nil
|
|
248
|
-
case '#':
|
|
249
|
-
fallthrough
|
|
250
|
-
case '%':
|
|
251
|
-
fallthrough
|
|
252
|
-
case '&':
|
|
253
|
-
return nil, fmt.Errorf("not implemented: %q", str)
|
|
254
|
-
default:
|
|
255
|
-
if str[0] >= '!' && str[0] <= '-' {
|
|
256
|
-
return nil, fmt.Errorf("invalid smallcaps encoding prefix: %q", str[:1])
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
return str, nil
|
|
260
|
-
} else {
|
|
261
|
-
return encoded, nil
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// DecodeSerializedCapdata accepts JSON text representing encoded CapData and
|
|
266
|
-
// decodes it, applying specified transformations for values that otherwise
|
|
267
|
-
// hinder interchange.
|
|
268
|
-
func DecodeSerializedCapdata(
|
|
269
|
-
serializedCapdata string,
|
|
270
|
-
transformations CapdataValueTransformations,
|
|
271
|
-
) (interface{}, error) {
|
|
272
|
-
var capdata Capdata
|
|
273
|
-
if err := json.Unmarshal([]byte(serializedCapdata), &capdata); err != nil {
|
|
274
|
-
return nil, err
|
|
275
|
-
}
|
|
276
|
-
if capdata.Body == "" || capdata.Slots == nil {
|
|
277
|
-
return nil, fmt.Errorf("invalid CapData")
|
|
278
|
-
}
|
|
279
|
-
serializedBody, decodeValue := capdata.Body, decodeCapdataLegacyValue
|
|
280
|
-
if strings.HasPrefix(serializedBody, "#") {
|
|
281
|
-
serializedBody, decodeValue = serializedBody[1:], decodeCapdataSmallcapsValue
|
|
282
|
-
}
|
|
283
|
-
var encoded interface{}
|
|
284
|
-
if err := json.Unmarshal([]byte(serializedBody), &encoded); err != nil {
|
|
285
|
-
return nil, err
|
|
286
|
-
}
|
|
287
|
-
remotables := map[uint64]*CapdataRemotable{}
|
|
288
|
-
decoded, err := decodeValue(encoded, capdata.Slots, remotables, transformations)
|
|
289
|
-
if err == nil && len(remotables) > 0 {
|
|
290
|
-
if transformations.Remotable == nil {
|
|
291
|
-
return nil, fmt.Errorf("untransformed remotable")
|
|
292
|
-
}
|
|
293
|
-
for _, r := range remotables {
|
|
294
|
-
r.Representation = transformations.Remotable(r)
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
return decoded, err
|
|
298
|
-
}
|
|
@@ -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
|
-
}
|