Skip to content

Commit 5ac5cb4

Browse files
paddybyersclaude
andcommitted
Add protocol variant convention to UTS integration specs (G1)
Establish a convention for running data-path integration tests with both JSON and msgpack protocols. Each annotated spec gets a Protocol Variants section and uses PROTOCOL == "msgpack" instead of hardcoded useBinaryProtocol: false. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b3c0f0f commit 5ac5cb4

12 files changed

Lines changed: 185 additions & 54 deletions

uts/docs/integration-testing.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,66 @@ The goal is: every await in the test is bounded, and the suite timeout is genero
236236
- Proxy tests should use proxy event logs for verification rather than timing-dependent assertions
237237
- When tests pass in isolation but fail in the full suite, suspect sandbox rate limiting or connection exhaustion — increase the suite timeout rather than adding retries
238238

239+
## Protocol Variants
240+
241+
The Ably client library spec (G1) requires that tests run with all supported protocols. Integration tests that exercise the data encoding/decoding path must run with both JSON and msgpack to verify data integrity through the full encode-transmit-decode pipeline.
242+
243+
### Which tests need both protocols?
244+
245+
Only tests on the **data path** need both protocols. These are tests where messages, presence data, or other payloads pass through the SDK's encoding layer, through the server, and back. Examples include publish/subscribe round-trips, history retrieval, presence data, delta decoding, and mutable message operations.
246+
247+
Tests for **connection lifecycle**, **authentication**, **channel attach/detach**, and other protocol-agnostic behaviours do not need protocol variants. These tests exercise control-plane operations whose correctness does not depend on the wire encoding of message payloads.
248+
249+
**Proxy tests always use JSON.** The proxy only supports text WebSocket frames, so proxy-based tests cannot use msgpack.
250+
251+
### Spec file convention
252+
253+
A spec file that requires protocol variant testing includes a `## Protocol Variants` section immediately after `## Test Type`:
254+
255+
```markdown
256+
## Test Type
257+
Integration test against Ably sandbox
258+
259+
## Protocol Variants
260+
json, msgpack
261+
262+
Each test in this file runs once per protocol variant. The `PROTOCOL` variable
263+
is set to `"json"` or `"msgpack"` for the current run. Client options should set
264+
`useBinaryProtocol: PROTOCOL == "msgpack"`.
265+
```
266+
267+
The `PROTOCOL` variable is available in pseudocode and is set to `"json"` or `"msgpack"` for the current run. Client options use the standard pattern:
268+
269+
```pseudo
270+
client = Rest(options: ClientOptions(
271+
key: api_key,
272+
endpoint: "nonprod:sandbox",
273+
useBinaryProtocol: PROTOCOL == "msgpack"
274+
))
275+
```
276+
277+
### Default behaviour
278+
279+
Spec files **without** a `## Protocol Variants` section default to JSON only. No special handling is required in derived test implementations for these specs.
280+
281+
### Annotated specs
282+
283+
The following integration test specs are annotated with `## Protocol Variants`:
284+
285+
**REST:**
286+
- `rest/integration/publish.md`
287+
- `rest/integration/history.md`
288+
- `rest/integration/presence.md`
289+
- `rest/integration/batch_presence.md`
290+
- `rest/integration/mutable_messages.md`
291+
292+
**Realtime:**
293+
- `realtime/integration/channels/channel_publish_test.md`
294+
- `realtime/integration/channel_history_test.md`
295+
- `realtime/integration/presence_lifecycle_test.md`
296+
- `realtime/integration/mutable_messages_test.md`
297+
- `realtime/integration/delta_decoding_test.md`
298+
239299
## Writing Proxy Tests
240300

241301
The proxy mediates between the SDK and the real Ably server. It is not a mock server. Tests should be written to rely on actual server responses as much as possible, with the proxy intervening only where necessary to create the specific fault or error condition under test.

uts/docs/writing-test-specs.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This guide provides comprehensive guidance for writing portable test specificati
1515
- Run against `https://sandbox.realtime.ably-nonprod.net`
1616
- Provision apps via `POST /apps` with body from `ably-common/test-resources/test-app-setup.json`
1717
- Use `endpoint: "nonprod:sandbox"` in ClientOptions
18+
- **Protocol variants:** Data-path tests (publish, history, presence, etc.) must run with both JSON and msgpack. Add a `## Protocol Variants` section after `## Test Type` and use `useBinaryProtocol: PROTOCOL == "msgpack"` in ClientOptions. See `docs/integration-testing.md` for the full convention. Specs without this header default to JSON only.
1819

