@durable-streams/client-conformance-tests 0.1.9 → 0.2.1
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/dist/adapters/typescript-adapter.cjs +109 -33
- package/dist/adapters/typescript-adapter.js +110 -34
- package/dist/{benchmark-runner-DliEfq9k.cjs → benchmark-runner-BQiarXdy.cjs} +80 -2
- package/dist/{benchmark-runner-81waaCzs.js → benchmark-runner-IGT51RTF.js} +80 -2
- package/dist/cli.cjs +2 -2
- package/dist/cli.js +2 -2
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +91 -3
- package/dist/index.d.ts +91 -3
- package/dist/index.js +2 -2
- package/dist/{protocol-BxZTqJmO.d.cts → protocol-9WN0gRRQ.d.ts} +97 -3
- package/dist/{protocol-1p0soayz.js → protocol-BnqUAMKe.js} +1 -0
- package/dist/{protocol-JuFzdV5x.d.ts → protocol-COHkkGmU.d.cts} +97 -3
- package/dist/{protocol-IioVPNaP.cjs → protocol-sDk3deGa.cjs} +1 -0
- package/dist/protocol.cjs +1 -1
- package/dist/protocol.d.cts +2 -2
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.js +1 -1
- package/package.json +3 -3
- package/src/adapters/typescript-adapter.ts +175 -36
- package/src/protocol.ts +108 -0
- package/src/runner.ts +143 -0
- package/src/test-cases.ts +102 -0
- package/test-cases/consumer/message-ordering.yaml +1 -0
- package/test-cases/consumer/offset-handling.yaml +3 -0
- package/test-cases/consumer/read-sse-base64.yaml +663 -0
- package/test-cases/consumer/read-sse.yaml +6 -1
- package/test-cases/consumer/sse-parsing-errors.yaml +4 -0
- package/test-cases/consumer/streaming-equivalence.yaml +6 -0
- package/test-cases/lifecycle/stream-closure.yaml +759 -0
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
id: consumer-sse-base64
|
|
2
|
+
name: SSE Base64 Encoding
|
|
3
|
+
description: Tests for auto-detected base64 encoding of binary data in SSE mode (Protocol Section 5.7)
|
|
4
|
+
category: consumer
|
|
5
|
+
tags:
|
|
6
|
+
- sse
|
|
7
|
+
- base64
|
|
8
|
+
- binary
|
|
9
|
+
requires:
|
|
10
|
+
- sse
|
|
11
|
+
|
|
12
|
+
tests:
|
|
13
|
+
- id: sse-base64-basic
|
|
14
|
+
name: SSE decodes base64 binary data
|
|
15
|
+
description: Client should decode base64-encoded SSE data events for binary streams
|
|
16
|
+
setup:
|
|
17
|
+
- action: create
|
|
18
|
+
as: streamPath
|
|
19
|
+
contentType: application/octet-stream
|
|
20
|
+
- action: append
|
|
21
|
+
path: ${streamPath}
|
|
22
|
+
binaryData: "SGVsbG8gV29ybGQ=" # "Hello World" in base64
|
|
23
|
+
operations:
|
|
24
|
+
- action: read
|
|
25
|
+
path: ${streamPath}
|
|
26
|
+
live: sse
|
|
27
|
+
waitForUpToDate: true
|
|
28
|
+
expect:
|
|
29
|
+
minChunks: 1
|
|
30
|
+
upToDate: true
|
|
31
|
+
|
|
32
|
+
# Data integrity verification tests
|
|
33
|
+
- id: sse-base64-data-integrity-simple
|
|
34
|
+
name: SSE base64 data integrity - simple text
|
|
35
|
+
description: Verify decoded data matches original content exactly
|
|
36
|
+
setup:
|
|
37
|
+
- action: create
|
|
38
|
+
as: streamPath
|
|
39
|
+
contentType: application/octet-stream
|
|
40
|
+
- action: append
|
|
41
|
+
path: ${streamPath}
|
|
42
|
+
binaryData: "SGVsbG8gV29ybGQ=" # "Hello World" in base64
|
|
43
|
+
operations:
|
|
44
|
+
- action: read
|
|
45
|
+
path: ${streamPath}
|
|
46
|
+
live: sse
|
|
47
|
+
waitForUpToDate: true
|
|
48
|
+
expect:
|
|
49
|
+
minChunks: 1
|
|
50
|
+
upToDate: true
|
|
51
|
+
data: "Hello World"
|
|
52
|
+
|
|
53
|
+
- id: sse-base64-data-integrity-multiline
|
|
54
|
+
name: SSE base64 data integrity - multiline text
|
|
55
|
+
skip: "Swift implementation broken"
|
|
56
|
+
description: Verify multiline text content decodes correctly
|
|
57
|
+
setup:
|
|
58
|
+
- action: create
|
|
59
|
+
as: streamPath
|
|
60
|
+
contentType: application/octet-stream
|
|
61
|
+
- action: append
|
|
62
|
+
path: ${streamPath}
|
|
63
|
+
# "Line 1\nLine 2\nLine 3" in base64
|
|
64
|
+
binaryData: "TGluZSAxCkxpbmUgMgpMaW5lIDM="
|
|
65
|
+
operations:
|
|
66
|
+
- action: read
|
|
67
|
+
path: ${streamPath}
|
|
68
|
+
live: sse
|
|
69
|
+
waitForUpToDate: true
|
|
70
|
+
expect:
|
|
71
|
+
minChunks: 1
|
|
72
|
+
upToDate: true
|
|
73
|
+
dataContains: "Line 1"
|
|
74
|
+
dataContainsAll:
|
|
75
|
+
- "Line 1"
|
|
76
|
+
- "Line 2"
|
|
77
|
+
- "Line 3"
|
|
78
|
+
|
|
79
|
+
- id: sse-base64-data-integrity-multiple-appends
|
|
80
|
+
name: SSE base64 data integrity - multiple appends
|
|
81
|
+
description: Verify multiple appends are decoded and concatenated correctly
|
|
82
|
+
setup:
|
|
83
|
+
- action: create
|
|
84
|
+
as: streamPath
|
|
85
|
+
contentType: application/octet-stream
|
|
86
|
+
- action: append
|
|
87
|
+
path: ${streamPath}
|
|
88
|
+
binaryData: "Zmlyc3Q=" # "first" in base64
|
|
89
|
+
- action: append
|
|
90
|
+
path: ${streamPath}
|
|
91
|
+
binaryData: "c2Vjb25k" # "second" in base64
|
|
92
|
+
- action: append
|
|
93
|
+
path: ${streamPath}
|
|
94
|
+
binaryData: "dGhpcmQ=" # "third" in base64
|
|
95
|
+
operations:
|
|
96
|
+
- action: read
|
|
97
|
+
path: ${streamPath}
|
|
98
|
+
live: sse
|
|
99
|
+
waitForUpToDate: true
|
|
100
|
+
expect:
|
|
101
|
+
minChunks: 1
|
|
102
|
+
upToDate: true
|
|
103
|
+
dataContainsAll:
|
|
104
|
+
- "first"
|
|
105
|
+
- "second"
|
|
106
|
+
- "third"
|
|
107
|
+
|
|
108
|
+
- id: sse-base64-data-integrity-ascii
|
|
109
|
+
name: SSE base64 data integrity - ASCII printable characters
|
|
110
|
+
description: Verify all printable ASCII characters (32-126) decode correctly
|
|
111
|
+
setup:
|
|
112
|
+
- action: create
|
|
113
|
+
as: streamPath
|
|
114
|
+
contentType: application/octet-stream
|
|
115
|
+
- action: append
|
|
116
|
+
path: ${streamPath}
|
|
117
|
+
# All printable ASCII chars: space through tilde
|
|
118
|
+
# " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
|
119
|
+
binaryData: "ICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX4="
|
|
120
|
+
operations:
|
|
121
|
+
- action: read
|
|
122
|
+
path: ${streamPath}
|
|
123
|
+
live: sse
|
|
124
|
+
waitForUpToDate: true
|
|
125
|
+
expect:
|
|
126
|
+
minChunks: 1
|
|
127
|
+
upToDate: true
|
|
128
|
+
dataContainsAll:
|
|
129
|
+
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
130
|
+
- "abcdefghijklmnopqrstuvwxyz"
|
|
131
|
+
- "0123456789"
|
|
132
|
+
|
|
133
|
+
- id: sse-base64-data-integrity-json-like
|
|
134
|
+
name: SSE base64 data integrity - JSON-like content
|
|
135
|
+
description: Verify JSON-like binary content is preserved through base64 encoding
|
|
136
|
+
setup:
|
|
137
|
+
- action: create
|
|
138
|
+
as: streamPath
|
|
139
|
+
contentType: application/octet-stream
|
|
140
|
+
- action: append
|
|
141
|
+
path: ${streamPath}
|
|
142
|
+
# {"key":"value","num":42} in base64
|
|
143
|
+
binaryData: "eyJrZXkiOiJ2YWx1ZSIsIm51bSI6NDJ9"
|
|
144
|
+
operations:
|
|
145
|
+
- action: read
|
|
146
|
+
path: ${streamPath}
|
|
147
|
+
live: sse
|
|
148
|
+
waitForUpToDate: true
|
|
149
|
+
expect:
|
|
150
|
+
minChunks: 1
|
|
151
|
+
upToDate: true
|
|
152
|
+
data: '{"key":"value","num":42}'
|
|
153
|
+
|
|
154
|
+
- id: sse-base64-empty-payload
|
|
155
|
+
name: SSE handles empty base64 payload
|
|
156
|
+
description: Empty binary data should be encoded as empty base64 and decoded correctly
|
|
157
|
+
setup:
|
|
158
|
+
- action: create
|
|
159
|
+
as: streamPath
|
|
160
|
+
contentType: application/octet-stream
|
|
161
|
+
- action: append
|
|
162
|
+
path: ${streamPath}
|
|
163
|
+
binaryData: "" # empty payload
|
|
164
|
+
operations:
|
|
165
|
+
- action: read
|
|
166
|
+
path: ${streamPath}
|
|
167
|
+
live: sse
|
|
168
|
+
waitForUpToDate: true
|
|
169
|
+
expect:
|
|
170
|
+
upToDate: true
|
|
171
|
+
|
|
172
|
+
- id: sse-base64-special-bytes
|
|
173
|
+
name: SSE handles special binary bytes
|
|
174
|
+
description: Binary data with null bytes, 0xFF, and other special values should round-trip correctly
|
|
175
|
+
setup:
|
|
176
|
+
- action: create
|
|
177
|
+
as: streamPath
|
|
178
|
+
contentType: application/octet-stream
|
|
179
|
+
- action: append
|
|
180
|
+
path: ${streamPath}
|
|
181
|
+
binaryData: "AP/+/fw=" # bytes: 0x00, 0xFF, 0xFE, 0xFD, 0xFC
|
|
182
|
+
operations:
|
|
183
|
+
- action: read
|
|
184
|
+
path: ${streamPath}
|
|
185
|
+
live: sse
|
|
186
|
+
waitForUpToDate: true
|
|
187
|
+
expect:
|
|
188
|
+
minChunks: 1
|
|
189
|
+
upToDate: true
|
|
190
|
+
|
|
191
|
+
- id: sse-base64-large-payload
|
|
192
|
+
name: SSE handles large base64 payload
|
|
193
|
+
description: Large binary payloads should be encoded and decoded correctly
|
|
194
|
+
setup:
|
|
195
|
+
- action: create
|
|
196
|
+
as: streamPath
|
|
197
|
+
contentType: application/octet-stream
|
|
198
|
+
- action: append
|
|
199
|
+
path: ${streamPath}
|
|
200
|
+
# 1KB of repeated pattern (base64 of 0x00-0xFF repeated ~4 times)
|
|
201
|
+
binaryData: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="
|
|
202
|
+
operations:
|
|
203
|
+
- action: read
|
|
204
|
+
path: ${streamPath}
|
|
205
|
+
live: sse
|
|
206
|
+
waitForUpToDate: true
|
|
207
|
+
expect:
|
|
208
|
+
minChunks: 1
|
|
209
|
+
upToDate: true
|
|
210
|
+
|
|
211
|
+
- id: sse-base64-multiple-chunks
|
|
212
|
+
name: SSE handles multiple base64 chunks
|
|
213
|
+
description: Multiple binary appends should each be decoded correctly
|
|
214
|
+
setup:
|
|
215
|
+
- action: create
|
|
216
|
+
as: streamPath
|
|
217
|
+
contentType: application/octet-stream
|
|
218
|
+
- action: append
|
|
219
|
+
path: ${streamPath}
|
|
220
|
+
binaryData: "AQID" # bytes: 1, 2, 3
|
|
221
|
+
- action: append
|
|
222
|
+
path: ${streamPath}
|
|
223
|
+
binaryData: "BAUG" # bytes: 4, 5, 6
|
|
224
|
+
- action: append
|
|
225
|
+
path: ${streamPath}
|
|
226
|
+
binaryData: "BwgJ" # bytes: 7, 8, 9
|
|
227
|
+
operations:
|
|
228
|
+
- action: read
|
|
229
|
+
path: ${streamPath}
|
|
230
|
+
live: sse
|
|
231
|
+
waitForUpToDate: true
|
|
232
|
+
expect:
|
|
233
|
+
minChunks: 1
|
|
234
|
+
upToDate: true
|
|
235
|
+
|
|
236
|
+
- id: sse-base64-resume-from-offset
|
|
237
|
+
name: SSE base64 resumes from offset correctly
|
|
238
|
+
description: Reading from a specific offset should work with base64 encoding
|
|
239
|
+
setup:
|
|
240
|
+
- action: create
|
|
241
|
+
as: streamPath
|
|
242
|
+
contentType: application/octet-stream
|
|
243
|
+
- action: append
|
|
244
|
+
path: ${streamPath}
|
|
245
|
+
binaryData: "AAAA" # skip this
|
|
246
|
+
expect:
|
|
247
|
+
storeOffsetAs: skipOffset
|
|
248
|
+
- action: append
|
|
249
|
+
path: ${streamPath}
|
|
250
|
+
binaryData: "//8=" # include this (0xFF, 0xFF)
|
|
251
|
+
operations:
|
|
252
|
+
- action: read
|
|
253
|
+
path: ${streamPath}
|
|
254
|
+
offset: ${skipOffset}
|
|
255
|
+
live: sse
|
|
256
|
+
waitForUpToDate: true
|
|
257
|
+
expect:
|
|
258
|
+
minChunks: 1
|
|
259
|
+
upToDate: true
|
|
260
|
+
|
|
261
|
+
- id: sse-base64-up-to-date
|
|
262
|
+
name: SSE base64 signals up-to-date
|
|
263
|
+
description: SSE with base64 encoding should signal when caught up to head
|
|
264
|
+
setup:
|
|
265
|
+
- action: create
|
|
266
|
+
as: streamPath
|
|
267
|
+
contentType: application/octet-stream
|
|
268
|
+
- action: append
|
|
269
|
+
path: ${streamPath}
|
|
270
|
+
binaryData: "AQIDBA==" # bytes: 1, 2, 3, 4
|
|
271
|
+
operations:
|
|
272
|
+
- action: read
|
|
273
|
+
path: ${streamPath}
|
|
274
|
+
live: sse
|
|
275
|
+
waitForUpToDate: true
|
|
276
|
+
expect:
|
|
277
|
+
upToDate: true
|
|
278
|
+
minChunks: 1
|
|
279
|
+
|
|
280
|
+
- id: sse-base64-padding-variations
|
|
281
|
+
name: SSE handles base64 padding variations
|
|
282
|
+
description: Base64 with different padding (=, ==, no padding) should decode correctly
|
|
283
|
+
setup:
|
|
284
|
+
- action: create
|
|
285
|
+
as: streamPath
|
|
286
|
+
contentType: application/octet-stream
|
|
287
|
+
- action: append
|
|
288
|
+
path: ${streamPath}
|
|
289
|
+
binaryData: "YQ==" # 'a' - 2 padding chars
|
|
290
|
+
- action: append
|
|
291
|
+
path: ${streamPath}
|
|
292
|
+
binaryData: "YWI=" # 'ab' - 1 padding char
|
|
293
|
+
- action: append
|
|
294
|
+
path: ${streamPath}
|
|
295
|
+
binaryData: "YWJj" # 'abc' - no padding
|
|
296
|
+
operations:
|
|
297
|
+
- action: read
|
|
298
|
+
path: ${streamPath}
|
|
299
|
+
live: sse
|
|
300
|
+
waitForUpToDate: true
|
|
301
|
+
expect:
|
|
302
|
+
minChunks: 1
|
|
303
|
+
upToDate: true
|
|
304
|
+
|
|
305
|
+
- id: sse-base64-all-byte-values
|
|
306
|
+
name: SSE handles all byte values 0-255
|
|
307
|
+
description: All possible byte values should round-trip correctly through base64
|
|
308
|
+
setup:
|
|
309
|
+
- action: create
|
|
310
|
+
as: streamPath
|
|
311
|
+
contentType: application/octet-stream
|
|
312
|
+
- action: append
|
|
313
|
+
path: ${streamPath}
|
|
314
|
+
# All bytes 0x00-0xFF encoded as base64
|
|
315
|
+
binaryData: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="
|
|
316
|
+
operations:
|
|
317
|
+
- action: read
|
|
318
|
+
path: ${streamPath}
|
|
319
|
+
live: sse
|
|
320
|
+
waitForUpToDate: true
|
|
321
|
+
expect:
|
|
322
|
+
minChunks: 1
|
|
323
|
+
upToDate: true
|
|
324
|
+
|
|
325
|
+
# SSE reconnection test - verifies decoder state resets properly
|
|
326
|
+
- id: sse-base64-reconnect-decoding
|
|
327
|
+
name: SSE base64 decoding works after reconnect
|
|
328
|
+
description: |
|
|
329
|
+
After SSE connection closes and client reconnects from last offset,
|
|
330
|
+
base64 decoding should work correctly without corruption from
|
|
331
|
+
any previous decoder state.
|
|
332
|
+
setup:
|
|
333
|
+
- action: create
|
|
334
|
+
as: streamPath
|
|
335
|
+
contentType: application/octet-stream
|
|
336
|
+
- action: append
|
|
337
|
+
path: ${streamPath}
|
|
338
|
+
binaryData: "Zmlyc3Q=" # "first"
|
|
339
|
+
expect:
|
|
340
|
+
storeOffsetAs: firstOffset
|
|
341
|
+
- action: append
|
|
342
|
+
path: ${streamPath}
|
|
343
|
+
binaryData: "c2Vjb25k" # "second"
|
|
344
|
+
operations:
|
|
345
|
+
# First read - gets "first", stops after 1 chunk
|
|
346
|
+
- action: read
|
|
347
|
+
path: ${streamPath}
|
|
348
|
+
live: sse
|
|
349
|
+
maxChunks: 1
|
|
350
|
+
expect:
|
|
351
|
+
minChunks: 1
|
|
352
|
+
dataContains: "first"
|
|
353
|
+
# Second read - reconnects from offset, should decode "second" correctly
|
|
354
|
+
- action: read
|
|
355
|
+
path: ${streamPath}
|
|
356
|
+
offset: ${firstOffset}
|
|
357
|
+
live: sse
|
|
358
|
+
waitForUpToDate: true
|
|
359
|
+
expect:
|
|
360
|
+
minChunks: 1
|
|
361
|
+
dataContains: "second"
|
|
362
|
+
upToDate: true
|
|
363
|
+
|
|
364
|
+
# Large payload test - verifies multi-line base64 handling
|
|
365
|
+
- id: sse-base64-large-payload-4kb
|
|
366
|
+
name: SSE handles 4KB base64 payload with potential line splits
|
|
367
|
+
skip: "Swift implementation broken"
|
|
368
|
+
description: |
|
|
369
|
+
Large binary payloads (4KB) may be split across multiple data: lines by servers.
|
|
370
|
+
Per Protocol Section 5.7, clients must concatenate lines and remove newlines
|
|
371
|
+
before decoding. This test uses ASCII-safe data to ensure proper verification
|
|
372
|
+
across all client implementations.
|
|
373
|
+
setup:
|
|
374
|
+
- action: create
|
|
375
|
+
as: streamPath
|
|
376
|
+
contentType: application/octet-stream
|
|
377
|
+
- action: append
|
|
378
|
+
path: ${streamPath}
|
|
379
|
+
# 4KB payload: 56 lines of "Line NNNN: ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz\n"
|
|
380
|
+
# All ASCII-safe characters that survive UTF-8 encoding
|
|
381
|
+
binaryData: "TGluZSAwMDAwOiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMDE6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAwMjogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDAzOiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMDQ6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAwNTogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDA2OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMDc6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAwODogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDA5OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMTA6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAxMTogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDEyOiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMTM6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAxNDogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDE1OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMTY6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAxNzogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDE4OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMTk6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAyMDogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDIxOiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMjI6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAyMzogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDI0OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMjU6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAyNjogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDI3OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMjg6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAyOTogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDMwOiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMzE6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAzMjogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDMzOiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMzQ6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAzNTogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDM2OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwMzc6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDAzODogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDM5OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwNDA6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDA0MTogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDQyOiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwNDM6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDA0NDogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDQ1OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwNDY6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDA0NzogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDQ4OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwNDk6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDA1MDogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDUxOiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwNTI6IEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6CkxpbmUgMDA1MzogQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoKTGluZSAwMDU0OiBBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5egpMaW5lIDAwNTU6IEFCQ0RFRkdISUpLTE1OTw=="
|
|
382
|
+
operations:
|
|
383
|
+
- action: read
|
|
384
|
+
path: ${streamPath}
|
|
385
|
+
live: sse
|
|
386
|
+
waitForUpToDate: true
|
|
387
|
+
timeoutMs: 10000
|
|
388
|
+
expect:
|
|
389
|
+
minChunks: 1
|
|
390
|
+
upToDate: true
|
|
391
|
+
# Verify the decoded data contains expected patterns from the ASCII-safe payload
|
|
392
|
+
dataContainsAll:
|
|
393
|
+
- "Line 0000"
|
|
394
|
+
- "Line 0025"
|
|
395
|
+
- "Line 0050"
|
|
396
|
+
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
397
|
+
- "0123456789"
|
|
398
|
+
- "abcdefghijklmnopqrstuvwxyz"
|
|
399
|
+
|
|
400
|
+
# Null byte handling (Gap 6)
|
|
401
|
+
- id: sse-base64-single-null-byte
|
|
402
|
+
name: SSE base64 handles single null byte
|
|
403
|
+
description: |
|
|
404
|
+
A single 0x00 byte must survive base64 round-trip. This catches
|
|
405
|
+
C-string termination bugs and JS typed-array edge cases.
|
|
406
|
+
setup:
|
|
407
|
+
- action: create
|
|
408
|
+
as: streamPath
|
|
409
|
+
contentType: application/octet-stream
|
|
410
|
+
- action: append
|
|
411
|
+
path: ${streamPath}
|
|
412
|
+
binaryData: "AA==" # single 0x00 byte
|
|
413
|
+
operations:
|
|
414
|
+
- action: read
|
|
415
|
+
path: ${streamPath}
|
|
416
|
+
live: sse
|
|
417
|
+
waitForUpToDate: true
|
|
418
|
+
expect:
|
|
419
|
+
minChunks: 1
|
|
420
|
+
upToDate: true
|
|
421
|
+
|
|
422
|
+
# Live streaming with base64 (Gap 9)
|
|
423
|
+
- id: sse-base64-live-streaming
|
|
424
|
+
name: SSE base64 receives live data
|
|
425
|
+
description: |
|
|
426
|
+
SSE stream with base64 encoding should receive data appended after
|
|
427
|
+
the connection is established, not just historical data.
|
|
428
|
+
setup:
|
|
429
|
+
- action: create
|
|
430
|
+
as: streamPath
|
|
431
|
+
contentType: application/octet-stream
|
|
432
|
+
- action: append
|
|
433
|
+
path: ${streamPath}
|
|
434
|
+
binaryData: "aW5pdGlhbA==" # "initial"
|
|
435
|
+
expect:
|
|
436
|
+
storeOffsetAs: offset
|
|
437
|
+
operations:
|
|
438
|
+
- action: read
|
|
439
|
+
path: ${streamPath}
|
|
440
|
+
offset: ${offset}
|
|
441
|
+
live: sse
|
|
442
|
+
maxChunks: 1
|
|
443
|
+
timeoutMs: 10000
|
|
444
|
+
background: true
|
|
445
|
+
as: readOp
|
|
446
|
+
- action: wait
|
|
447
|
+
ms: 200
|
|
448
|
+
- action: server-append
|
|
449
|
+
path: ${streamPath}
|
|
450
|
+
data: "live-update"
|
|
451
|
+
- action: await
|
|
452
|
+
ref: readOp
|
|
453
|
+
expect:
|
|
454
|
+
dataContains: "live-update"
|
|
455
|
+
minChunks: 1
|
|
456
|
+
|
|
457
|
+
# RFC 4648 Section 10 test vectors (Gap 10)
|
|
458
|
+
- id: sse-base64-rfc4648-1byte
|
|
459
|
+
name: SSE base64 RFC 4648 vector - 1 byte (double padding)
|
|
460
|
+
description: RFC 4648 canonical vector for "f" (1 byte, double == padding)
|
|
461
|
+
setup:
|
|
462
|
+
- action: create
|
|
463
|
+
as: streamPath
|
|
464
|
+
contentType: application/octet-stream
|
|
465
|
+
- action: append
|
|
466
|
+
path: ${streamPath}
|
|
467
|
+
binaryData: "Zg==" # "f"
|
|
468
|
+
operations:
|
|
469
|
+
- action: read
|
|
470
|
+
path: ${streamPath}
|
|
471
|
+
live: sse
|
|
472
|
+
waitForUpToDate: true
|
|
473
|
+
expect:
|
|
474
|
+
minChunks: 1
|
|
475
|
+
upToDate: true
|
|
476
|
+
data: "f"
|
|
477
|
+
|
|
478
|
+
- id: sse-base64-rfc4648-2byte
|
|
479
|
+
name: SSE base64 RFC 4648 vector - 2 bytes (single padding)
|
|
480
|
+
description: RFC 4648 canonical vector for "fo" (2 bytes, single = padding)
|
|
481
|
+
setup:
|
|
482
|
+
- action: create
|
|
483
|
+
as: streamPath
|
|
484
|
+
contentType: application/octet-stream
|
|
485
|
+
- action: append
|
|
486
|
+
path: ${streamPath}
|
|
487
|
+
binaryData: "Zm8=" # "fo"
|
|
488
|
+
operations:
|
|
489
|
+
- action: read
|
|
490
|
+
path: ${streamPath}
|
|
491
|
+
live: sse
|
|
492
|
+
waitForUpToDate: true
|
|
493
|
+
expect:
|
|
494
|
+
minChunks: 1
|
|
495
|
+
upToDate: true
|
|
496
|
+
data: "fo"
|
|
497
|
+
|
|
498
|
+
- id: sse-base64-rfc4648-3byte
|
|
499
|
+
name: SSE base64 RFC 4648 vector - 3 bytes (no padding)
|
|
500
|
+
description: RFC 4648 canonical vector for "foo" (3 bytes, no padding)
|
|
501
|
+
setup:
|
|
502
|
+
- action: create
|
|
503
|
+
as: streamPath
|
|
504
|
+
contentType: application/octet-stream
|
|
505
|
+
- action: append
|
|
506
|
+
path: ${streamPath}
|
|
507
|
+
binaryData: "Zm9v" # "foo"
|
|
508
|
+
operations:
|
|
509
|
+
- action: read
|
|
510
|
+
path: ${streamPath}
|
|
511
|
+
live: sse
|
|
512
|
+
waitForUpToDate: true
|
|
513
|
+
expect:
|
|
514
|
+
minChunks: 1
|
|
515
|
+
upToDate: true
|
|
516
|
+
data: "foo"
|
|
517
|
+
|
|
518
|
+
- id: sse-base64-rfc4648-6byte
|
|
519
|
+
name: SSE base64 RFC 4648 vector - 6 bytes (multi-block)
|
|
520
|
+
description: RFC 4648 canonical vector for "foobar" (6 bytes, multi-block boundary, no padding)
|
|
521
|
+
setup:
|
|
522
|
+
- action: create
|
|
523
|
+
as: streamPath
|
|
524
|
+
contentType: application/octet-stream
|
|
525
|
+
- action: append
|
|
526
|
+
path: ${streamPath}
|
|
527
|
+
binaryData: "Zm9vYmFy" # "foobar"
|
|
528
|
+
operations:
|
|
529
|
+
- action: read
|
|
530
|
+
path: ${streamPath}
|
|
531
|
+
live: sse
|
|
532
|
+
waitForUpToDate: true
|
|
533
|
+
expect:
|
|
534
|
+
minChunks: 1
|
|
535
|
+
upToDate: true
|
|
536
|
+
data: "foobar"
|
|
537
|
+
|
|
538
|
+
# Content-type variations (Gap 11)
|
|
539
|
+
- id: sse-base64-content-type-protobuf
|
|
540
|
+
name: SSE base64 works with application/x-protobuf streams
|
|
541
|
+
description: |
|
|
542
|
+
Binary streams with content type application/x-protobuf should
|
|
543
|
+
work with base64 encoding, catching implementations that hardcode
|
|
544
|
+
application/octet-stream checks.
|
|
545
|
+
setup:
|
|
546
|
+
- action: create
|
|
547
|
+
as: streamPath
|
|
548
|
+
contentType: application/x-protobuf
|
|
549
|
+
- action: append
|
|
550
|
+
path: ${streamPath}
|
|
551
|
+
binaryData: "CAYSBG5hbWU=" # protobuf-like bytes
|
|
552
|
+
operations:
|
|
553
|
+
- action: read
|
|
554
|
+
path: ${streamPath}
|
|
555
|
+
live: sse
|
|
556
|
+
waitForUpToDate: true
|
|
557
|
+
expect:
|
|
558
|
+
minChunks: 1
|
|
559
|
+
upToDate: true
|
|
560
|
+
|
|
561
|
+
- id: sse-base64-content-type-image
|
|
562
|
+
name: SSE base64 works with image/png streams
|
|
563
|
+
description: |
|
|
564
|
+
Binary streams with content type image/png should work with
|
|
565
|
+
base64 encoding.
|
|
566
|
+
setup:
|
|
567
|
+
- action: create
|
|
568
|
+
as: streamPath
|
|
569
|
+
contentType: image/png
|
|
570
|
+
- action: append
|
|
571
|
+
path: ${streamPath}
|
|
572
|
+
binaryData: "iVBORw0KGgo=" # PNG magic bytes (truncated)
|
|
573
|
+
operations:
|
|
574
|
+
- action: read
|
|
575
|
+
path: ${streamPath}
|
|
576
|
+
live: sse
|
|
577
|
+
waitForUpToDate: true
|
|
578
|
+
expect:
|
|
579
|
+
minChunks: 1
|
|
580
|
+
upToDate: true
|
|
581
|
+
|
|
582
|
+
# Offset=now with base64 (Gap 17)
|
|
583
|
+
- id: sse-base64-offset-now
|
|
584
|
+
name: SSE base64 works with offset=now
|
|
585
|
+
description: |
|
|
586
|
+
Starting an SSE read with offset=now on a binary stream should
|
|
587
|
+
skip historical data and receive only new live data.
|
|
588
|
+
setup:
|
|
589
|
+
- action: create
|
|
590
|
+
as: streamPath
|
|
591
|
+
contentType: application/octet-stream
|
|
592
|
+
- action: append
|
|
593
|
+
path: ${streamPath}
|
|
594
|
+
binaryData: "aGlzdG9yaWNhbA==" # "historical"
|
|
595
|
+
operations:
|
|
596
|
+
- action: read
|
|
597
|
+
path: ${streamPath}
|
|
598
|
+
offset: "now"
|
|
599
|
+
live: sse
|
|
600
|
+
maxChunks: 1
|
|
601
|
+
timeoutMs: 10000
|
|
602
|
+
background: true
|
|
603
|
+
as: readOp
|
|
604
|
+
- action: wait
|
|
605
|
+
ms: 200
|
|
606
|
+
- action: server-append
|
|
607
|
+
path: ${streamPath}
|
|
608
|
+
data: "new-data"
|
|
609
|
+
- action: await
|
|
610
|
+
ref: readOp
|
|
611
|
+
expect:
|
|
612
|
+
dataContains: "new-data"
|
|
613
|
+
minChunks: 1
|
|
614
|
+
|
|
615
|
+
# Many small messages (Gap 12)
|
|
616
|
+
- id: sse-base64-many-small-messages
|
|
617
|
+
name: SSE base64 handles many small binary messages
|
|
618
|
+
description: |
|
|
619
|
+
Ten small 3-byte binary payloads should all be decoded correctly,
|
|
620
|
+
catching decoder performance issues and event boundary bugs.
|
|
621
|
+
setup:
|
|
622
|
+
- action: create
|
|
623
|
+
as: streamPath
|
|
624
|
+
contentType: application/octet-stream
|
|
625
|
+
- action: append
|
|
626
|
+
path: ${streamPath}
|
|
627
|
+
binaryData: "AQID" # bytes: 1, 2, 3
|
|
628
|
+
- action: append
|
|
629
|
+
path: ${streamPath}
|
|
630
|
+
binaryData: "BAUG" # bytes: 4, 5, 6
|
|
631
|
+
- action: append
|
|
632
|
+
path: ${streamPath}
|
|
633
|
+
binaryData: "BwgJ" # bytes: 7, 8, 9
|
|
634
|
+
- action: append
|
|
635
|
+
path: ${streamPath}
|
|
636
|
+
binaryData: "CgsM" # bytes: 10, 11, 12
|
|
637
|
+
- action: append
|
|
638
|
+
path: ${streamPath}
|
|
639
|
+
binaryData: "DQ4P" # bytes: 13, 14, 15
|
|
640
|
+
- action: append
|
|
641
|
+
path: ${streamPath}
|
|
642
|
+
binaryData: "EBEW" # bytes: 16, 17, 22
|
|
643
|
+
- action: append
|
|
644
|
+
path: ${streamPath}
|
|
645
|
+
binaryData: "ExQV" # bytes: 19, 20, 21
|
|
646
|
+
- action: append
|
|
647
|
+
path: ${streamPath}
|
|
648
|
+
binaryData: "FhcY" # bytes: 22, 23, 24
|
|
649
|
+
- action: append
|
|
650
|
+
path: ${streamPath}
|
|
651
|
+
binaryData: "GRob" # bytes: 25, 26, 27
|
|
652
|
+
- action: append
|
|
653
|
+
path: ${streamPath}
|
|
654
|
+
binaryData: "HB0e" # bytes: 28, 29, 30
|
|
655
|
+
operations:
|
|
656
|
+
- action: read
|
|
657
|
+
path: ${streamPath}
|
|
658
|
+
live: sse
|
|
659
|
+
waitForUpToDate: true
|
|
660
|
+
timeoutMs: 10000
|
|
661
|
+
expect:
|
|
662
|
+
minChunks: 1
|
|
663
|
+
upToDate: true
|