27 byte-exact UDS vectors, three ISO standards, and no transport to buy
xaloqi.tester.conformance now ships inside the free, Apache-2.0 xaloqi-tester package: 27 byte-exact conformance vectors across three ISO standards — ISO 15765-2 (ISO-TP), ISO 14229-1 (UDS SID framing), ISO 13400-2 (DoIP) — each independently sourced from a real open-source UDS toolchain's own test fixtures, plus a runner that judges == on bytes. It needs nothing from xaloqi-tester-pro to run.
pip install xaloqi-tester python3 -m xaloqi.tester.conformance uds-sid --interface vcan0 --rx-id 0x7E8 --tx-id 0x7E0
That second line is the whole interface: point it at whatever already answers UDS on your bench, and it reports, vector by vector, whether the bytes matched.
"Bring your own transport" is the design, not a gap
The obvious way to ship a conformance suite from a company that also sells diagnostics tooling is to make it run on that company's own transports — SocketCAN, DoIP, PCAN/Kvaser, all xaloqi-tester-pro features. We didn't, on purpose. An earlier draft of this corpus assumed it could lean on this package's own real transports, and then ran into the fact that they don't exist in the free tier — real hardware transports are Pro's actual differentiator. Giving a third party no choice but to either pay for a transport or use ours would have made this "a test suite with marketing attached," which is the one outcome everyone involved explicitly wanted to avoid.
So the free core ships CanBus — two methods, send() and recv() — and UdsTester, which turns a CanBus into complete-PDU request/response handling (ISO-TP segmentation included). Nothing in xaloqi.tester.conformance depends on anything beyond that contract. Implement those two methods against whatever you already use to talk to your own stack — python-can, a raw socket, hardware you already have working — and every fixture-independent vector runs against it. examples/conformance_bindings/can_frame_python_can.py is a real, runnable one, using python-can (LGPL-3.0-only, an ordinary dependency, not modified or redistributed) as a convenient already-independent transport.
Where the 27 vectors actually come from
| Suite | Primitive needed | Vectors | requires_fixture |
|---|---|---|---|
isotp | CanBus.send()/recv() (raw frames) | 7 | 4 |
uds_sid | UdsTester.raw_exchange() (complete PDUs, any transport) | 15 | 4 |
doip | DoipRawProbe (new — raw TCP bytes) | 5 | 0 |
Every vector is a port, and every port is cited. isotp was transcribed from EDS's own tests/unit_runnable/test_isotp_conformance_vectors.c, itself an independent port of python-can-isotp's test_transport_layer_logic.py (MIT, Copyright (c) 2017 Pier-Yves Lessard). uds_sid was transcribed from EDS's test_uds_sid_conformance_vectors.c, itself an independent port of udsoncan's own test suite (MIT, Copyright (c) 2017 Pier-Yves Lessard — a different project, same original author as the ISO-TP one). doip was transcribed from EDS's test_doip_conformance_vectors.c, itself an independent port of python-doipclient's test_client.py (MIT, Copyright (c) 2020 Jacob Schaer). It is the one suite with no existing free primitive to run on: it tests the DoIP TCP header's own framing and addressing — routing activation, diagnostic message ACK, alive check — one level below a complete UDS PDU, which is as far down as UdsTester's message-oriented path goes. No free transport exposed that, so the package adds exactly one new, deliberately narrow primitive: DoipRawProbe opens a socket, writes exactly these bytes, reads up to a timeout. No routing-activation lifecycle, no reconnection — a conformance probe, not a transport for test campaigns. xaloqi-tester-pro's DoipBus is for that; this package's free tier isn't trying to be a smaller version of it.
All three suites assert the request/response envelope — echoed SID, sub-function, DID, length, NRC byte — not DID, DTC, or routine content. Eleven of the fifteen uds_sid vectors hold against any EDS build; the rest are described below.
requires_fixture — read this before a vector "fails" against your target
Eight of the 27 vectors assert against a specific test DID (0x0001), routine (0x0012), or flow-control configuration that EDS's own conformance test registers as a throwaway fixture — not a universal ISO requirement, and not present in most real targets' production configuration. Each is tagged requires_fixture: true with a note saying exactly what's needed. Run one against a target that doesn't have that fixture and you'll correctly get a mismatch — often a legitimate requestOutOfRange or invalidKey — which is the target behaving correctly, not a defect in either the target or the vector.
So every vector has somewhere real to pass: examples/conformance_bindings/reference_uds_stub.py registers exactly these fixtures in roughly 250 lines of plain Python that share no code with EDS, and the package's own test suite runs the full 15-vector uds_sid suite against that stub, fixture vectors included.
Two proofs, not one
The corpus is judged two ways, and neither alone would have been enough. Against real, unmodified EDS — the same examples/basic_ecu_cda_demo firmware and the same no-sudo vxcan-in-Docker pattern (--cap-add=NET_ADMIN --cap-add=NET_RAW, no privileged host access) described in our previous post on the real CDA interop — the fixture-independent vectors run end to end over a real CAN link against real firmware, not a mock. Against an independent reference implementation — the 250-line stub above, written specifically to share nothing with EDS — the full uds_sid suite, fixture vectors included, proves the vectors' mechanics hold on their own terms, not just against the one codebase they were transcribed from.
What this doesn't claim
This is not an ISO conformance certification. No suite here is a complete implementation of its standard — each suite's own scope_note and not_ported list in corpus/*.json names specific upstream behaviors deliberately left out, and why. It is not a check on DID, DTC, or routine content, only the envelope around them, and each vector's description says so. Despite this corpus's origin as a SOVD→UDS harness, it is not a check on the SOVD layer at all — nothing here touches an HTTP API; that claim is exercised instead by a real interop demo against a real SOVD gateway, which is what the previous post was. And a byte-exact pass across all 27 vectors is evidence of protocol mechanics, not a safety case or a certification that a target is fit to deploy.
Try it yourself
pip install xaloqi-tester python3 -m xaloqi.tester.conformance isotp --interface vcan0 --can-id 0x7E0 python3 -m xaloqi.tester.conformance uds-sid --interface vcan0 --rx-id 0x7E8 --tx-id 0x7E0 python3 -m xaloqi.tester.conformance doip --host 192.0.2.10 --port 13400
Point any of the three at whatever already answers UDS on your bench — real hardware, your own simulator, or the reference stub this corpus is itself judged against.