Skip to content

Commit 2487f9d

Browse files
authored
Merge branch 'development' into react-viewer-collapsible-streams
2 parents e440f34 + 29e5ac3 commit 2487f9d

389 files changed

Lines changed: 13515 additions & 5015 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/copilot-instructions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ See `.github/skills/build.md` for full build instructions. The project uses **CM
9999
| Platform | Notes |
100100
|---|---|
101101
| **Windows 10/11** | MSVC (Visual Studio 2019/2022) |
102-
| **Ubuntu 20.04 / 22.04 / 24.04** | GCC, primary Linux target |
102+
| **Ubuntu 20.04 / 22.04 / 24.04 / 26.04** | GCC, primary Linux target |
103103
| **macOS** | Clang, macOS 15+ tested in CI |
104104
| **NVIDIA Jetson** | ARM64, L4T |
105105
| **Raspberry Pi** | ARM (Raspbian) |

.github/skills/build.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
| **Windows 10/11** | Visual Studio 2019 or 2022 (MSVC) | CI uses `windows-2025` runners |
1616
| **Ubuntu 22.04** | GCC | Primary Linux target |
1717
| **Ubuntu 24.04** | GCC | Also tested in CI |
18+
| **Ubuntu 26.04** | GCC | Supported |
1819
| **macOS 15+** | Clang (Xcode) | Tested in CI on `macos-15` |
1920
| **NVIDIA Jetson** | GCC (ARM64, L4T) | See `doc/installation_jetson.md` |
2021
| **Raspberry Pi** | GCC (ARM) | See `doc/installation_raspbian.md` |

.github/skills/cpp_coding.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,10 @@ Use this protocol to ensure all C++ code modifications align with the project's
3131
### 6. Performance Checks
3232
* **Hot Paths**: Check for hidden allocations in loops or streaming callbacks.
3333
* **Copying**: Minimize data copying; use const references (`const T&`) for non-primitive arguments.
34+
35+
### 7. Comments
36+
* **Comments should be sparse.** Keep to 1–2 lines unless the code is large and genuinely complex.
37+
* **Intention:** Don't restate what the code already says, comment should convey the reason for the code.
38+
* **Locality:** The comment should refer to the local code. e.g. class description should not mention inheritors or where other logic live.
39+
* **Length:** Comment lines can be as long as the surrounding code. If code lines usually trim at 120 characters comment lines don't have to be 80 characters long.
40+
* **Generality:** Don't reference internal session reasoning e.g. "as you instructed"

.github/skills/testing.md

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@
1313

1414
## Test Framework
1515

16-
- librealsense uses a **custom Python-based test framework**
17-
- The test orchestrator is `unit-tests/run-unit-tests.py`
18-
- Tests must be run **from the `unit-tests/` directory**
16+
Two frameworks, split by test language:
17+
18+
- **C++ tests** (`test-*.cpp`) are orchestrated by the legacy runner `unit-tests/run-unit-tests.py`.
19+
Keeping that runner for C++ testing is its only remaining purpose.
20+
- **Python tests** (`pytest-*.py`) are pytest only. See `.github/skills/pytest-infra.md`.
21+
No legacy `test-*.py` scripts remain, and `run-unit-tests.py` never collects `pytest-*.py`.
22+
23+
Either way, run **from the `unit-tests/` directory**.
1924

2025
## Test Categories
2126

@@ -31,7 +36,21 @@
3136
| `unit-tests/log/` | Logging | Logging infrastructure tests |
3237
| `unit-tests/types/` | Types | Type system tests |
3338

34-
## Running All Tests
39+
## Running the pytest Tests
40+
41+
```bash
42+
cd unit-tests
43+
python3 -m pytest -v # all collectable tests
44+
python3 -m pytest -v live/frames # one directory
45+
python3 -m pytest -v pytest-fw-update.py # one file
46+
python3 -m pytest -v -k "hdr and not preset" # filter by test name
47+
```
48+
49+
Flags are registered in `conftest.py`: `--live`, `--not-live`, `--device`, `--exclude-device`,
50+
`--context`, `--tag`, `--repeat`, `--reruns`, `--debug`, `--rslog`, `--test-dir`. Note that `-s`
51+
disables the per-test log files. See `.github/skills/pytest-infra.md` for fixtures and markers.
52+
53+
## Running the C++ Tests (legacy runner)
3554

3655
Navigate to the `unit-tests/` directory and run:
3756

