Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions tests/conformance/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ A language-neutral set of golden-frame tests. Any DCP implementation should
be able to load `golden_frames.yaml` and verify that:

1. **Encode**: building a frame with the given fields produces the listed
`wire_hex`.
2. **Decode**: parsing the `wire_hex` reproduces the listed fields.
header plus `cbor_hex`.
2. **Decode**: parsing the frame bytes derived from the header and `cbor_hex`
reproduces the listed fields.
3. **Framing**: when `uart_wire_hex` is present, COBS+CRC encoding of the
frame produces those bytes; decoding them recovers the frame.
4. **CRC**: `crc16` is the CRC-16/CCITT of the named bytes.
4. **CRC**: when `crc16` is present, it is the CRC-16/CCITT of the frame
bytes before UART wrapping.

The Python reference test runner is in `test_conformance.py` and can serve
as a template for ports.
Expand All @@ -22,18 +24,20 @@ as a template for ports.
intent: "set_brightness" # required: source string for the intent_id
payload: # required: CBOR map contents
level: 50.0
wire_hex: "01 01 ..." # required: full DCP frame (header + cbor)
uart_wire_hex: "0a 01 ..." # optional: COBS-wrapped on-the-wire bytes (no trailing 0x00)
crc16: 0x29b1 # optional: CRC-16 of wire_hex bytes
cbor_hex: "a1 65 ..." # required: CBOR body bytes only
uart_wire_hex: "0a 01 ..." # optional: COBS-wrapped frame+CRC, no trailing 0x00
crc16: 0x29b1 # optional: CRC-16 of full frame bytes
```

Whitespace in hex is allowed and ignored. Hex is lowercase.

## Adding a new test

1. Pick a single concrete frame shape (call, reply, event, dry-run, error).
2. Compute `wire_hex` from a known-good implementation.
3. Where the spec is silent, prefer the simplest possible CBOR encoding (no
2. Compute `cbor_hex` from a known-good implementation.
3. Include `uart_wire_hex` and `crc16` when you want to pin framing and CRC
behavior for that case.
4. Where the spec is silent, prefer the simplest possible CBOR encoding (no
indefinite-length, no tags).

If your implementation disagrees with a golden frame, **the golden is the
Expand Down
47 changes: 47 additions & 0 deletions tests/conformance/golden_frames.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
value: 0.0
cbor_hex: "a1 65 76 61 6c 75 65 fb 00 00 00 00 00 00 00 00"

- name: reply with empty-map body
kind: 0x02
seq: 8
intent: "ping"
payload: {}
cbor_hex: "a0"

- name: dry-run call with one float
kind: 0x81
seq: 99
Expand All @@ -48,6 +55,16 @@
status: 4
cbor_hex: "a1 66 73 74 61 74 75 73 04"

- name: error with multi-field payload
kind: 0x04
seq: 13
intent: "unknown"
payload:
status: 4
message: unknown
code: 404
cbor_hex: "a3 66 73 74 61 74 75 73 04 67 6d 65 73 73 61 67 65 67 75 6e 6b 6e 6f 77 6e 64 63 6f 64 65 19 01 94"

- name: event with float payload
kind: 0x03
seq: 0
Expand All @@ -56,6 +73,15 @@
confidence: 1.0
cbor_hex: "a1 6a 63 6f 6e 66 69 64 65 6e 63 65 fb 3f f0 00 00 00 00 00 00"

- name: event with integer payload at boundaries
kind: 0x03
seq: 0
intent: "motion_detected"
payload:
min: 0
max: 255
cbor_hex: "a2 63 6d 69 6e 00 63 6d 61 78 18 ff"

- name: call with three small ints
kind: 0x01
seq: 0x1234
Expand All @@ -65,6 +91,27 @@
g: 100
b: 0
cbor_hex: "a3 61 72 18 ff 61 67 18 64 61 62 00"
uart_wire_hex: "12 01 01 12 34 7a 22 a3 61 72 18 ff 61 67 18 64 61 62 03 94 ef"
crc16: 0x94ef

- name: call with mixed-width sequence number
kind: 0x01
seq: 0xff01
intent: "set_color"
payload:
r: 255
g: 100
b: 0
cbor_hex: "a3 61 72 18 ff 61 67 18 64 61 62 00"

- name: call with explicit bool + string payload
kind: 0x01
seq: 6
intent: "set_enabled"
payload:
enabled: true
label: ok
cbor_hex: "a2 67 65 6e 61 62 6c 65 64 f5 65 6c 61 62 65 6c 62 6f 6b"

- name: reply with bool
kind: 0x02
Expand Down
8 changes: 8 additions & 0 deletions tests/conformance/test_conformance.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ def _build_frame(case: dict) -> bytes:
return header + _hex(case.get("cbor_hex", ""))


def _crc16_bytes(case: dict) -> bytes:
return _hex(f"{int(case['crc16']):04x}")


def load_cases() -> list[dict]:
return yaml.safe_load(GOLDEN.read_text(encoding="utf-8"))

Expand Down Expand Up @@ -90,6 +94,10 @@ def test_uart_wrap_roundtrip(case: dict):
assert wire.endswith(b"\x00")
assert b"\x00" not in wire[:-1]
assert unwrap(wire[:-1]) == frame_bytes
if "uart_wire_hex" in case:
assert wire[:-1] == _hex(case["uart_wire_hex"])
if "crc16" in case:
assert wire[-3:-1] == _crc16_bytes(case)


def test_intent_id_table():
Expand Down
Loading