Skip to content

[RNE Rewrite] test(cpp): add host GoogleTest suites for the native sources - #1347

Open
msluszniak wants to merge 6 commits into
rne-rewritefrom
@ms/native-tests
Open

[RNE Rewrite] test(cpp): add host GoogleTest suites for the native sources#1347
msluszniak wants to merge 6 commits into
rne-rewritefrom
@ms/native-tests

Conversation

@msluszniak

@msluszniak msluszniak commented Aug 4, 2026

Copy link
Copy Markdown
Member

Description

Adds host-side GoogleTest suites for the sources under cpp/, plus a native-tests CI job.

Every entry point in cpp/ is JSI-facing so rather than stub that boundary, the tests link a real Hermes runtime and a minimal ExecuTorch host build, install the production module, and drive it from JavaScript. That covers argument parsing, HostObject plumbing, TypedArray handling and the exact JSError messages.

All tests passes covering all modules, except model execution, see notes below.

Introduces a breaking change?

  • Yes
  • No

Type of change

  • Bug fix (change which fixes an issue)
  • New feature (change which adds functionality)
  • Documentation update (improves or adds clarity to existing documentation)
  • Other (chores, tests, code style improvements etc.)

Tested on

  • iOS
  • Android

Testing instructions

cd packages/react-native-executorch

# Headers (shared with clang-tidy/clangd)
RNET_HEADERS_ONLY=1 \
  RNET_BASE_URL=https://github.com/software-mansion/react-native-executorch/releases/download/v0.10.0-libs \
  node scripts/download-libs.js

# Hermes + ExecuTorch host builds (~2 min, cached in CI afterwards)
scripts/build-native-test-deps.sh

# Build and run (also fetches the .pte fixture)
scripts/run-native-tests.sh
scripts/run-native-tests.sh -R MathOpsTest   # extra args go to ctest

Pass RNE_TESTS_ENABLE_OPENCV=OFF to skip the cv suite, RNE_SKIP_FIXTURES=1 to work offline.

To confirm the tests work, mutate a source and re-run test suite. It should fail.

Screenshots

n/a

Related issues

Relates to #1291 — both CI jobs still need the RNET_BASE_URL override while the package version is 0.0.0.

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings

Additional notes

  • lint:cpp now skips cpp/tests, whose Hermes/GoogleTest headers aren't among that script's prerequisites. Test files can still be passed to it explicitly.
  • Model execution is not coveredexecute() needs the delegate the program was exported against, i.e. a host XNNPACK build. Argument validation ahead of it is. That plus tokenizer.cpp (compiled and linked, but no suite yet — needs fixture files) are the remaining gaps, documented in cpp/tests/README.md.

The cpp/ sources are entirely JSI-facing, so the tests link a real Hermes
runtime and a minimal ExecuTorch host build, install the production module
into it, and drive it from JavaScript the way the TS layer does. 103 tests
across dtype, conversions, tensor, schema, math, speech and cv, running in
~2s with no simulator or device.

Adds scripts/build-native-test-deps.sh (pinned Hermes + ExecuTorch host
builds, ~2 min, cached in CI) and scripts/run-native-tests.sh, plus a
native-tests CI job. clang-tidy now skips cpp/tests, whose headers are not
part of that script's prerequisites.
The v0.0.0-rewrite-libs-test prerelease was a throwaway. v0.10.0-libs carries
the same ExecuTorch 1.3.1 C++ headers (byte-identical; it only drops the
cpuinfo/pthreadpool and Obj-C headers the host tests never include).
Keeps it on the same headers source as the native-tests job instead of the
throwaway v0.0.0-rewrite-libs-test prerelease. The C++ headers are identical,
and the full cpp/ set clang-tidy sweeps compiles against them.
MethodMeta only exists once a program is loaded, which previously left
schema::methodSpecFromMetadata/validateSpec/getUsedBackends and all of
ModelHostObject's constructor untested.

They turn out not to need the XNNPACK delegate: Module::load() and
Module::method_meta() both parse the program without initialising backends
(only load_method() resolves them). So the whole load path runs on the host
against selfie-segmentation, the smallest model the org publishes at ~486 KB,
pinned to an exact HF revision and checksum-verified.

Adds 18 tests (121 total). The fixture is downloaded rather than committed;
when absent the suites are dropped with a CMake warning instead of failing.
Execution still needs a host XNNPACK build and stays out of scope.
@msluszniak msluszniak self-assigned this Aug 4, 2026
@msluszniak msluszniak added the test Issue and PR related to tests or testing infrastructure label Aug 4, 2026
@msluszniak msluszniak linked an issue Aug 4, 2026 that may be closed by this pull request
`libopencv-dev` is a meta-package that hard-depends on the viz and contrib
modules, pulling VTK, OpenMPI, tesseract and ~220 packages. On a throttled
Azure mirror that ran past 50 minutes (libvtk9 alone: 20 MB in ~10 min).
--no-install-recommends would not have helped, since those are hard Depends.

Install libopencv-{core,imgproc}-dev instead. OpenCVConfig.cmake ships only in
the meta-package, so cpp/tests now prefers OpenCV's CMake package when present
and otherwise locates core/imgproc directly; both paths verified to build and
pass all 121 tests.

Also caps the job at 30 minutes so a stalled download fails with logs rather
than running to the 6 h default.
Both were masked on macOS.

re2/abseil were linked before libtokenizers.a, their consumer. GNU ld resolves
archives left to right and only pulls members satisfying an already-undefined
symbol, so nothing was pulled and the re2 symbols came out undefined; Apple's
linker searches regardless of order. They are now interface dependencies of
et_tokenizers, so CMake emits them after it, wrapped in --start-group on GNU ld
to cover the cycles between abseil archives.

OpenCV was compiled against the vendored third-party/include/opencv2 headers
(4.13) while linking the system library (4.6 on Ubuntu) — cvtColor resolved to
the AlgorithmHint overload added in 4.10 and failed at link. Homebrew's 4.12 was
new enough to hide it. Vendored headers are now -isystem (matching
compile_flags.txt, and silencing ExecuTorch's deprecation warnings) while the
installed OpenCV goes on -I, which is always searched first, so headers and
library now come from the same install.

Also splits the dependency cache into restore/save so a failing test no longer
discards the ~9 min build.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test Issue and PR related to tests or testing infrastructure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[RNE Rewrite] Add native tests

1 participant