@@ -57,21 +76,23 @@ For full usage and all available flags:
5776
python3 run-unit-tests.py --help
5877
```
5978

60-
## Running Specific Tests
79+
## Running Specific C++ Tests
80+
81+
The flags below belong to `run-unit-tests.py`, so they select among the C++ tests.
82+
For pytest use `-k`, `-m` and the flags listed above.
6183

6284
### By Name (Regex)
6385

6486
Use `-r` / `--regex` to run tests whose names match a regular expression:
6587

6688
```bash
67-
python3 run-unit-tests.py -s -r "test-hdr"
68-
python3 run-unit-tests.py -s -r "test-metadata"
69-
python3 run-unit-tests.py -s --regex "test-stream.*"
89+
python3 run-unit-tests.py -s -r "test-log-vs-LOG"
90+
python3 run-unit-tests.py -s --regex "rsutils-string.*"
7091
```
7192

7293
**Test name derivation**: the orchestrator builds a test's name from its path relative to `unit-tests/`, replacing directory separators with `-` and stripping the leading `test-` from the filename. For example:
73-
- `live/hw-reset/test-stress.py` `test-live-hw-reset-stress`
74-
- `func/test-hdr.py` `test-func-hdr`
94+
- `rsutils/string/test-hexarray.cpp` becomes `test-rsutils-string-hexarray`
95+
- `log/test-vs-LOG-shared.cpp` becomes `test-log-vs-LOG-shared`
7596

7697
So when using `-r`, omit the `test-` filename prefix and join subdirectories with `-`.
7798

@@ -80,18 +101,18 @@ So when using `-r`, omit the `test-` filename prefix and join subdirectories wit
80101
Use `--skip-regex` to exclude tests whose names match:
81102

82103
```bash
83-
python3 run-unit-tests.py -s --skip-regex "test-fw-update"
104+
python3 run-unit-tests.py -s --skip-regex "test-rsutils-string-hexarray"
84105
```
85106

86107
### By Tag
87108

88-
Use `-t` / `--tag` to run tests with a specific tag. Tags are assigned automatically based on:
89-
- File type: `exe` (C++ binaries) or `py` (Python scripts)
109+
Use `-t` / `--tag` to run tests with a specific tag. Tags come from:
110+
- File type: `exe` (C++ binaries). The `py` tag matches nothing now that no legacy `test-*.py` remain.
90111
- Directory location: e.g., tests in `unit-tests/live/` get the `live` tag
112+
- An explicit `//#test:tag <name>` directive in the source file
91113

92114
```bash
93115
python3 run-unit-tests.py -s -t live # run only live tests
94-
python3 run-unit-tests.py -s -t py # run only Python tests
95116
python3 run-unit-tests.py -s -t exe # run only compiled C++ tests
96117
python3 run-unit-tests.py -s -t live -t exe # run tests that have BOTH tags
97118
```
@@ -136,31 +157,34 @@ python3 run-unit-tests.py --rslog # enable LibRS debug logging in tests
136157
python3 run-unit-tests.py --debug # enable framework debug output; also prints "test took X seconds" per test
137158
```
138159

139-
## Running Nightly-Only Tests
160+
## Running Nightly-Only and Weekly Tests
161+
162+
Both runners take `--context`, which accepts a **space-separated list**.
140163

141-
Some tests are marked `# test:donotrun:!nightly` and are **skipped by default**. Pass `--context nightly` to enable them:
164+
pytest tests gated with `@pytest.mark.context("nightly")` are skipped unless the context is passed:
142165

143166
```bash
144-
python3 run-unit-tests.py --context nightly -r hw-reset-stress ../build/Release
167+
python3 -m pytest -v live/hw-reset/pytest-stress.py --context nightly
145168
```
146169

147-
## Running Weekly Tests
148-
149-
Weekly tests use a higher iteration count / longer timeout (controlled by `'weekly' in test.context` inside the test). The `--context` flag accepts a **space-separated list**, so to run a nightly-guarded test with weekly behaviour pass **both** contexts:
170+
A test that also scales its iteration count or timeout for weekly runs reads the context through the
171+
`test_context_var` fixture, so pass both words to get nightly collection plus weekly behaviour:
150172

151173
```bash
152-
# 'nightly' satisfies the test:donotrun:!nightly guard
153-
# 'weekly' activates higher iteration counts and longer timeouts inside the test
154-
python3 run-unit-tests.py --context "nightly weekly" -r hw-reset-stress ../build/Release
174+
python3 -m pytest -v live/hw-reset/pytest-stress.py --context "nightly weekly"
155175
```
156176

157-
Passing `--context weekly` alone is **not sufficient** — the `test:donotrun:!nightly` directive will still filter the test out.
177+
C++ tests use a `//#test:donotrun:<context>` directive in the source file, evaluated by
178+
`run-unit-tests.py` against the same `--context` list.
158179

159180
## Repeating and Retrying
160181

161182
```bash
162183
python3 run-unit-tests.py --repeat 3 # repeat each test 3 times
163184
python3 run-unit-tests.py --retry 2 # retry failed tests up to 2 times
185+
186+
python3 -m pytest --repeat 3 # pytest: repeat each file's tests 3 times
187+
python3 -m pytest --reruns 2 # pytest: retry a failed test up to 2 times
164188
```
165189

