@enbox/dwn-sdk-js 0.1.0 → 0.1.2
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/LICENSE +3 -2
- package/dist/browser.mjs +6 -6
- package/dist/browser.mjs.map +3 -3
- package/dist/esm/src/dwn.js +19 -5
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +5 -1
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/utils/protocols.js +2 -2
- package/dist/esm/src/utils/protocols.js.map +1 -1
- package/dist/esm/tests/fuzz/arbitraries/dwn-message.arbitrary.js +72 -0
- package/dist/esm/tests/fuzz/arbitraries/dwn-message.arbitrary.js.map +1 -0
- package/dist/esm/tests/fuzz/arbitraries/filter.arbitrary.js +53 -0
- package/dist/esm/tests/fuzz/arbitraries/filter.arbitrary.js.map +1 -0
- package/dist/esm/tests/fuzz/arbitraries/jws.arbitrary.js +55 -0
- package/dist/esm/tests/fuzz/arbitraries/jws.arbitrary.js.map +1 -0
- package/dist/esm/tests/fuzz/arbitraries/protocol-definition.arbitrary.js +106 -0
- package/dist/esm/tests/fuzz/arbitraries/protocol-definition.arbitrary.js.map +1 -0
- package/dist/esm/tests/fuzz/arbitraries/store.arbitrary.js +139 -0
- package/dist/esm/tests/fuzz/arbitraries/store.arbitrary.js.map +1 -0
- package/dist/esm/tests/fuzz/cid.fuzz.spec.js +74 -0
- package/dist/esm/tests/fuzz/cid.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/compound-index.fuzz.spec.js +203 -0
- package/dist/esm/tests/fuzz/compound-index.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/data-store.fuzz.spec.js +146 -0
- package/dist/esm/tests/fuzz/data-store.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/data-stream.fuzz.spec.js +44 -0
- package/dist/esm/tests/fuzz/data-stream.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/encoder.fuzz.spec.js +76 -0
- package/dist/esm/tests/fuzz/encoder.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/encryption.fuzz.spec.js +132 -0
- package/dist/esm/tests/fuzz/encryption.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/filter.fuzz.spec.js +149 -0
- package/dist/esm/tests/fuzz/filter.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/get-rule-set-at-path.fuzz.spec.js +82 -0
- package/dist/esm/tests/fuzz/get-rule-set-at-path.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/hd-key.fuzz.spec.js +77 -0
- package/dist/esm/tests/fuzz/hd-key.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/immutable-properties.fuzz.spec.js +86 -0
- package/dist/esm/tests/fuzz/immutable-properties.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/index-level.fuzz.spec.js +195 -0
- package/dist/esm/tests/fuzz/index-level.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/jws.fuzz.spec.js +100 -0
- package/dist/esm/tests/fuzz/jws.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/message-store.fuzz.spec.js +154 -0
- package/dist/esm/tests/fuzz/message-store.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/object.fuzz.spec.js +82 -0
- package/dist/esm/tests/fuzz/object.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js +85 -0
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/protocol-definition.fuzz.spec.js +145 -0
- package/dist/esm/tests/fuzz/protocol-definition.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/protocol-validation.fuzz.spec.js +146 -0
- package/dist/esm/tests/fuzz/protocol-validation.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js +41 -0
- package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/records-utils.fuzz.spec.js +81 -0
- package/dist/esm/tests/fuzz/records-utils.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/resumable-task-store.fuzz.spec.js +106 -0
- package/dist/esm/tests/fuzz/resumable-task-store.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js +126 -0
- package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js +74 -0
- package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/secp256r1.fuzz.spec.js +60 -0
- package/dist/esm/tests/fuzz/secp256r1.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/time.fuzz.spec.js +82 -0
- package/dist/esm/tests/fuzz/time.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/fuzz/url.fuzz.spec.js +118 -0
- package/dist/esm/tests/fuzz/url.fuzz.spec.js.map +1 -0
- package/dist/esm/tests/handlers/records-read.spec.js +6 -2
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/types/src/dwn.d.ts +9 -0
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/handlers/records-read.d.ts.map +1 -1
- package/dist/types/tests/fuzz/arbitraries/dwn-message.arbitrary.d.ts +31 -0
- package/dist/types/tests/fuzz/arbitraries/dwn-message.arbitrary.d.ts.map +1 -0
- package/dist/types/tests/fuzz/arbitraries/filter.arbitrary.d.ts +27 -0
- package/dist/types/tests/fuzz/arbitraries/filter.arbitrary.d.ts.map +1 -0
- package/dist/types/tests/fuzz/arbitraries/jws.arbitrary.d.ts +26 -0
- package/dist/types/tests/fuzz/arbitraries/jws.arbitrary.d.ts.map +1 -0
- package/dist/types/tests/fuzz/arbitraries/protocol-definition.arbitrary.d.ts +31 -0
- package/dist/types/tests/fuzz/arbitraries/protocol-definition.arbitrary.d.ts.map +1 -0
- package/dist/types/tests/fuzz/arbitraries/store.arbitrary.d.ts +71 -0
- package/dist/types/tests/fuzz/arbitraries/store.arbitrary.d.ts.map +1 -0
- package/dist/types/tests/fuzz/cid.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/cid.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/compound-index.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/compound-index.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/data-store.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/data-store.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/data-stream.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/data-stream.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/encoder.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/encoder.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/encryption.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/encryption.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/filter.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/filter.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/get-rule-set-at-path.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/get-rule-set-at-path.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/hd-key.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/hd-key.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/immutable-properties.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/immutable-properties.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/index-level.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/index-level.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/jws.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/jws.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/message-store.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/message-store.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/object.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/object.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/process-message.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/process-message.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/protocol-definition.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/protocol-definition.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/protocol-validation.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/protocol-validation.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/protocols-utils.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/protocols-utils.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/records-utils.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/records-utils.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/resumable-task-store.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/resumable-task-store.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/schema-validation.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/schema-validation.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/secp256k1.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/secp256k1.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/secp256r1.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/secp256r1.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/time.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/time.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/fuzz/url.fuzz.spec.d.ts +2 -0
- package/dist/types/tests/fuzz/url.fuzz.spec.d.ts.map +1 -0
- package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
- package/package.json +8 -5
- package/src/dwn.ts +30 -5
- package/src/handlers/records-read.ts +5 -1
- package/src/utils/protocols.ts +2 -2
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { afterAll, afterEach, beforeAll, describe, expect, it } from 'bun:test';
|
|
2
|
+
import fc from 'fast-check';
|
|
3
|
+
import { IndexLevel } from '../../src/store/index-level.js';
|
|
4
|
+
import { SortDirection } from '../../src/types/query-types.js';
|
|
5
|
+
import { indexedItemSet, indexKeyValues, messageCid } from './arbitraries/store.arbitrary.js';
|
|
6
|
+
const numRuns = Number(process.env.FAST_CHECK_NUM_RUNS) || 100;
|
|
7
|
+
describe('IndexLevel — fuzz', () => {
|
|
8
|
+
let indexLevel;
|
|
9
|
+
const testDataPath = '__TESTDATA__/fuzz-index-level';
|
|
10
|
+
const tenant = 'did:example:fuzz-tenant';
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
indexLevel = new IndexLevel({ location: `${testDataPath}/index` });
|
|
13
|
+
await indexLevel.open();
|
|
14
|
+
});
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await indexLevel.clear();
|
|
17
|
+
});
|
|
18
|
+
afterAll(async () => {
|
|
19
|
+
await indexLevel.close();
|
|
20
|
+
});
|
|
21
|
+
describe('encodeNumberValue — order preservation', () => {
|
|
22
|
+
it('should preserve order for any two integers: a < b implies encode(a) < encode(b)', () => {
|
|
23
|
+
fc.assert(fc.property(fc.integer({ min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER }), fc.integer({ min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER }), (a, b) => {
|
|
24
|
+
const encodedA = IndexLevel.encodeNumberValue(a);
|
|
25
|
+
const encodedB = IndexLevel.encodeNumberValue(b);
|
|
26
|
+
if (a < b) {
|
|
27
|
+
expect(encodedA < encodedB).toBe(true);
|
|
28
|
+
}
|
|
29
|
+
else if (a > b) {
|
|
30
|
+
expect(encodedA > encodedB).toBe(true);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
expect(encodedA).toBe(encodedB);
|
|
34
|
+
}
|
|
35
|
+
}), { numRuns });
|
|
36
|
+
});
|
|
37
|
+
it('should produce consistent results for the same input', () => {
|
|
38
|
+
fc.assert(fc.property(fc.integer({ min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER }), (n) => {
|
|
39
|
+
expect(IndexLevel.encodeNumberValue(n)).toBe(IndexLevel.encodeNumberValue(n));
|
|
40
|
+
}), { numRuns });
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('encodeValue — type consistency', () => {
|
|
44
|
+
it('should return a string for any supported value type', () => {
|
|
45
|
+
fc.assert(fc.property(fc.oneof(fc.string({ minLength: 0, maxLength: 50 }), fc.integer({ min: -10000, max: 10000 }), fc.boolean()), (value) => {
|
|
46
|
+
const encoded = IndexLevel.encodeValue(value);
|
|
47
|
+
expect(typeof encoded).toBe('string');
|
|
48
|
+
expect(encoded.length).toBeGreaterThan(0);
|
|
49
|
+
}), { numRuns });
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
describe('put/query roundtrip', () => {
|
|
53
|
+
it('should find an item by any of its indexed properties after put', async () => {
|
|
54
|
+
await fc.assert(fc.asyncProperty(messageCid(), indexKeyValues(), async (cid, indexes) => {
|
|
55
|
+
await indexLevel.clear();
|
|
56
|
+
await indexLevel.put(tenant, cid, indexes);
|
|
57
|
+
// Query using the first string/number property as an equality filter
|
|
58
|
+
for (const [key, value] of Object.entries(indexes)) {
|
|
59
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
60
|
+
const results = await indexLevel.query(tenant, [{ [key]: value }], {
|
|
61
|
+
sortProperty: 'messageTimestamp',
|
|
62
|
+
sortDirection: SortDirection.Ascending,
|
|
63
|
+
});
|
|
64
|
+
const foundCids = results.map((r) => r.messageCid);
|
|
65
|
+
expect(foundCids).toContain(cid);
|
|
66
|
+
break; // one property is enough to verify the roundtrip
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}), { numRuns: Math.min(numRuns, 50) });
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
describe('put/delete roundtrip', () => {
|
|
73
|
+
it('should not find an item after deletion', async () => {
|
|
74
|
+
await fc.assert(fc.asyncProperty(messageCid(), indexKeyValues(), async (cid, indexes) => {
|
|
75
|
+
await indexLevel.clear();
|
|
76
|
+
await indexLevel.put(tenant, cid, indexes);
|
|
77
|
+
await indexLevel.delete(tenant, cid);
|
|
78
|
+
// Query with empty filter should return nothing
|
|
79
|
+
const results = await indexLevel.query(tenant, [{}], {
|
|
80
|
+
sortProperty: 'messageTimestamp',
|
|
81
|
+
sortDirection: SortDirection.Ascending,
|
|
82
|
+
});
|
|
83
|
+
const foundCids = results.map((r) => r.messageCid);
|
|
84
|
+
expect(foundCids).not.toContain(cid);
|
|
85
|
+
}), { numRuns: Math.min(numRuns, 50) });
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('count equals query length', () => {
|
|
89
|
+
it('should return the same count as query results length for any filter', async () => {
|
|
90
|
+
await fc.assert(fc.asyncProperty(indexedItemSet({ minSize: 3, maxSize: 10 }), async (items) => {
|
|
91
|
+
await indexLevel.clear();
|
|
92
|
+
for (const item of items) {
|
|
93
|
+
await indexLevel.put(tenant, item.cid, item.indexes);
|
|
94
|
+
}
|
|
95
|
+
const queryOptions = {
|
|
96
|
+
sortProperty: 'messageTimestamp',
|
|
97
|
+
sortDirection: SortDirection.Ascending,
|
|
98
|
+
};
|
|
99
|
+
// Count with empty filter
|
|
100
|
+
const count = await indexLevel.count(tenant, [{}], queryOptions);
|
|
101
|
+
const results = await indexLevel.query(tenant, [{}], queryOptions);
|
|
102
|
+
expect(count).toBe(results.length);
|
|
103
|
+
}), { numRuns: Math.min(numRuns, 30) });
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
describe('sort ordering invariant', () => {
|
|
107
|
+
it('should return results sorted by messageTimestamp ascending', async () => {
|
|
108
|
+
await fc.assert(fc.asyncProperty(indexedItemSet({ minSize: 3, maxSize: 15 }), async (items) => {
|
|
109
|
+
await indexLevel.clear();
|
|
110
|
+
for (const item of items) {
|
|
111
|
+
await indexLevel.put(tenant, item.cid, item.indexes);
|
|
112
|
+
}
|
|
113
|
+
const results = await indexLevel.query(tenant, [{}], {
|
|
114
|
+
sortProperty: 'messageTimestamp',
|
|
115
|
+
sortDirection: SortDirection.Ascending,
|
|
116
|
+
});
|
|
117
|
+
for (let i = 1; i < results.length; i++) {
|
|
118
|
+
const prev = IndexLevel.encodeValue(results[i - 1].indexes.messageTimestamp);
|
|
119
|
+
const curr = IndexLevel.encodeValue(results[i].indexes.messageTimestamp);
|
|
120
|
+
// When timestamps are equal, the messageCid acts as tiebreaker
|
|
121
|
+
if (prev === curr) {
|
|
122
|
+
expect(results[i - 1].messageCid <= results[i].messageCid).toBe(true);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
expect(prev <= curr).toBe(true);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}), { numRuns: Math.min(numRuns, 30) });
|
|
129
|
+
});
|
|
130
|
+
it('should return results sorted by messageTimestamp descending', async () => {
|
|
131
|
+
await fc.assert(fc.asyncProperty(indexedItemSet({ minSize: 3, maxSize: 15 }), async (items) => {
|
|
132
|
+
await indexLevel.clear();
|
|
133
|
+
for (const item of items) {
|
|
134
|
+
await indexLevel.put(tenant, item.cid, item.indexes);
|
|
135
|
+
}
|
|
136
|
+
const results = await indexLevel.query(tenant, [{}], {
|
|
137
|
+
sortProperty: 'messageTimestamp',
|
|
138
|
+
sortDirection: SortDirection.Descending,
|
|
139
|
+
});
|
|
140
|
+
for (let i = 1; i < results.length; i++) {
|
|
141
|
+
const prev = IndexLevel.encodeValue(results[i - 1].indexes.messageTimestamp);
|
|
142
|
+
const curr = IndexLevel.encodeValue(results[i].indexes.messageTimestamp);
|
|
143
|
+
if (prev === curr) {
|
|
144
|
+
expect(results[i - 1].messageCid >= results[i].messageCid).toBe(true);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
expect(prev >= curr).toBe(true);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}), { numRuns: Math.min(numRuns, 30) });
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe('pagination completeness', () => {
|
|
154
|
+
it('should yield all items when paginating with any page size', async () => {
|
|
155
|
+
await fc.assert(fc.asyncProperty(indexedItemSet({ minSize: 3, maxSize: 12 }), fc.integer({ min: 1, max: 5 }), async (items, pageSize) => {
|
|
156
|
+
await indexLevel.clear();
|
|
157
|
+
for (const item of items) {
|
|
158
|
+
await indexLevel.put(tenant, item.cid, item.indexes);
|
|
159
|
+
}
|
|
160
|
+
const sortProperty = 'messageTimestamp';
|
|
161
|
+
const queryOptions = {
|
|
162
|
+
sortProperty,
|
|
163
|
+
sortDirection: SortDirection.Ascending,
|
|
164
|
+
limit: pageSize,
|
|
165
|
+
};
|
|
166
|
+
// Get all results without pagination for reference
|
|
167
|
+
const allResults = await indexLevel.query(tenant, [{}], {
|
|
168
|
+
sortProperty,
|
|
169
|
+
sortDirection: SortDirection.Ascending,
|
|
170
|
+
});
|
|
171
|
+
// Paginate through all results
|
|
172
|
+
const paginatedResults = [];
|
|
173
|
+
let cursor = undefined;
|
|
174
|
+
let iterations = 0;
|
|
175
|
+
const maxIterations = allResults.length + 5; // safety bound
|
|
176
|
+
while (iterations < maxIterations) {
|
|
177
|
+
const page = await indexLevel.query(tenant, [{}], { ...queryOptions, cursor });
|
|
178
|
+
if (page.length === 0) {
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
paginatedResults.push(...page.map((r) => r.messageCid));
|
|
182
|
+
// Create cursor from last item for next page
|
|
183
|
+
if (page.length < pageSize) {
|
|
184
|
+
break; // last page
|
|
185
|
+
}
|
|
186
|
+
cursor = IndexLevel.createCursorFromLastArrayItem(page, sortProperty);
|
|
187
|
+
iterations++;
|
|
188
|
+
}
|
|
189
|
+
// All CIDs from pagination should match all CIDs from full query
|
|
190
|
+
expect(paginatedResults).toEqual(allResults.map((r) => r.messageCid));
|
|
191
|
+
}), { numRuns: Math.min(numRuns, 20) });
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
//# sourceMappingURL=index-level.fuzz.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-level.fuzz.spec.js","sourceRoot":"","sources":["../../../../tests/fuzz/index-level.fuzz.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAEhF,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9F,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,GAAG,CAAC;AAE/D,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,UAAsB,CAAC;IAC3B,MAAM,YAAY,GAAG,+BAA+B,CAAC;IACrD,MAAM,MAAM,GAAG,yBAAyB,CAAC;IAEzC,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,UAAU,GAAG,IAAI,UAAU,CAAC,EAAE,QAAQ,EAAE,GAAG,YAAY,QAAQ,EAAE,CAAC,CAAC;QACnE,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;QACtD,EAAE,CAAC,iFAAiF,EAAE,GAAG,EAAE;YACzF,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,gBAAgB,EAAE,GAAG,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,EAC1E,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,gBAAgB,EAAE,GAAG,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,EAC1E,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACP,MAAM,QAAQ,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;gBACjD,MAAM,QAAQ,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;gBACjD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACV,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzC,CAAC;qBAAM,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACjB,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzC,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC,CACF,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,gBAAgB,EAAE,GAAG,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,EAC1E,CAAC,CAAC,EAAE,EAAE;gBACJ,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;YAChF,CAAC,CACF,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;QAC9C,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,EAAE,CAAC,KAAK,CACN,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,EAC1C,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EACvC,EAAE,CAAC,OAAO,EAAE,CACb,EACD,CAAC,KAAK,EAAE,EAAE;gBACR,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBAC9C,MAAM,CAAC,OAAO,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACtC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAC5C,CAAC,CACF,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;YAC9E,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,UAAU,EAAE,EACZ,cAAc,EAAE,EAChB,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;gBACrB,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;gBACzB,MAAM,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;gBAE3C,qEAAqE;gBACrE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;wBACzF,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;4BACjE,YAAY,EAAI,kBAAkB;4BAClC,aAAa,EAAG,aAAa,CAAC,SAAS;yBACxC,CAAC,CAAC;wBACH,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;wBACnD,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;wBACjC,MAAM,CAAC,iDAAiD;oBAC1D,CAAC;gBACH,CAAC;YACH,CAAC,CACF,EACD,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,UAAU,EAAE,EACZ,cAAc,EAAE,EAChB,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;gBACrB,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;gBACzB,MAAM,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;gBAC3C,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;gBAErC,gDAAgD;gBAChD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE;oBACnD,YAAY,EAAI,kBAAkB;oBAClC,aAAa,EAAG,aAAa,CAAC,SAAS;iBACxC,CAAC,CAAC;gBACH,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;gBACnD,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACvC,CAAC,CACF,EACD,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACzC,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;YACnF,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,EAC3C,KAAK,EAAE,KAAK,EAAE,EAAE;gBACd,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;gBAEzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,MAAM,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBACvD,CAAC;gBAED,MAAM,YAAY,GAAG;oBACnB,YAAY,EAAI,kBAAkB;oBAClC,aAAa,EAAG,aAAa,CAAC,SAAS;iBACxC,CAAC;gBAEF,0BAA0B;gBAC1B,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;gBACjE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;gBACnE,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC,CACF,EACD,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,EAC3C,KAAK,EAAE,KAAK,EAAE,EAAE;gBACd,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;gBAEzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,MAAM,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBACvD,CAAC;gBAED,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE;oBACnD,YAAY,EAAI,kBAAkB;oBAClC,aAAa,EAAG,aAAa,CAAC,SAAS;iBACxC,CAAC,CAAC;gBAEH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACxC,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,gBAA0B,CAAC,CAAC;oBACvF,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAA0B,CAAC,CAAC;oBACnF,+DAA+D;oBAC/D,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;wBAClB,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACxE,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAClC,CAAC;gBACH,CAAC;YACH,CAAC,CACF,EACD,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;YAC3E,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,EAC3C,KAAK,EAAE,KAAK,EAAE,EAAE;gBACd,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;gBAEzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,MAAM,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBACvD,CAAC;gBAED,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE;oBACnD,YAAY,EAAI,kBAAkB;oBAClC,aAAa,EAAG,aAAa,CAAC,UAAU;iBACzC,CAAC,CAAC;gBAEH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACxC,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,gBAA0B,CAAC,CAAC;oBACvF,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAA0B,CAAC,CAAC;oBACnF,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;wBAClB,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACxE,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAClC,CAAC;gBACH,CAAC;YACH,CAAC,CACF,EACD,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;YACzE,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,EAC3C,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAC9B,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBACxB,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;gBAEzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,MAAM,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBACvD,CAAC;gBAED,MAAM,YAAY,GAAG,kBAAkB,CAAC;gBACxC,MAAM,YAAY,GAAG;oBACnB,YAAY;oBACZ,aAAa,EAAG,aAAa,CAAC,SAAS;oBACvC,KAAK,EAAW,QAAQ;iBACzB,CAAC;gBAEF,mDAAmD;gBACnD,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE;oBACtD,YAAY;oBACZ,aAAa,EAAE,aAAa,CAAC,SAAS;iBACvC,CAAC,CAAC;gBAEH,+BAA+B;gBAC/B,MAAM,gBAAgB,GAAa,EAAE,CAAC;gBACtC,IAAI,MAAM,GAAG,SAAS,CAAC;gBACvB,IAAI,UAAU,GAAG,CAAC,CAAC;gBACnB,MAAM,aAAa,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,eAAe;gBAE5D,OAAO,UAAU,GAAG,aAAa,EAAE,CAAC;oBAClC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC/E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBACtB,MAAM;oBACR,CAAC;oBAED,gBAAgB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;oBAExD,6CAA6C;oBAC7C,IAAI,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;wBAC3B,MAAM,CAAC,YAAY;oBACrB,CAAC;oBACD,MAAM,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;oBACtE,UAAU,EAAE,CAAC;gBACf,CAAC;gBAED,iEAAiE;gBACjE,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YACxE,CAAC,CACF,EACD,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import fc from 'fast-check';
|
|
3
|
+
import { DwnError } from '../../src/core/dwn-error.js';
|
|
4
|
+
import { Encoder } from '../../src/utils/encoder.js';
|
|
5
|
+
import { Jws } from '../../src/utils/jws.js';
|
|
6
|
+
import { generalJws, malformedJws } from './arbitraries/jws.arbitrary.js';
|
|
7
|
+
const numRuns = Number(process.env.FAST_CHECK_NUM_RUNS) || 200;
|
|
8
|
+
describe('Jws — fuzz', () => {
|
|
9
|
+
describe('decodePlainObjectPayload — crash resistance with random JWS', () => {
|
|
10
|
+
it('should throw DwnError on malformed JWS payloads, never an unhandled error', () => {
|
|
11
|
+
fc.assert(fc.property(generalJws(), (jws) => {
|
|
12
|
+
try {
|
|
13
|
+
Jws.decodePlainObjectPayload(jws);
|
|
14
|
+
// If it succeeds, the decoded value should be a plain object
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
expect(error).toBeInstanceOf(DwnError);
|
|
18
|
+
}
|
|
19
|
+
}), { numRuns });
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
describe('decodePlainObjectPayload — crash resistance with malformed JWS', () => {
|
|
23
|
+
it('should handle completely malformed JWS-like structures', () => {
|
|
24
|
+
fc.assert(fc.property(malformedJws(), (jws) => {
|
|
25
|
+
try {
|
|
26
|
+
Jws.decodePlainObjectPayload(jws);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
// Any error is acceptable — verify no unhandled crash
|
|
30
|
+
expect(error).toBeDefined();
|
|
31
|
+
}
|
|
32
|
+
}), { numRuns });
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe('decodePlainObjectPayload — roundtrip with valid encoded objects', () => {
|
|
36
|
+
it('should decode a payload that was properly base64url-encoded from a plain object', () => {
|
|
37
|
+
fc.assert(fc.property(fc.dictionary(fc.string({ minLength: 1, maxLength: 20 }), fc.oneof(fc.string(), fc.integer(), fc.boolean(), fc.constant(null)), { minKeys: 1, maxKeys: 5 }), (obj) => {
|
|
38
|
+
const payload = Encoder.stringToBase64Url(JSON.stringify(obj));
|
|
39
|
+
const jws = { payload, signatures: [] };
|
|
40
|
+
const decoded = Jws.decodePlainObjectPayload(jws);
|
|
41
|
+
expect(decoded).toEqual(obj);
|
|
42
|
+
}), { numRuns });
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe('decodePlainObjectPayload — rejects non-object payloads', () => {
|
|
46
|
+
it('should throw DwnError when the decoded payload is not a plain object', () => {
|
|
47
|
+
fc.assert(fc.property(fc.oneof(fc.string(), fc.integer(), fc.boolean(), fc.constant(null), fc.array(fc.integer())), (value) => {
|
|
48
|
+
const payload = Encoder.stringToBase64Url(JSON.stringify(value));
|
|
49
|
+
const jws = { payload, signatures: [] };
|
|
50
|
+
try {
|
|
51
|
+
Jws.decodePlainObjectPayload(jws);
|
|
52
|
+
// Arrays might pass isPlainObject, strings/numbers/booleans/null should not
|
|
53
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
54
|
+
expect(true).toBe(false); // should have thrown
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
expect(error).toBeInstanceOf(DwnError);
|
|
59
|
+
}
|
|
60
|
+
}), { numRuns });
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('getKid — crash resistance', () => {
|
|
64
|
+
it('should handle signature entries with random protected headers', () => {
|
|
65
|
+
fc.assert(fc.property(fc.string({ minLength: 1, maxLength: 100 }), (protectedHeader) => {
|
|
66
|
+
try {
|
|
67
|
+
Jws.getKid({ protected: protectedHeader, signature: 'dummysig' });
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Any error is acceptable — we verify no unhandled crash
|
|
71
|
+
}
|
|
72
|
+
}), { numRuns });
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('getKid — roundtrip with valid protected headers', () => {
|
|
76
|
+
it('should extract kid from a properly encoded protected header', () => {
|
|
77
|
+
fc.assert(fc.property(fc.string({ minLength: 1, maxLength: 50 }), (kid) => {
|
|
78
|
+
const protectedHeader = Encoder.stringToBase64Url(JSON.stringify({ kid }));
|
|
79
|
+
const extracted = Jws.getKid({ protected: protectedHeader, signature: 'dummysig' });
|
|
80
|
+
expect(extracted).toBe(kid);
|
|
81
|
+
}), { numRuns });
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('extractDid — property', () => {
|
|
85
|
+
it('should extract the part before # from a kid string', () => {
|
|
86
|
+
fc.assert(fc.property(fc.string({ minLength: 1, maxLength: 50 }).filter((s) => !s.includes('#')), fc.string({ minLength: 1, maxLength: 20 }), (did, fragment) => {
|
|
87
|
+
const kid = `${did}#${fragment}`;
|
|
88
|
+
const extracted = Jws.extractDid(kid);
|
|
89
|
+
expect(extracted).toBe(did);
|
|
90
|
+
}), { numRuns });
|
|
91
|
+
});
|
|
92
|
+
it('should return the full string if there is no # separator', () => {
|
|
93
|
+
fc.assert(fc.property(fc.string({ minLength: 1, maxLength: 50 }).filter((s) => !s.includes('#')), (kid) => {
|
|
94
|
+
const extracted = Jws.extractDid(kid);
|
|
95
|
+
expect(extracted).toBe(kid);
|
|
96
|
+
}), { numRuns });
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=jws.fuzz.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jws.fuzz.spec.js","sourceRoot":"","sources":["../../../../tests/fuzz/jws.fuzz.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { afterAll, afterEach, beforeAll, describe, expect, it } from 'bun:test';
|
|
2
|
+
import fc from 'fast-check';
|
|
3
|
+
import { Message } from '../../src/core/message.js';
|
|
4
|
+
import { MessageStoreLevel } from '../../src/store/message-store-level.js';
|
|
5
|
+
import { SortDirection } from '../../src/types/query-types.js';
|
|
6
|
+
import { genericMessage, genericMessageSet, indexKeyValues, tenantDid } from './arbitraries/store.arbitrary.js';
|
|
7
|
+
const numRuns = Number(process.env.FAST_CHECK_NUM_RUNS) || 100;
|
|
8
|
+
describe('MessageStoreLevel — fuzz', () => {
|
|
9
|
+
let messageStore;
|
|
10
|
+
const testDataPath = '__TESTDATA__/fuzz-message-store';
|
|
11
|
+
const tenant = 'did:example:fuzz-message-tenant';
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
messageStore = new MessageStoreLevel({
|
|
14
|
+
blockstoreLocation: `${testDataPath}/blocks`,
|
|
15
|
+
indexLocation: `${testDataPath}/index`,
|
|
16
|
+
});
|
|
17
|
+
await messageStore.open();
|
|
18
|
+
});
|
|
19
|
+
afterEach(async () => {
|
|
20
|
+
await messageStore.clear();
|
|
21
|
+
});
|
|
22
|
+
afterAll(async () => {
|
|
23
|
+
await messageStore.close();
|
|
24
|
+
});
|
|
25
|
+
describe('put/get CID roundtrip', () => {
|
|
26
|
+
it('should store and retrieve any message by its computed CID', async () => {
|
|
27
|
+
await fc.assert(fc.asyncProperty(genericMessage(), indexKeyValues(), async (message, indexes) => {
|
|
28
|
+
await messageStore.clear();
|
|
29
|
+
// Ensure indexes include the message's own timestamp
|
|
30
|
+
indexes.messageTimestamp = message.descriptor.messageTimestamp;
|
|
31
|
+
await messageStore.put(tenant, message, indexes);
|
|
32
|
+
const cid = await Message.getCid(message);
|
|
33
|
+
const retrieved = await messageStore.get(tenant, cid);
|
|
34
|
+
expect(retrieved).toBeDefined();
|
|
35
|
+
expect(retrieved.descriptor.interface).toBe(message.descriptor.interface);
|
|
36
|
+
expect(retrieved.descriptor.method).toBe(message.descriptor.method);
|
|
37
|
+
expect(retrieved.descriptor.messageTimestamp).toBe(message.descriptor.messageTimestamp);
|
|
38
|
+
// The retrieved CID should match the original
|
|
39
|
+
const retrievedCid = await Message.getCid(retrieved);
|
|
40
|
+
expect(retrievedCid).toBe(cid);
|
|
41
|
+
}), { numRuns: Math.min(numRuns, 30) });
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('get returns undefined for missing CID', () => {
|
|
45
|
+
it('should return undefined for a CID that was never stored', async () => {
|
|
46
|
+
await fc.assert(fc.asyncProperty(genericMessage(), async (message) => {
|
|
47
|
+
// Don't store the message — just compute its CID
|
|
48
|
+
const cid = await Message.getCid(message);
|
|
49
|
+
const retrieved = await messageStore.get(tenant, cid);
|
|
50
|
+
expect(retrieved).toBeUndefined();
|
|
51
|
+
}), { numRuns: Math.min(numRuns, 30) });
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe('put/delete roundtrip', () => {
|
|
55
|
+
it('should return undefined after deleting a message', async () => {
|
|
56
|
+
await fc.assert(fc.asyncProperty(genericMessage(), indexKeyValues(), async (message, indexes) => {
|
|
57
|
+
await messageStore.clear();
|
|
58
|
+
indexes.messageTimestamp = message.descriptor.messageTimestamp;
|
|
59
|
+
await messageStore.put(tenant, message, indexes);
|
|
60
|
+
const cid = await Message.getCid(message);
|
|
61
|
+
await messageStore.delete(tenant, cid);
|
|
62
|
+
const retrieved = await messageStore.get(tenant, cid);
|
|
63
|
+
expect(retrieved).toBeUndefined();
|
|
64
|
+
}), { numRuns: Math.min(numRuns, 30) });
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('tenant isolation', () => {
|
|
68
|
+
it('should not allow one tenant to read another tenant\'s messages', async () => {
|
|
69
|
+
await fc.assert(fc.asyncProperty(tenantDid(), tenantDid(), genericMessage(), indexKeyValues(), async (tenant1, tenant2, message, indexes) => {
|
|
70
|
+
if (tenant1 === tenant2) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
await messageStore.clear();
|
|
74
|
+
indexes.messageTimestamp = message.descriptor.messageTimestamp;
|
|
75
|
+
await messageStore.put(tenant1, message, indexes);
|
|
76
|
+
const cid = await Message.getCid(message);
|
|
77
|
+
const retrieved = await messageStore.get(tenant2, cid);
|
|
78
|
+
expect(retrieved).toBeUndefined();
|
|
79
|
+
}), { numRuns: Math.min(numRuns, 20) });
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe('count consistency', () => {
|
|
83
|
+
it('should return the same count as query results length', async () => {
|
|
84
|
+
await fc.assert(fc.asyncProperty(genericMessageSet({ minSize: 2, maxSize: 8 }), async (items) => {
|
|
85
|
+
await messageStore.clear();
|
|
86
|
+
for (const { message, indexes } of items) {
|
|
87
|
+
indexes.messageTimestamp = message.descriptor.messageTimestamp;
|
|
88
|
+
await messageStore.put(tenant, message, indexes);
|
|
89
|
+
}
|
|
90
|
+
const messageSort = { messageTimestamp: SortDirection.Ascending };
|
|
91
|
+
const count = await messageStore.count(tenant, [{}], messageSort);
|
|
92
|
+
const { messages } = await messageStore.query(tenant, [{}], messageSort);
|
|
93
|
+
expect(count).toBe(messages.length);
|
|
94
|
+
}), { numRuns: Math.min(numRuns, 15) });
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe('pagination completeness', () => {
|
|
98
|
+
it('should yield all messages when paginating with any page size', async () => {
|
|
99
|
+
await fc.assert(fc.asyncProperty(genericMessageSet({ minSize: 3, maxSize: 8 }), fc.integer({ min: 1, max: 4 }), async (items, pageSize) => {
|
|
100
|
+
await messageStore.clear();
|
|
101
|
+
for (const { message, indexes } of items) {
|
|
102
|
+
indexes.messageTimestamp = message.descriptor.messageTimestamp;
|
|
103
|
+
await messageStore.put(tenant, message, indexes);
|
|
104
|
+
}
|
|
105
|
+
const messageSort = { messageTimestamp: SortDirection.Ascending };
|
|
106
|
+
// Get all results without pagination for reference
|
|
107
|
+
const { messages: allMessages } = await messageStore.query(tenant, [{}], messageSort);
|
|
108
|
+
// Paginate through all results
|
|
109
|
+
const paginatedCids = [];
|
|
110
|
+
let cursor = undefined;
|
|
111
|
+
let iterations = 0;
|
|
112
|
+
const maxIterations = allMessages.length + 5; // safety bound
|
|
113
|
+
while (iterations < maxIterations) {
|
|
114
|
+
const { messages: page, cursor: nextCursor } = await messageStore.query(tenant, [{}], messageSort, { limit: pageSize, cursor });
|
|
115
|
+
if (page.length === 0) {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
for (const msg of page) {
|
|
119
|
+
paginatedCids.push(await Message.getCid(msg));
|
|
120
|
+
}
|
|
121
|
+
if (!nextCursor) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
cursor = nextCursor;
|
|
125
|
+
iterations++;
|
|
126
|
+
}
|
|
127
|
+
// All CIDs from pagination should match all CIDs from full query
|
|
128
|
+
const allCids = [];
|
|
129
|
+
for (const msg of allMessages) {
|
|
130
|
+
allCids.push(await Message.getCid(msg));
|
|
131
|
+
}
|
|
132
|
+
expect(paginatedCids).toEqual(allCids);
|
|
133
|
+
}), { numRuns: Math.min(numRuns, 10) });
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
describe('idempotent put', () => {
|
|
137
|
+
it('should allow putting the same message twice without error', async () => {
|
|
138
|
+
await fc.assert(fc.asyncProperty(genericMessage(), indexKeyValues(), async (message, indexes) => {
|
|
139
|
+
await messageStore.clear();
|
|
140
|
+
indexes.messageTimestamp = message.descriptor.messageTimestamp;
|
|
141
|
+
// Put the same message twice
|
|
142
|
+
await messageStore.put(tenant, message, indexes);
|
|
143
|
+
await messageStore.put(tenant, message, indexes);
|
|
144
|
+
const cid = await Message.getCid(message);
|
|
145
|
+
const retrieved = await messageStore.get(tenant, cid);
|
|
146
|
+
expect(retrieved).toBeDefined();
|
|
147
|
+
// Should still only count as one message
|
|
148
|
+
const count = await messageStore.count(tenant, [{}], { messageTimestamp: SortDirection.Ascending });
|
|
149
|
+
expect(count).toBe(1);
|
|
150
|
+
}), { numRuns: Math.min(numRuns, 20) });
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
//# sourceMappingURL=message-store.fuzz.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-store.fuzz.spec.js","sourceRoot":"","sources":["../../../../tests/fuzz/message-store.fuzz.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import fc from 'fast-check';
|
|
3
|
+
import { isEmptyObject, removeEmptyObjects, removeUndefinedProperties } from '../../src/utils/object.js';
|
|
4
|
+
const numRuns = Number(process.env.FAST_CHECK_NUM_RUNS) || 100;
|
|
5
|
+
/**
|
|
6
|
+
* Generates nested objects with a mix of primitives, undefined values, and empty objects.
|
|
7
|
+
* Excludes null in nested positions — the production code's recursive helpers
|
|
8
|
+
* (`removeUndefinedProperties`, `removeEmptyObjects`) call `Object.keys()` on
|
|
9
|
+
* values where `typeof value === 'object'`, which includes `null` and would throw.
|
|
10
|
+
* Real DWN messages use `undefined` (not `null`) for absent properties.
|
|
11
|
+
*/
|
|
12
|
+
function nestedObject() {
|
|
13
|
+
const leaf = fc.oneof(fc.string(), fc.integer(), fc.boolean(), fc.constant(undefined), fc.constant({}));
|
|
14
|
+
return fc.dictionary(fc.string({ minLength: 1, maxLength: 10 }), fc.oneof(leaf, fc.dictionary(fc.string({ minLength: 1, maxLength: 8 }), leaf, { minKeys: 0, maxKeys: 3 })), { minKeys: 0, maxKeys: 5 });
|
|
15
|
+
}
|
|
16
|
+
/** Check that no property in the (possibly nested) object is undefined. */
|
|
17
|
+
function hasNoUndefined(obj) {
|
|
18
|
+
for (const key of Object.keys(obj)) {
|
|
19
|
+
if (obj[key] === undefined) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
|
23
|
+
if (!hasNoUndefined(obj[key])) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
describe('Object utilities — fuzz', () => {
|
|
31
|
+
describe('isEmptyObject', () => {
|
|
32
|
+
it('should return false for all primitives', () => {
|
|
33
|
+
fc.assert(fc.property(fc.oneof(fc.string(), fc.integer(), fc.float(), fc.boolean(), fc.constant(undefined)), (value) => {
|
|
34
|
+
expect(isEmptyObject(value)).toBe(false);
|
|
35
|
+
}), { numRuns });
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe('removeUndefinedProperties — idempotency', () => {
|
|
39
|
+
it('should produce the same result when applied twice', () => {
|
|
40
|
+
fc.assert(fc.property(nestedObject(), (obj) => {
|
|
41
|
+
const clone1 = structuredClone(obj);
|
|
42
|
+
const clone2 = structuredClone(obj);
|
|
43
|
+
removeUndefinedProperties(clone1);
|
|
44
|
+
removeUndefinedProperties(clone2);
|
|
45
|
+
removeUndefinedProperties(clone2); // second pass
|
|
46
|
+
expect(clone2).toEqual(clone1);
|
|
47
|
+
}), { numRuns });
|
|
48
|
+
});
|
|
49
|
+
it('should leave no undefined properties after one pass', () => {
|
|
50
|
+
fc.assert(fc.property(nestedObject(), (obj) => {
|
|
51
|
+
removeUndefinedProperties(obj);
|
|
52
|
+
expect(hasNoUndefined(obj)).toBe(true);
|
|
53
|
+
}), { numRuns });
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('removeEmptyObjects — idempotency', () => {
|
|
57
|
+
it('should produce the same result when applied twice', () => {
|
|
58
|
+
fc.assert(fc.property(nestedObject(), (obj) => {
|
|
59
|
+
const clone1 = structuredClone(obj);
|
|
60
|
+
const clone2 = structuredClone(obj);
|
|
61
|
+
removeEmptyObjects(clone1);
|
|
62
|
+
removeEmptyObjects(clone2);
|
|
63
|
+
removeEmptyObjects(clone2); // second pass
|
|
64
|
+
expect(clone2).toEqual(clone1);
|
|
65
|
+
}), { numRuns });
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('removeUndefinedProperties then removeEmptyObjects — clean result', () => {
|
|
69
|
+
it('should leave an object with no undefined properties and no empty objects', () => {
|
|
70
|
+
fc.assert(fc.property(nestedObject(), (obj) => {
|
|
71
|
+
removeUndefinedProperties(obj);
|
|
72
|
+
removeEmptyObjects(obj);
|
|
73
|
+
// After both passes: no undefined, no empty objects
|
|
74
|
+
expect(hasNoUndefined(obj)).toBe(true);
|
|
75
|
+
for (const key of Object.keys(obj)) {
|
|
76
|
+
expect(isEmptyObject(obj[key])).toBe(false);
|
|
77
|
+
}
|
|
78
|
+
}), { numRuns });
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=object.fuzz.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object.fuzz.spec.js","sourceRoot":"","sources":["../../../../tests/fuzz/object.fuzz.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEzG,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,GAAG,CAAC;AAE/D;;;;;;GAMG;AACH,SAAS,YAAY;IACnB,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CACnB,EAAE,CAAC,MAAM,EAAE,EACX,EAAE,CAAC,OAAO,EAAE,EACZ,EAAE,CAAC,OAAO,EAAE,EACZ,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EACtB,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAChB,CAAC;IACF,OAAO,EAAE,CAAC,UAAU,CAClB,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,EAC1C,EAAE,CAAC,KAAK,CACN,IAAI,EACJ,EAAE,CAAC,UAAU,CACX,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EACzC,IAAI,EACJ,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAC3B,CACF,EACD,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAC3B,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,SAAS,cAAc,CAAC,GAA4B;IAClD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;QAC7C,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;YACtD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAA4B,CAAC,EAAE,CAAC;gBAAC,OAAO,KAAK,CAAC;YAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IAEvC,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,EAAE,CAAC,KAAK,CACN,EAAE,CAAC,MAAM,EAAE,EACX,EAAE,CAAC,OAAO,EAAE,EACZ,EAAE,CAAC,KAAK,EAAE,EACV,EAAE,CAAC,OAAO,EAAE,EACZ,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CACvB,EACD,CAAC,KAAK,EAAE,EAAE;gBACR,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3C,CAAC,CACF,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACvD,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,YAAY,EAAE,EACd,CAAC,GAAG,EAAE,EAAE;gBACN,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;gBACpC,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;gBAEpC,yBAAyB,CAAC,MAAM,CAAC,CAAC;gBAClC,yBAAyB,CAAC,MAAM,CAAC,CAAC;gBAClC,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc;gBAEjD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACjC,CAAC,CACF,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,YAAY,EAAE,EACd,CAAC,GAAG,EAAE,EAAE;gBACN,yBAAyB,CAAC,GAAG,CAAC,CAAC;gBAC/B,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzC,CAAC,CACF,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,YAAY,EAAE,EACd,CAAC,GAAG,EAAE,EAAE;gBACN,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;gBACpC,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;gBAEpC,kBAAkB,CAAC,MAAM,CAAC,CAAC;gBAC3B,kBAAkB,CAAC,MAAM,CAAC,CAAC;gBAC3B,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc;gBAE1C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACjC,CAAC,CACF,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAChF,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;YAClF,EAAE,CAAC,MAAM,CACP,EAAE,CAAC,QAAQ,CACT,YAAY,EAAE,EACd,CAAC,GAAG,EAAE,EAAE;gBACN,yBAAyB,CAAC,GAAG,CAAC,CAAC;gBAC/B,kBAAkB,CAAC,GAAG,CAAC,CAAC;gBAExB,oDAAoD;gBACpD,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACvC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACnC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC,CACF,EACD,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|