Skip to content
Merged
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
83 changes: 83 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,86 @@ jobs:

- name: Build all packages
run: yarn workspaces foreach --all --exclude react-native-executorch-webrtc --topological-dev run prepare

native-tests:
name: C++ unit tests
runs-on: ubuntu-latest
# Well clear of a cold run (the Hermes + ExecuTorch dependency build is the
# bulk of it) but far below the 6 h default, so a stalled download fails
# with logs instead of hanging.
timeout-minutes: 45
defaults:
run:
working-directory: packages/react-native-executorch
steps:
- name: Checkout
uses: actions/checkout@v6

# googletest for the harness, phonemis because cpp/extensions/speech
# compiles it. GIT_LFS_SKIP_SMUDGE keeps phonemis' `data/` as pointer
# files: it is Git LFS, several tens of MB, and nothing in the host suite
# reads it (see cpp/tests/extensions/PhonemizerTest.cpp).
- name: Check out the submodules the tests build
run: |
git submodule update --init --depth 1 third-party/googletest
GIT_LFS_SKIP_SMUDGE=1 git submodule update --init --depth 1 \
packages/react-native-executorch/third-party/common/phonemis
working-directory: ${{ github.workspace }}

# download-libs.js is dependency-free, so this job needs node but not a
# yarn install.
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: .nvmrc

# Only the two OpenCV modules the cv extension uses. The `libopencv-dev`
# meta-package hard-depends on the viz and contrib modules, which pull VTK,
# OpenMPI and ~220 packages — over 50 minutes on a throttled mirror.
# OpenCVConfig.cmake ships only in that meta-package, so cpp/tests
# falls back to locating the libraries directly.
- name: Install build tooling
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
ninja-build libopencv-core-dev libopencv-imgproc-dev
working-directory: ${{ github.workspace }}
env:
DEBIAN_FRONTEND: noninteractive

- name: Provision third-party headers
run: RNET_HEADERS_ONLY=1 node scripts/download-libs.js

# Hermes and ExecuTorch are pinned to exact tags, so the cache only misses
# when scripts/build-native-test-deps.sh changes those pins.
#
# Split restore/save rather than actions/cache: the combined action only
# saves in a post step when the job succeeds, so a failing test would throw
# away the ~9 min dependency build and rebuild it on every retry.
- name: Restore native test dependencies
id: deps-cache
uses: actions/cache/restore@v5
with:
path: packages/react-native-executorch/.native-test-deps
key: ${{ runner.os }}-native-test-deps-${{ hashFiles('packages/react-native-executorch/scripts/build-native-test-deps.sh') }}

- name: Build native test dependencies
if: steps.deps-cache.outputs.cache-hit != 'true'
run: scripts/build-native-test-deps.sh

- name: Save native test dependencies
if: steps.deps-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
path: packages/react-native-executorch/.native-test-deps
key: ${{ steps.deps-cache.outputs.cache-primary-key }}

# ~3 MB in total (a .pte program and a tokenizer.json), each pinned to an
# exact HF revision and checksum-verified. Fetched as its own step so a
# Hugging Face outage is an obvious failure rather than a confusing one
# inside the test run.
- name: Fetch test fixtures
run: scripts/fetch-test-fixtures.sh

- name: Run C++ unit tests
run: scripts/run-native-tests.sh
10 changes: 10 additions & 0 deletions packages/react-native-executorch/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,13 @@ rne-build-config.json

# Generated by scripts/package-release-artifacts.sh
dist-artifacts/

# Hermes + ExecuTorch host builds for the C++ tests, produced by
# scripts/build-native-test-deps.sh
.native-test-deps

# C++ test build output (scripts/run-native-tests.sh)
cpp/tests/build/

# Model and tokenizer fixtures downloaded by scripts/fetch-test-fixtures.sh
cpp/tests/fixtures/
6 changes: 6 additions & 0 deletions packages/react-native-executorch/compile_flags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@
-isystemthird-party/include/executorch/extension/llm/tokenizers/third-party/json/include
-isystemthird-party/include/executorch/extension/llm/tokenizers/third-party/re2
-isystemthird-party/include/executorch/extension/llm/tokenizers/third-party/abseil-cpp
-Icpp/tests
-isystem../../third-party/googletest/googletest/include
-isystem../../third-party/googletest/googlemock/include
-isystem.native-test-deps/hermes/src/API
-isystem.native-test-deps/hermes/src/API/jsi
-isystem.native-test-deps/hermes/src/public
15 changes: 10 additions & 5 deletions packages/react-native-executorch/cpp/extensions/cv/ocr_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,20 @@ void install_extractDbnetTextQuads(jsi::Runtime &rt, jsi::Object &module) {
const int32_t h = src->shape_[2];
const int32_t w = src->shape_[3];

// Read the options outside the try below: a missing or mistyped one is an
// InvalidArgument from the caller, and rewrapping it as an OpenCV
// failure would both mislabel it and lose the code.
const char *ctx = "extractDbnetTextQuads";
const auto binThreshold = conversions::getRequiredProperty<float>(rt, ctx, opts, "binThreshold");
const auto boxThreshold = conversions::getRequiredProperty<float>(rt, ctx, opts, "boxThreshold");
const auto unclipRatio = conversions::getRequiredProperty<float>(rt, ctx, opts, "unclipRatio");
const auto minBoxSide = conversions::getRequiredProperty<int32_t>(rt, ctx, opts, "minBoxSide");
const auto maxCandidates = conversions::getRequiredProperty<int32_t>(rt, ctx, opts, "maxCandidates");

std::vector<Quad> quads;
try {
::cv::Mat prob(h, w, CV_32F, dataPtr);
quads = extractDbnet(prob, conversions::getRequiredProperty<float>(rt, ctx, opts, "binThreshold"),
conversions::getRequiredProperty<float>(rt, ctx, opts, "boxThreshold"),
conversions::getRequiredProperty<float>(rt, ctx, opts, "unclipRatio"),
conversions::getRequiredProperty<int32_t>(rt, ctx, opts, "minBoxSide"),
conversions::getRequiredProperty<int32_t>(rt, ctx, opts, "maxCandidates"));
quads = extractDbnet(prob, binThreshold, boxThreshold, unclipRatio, minBoxSide, maxCandidates);
} catch (const std::exception &e) {
throw error::ExecutionFailed(std::format("extractDbnetTextQuads: OpenCV error: {}", e.what()));
}
Expand Down
Loading