1920
### Proxy Integration Tests (Ably Sandbox via Proxy)
2021
- Run against Ably Sandbox through a programmable proxy ([ably/uts-proxy](https://github.com/ably/uts-proxy))

uts/realtime/integration/channel_history_test.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ Spec points: `RTL10d`
55
## Test Type
66
Integration test against Ably Sandbox endpoint
77

8+
## Protocol Variants
9+
json, msgpack
10+
11+
Each test in this file runs once per protocol variant. The `PROTOCOL` variable
12+
is set to `"json"` or `"msgpack"` for the current run. Client options should set
13+
`useBinaryProtocol: PROTOCOL == "msgpack"`.
14+
815
## Sandbox Setup
916

1017
Tests run against the Ably Sandbox at `https://sandbox.realtime.ably-nonprod.net`.

uts/realtime/integration/channels/channel_publish_test.md

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ Spec points: `RTL6`, `RTL6f`, `RSL4`, `RSL6`, `RSL6a2`
55
## Test Type
66
Integration test against Ably sandbox
77

8+
## Protocol Variants
9+
json, msgpack
10+
11+
Each test in this file runs once per protocol variant. The `PROTOCOL` variable
12+
is set to `"json"` or `"msgpack"` for the current run. Client options should set
13+
`useBinaryProtocol: PROTOCOL == "msgpack"`.
14+
815
## Purpose
916

1017
End-to-end verification that messages published on one realtime connection are
@@ -50,14 +57,14 @@ publisher = Realtime(options: ClientOptions(
5057
key: api_key,
5158
endpoint: "nonprod:sandbox",
5259
autoConnect: false,
53-
useBinaryProtocol: false
60+
useBinaryProtocol: PROTOCOL == "msgpack"
5461
))
5562
5663
subscriber = Realtime(options: ClientOptions(
5764
key: api_key,
5865
endpoint: "nonprod:sandbox",
5966
autoConnect: false,
60-
useBinaryProtocol: false
67+
useBinaryProtocol: PROTOCOL == "msgpack"
6168
))
6269
6370
publisher.connect()
@@ -118,14 +125,14 @@ publisher = Realtime(options: ClientOptions(
118125
key: api_key,
119126
endpoint: "nonprod:sandbox",
120127
autoConnect: false,
121-
useBinaryProtocol: false
128+
useBinaryProtocol: PROTOCOL == "msgpack"
122129
))
123130
124131
subscriber = Realtime(options: ClientOptions(
125132
key: api_key,
126133
endpoint: "nonprod:sandbox",
127134
autoConnect: false,
128-
useBinaryProtocol: false
135+
useBinaryProtocol: PROTOCOL == "msgpack"
129136
))
130137
131138
publisher.connect()
@@ -190,14 +197,14 @@ publisher = Realtime(options: ClientOptions(
190197
key: api_key,
191198
endpoint: "nonprod:sandbox",
192199
autoConnect: false,
193-
useBinaryProtocol: false
200+
useBinaryProtocol: PROTOCOL == "msgpack"
194201
))
195202
196203
subscriber = Realtime(options: ClientOptions(
197204
key: api_key,
198205
endpoint: "nonprod:sandbox",
199206
autoConnect: false,
200-
useBinaryProtocol: false
207+
useBinaryProtocol: PROTOCOL == "msgpack"
201208
))
202209
203210
publisher.connect()
@@ -259,14 +266,14 @@ publisher = Realtime(options: ClientOptions(
259266
key: api_key,
260267
endpoint: "nonprod:sandbox",
261268
autoConnect: false,
262-
useBinaryProtocol: false
269+
useBinaryProtocol: PROTOCOL == "msgpack"
263270
))
264271
265272
subscriber = Realtime(options: ClientOptions(
266273
key: api_key,
267274
endpoint: "nonprod:sandbox",
268275
autoConnect: false,
269-
useBinaryProtocol: false
276+
useBinaryProtocol: PROTOCOL == "msgpack"
270277
))
271278
272279
publisher.connect()
@@ -325,14 +332,14 @@ publisher = Realtime(options: ClientOptions(
325332
key: api_key,
326333
endpoint: "nonprod:sandbox",
327334
autoConnect: false,
328-
useBinaryProtocol: false
335+
useBinaryProtocol: PROTOCOL == "msgpack"
329336
))
330337
331338
subscriber = Realtime(options: ClientOptions(
332339
key: api_key,
333340
endpoint: "nonprod:sandbox",
334341
autoConnect: false,
335-
useBinaryProtocol: false
342+
useBinaryProtocol: PROTOCOL == "msgpack"
336343
))
337344
338345
publisher.connect()

uts/realtime/integration/delta_decoding_test.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ Spec points: `PC3`, `PC3a`, `RTL18`, `RTL18b`, `RTL18c`, `RTL19b`, `RTL20`
55
## Test Type
66
Integration test against Ably sandbox
77

8+
## Protocol Variants
9+
json, msgpack
10+
11+
Each test in this file runs once per protocol variant. The `PROTOCOL` variable
12+
is set to `"json"` or `"msgpack"` for the current run. Client options should set
13+
`useBinaryProtocol: PROTOCOL == "msgpack"`.
14+
815
## Purpose
916

1017
End-to-end verification of vcdiff delta decoding using real connections against the
@@ -30,7 +37,7 @@ order compared to `VD2a`.
3037

3138
Tests run against the Ably Sandbox at `https://sandbox.realtime.ably-nonprod.net`.
3239

33-
**Note:** `useBinaryProtocol: false` is required if the SDK does not implement msgpack.
40+
**Note:** `useBinaryProtocol: PROTOCOL == "msgpack"` is used so tests run with both protocols (see Protocol Variants).
3441

3542
### App Provisioning
3643

@@ -93,7 +100,7 @@ counting_decoder = VCDiffDecoder(
93100
client = Realtime(options: ClientOptions(
94101
key: api_key,
95102
endpoint: "nonprod:sandbox",
96-
useBinaryProtocol: false,
103+
useBinaryProtocol: PROTOCOL == "msgpack",
97104
plugins: { vcdiff: counting_decoder }
98105
))
99106
```
@@ -175,7 +182,7 @@ counting_decoder = VCDiffDecoder(
175182
client = Realtime(options: ClientOptions(
176183
key: api_key,
177184
endpoint: "nonprod:sandbox",
178-
useBinaryProtocol: false,
185+
useBinaryProtocol: PROTOCOL == "msgpack",
179186
plugins: { vcdiff: counting_decoder }
180187
))
181188
@@ -257,7 +264,7 @@ counting_decoder = VCDiffDecoder(
257264
client = Realtime(options: ClientOptions(
258265
key: api_key,
259266
endpoint: "nonprod:sandbox",
260-
useBinaryProtocol: false,
267+
useBinaryProtocol: PROTOCOL == "msgpack",
261268
plugins: { vcdiff: counting_decoder }
262269
))
263270
```
@@ -331,7 +338,7 @@ counting_decoder = VCDiffDecoder(
331338
client = Realtime(options: ClientOptions(
332339
key: api_key,
333340
endpoint: "nonprod:sandbox",
334-
useBinaryProtocol: false,
341+
useBinaryProtocol: PROTOCOL == "msgpack",
335342
plugins: { vcdiff: counting_decoder }
336343
))
337344
```
@@ -428,7 +435,7 @@ failing_decoder = FailingVCDiffDecoder()
428435
client = Realtime(options: ClientOptions(
429436
key: api_key,
430437
endpoint: "nonprod:sandbox",
431-
useBinaryProtocol: false,
438+
useBinaryProtocol: PROTOCOL == "msgpack",
432439
plugins: { vcdiff: failing_decoder }
433440
))
434441
```
@@ -507,14 +514,14 @@ channel_name = "delta-no-plugin-" + random_id()
507514
subscriber = Realtime(options: ClientOptions(
508515
key: api_key,
509516
endpoint: "nonprod:sandbox",
510-
useBinaryProtocol: false
517+
useBinaryProtocol: PROTOCOL == "msgpack"
511518
))
512519
513520
# Publisher — separate connection, publishes without delta param
514521
publisher = Realtime(options: ClientOptions(
515522
key: api_key,
516523
endpoint: "nonprod:sandbox",
517-
useBinaryProtocol: false
524+
useBinaryProtocol: PROTOCOL == "msgpack"
518525
))
519526
```
520527

0 commit comments

Comments
 (0)