Xaloqi/xaloqi-testlab-core

Free, Apache-2.0 UDS (ISO 14229) client, ECU simulator, and campaign runner for automotive diagnostics — pip install xaloqi-tester, zero hardware, zero license.

1

stars

18

commits

Python

primary language

Sep 4, 2026

updated

automotive
diagnostics
doip
embedded
iso14229
python
testing
uds

README

Xaloqi TestLab Core

Run UDS tests without an ECU.

CI License: Apache 2.0 PyPI

Free, open-source Python UDS (ISO 14229) client, ECU simulator, and campaign runner. No hardware. No CAN interface. No commercial diagnostic tool required.

pipx run --spec xaloqi-tester xaloqi-sim --demo

That's it. The command starts an in-process simulated ECU and runs a real UDS conversation against it: session control, VIN read, AES-CMAC SecurityAccess unlock, a security-gated DID read, DTC read — the same protocol traffic a real bench would see.

Or install it:

pip install xaloqi-tester
xaloqi-sim --demo

Build diagnostics?Xaloqi EDS — generate production UDS implementations for Zephyr and FreeRTOS. Test diagnostics? You're in the right place.

Xaloqi TestLab Core demo — pipx run --spec xaloqi-tester xaloqi-sim --demo, showing a real UDS conversation: VIN read, extended session, AES-CMAC SecurityAccess unlock, a security-gated DID read, and a DTC read, ending "All exchanges OK."

Recorded from the actual published package — not a mockup. Command and output are real; only the reveal pacing of the (near-instantaneous) result lines was adjusted for legibility.


Why TestLab?

Exercising UDS normally means an ECU on the bench, a CAN interface, a diagnostic tool, and hand-maintained test scripts. TestLab Core gives you a test environment before any of that exists:

your test campaign (YAML)
          │
          ▼
   ┌────────────────┐
   │  TestLab Core   │
   │  UDS client     │
   │  campaign runner│
   │  ECU simulator  │
   └────────┬────────┘
            │
            ▼
       virtual ECU
      — no hardware —

The same campaign YAML runs against the simulator locally and in CI, then against real hardware unmodified once you add Xaloqi TestLab Pro.


Run a full campaign against it

testlab-run --config testlab_config.yaml \
            --campaign campaigns/standalone_validation.yaml \
            --job basic_validation --virtual --json reports/run.json
testlab analyze --results reports/run.json