166190
## Recording and Playback (Mock Hardware)
@@ -185,7 +209,7 @@ This is useful for:
185209
The `UNIT_TESTS_ARGS` CMake variable passes arguments to `unit-test-config.py` during configuration:
186210

187211
```bash
188-
cmake .. -DBUILD_UNIT_TESTS=ON -DUNIT_TESTS_ARGS="-t live -r test-streaming"
212+
cmake .. -DBUILD_UNIT_TESTS=ON -DUNIT_TESTS_ARGS="-t live -r rsutils-string.*"
189213
```
190214

191215
## Using a Custom Test Directory
@@ -196,13 +220,17 @@ python3 run-unit-tests.py --test-dir /path/to/custom/tests
196220

197221
## Custom Firmware for Testing
198222

199-
The SDK no longer ships a bundled firmware blob, so `test-fw-update` **requires** a custom firmware path for the device under test. Without one it logs a warning and skips. Download a signed `.bin` from <https://dev.realsenseai.com/docs/firmware-updates>, then:
223+
The SDK no longer ships a bundled firmware blob, so `pytest-fw-update` **requires** a custom firmware path for the device under test. Without one it skips. Download a signed `.bin` from <https://dev.realsenseai.com/docs/firmware-updates>, then:
200224

201225
```bash
202-
python3 run-unit-tests.py --custom-fw-d400 /path/to/firmware.bin
203-
python3 run-unit-tests.py --custom-fw-d555 /path/to/firmware.bin
226+
python3 -m pytest pytest-fw-update.py --custom-fw-d400 /path/to/firmware.bin
227+
python3 -m pytest pytest-fw-update.py --custom-fw-d555 /path/to/firmware.bin
228+
python3 -m pytest pytest-fw-update.py --custom-fw-d585 /path/to/firmware.bin
204229
```
205230

231+
`--custom-fw-d585` targets the non-safety D585 only (e.g. "D585 Prototype"). The safety SKU is kept
232+
out of the test by `pytest.mark.device_exclude("D585S")`, so it is never collected and never flashed.
233+
206234
## Troubleshooting
207235

208236
- If tests fail due to missing `pyrealsense2`, ensure `-DBUILD_PYTHON_BINDINGS=ON` was set during the CMake configure step

.github/workflows/build-ROS2-package-CI.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ jobs:
9090
with:
9191
required-ros-distributions: ${{ matrix.ros_distribution }}
9292

93+
- name: checkout repository
94+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
95+
with:
96+
fetch-depth: 1
97+
persist-credentials: false
98+
submodules: recursive
99+
93100
- name: build librealsense ROS 2
94101
uses: ros-tooling/action-ros-ci@3a640b10f09b756dabe556dac5413aba369f71b0 #v0.4.8
95102
with:

.github/workflows/build-ROS2-rolling-CI.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ jobs:
7676
# in the stable ros2 apt index.
7777
use-ros2-testing: true
7878

79+
- name: checkout repository
80+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
81+
with:
82+
fetch-depth: 1
83+
persist-credentials: false
84+
submodules: recursive
85+
7986
- name: build librealsense ROS 2
8087
uses: ros-tooling/action-ros-ci@3a640b10f09b756dabe556dac5413aba369f71b0 #v0.4.8
8188
with:

.github/workflows/buildsCI.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,53 @@ jobs:
412412
python3 -m pip install -r unit-tests/requirements.txt
413413
python3 -m pytest unit-tests/ --color=no --debug -s --not-live --context "linux"
414414
415+
#--------------------------------------------------------------------------------
416+
U26_SH_Py_CI_SYS_JSON: # Ubuntu 26.04, Shared, Python, LibCI with executables and system provided nlohmann_json library
417+
runs-on: ubuntu-26.04
418+
timeout-minutes: 60
419+
steps:
420+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
421+
422+
- name: Prebuild
423+
shell: bash
424+
run: |
425+
sudo apt-get update;
426+
sudo apt-get install -qq build-essential xorg-dev libgl1-mesa-dev libglu1-mesa-dev libglew-dev libglm-dev;
427+
sudo apt-get install -qq libusb-1.0-0-dev;
428+
sudo apt-get install -qq libgtk-3-dev;
429+
sudo apt-get install -qq libglfw3-dev libglfw3;
430+
sudo apt-get install -qq nlohmann-json3-dev;
431+
python3 -m pip install numpy
432+
# for debugging purpose
433+
dpkg -s nlohmann-json3-dev | grep "Package\|Version" | xargs
434+
435+
- name: Check_API
436+
shell: bash
437+
run: |
438+
cd scripts
439+
./api_check.sh
440+
./pr_check.sh
441+
cd ..
442+
mkdir build
443+
444+
- name: Build
445+
shell: bash
446+
run: |
447+
cd build
448+
cmake .. -DCMAKE_BUILD_TYPE=${{env.LRS_RUN_CONFIG}} -DBUILD_SHARED_LIBS=true -DBUILD_EXAMPLES=false -DBUILD_TOOLS=true -DBUILD_UNIT_TESTS=true -DUNIT_TESTS_ARGS="--not-live --context=linux" -DCHECK_FOR_UPDATES=false -DBUILD_WITH_DDS=false -DBUILD_PYTHON_BINDINGS=true -DPYTHON_EXECUTABLE=$(which python3) -DUSE_EXTERNAL_NLOHMANN_JSON=ON
449+
cmake --build . -- -j4
450+
451+
- name: LibCI
452+
# Note: requires BUILD_UNIT_TESTS or the executable C++ unit-tests won't run (and it won't complain)
453+
shell: bash
454+
run: |
455+
python3 unit-tests/run-unit-tests.py --no-color --debug --stdout --not-live --context "linux"
456+
457+
- name: LibCI (pytest)
458+
shell: bash
459+
run: |
460+
python3 -m pip install -r unit-tests/requirements.txt
461+
python3 -m pytest unit-tests/ --color=no --debug -s --not-live --context "linux"
415462
416463
#--------------------------------------------------------------------------------
417464
U22_ST_Py_DDS_RSUSB_SEC: # Ubuntu 2020, Static, Python, DDS, RSUSB, additional security checks

.github/workflows/pre-release.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# This adds "pre-release" builds for GitHub Actions. These:
2+
# - build the package the same way the ROS build farm builds release
3+
# binarydebs (bloom-generated debian packaging + dpkg-buildpackage,
4+
# including the distro's default hardening flags)
5+
# - catch farm-only failures before a release ships (e.g. the 2.58.2
6+
# binarydeb failure on Ubuntu resolute: the distro hardening flag
7+
# -Werror=implicit-function-declaration turned a qsort_r declaration
8+
# issue into a hard error that the plain colcon CI builds never saw)
9+
#
10+
# These builds run on GitHub machines, but in the same environment and using
11+
# the same flow as actual ROS distro build farm releases, hence "pre-release".
12+
#
13+
# NOTE: This workflow is informational only — do not add to required branch
14+
# protection checks. It may fail due to ROS package server sync issues or
15+
# build farm infrastructure changes. The main CI workflows are the
16+
# authoritative build checks.
17+
#
18+
# This config uses industrial_ci (https://github.com/ros-industrial/industrial_ci.git).
19+
# For troubleshooting, see readme (https://github.com/ros-industrial/industrial_ci/blob/master/README.rst)
20+
21+
name: pre-release
22+
23+
on:
24+
push:
25+
branches:
26+
- development
27+
pull_request:
28+
branches:
29+
- development
30+
# Allows running this workflow manually from the Actions tab
31+
workflow_dispatch:
32+
33+
permissions:
34+
contents: read
35+
36+
jobs:
37+
build:
38+
name: Build pre-release tests for ROS2 ${{ matrix.ros_distro }} and ${{ matrix.os }}
39+
runs-on: ${{ matrix.os }}
40+
timeout-minutes: 120
41+
strategy:
42+
fail-fast: false
43+
matrix:
44+
ros_distro: [rolling, lyrical, kilted, jazzy, humble]
45+
include:
46+
- ros_distro: 'rolling'
47+
os: ubuntu-latest
48+
- ros_distro: 'lyrical'
49+
os: ubuntu-26.04
50+
- ros_distro: 'kilted'
51+
os: ubuntu-24.04
52+
- ros_distro: 'jazzy'
53+
os: ubuntu-24.04
54+
- ros_distro: 'humble'
55+
os: ubuntu-22.04
56+
57+
env:
58+
ROS_DISTRO: ${{ matrix.ros_distro }}
59+
PRERELEASE: true
60+
BASEDIR: ${{ github.workspace }}/.work
61+
# industrial_ci defaults the prerelease host container to ros:noetic-ros-core
62+
# (focal, EOL). Must stay a ros:* image — setting DOCKER_IMAGE disables
63+
# industrial_ci's ROS apt setup, so colcon must be installable already.
64+
DOCKER_IMAGE: ros:jazzy-ros-core
65+
66+
steps:
67+
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4
68+
with:
69+
persist-credentials: false
70+
- name: industrial_ci
71+
# Pinned to master as of 2026-04-30 — first version that knows the
72+
# lyrical distro and rolling's retarget to resolute.
73+
uses: ros-industrial/industrial_ci@125164b9f1883cdf1858897a7146d1bebf2be5c6

0 commit comments

Comments
 (0)