@durable-streams/client-conformance-tests 0.1.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/README.md +451 -0
- package/dist/adapters/typescript-adapter.d.ts +1 -0
- package/dist/adapters/typescript-adapter.js +586 -0
- package/dist/benchmark-runner-C_Yghc8f.js +1333 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +265 -0
- package/dist/index.d.ts +508 -0
- package/dist/index.js +4 -0
- package/dist/protocol-DyEvTHPF.d.ts +472 -0
- package/dist/protocol-qb83AeUH.js +120 -0
- package/dist/protocol.d.ts +2 -0
- package/dist/protocol.js +3 -0
- package/package.json +53 -0
- package/src/adapters/typescript-adapter.ts +848 -0
- package/src/benchmark-runner.ts +860 -0
- package/src/benchmark-scenarios.ts +311 -0
- package/src/cli.ts +294 -0
- package/src/index.ts +50 -0
- package/src/protocol.ts +656 -0
- package/src/runner.ts +1191 -0
- package/src/test-cases.ts +475 -0
- package/test-cases/consumer/cache-headers.yaml +150 -0
- package/test-cases/consumer/error-handling.yaml +108 -0
- package/test-cases/consumer/message-ordering.yaml +209 -0
- package/test-cases/consumer/offset-handling.yaml +209 -0
- package/test-cases/consumer/offset-resumption.yaml +197 -0
- package/test-cases/consumer/read-catchup.yaml +173 -0
- package/test-cases/consumer/read-longpoll.yaml +132 -0
- package/test-cases/consumer/read-sse.yaml +145 -0
- package/test-cases/consumer/retry-resilience.yaml +160 -0
- package/test-cases/consumer/streaming-equivalence.yaml +226 -0
- package/test-cases/lifecycle/dynamic-headers.yaml +147 -0
- package/test-cases/lifecycle/headers-params.yaml +117 -0
- package/test-cases/lifecycle/stream-lifecycle.yaml +148 -0
- package/test-cases/producer/append-data.yaml +142 -0
- package/test-cases/producer/batching.yaml +112 -0
- package/test-cases/producer/create-stream.yaml +87 -0
- package/test-cases/producer/error-handling.yaml +90 -0
- package/test-cases/producer/sequence-ordering.yaml +148 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
id: consumer-streaming-equivalence
|
|
2
|
+
name: Streaming Mode Equivalence
|
|
3
|
+
description: Tests that SSE and Long-poll modes produce identical results
|
|
4
|
+
category: consumer
|
|
5
|
+
tags:
|
|
6
|
+
- core
|
|
7
|
+
- equivalence
|
|
8
|
+
- sse
|
|
9
|
+
- longpoll
|
|
10
|
+
|
|
11
|
+
tests:
|
|
12
|
+
- id: equivalence-existing-data
|
|
13
|
+
name: Both modes return same existing data
|
|
14
|
+
description: SSE and long-poll should return identical data for existing content
|
|
15
|
+
setup:
|
|
16
|
+
- action: create
|
|
17
|
+
as: streamPath
|
|
18
|
+
- action: append
|
|
19
|
+
path: ${streamPath}
|
|
20
|
+
data: "chunk1"
|
|
21
|
+
- action: append
|
|
22
|
+
path: ${streamPath}
|
|
23
|
+
data: "chunk2"
|
|
24
|
+
- action: append
|
|
25
|
+
path: ${streamPath}
|
|
26
|
+
data: "chunk3"
|
|
27
|
+
operations:
|
|
28
|
+
# Read with long-poll
|
|
29
|
+
- action: read
|
|
30
|
+
path: ${streamPath}
|
|
31
|
+
live: long-poll
|
|
32
|
+
waitForUpToDate: true
|
|
33
|
+
expect:
|
|
34
|
+
data: "chunk1chunk2chunk3"
|
|
35
|
+
upToDate: true
|
|
36
|
+
storeDataAs: longpollData
|
|
37
|
+
# Read same stream with SSE
|
|
38
|
+
- action: read
|
|
39
|
+
path: ${streamPath}
|
|
40
|
+
live: sse
|
|
41
|
+
waitForUpToDate: true
|
|
42
|
+
expect:
|
|
43
|
+
data: "chunk1chunk2chunk3"
|
|
44
|
+
upToDate: true
|
|
45
|
+
# Verify both got same data
|
|
46
|
+
- action: assert
|
|
47
|
+
equals:
|
|
48
|
+
left: ${longpollData}
|
|
49
|
+
right: "chunk1chunk2chunk3"
|
|
50
|
+
message: "Long-poll and SSE should return identical data"
|
|
51
|
+
|
|
52
|
+
- id: equivalence-from-offset
|
|
53
|
+
name: Both modes resume from same offset correctly
|
|
54
|
+
description: SSE and long-poll should resume from offset identically
|
|
55
|
+
setup:
|
|
56
|
+
- action: create
|
|
57
|
+
as: streamPath
|
|
58
|
+
- action: append
|
|
59
|
+
path: ${streamPath}
|
|
60
|
+
data: "before"
|
|
61
|
+
expect:
|
|
62
|
+
storeOffsetAs: midOffset
|
|
63
|
+
- action: append
|
|
64
|
+
path: ${streamPath}
|
|
65
|
+
data: "after"
|
|
66
|
+
operations:
|
|
67
|
+
# Read from offset with long-poll
|
|
68
|
+
- action: read
|
|
69
|
+
path: ${streamPath}
|
|
70
|
+
offset: ${midOffset}
|
|
71
|
+
live: long-poll
|
|
72
|
+
waitForUpToDate: true
|
|
73
|
+
expect:
|
|
74
|
+
data: "after"
|
|
75
|
+
upToDate: true
|
|
76
|
+
# Read from same offset with SSE
|
|
77
|
+
- action: read
|
|
78
|
+
path: ${streamPath}
|
|
79
|
+
offset: ${midOffset}
|
|
80
|
+
live: sse
|
|
81
|
+
waitForUpToDate: true
|
|
82
|
+
expect:
|
|
83
|
+
data: "after"
|
|
84
|
+
upToDate: true
|
|
85
|
+
|
|
86
|
+
- id: equivalence-empty-stream
|
|
87
|
+
name: Both modes handle empty stream identically
|
|
88
|
+
description: SSE and long-poll should both report up-to-date on empty stream
|
|
89
|
+
setup:
|
|
90
|
+
- action: create
|
|
91
|
+
as: streamPath
|
|
92
|
+
operations:
|
|
93
|
+
# Read empty stream with long-poll
|
|
94
|
+
- action: read
|
|
95
|
+
path: ${streamPath}
|
|
96
|
+
live: long-poll
|
|
97
|
+
waitForUpToDate: true
|
|
98
|
+
expect:
|
|
99
|
+
chunkCount: 0
|
|
100
|
+
upToDate: true
|
|
101
|
+
# Read empty stream with SSE
|
|
102
|
+
- action: read
|
|
103
|
+
path: ${streamPath}
|
|
104
|
+
live: sse
|
|
105
|
+
waitForUpToDate: true
|
|
106
|
+
expect:
|
|
107
|
+
chunkCount: 0
|
|
108
|
+
upToDate: true
|
|
109
|
+
|
|
110
|
+
- id: equivalence-live-new-data
|
|
111
|
+
name: Both modes receive live data
|
|
112
|
+
description: SSE and long-poll should both receive newly appended data
|
|
113
|
+
requires:
|
|
114
|
+
- sse
|
|
115
|
+
- long-poll
|
|
116
|
+
setup:
|
|
117
|
+
- action: create
|
|
118
|
+
as: streamPath
|
|
119
|
+
- action: append
|
|
120
|
+
path: ${streamPath}
|
|
121
|
+
data: "initial"
|
|
122
|
+
expect:
|
|
123
|
+
storeOffsetAs: initialOffset
|
|
124
|
+
operations:
|
|
125
|
+
# Test long-poll receives new data
|
|
126
|
+
- action: read
|
|
127
|
+
path: ${streamPath}
|
|
128
|
+
offset: ${initialOffset}
|
|
129
|
+
live: long-poll
|
|
130
|
+
timeoutMs: 5000
|
|
131
|
+
background: true
|
|
132
|
+
as: longpollRead
|
|
133
|
+
- action: wait
|
|
134
|
+
ms: 100
|
|
135
|
+
- action: server-append
|
|
136
|
+
path: ${streamPath}
|
|
137
|
+
data: "live-data-lp"
|
|
138
|
+
- action: await
|
|
139
|
+
ref: longpollRead
|
|
140
|
+
expect:
|
|
141
|
+
dataContains: "live-data-lp"
|
|
142
|
+
|
|
143
|
+
- id: equivalence-sse-live-new-data
|
|
144
|
+
name: SSE receives live data
|
|
145
|
+
description: SSE should receive newly appended data in live mode
|
|
146
|
+
requires:
|
|
147
|
+
- sse
|
|
148
|
+
setup:
|
|
149
|
+
- action: create
|
|
150
|
+
as: streamPath
|
|
151
|
+
- action: append
|
|
152
|
+
path: ${streamPath}
|
|
153
|
+
data: "initial"
|
|
154
|
+
expect:
|
|
155
|
+
storeOffsetAs: initialOffset
|
|
156
|
+
operations:
|
|
157
|
+
# Test SSE receives new data
|
|
158
|
+
- action: read
|
|
159
|
+
path: ${streamPath}
|
|
160
|
+
offset: ${initialOffset}
|
|
161
|
+
live: sse
|
|
162
|
+
timeoutMs: 5000
|
|
163
|
+
background: true
|
|
164
|
+
as: sseRead
|
|
165
|
+
- action: wait
|
|
166
|
+
ms: 100
|
|
167
|
+
- action: server-append
|
|
168
|
+
path: ${streamPath}
|
|
169
|
+
data: "live-data-sse"
|
|
170
|
+
- action: await
|
|
171
|
+
ref: sseRead
|
|
172
|
+
expect:
|
|
173
|
+
dataContains: "live-data-sse"
|
|
174
|
+
|
|
175
|
+
- id: equivalence-offset-semantics
|
|
176
|
+
name: Offset semantics identical between modes
|
|
177
|
+
description: Reading from specific offsets should work identically
|
|
178
|
+
setup:
|
|
179
|
+
- action: create
|
|
180
|
+
as: streamPath
|
|
181
|
+
- action: append
|
|
182
|
+
path: ${streamPath}
|
|
183
|
+
data: "a"
|
|
184
|
+
expect:
|
|
185
|
+
storeOffsetAs: offset1
|
|
186
|
+
- action: append
|
|
187
|
+
path: ${streamPath}
|
|
188
|
+
data: "b"
|
|
189
|
+
expect:
|
|
190
|
+
storeOffsetAs: offset2
|
|
191
|
+
- action: append
|
|
192
|
+
path: ${streamPath}
|
|
193
|
+
data: "c"
|
|
194
|
+
operations:
|
|
195
|
+
# Long-poll from offset1 should get "bc"
|
|
196
|
+
- action: read
|
|
197
|
+
path: ${streamPath}
|
|
198
|
+
offset: ${offset1}
|
|
199
|
+
live: long-poll
|
|
200
|
+
waitForUpToDate: true
|
|
201
|
+
expect:
|
|
202
|
+
data: "bc"
|
|
203
|
+
# SSE from offset1 should also get "bc"
|
|
204
|
+
- action: read
|
|
205
|
+
path: ${streamPath}
|
|
206
|
+
offset: ${offset1}
|
|
207
|
+
live: sse
|
|
208
|
+
waitForUpToDate: true
|
|
209
|
+
expect:
|
|
210
|
+
data: "bc"
|
|
211
|
+
# Long-poll from offset2 should get "c"
|
|
212
|
+
- action: read
|
|
213
|
+
path: ${streamPath}
|
|
214
|
+
offset: ${offset2}
|
|
215
|
+
live: long-poll
|
|
216
|
+
waitForUpToDate: true
|
|
217
|
+
expect:
|
|
218
|
+
data: "c"
|
|
219
|
+
# SSE from offset2 should also get "c"
|
|
220
|
+
- action: read
|
|
221
|
+
path: ${streamPath}
|
|
222
|
+
offset: ${offset2}
|
|
223
|
+
live: sse
|
|
224
|
+
waitForUpToDate: true
|
|
225
|
+
expect:
|
|
226
|
+
data: "c"
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
id: lifecycle-dynamic-headers
|
|
2
|
+
name: Dynamic Headers and Parameters
|
|
3
|
+
description: |
|
|
4
|
+
Tests for dynamic header and parameter handling.
|
|
5
|
+
Production clients need to support headers/params that are computed per-request
|
|
6
|
+
(e.g., OAuth token refresh, request timestamps, correlation IDs).
|
|
7
|
+
category: lifecycle
|
|
8
|
+
tags:
|
|
9
|
+
- headers
|
|
10
|
+
- params
|
|
11
|
+
- auth
|
|
12
|
+
- dynamic
|
|
13
|
+
requires:
|
|
14
|
+
- dynamicHeaders
|
|
15
|
+
|
|
16
|
+
tests:
|
|
17
|
+
- id: dynamic-header-per-request
|
|
18
|
+
name: Dynamic headers evaluated per request
|
|
19
|
+
description: |
|
|
20
|
+
Headers provided as functions should be evaluated on each request,
|
|
21
|
+
not cached. This is critical for token refresh scenarios.
|
|
22
|
+
setup:
|
|
23
|
+
- action: create
|
|
24
|
+
as: streamPath
|
|
25
|
+
operations:
|
|
26
|
+
# Configure adapter to use a counter-based dynamic header
|
|
27
|
+
- action: set-dynamic-header
|
|
28
|
+
name: X-Request-Counter
|
|
29
|
+
valueType: counter
|
|
30
|
+
# First append - should have counter=1
|
|
31
|
+
- action: append
|
|
32
|
+
path: ${streamPath}
|
|
33
|
+
data: "first"
|
|
34
|
+
expect:
|
|
35
|
+
status: 200
|
|
36
|
+
headersSent:
|
|
37
|
+
X-Request-Counter: "1"
|
|
38
|
+
# Second append - should have counter=2 (not cached)
|
|
39
|
+
- action: append
|
|
40
|
+
path: ${streamPath}
|
|
41
|
+
data: "second"
|
|
42
|
+
expect:
|
|
43
|
+
status: 200
|
|
44
|
+
headersSent:
|
|
45
|
+
X-Request-Counter: "2"
|
|
46
|
+
# Third append - should have counter=3
|
|
47
|
+
- action: append
|
|
48
|
+
path: ${streamPath}
|
|
49
|
+
data: "third"
|
|
50
|
+
expect:
|
|
51
|
+
status: 200
|
|
52
|
+
headersSent:
|
|
53
|
+
X-Request-Counter: "3"
|
|
54
|
+
|
|
55
|
+
- id: dynamic-header-on-read
|
|
56
|
+
name: Dynamic headers on repeated reads
|
|
57
|
+
description: Headers should be freshly evaluated on each read request
|
|
58
|
+
setup:
|
|
59
|
+
- action: create
|
|
60
|
+
as: streamPath
|
|
61
|
+
- action: append
|
|
62
|
+
path: ${streamPath}
|
|
63
|
+
data: "test-data"
|
|
64
|
+
operations:
|
|
65
|
+
- action: set-dynamic-header
|
|
66
|
+
name: X-Request-Counter
|
|
67
|
+
valueType: counter
|
|
68
|
+
# First read
|
|
69
|
+
- action: read
|
|
70
|
+
path: ${streamPath}
|
|
71
|
+
live: false
|
|
72
|
+
expect:
|
|
73
|
+
status: 200
|
|
74
|
+
headersSent:
|
|
75
|
+
X-Request-Counter: "1"
|
|
76
|
+
# Second read from same offset - counter should increment
|
|
77
|
+
- action: read
|
|
78
|
+
path: ${streamPath}
|
|
79
|
+
live: false
|
|
80
|
+
expect:
|
|
81
|
+
status: 200
|
|
82
|
+
headersSent:
|
|
83
|
+
X-Request-Counter: "2"
|
|
84
|
+
|
|
85
|
+
- id: dynamic-param-per-request
|
|
86
|
+
name: Dynamic params evaluated per request
|
|
87
|
+
description: |
|
|
88
|
+
URL parameters provided as functions should be evaluated on each request.
|
|
89
|
+
Useful for signed URLs, dynamic routing, etc.
|
|
90
|
+
setup:
|
|
91
|
+
- action: create
|
|
92
|
+
as: streamPath
|
|
93
|
+
- action: append
|
|
94
|
+
path: ${streamPath}
|
|
95
|
+
data: "data"
|
|
96
|
+
operations:
|
|
97
|
+
- action: set-dynamic-param
|
|
98
|
+
name: request_id
|
|
99
|
+
valueType: counter
|
|
100
|
+
- action: read
|
|
101
|
+
path: ${streamPath}
|
|
102
|
+
live: false
|
|
103
|
+
expect:
|
|
104
|
+
status: 200
|
|
105
|
+
paramsSent:
|
|
106
|
+
request_id: "1"
|
|
107
|
+
- action: read
|
|
108
|
+
path: ${streamPath}
|
|
109
|
+
live: false
|
|
110
|
+
expect:
|
|
111
|
+
status: 200
|
|
112
|
+
paramsSent:
|
|
113
|
+
request_id: "2"
|
|
114
|
+
|
|
115
|
+
- id: token-refresh-simulation
|
|
116
|
+
name: Token refresh simulation
|
|
117
|
+
description: |
|
|
118
|
+
Simulates OAuth token refresh by changing the Authorization header value
|
|
119
|
+
between requests. The client must use the new value, not cache the old one.
|
|
120
|
+
setup:
|
|
121
|
+
- action: create
|
|
122
|
+
as: streamPath
|
|
123
|
+
operations:
|
|
124
|
+
# Set initial token
|
|
125
|
+
- action: set-dynamic-header
|
|
126
|
+
name: Authorization
|
|
127
|
+
valueType: token
|
|
128
|
+
initialValue: "Bearer token-v1"
|
|
129
|
+
- action: append
|
|
130
|
+
path: ${streamPath}
|
|
131
|
+
data: "first"
|
|
132
|
+
expect:
|
|
133
|
+
status: 200
|
|
134
|
+
headersSent:
|
|
135
|
+
Authorization: "Bearer token-v1"
|
|
136
|
+
# Simulate token refresh
|
|
137
|
+
- action: set-dynamic-header
|
|
138
|
+
name: Authorization
|
|
139
|
+
valueType: token
|
|
140
|
+
initialValue: "Bearer token-v2"
|
|
141
|
+
- action: append
|
|
142
|
+
path: ${streamPath}
|
|
143
|
+
data: "second"
|
|
144
|
+
expect:
|
|
145
|
+
status: 200
|
|
146
|
+
headersSent:
|
|
147
|
+
Authorization: "Bearer token-v2"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
id: lifecycle-headers
|
|
2
|
+
name: Headers and Parameters
|
|
3
|
+
description: Tests for header and parameter handling
|
|
4
|
+
category: lifecycle
|
|
5
|
+
tags:
|
|
6
|
+
- headers
|
|
7
|
+
- params
|
|
8
|
+
- auth
|
|
9
|
+
|
|
10
|
+
tests:
|
|
11
|
+
- id: custom-headers-create
|
|
12
|
+
name: Custom headers on create
|
|
13
|
+
description: Client should send custom headers on create
|
|
14
|
+
operations:
|
|
15
|
+
- action: create
|
|
16
|
+
as: streamPath
|
|
17
|
+
headers:
|
|
18
|
+
X-Custom-Header: "custom-value"
|
|
19
|
+
X-Another-Header: "another-value"
|
|
20
|
+
expect:
|
|
21
|
+
status: 201
|
|
22
|
+
|
|
23
|
+
- id: custom-headers-append
|
|
24
|
+
name: Custom headers on append
|
|
25
|
+
description: Client should send custom headers on append
|
|
26
|
+
setup:
|
|
27
|
+
- action: create
|
|
28
|
+
as: streamPath
|
|
29
|
+
operations:
|
|
30
|
+
- action: append
|
|
31
|
+
path: ${streamPath}
|
|
32
|
+
data: "with-headers"
|
|
33
|
+
headers:
|
|
34
|
+
X-Request-Id: "req-12345"
|
|
35
|
+
Authorization: "Bearer test-token"
|
|
36
|
+
expect:
|
|
37
|
+
status: 200
|
|
38
|
+
|
|
39
|
+
- id: custom-headers-read
|
|
40
|
+
name: Custom headers on read
|
|
41
|
+
description: Client should send custom headers on read
|
|
42
|
+
setup:
|
|
43
|
+
- action: create
|
|
44
|
+
as: streamPath
|
|
45
|
+
- action: append
|
|
46
|
+
path: ${streamPath}
|
|
47
|
+
data: "data"
|
|
48
|
+
operations:
|
|
49
|
+
- action: read
|
|
50
|
+
path: ${streamPath}
|
|
51
|
+
headers:
|
|
52
|
+
Authorization: "Bearer read-token"
|
|
53
|
+
live: false
|
|
54
|
+
expect:
|
|
55
|
+
status: 200
|
|
56
|
+
|
|
57
|
+
- id: custom-headers-head
|
|
58
|
+
name: Custom headers on head
|
|
59
|
+
description: Client should send custom headers on HEAD
|
|
60
|
+
setup:
|
|
61
|
+
- action: create
|
|
62
|
+
as: streamPath
|
|
63
|
+
operations:
|
|
64
|
+
- action: head
|
|
65
|
+
path: ${streamPath}
|
|
66
|
+
headers:
|
|
67
|
+
X-Trace-Id: "trace-abc"
|
|
68
|
+
expect:
|
|
69
|
+
status: 200
|
|
70
|
+
|
|
71
|
+
- id: custom-headers-delete
|
|
72
|
+
name: Custom headers on delete
|
|
73
|
+
description: Client should send custom headers on delete
|
|
74
|
+
setup:
|
|
75
|
+
- action: create
|
|
76
|
+
as: streamPath
|
|
77
|
+
operations:
|
|
78
|
+
- action: delete
|
|
79
|
+
path: ${streamPath}
|
|
80
|
+
headers:
|
|
81
|
+
Authorization: "Bearer delete-token"
|
|
82
|
+
expect:
|
|
83
|
+
status: 200
|
|
84
|
+
|
|
85
|
+
- id: content-type-preserved
|
|
86
|
+
name: Content type is preserved
|
|
87
|
+
description: Content type set on create should be returned on read
|
|
88
|
+
operations:
|
|
89
|
+
- action: create
|
|
90
|
+
as: streamPath
|
|
91
|
+
contentType: application/x-custom-type
|
|
92
|
+
expect:
|
|
93
|
+
status: 201
|
|
94
|
+
- action: head
|
|
95
|
+
path: ${streamPath}
|
|
96
|
+
expect:
|
|
97
|
+
contentType: application/x-custom-type
|
|
98
|
+
cleanup:
|
|
99
|
+
- action: delete
|
|
100
|
+
path: ${streamPath}
|
|
101
|
+
|
|
102
|
+
- id: content-type-with-charset
|
|
103
|
+
name: Content type with charset
|
|
104
|
+
description: Content type with charset parameter should be preserved
|
|
105
|
+
operations:
|
|
106
|
+
- action: create
|
|
107
|
+
as: streamPath
|
|
108
|
+
contentType: text/plain; charset=utf-8
|
|
109
|
+
expect:
|
|
110
|
+
status: 201
|
|
111
|
+
- action: head
|
|
112
|
+
path: ${streamPath}
|
|
113
|
+
expect:
|
|
114
|
+
contentType: text/plain; charset=utf-8
|
|
115
|
+
cleanup:
|
|
116
|
+
- action: delete
|
|
117
|
+
path: ${streamPath}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
id: lifecycle-stream
|
|
2
|
+
name: Stream Lifecycle
|
|
3
|
+
description: Tests for complete stream lifecycle operations
|
|
4
|
+
category: lifecycle
|
|
5
|
+
tags:
|
|
6
|
+
- core
|
|
7
|
+
- lifecycle
|
|
8
|
+
|
|
9
|
+
tests:
|
|
10
|
+
- id: full-lifecycle
|
|
11
|
+
name: Full stream lifecycle
|
|
12
|
+
description: Create, append, read, and delete a stream
|
|
13
|
+
operations:
|
|
14
|
+
- action: create
|
|
15
|
+
as: streamPath
|
|
16
|
+
contentType: text/plain
|
|
17
|
+
expect:
|
|
18
|
+
status: 201
|
|
19
|
+
- action: append
|
|
20
|
+
path: ${streamPath}
|
|
21
|
+
data: "lifecycle-test-data"
|
|
22
|
+
expect:
|
|
23
|
+
status: 200
|
|
24
|
+
- action: read
|
|
25
|
+
path: ${streamPath}
|
|
26
|
+
live: false
|
|
27
|
+
expect:
|
|
28
|
+
data: "lifecycle-test-data"
|
|
29
|
+
upToDate: true
|
|
30
|
+
- action: delete
|
|
31
|
+
path: ${streamPath}
|
|
32
|
+
expect:
|
|
33
|
+
status: 200
|
|
34
|
+
- action: read
|
|
35
|
+
path: ${streamPath}
|
|
36
|
+
live: false
|
|
37
|
+
expect:
|
|
38
|
+
status: 404
|
|
39
|
+
|
|
40
|
+
- id: connect-existing
|
|
41
|
+
name: Connect to existing stream
|
|
42
|
+
description: Connect should work for existing streams
|
|
43
|
+
setup:
|
|
44
|
+
- action: create
|
|
45
|
+
as: streamPath
|
|
46
|
+
- action: append
|
|
47
|
+
path: ${streamPath}
|
|
48
|
+
data: "pre-existing"
|
|
49
|
+
operations:
|
|
50
|
+
- action: connect
|
|
51
|
+
path: ${streamPath}
|
|
52
|
+
expect:
|
|
53
|
+
status: 200
|
|
54
|
+
- action: read
|
|
55
|
+
path: ${streamPath}
|
|
56
|
+
live: false
|
|
57
|
+
expect:
|
|
58
|
+
data: "pre-existing"
|
|
59
|
+
|
|
60
|
+
- id: head-metadata
|
|
61
|
+
name: HEAD returns metadata
|
|
62
|
+
description: HEAD should return stream metadata without body
|
|
63
|
+
setup:
|
|
64
|
+
- action: create
|
|
65
|
+
as: streamPath
|
|
66
|
+
contentType: application/json
|
|
67
|
+
- action: append
|
|
68
|
+
path: ${streamPath}
|
|
69
|
+
data: '{"key": "value"}'
|
|
70
|
+
operations:
|
|
71
|
+
- action: head
|
|
72
|
+
path: ${streamPath}
|
|
73
|
+
expect:
|
|
74
|
+
status: 200
|
|
75
|
+
contentType: application/json
|
|
76
|
+
hasOffset: true
|
|
77
|
+
|
|
78
|
+
- id: head-empty-stream
|
|
79
|
+
name: HEAD on empty stream
|
|
80
|
+
description: HEAD should work on empty stream
|
|
81
|
+
setup:
|
|
82
|
+
- action: create
|
|
83
|
+
as: streamPath
|
|
84
|
+
operations:
|
|
85
|
+
- action: head
|
|
86
|
+
path: ${streamPath}
|
|
87
|
+
expect:
|
|
88
|
+
status: 200
|
|
89
|
+
hasOffset: true
|
|
90
|
+
|
|
91
|
+
- id: multiple-streams
|
|
92
|
+
name: Multiple independent streams
|
|
93
|
+
description: Operations on one stream should not affect others
|
|
94
|
+
operations:
|
|
95
|
+
- action: create
|
|
96
|
+
as: stream1
|
|
97
|
+
- action: create
|
|
98
|
+
as: stream2
|
|
99
|
+
- action: append
|
|
100
|
+
path: ${stream1}
|
|
101
|
+
data: "stream1-data"
|
|
102
|
+
- action: append
|
|
103
|
+
path: ${stream2}
|
|
104
|
+
data: "stream2-data"
|
|
105
|
+
- action: read
|
|
106
|
+
path: ${stream1}
|
|
107
|
+
live: false
|
|
108
|
+
expect:
|
|
109
|
+
data: "stream1-data"
|
|
110
|
+
- action: read
|
|
111
|
+
path: ${stream2}
|
|
112
|
+
live: false
|
|
113
|
+
expect:
|
|
114
|
+
data: "stream2-data"
|
|
115
|
+
- action: delete
|
|
116
|
+
path: ${stream1}
|
|
117
|
+
- action: read
|
|
118
|
+
path: ${stream2}
|
|
119
|
+
live: false
|
|
120
|
+
expect:
|
|
121
|
+
data: "stream2-data"
|
|
122
|
+
cleanup:
|
|
123
|
+
- action: delete
|
|
124
|
+
path: ${stream2}
|
|
125
|
+
|
|
126
|
+
- id: recreate-after-delete
|
|
127
|
+
name: Create after delete
|
|
128
|
+
description: Creating after delete should succeed as a new stream
|
|
129
|
+
operations:
|
|
130
|
+
- action: create
|
|
131
|
+
as: streamPath
|
|
132
|
+
expect:
|
|
133
|
+
status: 201
|
|
134
|
+
- action: append
|
|
135
|
+
path: ${streamPath}
|
|
136
|
+
data: "original"
|
|
137
|
+
- action: delete
|
|
138
|
+
path: ${streamPath}
|
|
139
|
+
expect:
|
|
140
|
+
status: 200
|
|
141
|
+
# Create at same path should succeed as a new stream
|
|
142
|
+
- action: create
|
|
143
|
+
path: ${streamPath}
|
|
144
|
+
expect:
|
|
145
|
+
status: 201
|
|
146
|
+
cleanup:
|
|
147
|
+
- action: delete
|
|
148
|
+
path: ${streamPath}
|