campaigns/*.yaml define test jobs — session control, SecurityAccess, DID/memory read-write, DTC handling, firmware transfer, expected NRCs, variable capture/interpolation — as data, not code. --virtual runs them against the built-in simulator.

What's in core (Apache-2.0)

  • UDS client (xaloqi.tester.UdsTester) — async and sync, all major UDS services including 0x27 SecurityAccess (AES-CMAC) and the 0x34/0x35/0x36/0x37 firmware up/download sequence. ISO-TP multi-frame sends honour the ECU's real Flow Control: BlockSize, STmin (both the millisecond and the 100–900us encodings), WAIT with a bounded WFTmax, and OVERFLOW.
  • VirtualBus — the in-process transport and the simulated ECU (xaloqi.sim, also the xaloqi-sim command).
  • Campaign runner (testlab-run) — 20 UDS actions, expect_nrc, variable capture/interpolation, JSON output (schema shared with the Xaloqi EDS diagnostics stack, so the same result format works with either).
  • testlab analyze — terminal summary of a run's JSON results.

Core is licensed under Apache-2.0 — use it for learning UDS, local diagnostic development, virtual ECU testing, campaign development, automated CI validation, and building your own integrations.


How this compares to udsoncan, python-can and can-isotp

If you are doing UDS in Python, you have almost certainly found the established stack: python-can (the CAN bus layer) + can-isotp (ISO 15765-2 transport) + udsoncan (the ISO 14229 client). They are good, mature libraries and this project does not try to replace them.

They answer a different question. That stack is a client — it speaks UDS to an ECU that already exists. TestLab Core is a test harness — a campaign runner plus an ECU that answers, so you can write and run tests before any hardware does.

udsoncan + python-can + can-isotpTestLab Core
What it isUDS client library stackCampaign runner + simulated ECU
Something that answers youNeeds a real ECU. FakeConnection replays a 2-entry static dict — enough to smoke-test your own plumbing, not an ECUStateful simulator: sessions, SecurityAccess seed/key (AES-CMAC), DTCs, NRCs
Real CAN / DoIP hardwareYes, free — socketcan, J2534, and every python-can interfaceNot in core. Core is virtual-transport only; real transports are Pro
Raw UDS service coverageBroader — 27 services, 91 client methods, incl. the full ReadDTCInformation subfunction set, 0x29 Authentication, DynamicallyDefineDataIdentifierFocused on the ~20 actions a validation campaign uses
How you express a testWrite PythonDeclarative YAML campaign
Pass/fail + timing reportBuild it yourselfBuilt in (testlab-run, testlab analyze, JSON out)
Time to first resultA CAN interface and an ECU — or write your own responderpip install xaloqi-tester && xaloqi-sim --demo
LicenseMIT (udsoncan, can-isotp), LGPL-3.0-only (python-can)Apache-2.0

Use udsoncan instead when

  • You have hardware on the bench now and want to drive it for free — core's real transports are a paid tier, theirs are not.
  • You need UDS services outside a validation campaign's usual set — ResponseOnEvent, RequestFileTransfer, the deeper ReadDTCInformation subfunctions, LinkControl.
  • You are building an application that happens to speak UDS, rather than running repeatable tests against an ECU.

Use TestLab Core instead when

  • The ECU does not exist yet, or the bench is occupied, and you still want to write and run the tests.
  • You want the tests to run in CI on every commit, with no hardware and no self-hosted runner.
  • You want tests as reviewable YAML with a pass/fail report, rather than a growing pile of scripts.

They also compose. Nothing stops you developing campaigns against the simulator here and driving real hardware with udsoncan — the JSON result schema is documented, and the same campaign YAML runs unmodified on real transports if you later move to Pro.

Comparison verified 2026-09-04 against udsoncan 1.26.1, python-can 4.6.1, can-isotp 2.0.7 and xaloqi-tester 1.5.2, by installing each from PyPI and inspecting the actual APIs — not from documentation. If something here is out of date or wrong, open an issue and it will be corrected.


Use it in CI

A virtual ECU is useful in CI precisely because the test doesn't depend on a bench being available. A minimal GitHub Actions job:

name: UDS tests
on: [push, pull_request]
jobs:
  uds:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install xaloqi-tester
      - run: |
          mkdir -p reports
          testlab-run --config testlab_config.yaml \
            --campaign campaigns/standalone_validation.yaml \
            --job basic_validation --virtual --json reports/run.json
      - run: testlab analyze --results reports/run.json

Repeatable diagnostic tests on every push and pull request, no ECU hardware allocated to the CI runner.


Learn by doing

RecipeWhat you'll proveHardware
SecurityAccessProtected resources stay locked until UDS 0x27 unlockNone
GitHub ActionsRun UDS regression tests on every PRNone
Negative responsesAssert the ECU rejects what it should, with the right NRCNone
DTCsRead, clear and re-read Diagnostic Trouble Codes (0x19 / 0x14)None
Firmware downloadExercise the 0x340x360x37 programming flowNone
DoIPMove the same UDS testing model to Automotive EthernetDoIP endpoint (Pro) for real-network testing

Start here: pipx run --spec xaloqi-tester xaloqi-sim --demo

Every recipe above is run and verified against the real published package before being committed — not just described.

Try the examples

The bundled config and campaigns are meant to be changed, not just run:

examples/diagnostics_config.yaml
campaigns/standalone_validation.yaml
campaigns/basic_validation.yaml
testlab_config.yaml

Run the bundled campaign first:

testlab-run --config testlab_config.yaml \
            --campaign campaigns/standalone_validation.yaml \
            --job basic_validation --virtual

Then fork this repository and adapt it to your own ECU: change a DID or expected value, add an expected NRC, add another diagnostic step, run it locally, then put it in CI. If you build a useful campaign for a common ECU workflow, contributions are welcome.


Cross-implementation tested, not just self-tested

Xaloqi Compatibility Tests runs the same UDS campaign against every combination of transport (CAN, DoIP) and RTOS (Zephyr, FreeRTOS) Xaloqi EDS ships examples for, using xaloqi-tester's Python client against EDS's C runtime — a genuine cross-language, cross-implementation check, not two halves of one codebase validating each other. Honestly: the virtual-ECU check there is green and reproducible by anyone with no license; the real-transport matrix is still being wired up (tracked openly at xaloqi-compatibility-tests#2, including EDS#230 — EDS's own DoIP Integration CI job currently skips this exact check rather than proving it).

Build → Test with Xaloqi

TestLab is the test side of the Xaloqi workflow. Xaloqi EDS is the build side — generate production ISO 14229 diagnostics for Zephyr and FreeRTOS from YAML.

diagnostics_config.yaml
          │
          ▼
   ┌──────────────┐
   │  Xaloqi EDS  │  BUILD
   └──────┬───────┘
          │ generated ECU diagnostics
          ▼
   ┌──────────────┐
   │   TestLab    │  TEST
   └──────────────┘
          │
          ▼
  virtual ECU / CI / real hardware

Need to implement ISO 14229 diagnostics on Zephyr or FreeRTOS? → Xaloqi EDS. Already have an ECU and need to test it? Stay here.


What's in Pro

Real transports (SocketCAN, PCAN/Kvaser, DoIP, SOME/IP), the SOVD client, multi-ECU workspace mode, RTOS comparison, HTML reports/trends/dashboard, and AI-assisted failure analysis are part of Xaloqi TestLab Pro — installed as an additional wheel alongside this package. Core discovers Pro automatically through Python entry points: install Pro and every testlab command and campaign action above works unchanged, plus the paid ones. Without Pro installed, a paid transport, action, or subcommand fails with one clear message telling you what it needs.

Installing from source

git clone https://github.com/Xaloqi/xaloqi-testlab-core
cd xaloqi-testlab-core
pip install -e ".[dev]"
XALOQI_LICENSE_SKIP=1 pytest tests/ -v

Who is this for?

Automotive ECUs, software-defined vehicles, battery management systems, motor controllers, gateways, embedded controllers, diagnostic bootloaders, Zephyr or FreeRTOS projects, CI pipelines for embedded software — and learning ISO 14229 without buying hardware first.

Contributing

See CONTRIBUTING.md. If you've built something with TestLab, opening a discussion or linking your project helps us understand which workflows deserve more attention. Found a security issue? See SECURITY.md — please don't open a public issue for it.

License

Apache License 2.0 — see LICENSE.


If TestLab saved you from setting up a bench just to exercise a UDS flow, consider starring the repository. More usefully: fork it, change a campaign, and make it test your ECU.

Build diagnostics: Xaloqi EDS · Test diagnostics: Xaloqi TestLab Core · Commercial tooling: xaloqi.com

Contributors

Xaloqi

18 commits

Xaloqi/xaloqi-testlab-core

Free, Apache-2.0 UDS (ISO 14229) client, ECU simulator, and campaign runner for automotive diagnostics — pip install xaloqi-tester, zero hardware, zero license.

1

stars

18

commits

Python

primary language

Sep 4, 2026

updated

automotive
diagnostics
doip
embedded
iso14229
python
testing
uds

README

Xaloqi TestLab Core

Run UDS tests without an ECU.

CI License: Apache 2.0 PyPI

Free, open-source Python UDS (ISO 14229) client, ECU simulator, and campaign runner. No hardware. No CAN interface. No commercial diagnostic tool required.

pipx run --spec xaloqi-tester xaloqi-sim --demo

That's it. The command starts an in-process simulated ECU and runs a real UDS conversation against it: session control, VIN read, AES-CMAC SecurityAccess unlock, a security-gated DID read, DTC read — the same protocol traffic a real bench would see.

Or install it:

pip install xaloqi-tester
xaloqi-sim --demo

Build diagnostics?Xaloqi EDS — generate production UDS implementations for Zephyr and FreeRTOS. Test diagnostics? You're in the right place.

Xaloqi TestLab Core demo — pipx run --spec xaloqi-tester xaloqi-sim --demo, showing a real UDS conversation: VIN read, extended session, AES-CMAC SecurityAccess unlock, a security-gated DID read, and a DTC read, ending "All exchanges OK."

Recorded from the actual published package — not a mockup. Command and output are real; only the reveal pacing of the (near-instantaneous) result lines was adjusted for legibility.


Why TestLab?

Exercising UDS normally means an ECU on the bench, a CAN interface, a diagnostic tool, and hand-maintained test scripts. TestLab Core gives you a test environment before any of that exists:

your test campaign (YAML)
          │
          ▼
   ┌────────────────┐
   │  TestLab Core   │
   │  UDS client     │
   │  campaign runner│
   │  ECU simulator  │
   └────────┬────────┘
            │
            ▼
       virtual ECU
      — no hardware —

The same campaign YAML runs against the simulator locally and in CI, then against real hardware unmodified once you add Xaloqi TestLab Pro.


Run a full campaign against it

testlab-run --config testlab_config.yaml \
            --campaign campaigns/standalone_validation.yaml \
            --job basic_validation --virtual --json reports/run.json
testlab analyze --results reports/run.json

campaigns/*.yaml define test jobs — session control, SecurityAccess, DID/memory read-write, DTC handling, firmware transfer, expected NRCs, variable capture/interpolation — as data, not code. --virtual runs them against the built-in simulator.

What's in core (Apache-2.0)

  • UDS client (xaloqi.tester.UdsTester) — async and sync, all major UDS services including 0x27 SecurityAccess (AES-CMAC) and the 0x34/0x35/0x36/0x37 firmware up/download sequence. ISO-TP multi-frame sends honour the ECU's real Flow Control: BlockSize, STmin (both the millisecond and the 100–900us encodings), WAIT with a bounded WFTmax, and OVERFLOW.
  • VirtualBus — the in-process transport and the simulated ECU (xaloqi.sim, also the xaloqi-sim command).
  • Campaign runner (testlab-run) — 20 UDS actions, expect_nrc, variable capture/interpolation, JSON output (schema shared with the Xaloqi EDS diagnostics stack, so the same result format works with either).
  • testlab analyze — terminal summary of a run's JSON results.

Core is licensed under Apache-2.0 — use it for learning UDS, local diagnostic development, virtual ECU testing, campaign development, automated CI validation, and building your own integrations.


How this compares to udsoncan, python-can and can-isotp

If you are doing UDS in Python, you have almost certainly found the established stack: python-can (the CAN bus layer) + can-isotp (ISO 15765-2 transport) + udsoncan (the ISO 14229 client). They are good, mature libraries and this project does not try to replace them.

They answer a different question. That stack is a client — it speaks UDS to an ECU that already exists. TestLab Core is a test harness — a campaign runner plus an ECU that answers, so you can write and run tests before any hardware does.

udsoncan + python-can + can-isotpTestLab Core
What it isUDS client library stackCampaign runner + simulated ECU
Something that answers youNeeds a real ECU. FakeConnection replays a 2-entry static dict — enough to smoke-test your own plumbing, not an ECUStateful simulator: sessions, SecurityAccess seed/key (AES-CMAC), DTCs, NRCs
Real CAN / DoIP hardwareYes, free — socketcan, J2534, and every python-can interfaceNot in core. Core is virtual-transport only; real transports are Pro
Raw UDS service coverageBroader — 27 services, 91 client methods, incl. the full ReadDTCInformation subfunction set, 0x29 Authentication, DynamicallyDefineDataIdentifierFocused on the ~20 actions a validation campaign uses
How you express a testWrite PythonDeclarative YAML campaign
Pass/fail + timing reportBuild it yourselfBuilt in (testlab-run, testlab analyze, JSON out)
Time to first resultA CAN interface and an ECU — or write your own responderpip install xaloqi-tester && xaloqi-sim --demo
LicenseMIT (udsoncan, can-isotp), LGPL-3.0-only (python-can)Apache-2.0

Use udsoncan instead when

  • You have hardware on the bench now and want to drive it for free — core's real transports are a paid tier, theirs are not.
  • You need UDS services outside a validation campaign's usual set — ResponseOnEvent, RequestFileTransfer, the deeper ReadDTCInformation subfunctions, LinkControl.
  • You are building an application that happens to speak UDS, rather than running repeatable tests against an ECU.

Use TestLab Core instead when

  • The ECU does not exist yet, or the bench is occupied, and you still want to write and run the tests.
  • You want the tests to run in CI on every commit, with no hardware and no self-hosted runner.
  • You want tests as reviewable YAML with a pass/fail report, rather than a growing pile of scripts.

They also compose. Nothing stops you developing campaigns against the simulator here and driving real hardware with udsoncan — the JSON result schema is documented, and the same campaign YAML runs unmodified on real transports if you later move to Pro.

Comparison verified 2026-09-04 against udsoncan 1.26.1, python-can 4.6.1, can-isotp 2.0.7 and xaloqi-tester 1.5.2, by installing each from PyPI and inspecting the actual APIs — not from documentation. If something here is out of date or wrong, open an issue and it will be corrected.


Use it in CI

A virtual ECU is useful in CI precisely because the test doesn't depend on a bench being available. A minimal GitHub Actions job:

name: UDS tests
on: [push, pull_request]
jobs:
  uds:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install xaloqi-tester
      - run: |
          mkdir -p reports
          testlab-run --config testlab_config.yaml \
            --campaign campaigns/standalone_validation.yaml \
            --job basic_validation --virtual --json reports/run.json
      - run: testlab analyze --results reports/run.json

Repeatable diagnostic tests on every push and pull request, no ECU hardware allocated to the CI runner.


Learn by doing

RecipeWhat you'll proveHardware
SecurityAccessProtected resources stay locked until UDS 0x27 unlockNone
GitHub ActionsRun UDS regression tests on every PRNone
Negative responsesAssert the ECU rejects what it should, with the right NRCNone
DTCsRead, clear and re-read Diagnostic Trouble Codes (0x19 / 0x14)None
Firmware downloadExercise the 0x340x360x37 programming flowNone
DoIPMove the same UDS testing model to Automotive EthernetDoIP endpoint (Pro) for real-network testing

Start here: pipx run --spec xaloqi-tester xaloqi-sim --demo

Every recipe above is run and verified against the real published package before being committed — not just described.

Try the examples

The bundled config and campaigns are meant to be changed, not just run:

examples/diagnostics_config.yaml
campaigns/standalone_validation.yaml
campaigns/basic_validation.yaml
testlab_config.yaml

Run the bundled campaign first:

testlab-run --config testlab_config.yaml \
            --campaign campaigns/standalone_validation.yaml \
            --job basic_validation --virtual

Then fork this repository and adapt it to your own ECU: change a DID or expected value, add an expected NRC, add another diagnostic step, run it locally, then put it in CI. If you build a useful campaign for a common ECU workflow, contributions are welcome.


Cross-implementation tested, not just self-tested

Xaloqi Compatibility Tests runs the same UDS campaign against every combination of transport (CAN, DoIP) and RTOS (Zephyr, FreeRTOS) Xaloqi EDS ships examples for, using xaloqi-tester's Python client against EDS's C runtime — a genuine cross-language, cross-implementation check, not two halves of one codebase validating each other. Honestly: the virtual-ECU check there is green and reproducible by anyone with no license; the real-transport matrix is still being wired up (tracked openly at xaloqi-compatibility-tests#2, including EDS#230 — EDS's own DoIP Integration CI job currently skips this exact check rather than proving it).

Build → Test with Xaloqi

TestLab is the test side of the Xaloqi workflow. Xaloqi EDS is the build side — generate production ISO 14229 diagnostics for Zephyr and FreeRTOS from YAML.

diagnostics_config.yaml
          │
          ▼
   ┌──────────────┐
   │  Xaloqi EDS  │  BUILD
   └──────┬───────┘
          │ generated ECU diagnostics
          ▼
   ┌──────────────┐
   │   TestLab    │  TEST
   └──────────────┘
          │
          ▼
  virtual ECU / CI / real hardware

Need to implement ISO 14229 diagnostics on Zephyr or FreeRTOS? → Xaloqi EDS. Already have an ECU and need to test it? Stay here.


What's in Pro

Real transports (SocketCAN, PCAN/Kvaser, DoIP, SOME/IP), the SOVD client, multi-ECU workspace mode, RTOS comparison, HTML reports/trends/dashboard, and AI-assisted failure analysis are part of Xaloqi TestLab Pro — installed as an additional wheel alongside this package. Core discovers Pro automatically through Python entry points: install Pro and every testlab command and campaign action above works unchanged, plus the paid ones. Without Pro installed, a paid transport, action, or subcommand fails with one clear message telling you what it needs.

Installing from source

git clone https://github.com/Xaloqi/xaloqi-testlab-core
cd xaloqi-testlab-core
pip install -e ".[dev]"
XALOQI_LICENSE_SKIP=1 pytest tests/ -v

Who is this for?

Automotive ECUs, software-defined vehicles, battery management systems, motor controllers, gateways, embedded controllers, diagnostic bootloaders, Zephyr or FreeRTOS projects, CI pipelines for embedded software — and learning ISO 14229 without buying hardware first.

Contributing

See CONTRIBUTING.md. If you've built something with TestLab, opening a discussion or linking your project helps us understand which workflows deserve more attention. Found a security issue? See SECURITY.md — please don't open a public issue for it.

License

Apache License 2.0 — see LICENSE.


If TestLab saved you from setting up a bench just to exercise a UDS flow, consider starring the repository. More usefully: fork it, change a campaign, and make it test your ECU.

Build diagnostics: Xaloqi EDS · Test diagnostics: Xaloqi TestLab Core · Commercial tooling: xaloqi.com

Contributors

Xaloqi

18 commits

Languages

Python

100.0%