Skip to content
Open
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
10 changes: 4 additions & 6 deletions .github/workflows/build-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,7 @@ jobs:
--gcov-exclude "${BUILD_DIR}/CMakeFiles/.*/CompilerId.*/.*"
--exclude-directories "${BUILD_DIR}/CMakeFiles"
--filter "src/"
--exclude "src/.*/.*_tests/.*"
--exclude "src/.*/tests/.*"
--exclude "src/.*/python_tests/.*"
--exclude "tests/.*"
)

gcovr "${gcovr_args[@]}" --txt --output coverage/summary.txt --print-summary | tee coverage/totals.txt
Expand Down Expand Up @@ -229,10 +227,10 @@ jobs:
mkdir -p viz-tests-pkg
# Glob all viz_*_tests executables (covers viz_core_tests today, and
# viz_layers_tests / viz_session_tests / viz_xr_tests as they ship).
find "${BUILD_DIR}/src/viz" -name 'viz_*_tests' -type f -executable \
find "${BUILD_DIR}/tests/cpp/viz" -name 'viz_*_tests' -type f -executable \
-exec cp -v {} viz-tests-pkg/ \;
if ! ls viz-tests-pkg/viz_*_tests >/dev/null 2>&1; then
echo "No viz test binaries found under ${BUILD_DIR}/src/viz/"
echo "No viz test binaries found under ${BUILD_DIR}/tests/cpp/viz/"
exit 1
fi
tar -cvzf viz-tests.tar.gz -C viz-tests-pkg .
Expand Down Expand Up @@ -499,7 +497,7 @@ jobs:
--with pytest \
--with numpy \
--with cupy-cuda12x \
pytest -v --tb=short src/viz/python_tests/
pytest -v --tb=short tests/python/viz/
}
if ! run_pytest; then
echo "::warning::viz_python GPU tests failed on first attempt; retrying after 5s"
Expand Down
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ if(BUILD_EXAMPLES)
add_subdirectory(examples/deviceio_live_view)
add_subdirectory(examples/haptic_feedback)
if(BUILD_VIZ)
add_subdirectory(examples/camera_viz/tests)
add_subdirectory(examples/mujoco_xr)
endif()
elseif(BUILD_EXAMPLE_TELEOP_ROS2)
Expand Down Expand Up @@ -200,6 +199,11 @@ if(BUILD_PLUGINS)
endif()
endif()

# Tests (pytest + Catch2/CTest). After production libs so link targets exist.
if(BUILD_TESTING)
add_subdirectory(tests)
endif()

# Formatting enforcement (runs on Linux by default)
include(cmake/ClangFormat.cmake)

Expand Down
6 changes: 4 additions & 2 deletions cmake/cmake-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ CMakeLists.txt ← top level: adds deps/ and src/ subdirectories
x.cpp ← private implementation
x.h ← private header
z.cpp ← (see include-ordering example above)
mod1_tests/ ... ← test executable; links mod1::mod1 + deps (e.g. gtest)
mod2/ ... ← another module (one CMake target per dir)
mod1/ ... ← another module (one CMake target per dir)
tests/ ← pytest + Catch2/CTest (see tests/AGENTS.md)
cpp/ ... ← Catch2 executables; links src/ libs + deps
python/ ... ← pytest suites; one pyproject.toml per leaf
```

## This repo's concrete conventions
Expand Down
2 changes: 1 addition & 1 deletion docs/source/device/haptic_feedback.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,5 @@ See also
--------

- Example + tests: ``examples/haptic_feedback/python/`` and
``src/core/retargeting_engine_tests/python/test_haptic_devices.py`` /
``tests/python/core/retargeting_engine/test_haptic_devices.py`` /
``test_haptic_sink.py``.
24 changes: 12 additions & 12 deletions docs/source/device/trackers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ Tracks the HMD head pose via the OpenXR view space.
- Record channels: ``head`` | MCAP schema: ``core.HeadPoseRecord``
- Tests:

- :code-file:`src/core/schema_tests/cpp/test_head.cpp`
- :code-file:`src/core/schema_tests/python/test_head.py`
- :code-file:`tests/cpp/core/schema/test_head.cpp`
- :code-file:`tests/python/core/schema/test_head.py`

- Examples:

Expand All @@ -153,8 +153,8 @@ Tracks articulated hand joints (26 joints per hand, following the OpenXR
- Record channels: ``left_hand``, ``right_hand`` | MCAP schema: ``core.HandPoseRecord``
- Tests:

- :code-file:`src/core/schema_tests/cpp/test_hand.cpp`
- :code-file:`src/core/schema_tests/python/test_hand.py`
- :code-file:`tests/cpp/core/schema/test_hand.cpp`
- :code-file:`tests/python/core/schema/test_hand.py`
- :code-file:`examples/oxr/python/test_synthetic_hands.py`

- Examples:
Expand All @@ -175,8 +175,8 @@ axis inputs. Uses standard OpenXR action bindings.
- Record channels: ``left_controller``, ``right_controller`` | MCAP schema: ``core.ControllerSnapshotRecord``
- Tests:

- :code-file:`src/core/schema_tests/cpp/test_controller.cpp`
- :code-file:`src/core/schema_tests/python/test_controller.py`
- :code-file:`tests/cpp/core/schema/test_controller.cpp`
- :code-file:`tests/python/core/schema/test_controller.py`
- :code-file:`examples/oxr/python/test_controller_tracker.py`

- Examples:
Expand All @@ -201,8 +201,8 @@ reads the PICO ``XR_BD_body_tracking`` extension directly.
- Record channels: ``full_body`` | MCAP schema: ``core.FullBodyPoseRecord``
- Tests:

- :code-file:`src/core/schema_tests/cpp/test_full_body.cpp`
- :code-file:`src/core/schema_tests/python/test_full_body.py`
- :code-file:`tests/cpp/core/schema/test_full_body.cpp`
- :code-file:`tests/python/core/schema/test_full_body.py`
- :code-file:`examples/oxr/python/test_full_body_tracker.py`

- Examples:
Expand Down Expand Up @@ -234,8 +234,8 @@ utility internally.
- Record channels: ``oak``, ``oak_tracked`` | MCAP schema: ``core.FrameMetadataOakRecord``
- Tests:

- :code-file:`src/core/schema_tests/cpp/test_oak.cpp`
- :code-file:`src/core/schema_tests/python/test_camera.py`
- :code-file:`tests/cpp/core/schema/test_oak.cpp`
- :code-file:`tests/python/core/schema/test_camera.py`
- :code-file:`examples/oxr/python/test_oak_camera.py`

- Examples:
Expand All @@ -255,8 +255,8 @@ utility internally.
- Record channels: ``pedals`` | MCAP schema: ``core.Generic3AxisPedalOutputRecord``
- Tests:

- :code-file:`src/core/schema_tests/cpp/test_pedals.cpp`
- :code-file:`src/core/schema_tests/python/test_pedals.py`
- :code-file:`tests/cpp/core/schema/test_pedals.cpp`
- :code-file:`tests/python/core/schema/test_pedals.py`

- Examples:

Expand Down
31 changes: 18 additions & 13 deletions examples/mujoco_xr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,32 @@ endif()
# ImportError on the headset. MATCHALL because pyproject.toml carries the pin
# twice and those must agree -- and because it would match a version written in
# prose too, which is why those comments never restate the number.
set(_mujoco_pin_files "pyproject.toml" "tests/pyproject.toml")
set(_mujoco_pin_paths "${CMAKE_CURRENT_SOURCE_DIR}/pyproject.toml")
# The ctest pin lives in the repository's tests/ tree, which the standalone
# wheel configure cannot see -- and has no ctest to keep in sync either.
if(NOT _mujoco_xr_standalone)
list(APPEND _mujoco_pin_paths
"${CMAKE_SOURCE_DIR}/tests/python/examples/mujoco_xr/pyproject.toml")
endif()
set(_mujoco_pins "")
set(_mujoco_pin_labels "")
foreach(_pin_file IN LISTS _mujoco_pin_files)
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/${_pin_file}" _pin_file_text)
foreach(_pin_path IN LISTS _mujoco_pin_paths)
if(_pin_path STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}/pyproject.toml")
set(_pin_label "pyproject.toml")
else()
set(_pin_label "tests/python/examples/mujoco_xr/pyproject.toml")
endif()
file(READ "${_pin_path}" _pin_file_text)
string(REGEX MATCHALL "mujoco==[0-9][0-9a-zA-Z._-]*" _pin_matches "${_pin_file_text}")
if(NOT _pin_matches)
message(FATAL_ERROR "mujoco_xr: ${_pin_file} declares no `mujoco==<version>` pin; "
message(FATAL_ERROR "mujoco_xr: ${_pin_label} declares no `mujoco==<version>` pin; "
"this file reads that pin instead of hardcoding one.")
endif()
foreach(_pin_match IN LISTS _pin_matches)
# MATCHALL populates no CMAKE_MATCH_<n>, so strip the fixed prefix.
string(REPLACE "mujoco==" "" _pin_version "${_pin_match}")
list(APPEND _mujoco_pins "${_pin_version}")
list(APPEND _mujoco_pin_labels "${_pin_file}")
list(APPEND _mujoco_pin_labels "${_pin_label}")
endforeach()
endforeach()
list(GET _mujoco_pins 0 _mujoco_declared_pin)
Expand All @@ -97,7 +108,7 @@ list(LENGTH _mujoco_distinct_pins _mujoco_distinct_pin_count)
if(NOT _mujoco_distinct_pin_count EQUAL 1)
message(FATAL_ERROR "mujoco_xr: the mujoco pins disagree -- pyproject.toml (both "
"build-system.requires and project.dependencies) and "
"tests/pyproject.toml must all name the SAME mujoco version "
"tests/python/examples/mujoco_xr/pyproject.toml must all name the SAME mujoco version "
"(exactly one libmujoco may be loaded in the process). "
"Found: ${_mujoco_pins} in ${_mujoco_pin_labels}")
endif()
Expand Down Expand Up @@ -151,7 +162,7 @@ foreach(_pin_file _pin IN ZIP_LISTS _mujoco_pin_labels _mujoco_pins)
"${_mujoco_version}. The C++ module and the Python app must load ONE libmujoco. Either "
"install the declared pin (uv pip install --python ${Python3_EXECUTABLE} "
"\"mujoco==${_pin}\") or update EVERY pin -- pyproject.toml carries it twice "
"(build-system.requires and project.dependencies) and tests/pyproject.toml once -- "
"(build-system.requires and project.dependencies) and tests/python/examples/mujoco_xr/pyproject.toml once -- "
"to ${_mujoco_version}.")
endif()
endforeach()
Expand Down Expand Up @@ -180,11 +191,5 @@ set(_mujoco_xr_root "${CMAKE_CURRENT_SOURCE_DIR}")

add_subdirectory(cpp)

# BUILD_TESTING is undefined standalone, so ctest entries are in-tree only --
# which is right: they need the in-place extension and the repo's isaacteleop.
if(BUILD_TESTING)
add_subdirectory(tests)
endif()

# No install() rules here, deliberately: the wheel is the only run path, and
# standalone it is cpp/CMakeLists.txt's install(TARGETS) that fills it.
2 changes: 1 addition & 1 deletion examples/teleop_ros2/python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ dev = [

[tool.pytest.ini_options]
pythonpath = ["."]
testpaths = ["tests"]
testpaths = ["../../../tests/python/examples/teleop_ros2"]
34 changes: 0 additions & 34 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,37 +43,3 @@ add_subdirectory(cloudxr)
if(BUILD_PYTHON_BINDINGS)
add_subdirectory(python)
endif()

# ==============================================================================
# Tests
# ==============================================================================

if(BUILD_TESTING)
# Schema tests (C++ and Python)
add_subdirectory(schema_tests)

# Retargeting engine tests (Python)
add_subdirectory(retargeting_engine_tests)

# Teleop session manager tests (Python)
add_subdirectory(teleop_session_manager_tests)

# CloudXR tests (Python — requires the built wheel from python/)
if(BUILD_PYTHON_BINDINGS)
add_subdirectory(cloudxr_tests)
endif()

# Rig launcher tests (Python)
if(BUILD_PYTHON_BINDINGS)
add_subdirectory(rig_tests)
endif()

# MCAP tests (C++)
add_subdirectory(mcap_tests/cpp)

# Replay DeviceIO session tests (C++)
add_subdirectory(replay_deviceio_session_tests/cpp)

# Live trackers tests (C++)
add_subdirectory(live_trackers_tests/cpp)
endif()
9 changes: 0 additions & 9 deletions src/core/cloudxr_tests/CMakeLists.txt

This file was deleted.

9 changes: 0 additions & 9 deletions src/core/retargeting_engine_tests/CMakeLists.txt

This file was deleted.

4 changes: 0 additions & 4 deletions src/core/retargeting_engine_tests/python/__init__.py

This file was deleted.

14 changes: 0 additions & 14 deletions src/core/schema_tests/CMakeLists.txt

This file was deleted.

4 changes: 0 additions & 4 deletions src/core/schema_tests/python/__init__.py

This file was deleted.

9 changes: 0 additions & 9 deletions src/core/teleop_session_manager_tests/CMakeLists.txt

This file was deleted.

13 changes: 0 additions & 13 deletions src/plugins/oglo_tactile/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,3 @@ set_target_properties(oglo_tactile_plugin PROPERTIES INSTALL_RPATH "$ORIGIN")

install(TARGETS oglo_tactile_plugin RUNTIME DESTINATION plugins/oglo_tactile)
install(FILES plugin.yaml README.md DESTINATION plugins/oglo_tactile)

# ------------------------------------------------------------------------------
# Parser unit test (dependency-free; validates the packed12 v5 wire decode
# against the firmware's packing reference).
# ------------------------------------------------------------------------------
if(BUILD_TESTING)
add_executable(test_oglo_packet_parser
tests/test_oglo_packet_parser.cpp
oglo_packet_parser.cpp
)
target_include_directories(test_oglo_packet_parser PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
add_test(NAME oglo_packet_parser COMMAND test_oglo_packet_parser)
endif()
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def _mat_to_quat_xyzw(matrix: np.ndarray) -> np.ndarray:

Branch-on-trace conversions are not eyeball-verifiable, so this is pinned numerically against
an independent reference over random SO(3) in
``retargeting_engine_tests/python/test_so101_retargeters.py``.
``tests/python/core/retargeting_engine/test_so101_retargeters.py``.
"""
m00, m01, m02 = matrix[0, 0], matrix[0, 1], matrix[0, 2]
m10, m11, m12 = matrix[1, 0], matrix[1, 1], matrix[1, 2]
Expand Down
21 changes: 10 additions & 11 deletions src/viz/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ mandatory **`AGENTS.md` preflight** in [`../../AGENTS.md`](../../AGENTS.md)
## Package shape

`src/viz/` mirrors **`src/core/`**: a peer container of sub-modules, not a
single sub-module. Each sub-module is its own static library with its own
sibling `<sub-module>_tests/` directory:
single sub-module. Each sub-module is its own static library. Tests live under
[`../../../tests/`](../../../tests/) — see [`tests/AGENTS.md`](../../../tests/AGENTS.md).

- **`viz/core/`** — foundational types + Vulkan/CUDA infrastructure.
Library: `viz_core`. Today: `VkContext`, `VizBuffer`, `Pose3D`,
Expand Down Expand Up @@ -51,7 +51,7 @@ sibling `<sub-module>_tests/` directory:
questions are captured under "Future: zero-copy acquire/release"
in `DESIGN.md`.
Test-only fixture layers (`ClearRectLayer`, `ThrowingLayer`) live in
`viz/layers_tests/cpp/inc/viz/layers/testing/` and are exposed via
`tests/cpp/viz/support/layers_testing/inc/viz/layers/testing/` and are exposed via
the `viz::layers_testing` static library — used by `viz_session_tests`
to compose into a `VizSession`.
- **`viz/session/`** — `VizSession`, `VizCompositor`, `FrameInfo`,
Expand All @@ -73,9 +73,9 @@ sibling `<sub-module>_tests/` directory:
`viz/shaders/cpp/` and calling `compile_shader(<name>.vert kVarName)`
in the local CMakeLists.

Test directories follow the same per-module pattern:
`viz/core_tests/`, `viz/layers_tests/`, `viz/session_tests/`,
`viz/shaders_tests/`, `viz/xr_tests/`.
Catch2 and pytest suites for viz live under `tests/cpp/viz/<sub-module>/`
and `tests/python/viz/` respectively (one Catch2 executable per sub-module:
`viz_core_tests`, `viz_layers_tests`, …).

`src/viz/CMakeLists.txt` is an **orchestrator only** — it adds the
sub-module sub-directories. Sub-module `CMakeLists.txt` files build the
Expand Down Expand Up @@ -162,17 +162,16 @@ Beyond happy-path coverage, every new feature MUST add tests for:
### Test fixtures

Test-only `LayerBase` subclasses and helpers live in
`viz/layers_tests/cpp/inc/viz/layers/testing/` and ship via the
`tests/cpp/viz/support/layers_testing/inc/viz/layers/testing/` and ship via the
`viz::layers_testing` static library. Other test executables link
that library to compose fixtures. Today:
- `ClearRectLayer` — paints a rect via `vkCmdClearAttachments` (no
shaders); used to verify compositor dispatch produces real pixels.
- `ThrowingLayer` — throws from `record()` on a configurable schedule;
used for exception-recovery tests.
- Test files live alongside the code they test, in
`<sub-module>_tests/cpp/`. One executable per sub-module
(`viz_core_tests`, `viz_layers_tests`, ...). Do **not** dump tests
into a top-level `viz_tests/` directory.
- Catch2 sources live under `tests/cpp/viz/<sub-module>/`. One executable
per sub-module (`viz_core_tests`, `viz_layers_tests`, …). Do **not**
collapse viz tests into a single mega-target.

## CI coverage

Expand Down
Loading
Loading