From 051c40b2a14b675c50103b5079d98442c5ad5521 Mon Sep 17 00:00:00 2001 From: Kacper Orszulak <42392219+SomePersonFromMars@users.noreply.github.com> Date: Thu, 6 Aug 2026 15:30:07 +0200 Subject: [PATCH] refactor: split C++ gtests into smoke/extended runners by category Replace the graph-only test scripts with a unified RunTests.sh (smoke|extended|full), category filters, and reusable CI/validate entry points so slow suites stay off the default PR path. --- .../build-compilation-dependencies/SKILL.md | 32 ++- .../maintenance.md | 3 +- .claude/skills/post-work-checks/SKILL.md | 34 +-- .../skills/post-work-checks/maintenance.md | 2 +- .github/workflows/cpp-extended-job.yml | 78 ++++++ .github/workflows/graph-tests.yml | 15 -- .github/workflows/tests.yml | 26 +- package.json | 3 + .../common/cpp/test/RunCoverage.sh | 41 +++- .../common/cpp/test/RunTests.sh | 223 +++++++++++++++++- .../common/cpp/test/RunTestsGraph.sh | 45 ++-- .../common/cpp/test/RunTestsGraphDocker.sh | 48 +++- .../common/cpp/test/TESTING.md | 39 +++ .../common/cpp/test/filters.sh | 51 ++++ .../common/cpp/test/graph_tests_docs.md | 34 +-- packages/react-native-audio-api/package.json | 7 +- scripts/validate.sh | 128 ++++++---- 17 files changed, 633 insertions(+), 176 deletions(-) create mode 100644 .github/workflows/cpp-extended-job.yml delete mode 100644 .github/workflows/graph-tests.yml create mode 100644 packages/react-native-audio-api/common/cpp/test/TESTING.md create mode 100755 packages/react-native-audio-api/common/cpp/test/filters.sh diff --git a/.claude/skills/build-compilation-dependencies/SKILL.md b/.claude/skills/build-compilation-dependencies/SKILL.md index ae2b48122..f8cadc642 100644 --- a/.claude/skills/build-compilation-dependencies/SKILL.md +++ b/.claude/skills/build-compilation-dependencies/SKILL.md @@ -39,7 +39,7 @@ react-native-audio-api/ │ │ └── include_ffmpeg/ # Headers for FFmpeg │ ├── common/cpp/test/ │ │ ├── CMakeLists.txt # Standalone test build (no Android/iOS) -│ │ ├── RunTests.sh # Test runner script +│ │ ├── RunTests.sh / filters.sh # smoke|extended|full (+ categories) │ │ └── src/ # Google Test files │ ├── RNAudioAPI.podspec # CocoaPods spec for iOS │ └── scripts/ @@ -185,10 +185,12 @@ CI intentionally skips native Android/iOS builds (expensive). Use the tiered loc ```bash yarn validate:fast # CI parity (format, lint, typecheck, enum sync, build, C++ + JS tests) -yarn validate:graph # graph tests + ASan (optional; graph path changes) +yarn validate:cpp # C++ smoke +yarn validate:cpp-extended # C++ extended (all categories) +yarn validate:graph # legacy alias: extended category graph only yarn validate:android # yarn workspace … build:android yarn validate:ios # yarn workspace … build:ios (macOS only) -yarn validate:full # --fast + --android + --ios +yarn validate:full # --fast + C++ extended + --android + --ios ``` Script: [`scripts/validate.sh`](../../../scripts/validate.sh) at monorepo root. @@ -198,10 +200,10 @@ Script: [`scripts/validate.sh`](../../../scripts/validate.sh) at monorepo root. | Layer | CI (`ci.yml` + `tests.yml`) | Local tiers | |---|---|---| | TS build (`bob build`) | Yes | `--fast` | -| C++ test subset (`RunTests.sh`) | Yes | `--fast` | -| C++ coverage (`RunCoverage.sh`, Clang) | Yes (`cpp-coverage` artifact) | `yarn test:cpp:coverage` | +| C++ smoke (`RunTests.sh`) | Yes | `--fast` | +| C++ coverage (`RunCoverage.sh`, smoke, Clang) | Yes (`cpp-coverage` artifact) | `yarn test:cpp:coverage` | | Jest | Yes | `--fast` | -| Graph tests | No, path-filtered in `graph-tests.yml` | `--graph` | +| Extended C++ by category (e.g. graph) | Path change or manual dispatch in `tests.yml` | `--cpp-extended` / `--graph` | | HostObjects (26 JSI `.cpp` files) | **No** | `--android` + `--ios` | | Android JNI C++ + Kotlin | **No** | `--android` | | iOS ObjC++ | **No** | `--ios` | @@ -224,7 +226,7 @@ Android (NDK) and iOS (Clang) cannot share object files — reuse is at the preb - `--ios` on Linux → skip with message (exit 0) - `--android` without `ANDROID_HOME` → fail on explicit `--android`; skip with warning inside `--full` -- Graph tests are separate from `--full` (slow; CI path-filters them) +- `--full` includes C++ extended (all categories) after `--fast`’s smoke, so local full covers C++ full + native builds ### Which tier to run @@ -239,18 +241,12 @@ See the decision table in [post-work-checks](../post-work-checks/SKILL.md). ### How to run ```bash -yarn test # from monorepo root — runs RunTests.sh +yarn test # Jest + C++ smoke +yarn workspace react-native-audio-api test:cpp:smoke|extended|full +yarn workspace react-native-audio-api test:cpp:extended -- graph ``` -`RunTests.sh` does: -```bash -cd packages/react-native-audio-api/common/cpp/test -cmake -S . -B build -Wno-dev -cd build && make -j10 -./tests --gtest_print_time=1 -``` - -The `build/` directory is deleted after each run. +`RunTests.sh [smoke|extended|full] [category…] [--ubasan|--tsan|--no-ubasan]` uses filters from `filters.sh`. Docs: `common/cpp/test/TESTING.md`. `yarn test:graph` is a legacy alias for `extended graph`. ### Coverage (Clang / llvm-cov) @@ -259,7 +255,7 @@ yarn workspace react-native-audio-api test:cpp:coverage # open packages/react-native-audio-api/common/cpp/test/coverage-html/index.html ``` -`RunCoverage.sh` configures a separate `build-coverage/` tree with `-DENABLE_COVERAGE=ON` (Clang-only LLVM source-based coverage: `-fprofile-instr-generate -fcoverage-mapping`), defaults `CC`/`CXX` to `clang`/`clang++` when unset, runs the same gtest filter as `RunTests.sh`, then prints `llvm-cov report` and writes HTML via `llvm-cov show -format=html`. When `GITHUB_STEP_SUMMARY` is set, the report is also appended there. Sanitizer targets are skipped when coverage is enabled. Requires Apple Clang / `xcrun llvm-profdata` and `xcrun llvm-cov` on macOS (or the same tools on PATH for Linux). +`RunCoverage.sh` configures a separate `build-coverage/` tree with `-DENABLE_COVERAGE=ON` (Clang-only LLVM source-based coverage: `-fprofile-instr-generate -fcoverage-mapping`), defaults `CC`/`CXX` to `clang`/`clang++` when unset, runs the **smoke** filter from `filters.sh`, then prints `llvm-cov report` and writes HTML via `llvm-cov show -format=html`. When `GITHUB_STEP_SUMMARY` is set, the report is also appended there. Sanitizer targets are skipped when coverage is enabled. Requires Apple Clang / `xcrun llvm-profdata` and `xcrun llvm-cov` on macOS (or the same tools on PATH for Linux). CI runs a parallel `cpp-coverage` job via `.github/workflows/cpp-coverage-job.yml` (called from `tests.yml` on pull requests; Clang + LLVM apt packages, separate from the GCC `cpp-tests` job). It uploads the HTML tree as the `cpp-coverage-html` artifact (14-day retention); download the zip from the Actions run and open `index.html`. Manual `workflow_dispatch` on `tests.yml` accepts booleans `run_cpp_tests` / `run_cpp_coverage` / `run_js_tests` (default true); PRs always run all three. diff --git a/.claude/skills/build-compilation-dependencies/maintenance.md b/.claude/skills/build-compilation-dependencies/maintenance.md index a7e3bf44d..fd719d1aa 100644 --- a/.claude/skills/build-compilation-dependencies/maintenance.md +++ b/.claude/skills/build-compilation-dependencies/maintenance.md @@ -12,7 +12,8 @@ Review this skill when `pre-push-update` reports changes in: | `RNAudioAPI.podspec` | Subspecs table, `miniaudio_impl` workaround, `-force_load` list, xcframeworks list, `rnaa_utils.rb` dynamic paths | | `apps/fabric-example/ios/Podfile` | New Architecture enablement, minimum iOS version helper | | `common/cpp/test/CMakeLists.txt` | Excluded sources list, compile definitions, GoogleTest fetch URL, include paths, `ENABLE_COVERAGE` | -| `common/cpp/test/RunCoverage.sh` | Coverage build dir, Clang CC/CXX defaults, llvm-profdata/llvm-cov report+HTML, `GITHUB_STEP_SUMMARY`, ignore regexes | +| `common/cpp/test/RunCoverage.sh` | Coverage build dir, Clang CC/CXX defaults, llvm-profdata/llvm-cov report+HTML, `GITHUB_STEP_SUMMARY`, ignore regexes, smoke filter via `filters.sh` | +| `common/cpp/test/filters.sh` / `RunTests.sh` | Mode/category filters (smoke/extended/full) and sanitizer flags | | `.github/workflows/cpp-coverage-job.yml` | Reusable coverage job (Clang/LLVM install, artifact `cpp-coverage-html`) | | `.github/workflows/js-job.yml` | Reusable JS integration tests job (draft-PR skip) | | `.github/workflows/tests.yml` | Calls cpp/js/coverage jobs; `workflow_dispatch` booleans select jobs | diff --git a/.claude/skills/post-work-checks/SKILL.md b/.claude/skills/post-work-checks/SKILL.md index 951f994fc..55af5dbc8 100644 --- a/.claude/skills/post-work-checks/SKILL.md +++ b/.claude/skills/post-work-checks/SKILL.md @@ -19,14 +19,16 @@ Run these checks after any code change and before opening a PR. ## Quick Reference — Local Validation Tiers -CI always runs the **fast** tier (format, lint, typecheck, enum sync, TS build, C++ + JS tests). Graph tests run in a separate path-filtered workflow (`graph-tests.yml`). CI does **not** build Android Gradle, iOS pods, or example apps. Use `validate.sh` locally to close that gap: +CI always runs the **fast** tier (format, lint, typecheck, enum sync, TS build, C++ smoke + JS tests). Extended C++ categories (e.g. graph) run from `tests.yml` when matching paths change, or via `workflow_dispatch` booleans. CI does **not** build Android Gradle, iOS pods, or example apps. Use `validate.sh` locally to close that gap: ```bash -yarn validate:fast # CI parity — always run before opening a PR -yarn validate:graph # graph tests (when graph/audio-thread code changes) -yarn validate:android # Android native build (requires ANDROID_HOME) -yarn validate:ios # iOS native build (macOS only) -yarn validate:full # --fast + --android + --ios (skips unavailable platforms) +yarn validate:fast # CI parity — always run before opening a PR +yarn validate:cpp # C++ smoke +yarn validate:cpp-extended # C++ extended (all categories) +yarn validate:graph # legacy alias: extended category graph only +yarn validate:android # Android native build (requires ANDROID_HOME) +yarn validate:ios # iOS native build (macOS only) +yarn validate:full # --fast + C++ extended + --android + --ios ``` Equivalent: `./scripts/validate.sh --fast` (etc.) @@ -42,7 +44,7 @@ Equivalent: `./scripts/validate.sh --fast` (etc.) | `ios/audioapi/` | `--fast` + `--ios` | | `CMakeLists.txt`, `build.gradle`, `podspec` | `--full` | -Graph changes under `common/cpp/audioapi/core/utils/graph/` → also run `yarn validate:graph`. +Graph changes under `common/cpp/audioapi/core/utils/graph/` → also run `yarn validate:graph` or `yarn validate:cpp-extended` (extended category `graph`). --- @@ -73,7 +75,7 @@ Hooks run when lefthook is installed (`lefthook install`). **If a hook fails, the commit is aborted.** Fix the issue and re-commit — do NOT use `--no-verify`. -There is no pre-push hook — `yarn validate:fast` (and native/graph tiers) are run manually before opening a PR. Native builds (`validate:android`, `validate:ios`, `validate:full`) and graph tests (`validate:graph`) are never run by lefthook. +There is no pre-push hook — `yarn validate:fast` (and native/C++ extended tiers) are run manually before opening a PR. Native builds (`validate:android`, `validate:ios`, `validate:full`) and extended C++ (`validate:cpp-extended` / legacy `validate:graph`) are never run by lefthook. --- @@ -92,24 +94,28 @@ yarn validate:fast ```bash yarn validate:android # yarn workspace … build:android (~3–4 min) yarn validate:ios # yarn workspace … build:ios (macOS only) -yarn validate:full # --fast + --android + --ios +yarn validate:full # --fast + C++ extended + --android + --ios ``` The Gradle project resolves through the `node_modules/react-native-audio-api` workspace symlink, so local edits in `packages/react-native-audio-api/` are picked up. -### Graph tests (when graph / audio-thread code changes) +### Extended graph (when graph / audio-thread code changes) ```bash -yarn validate:graph +yarn validate:graph # legacy alias: extended category graph +yarn validate:cpp-extended # all extended categories +# or: yarn workspace react-native-audio-api test:cpp:extended -- graph ``` ### C++ tests only ```bash -yarn workspace react-native-audio-api run test:cpp +yarn validate:cpp # smoke via validate.sh +yarn workspace react-native-audio-api run test:cpp # smoke +yarn workspace react-native-audio-api run test:cpp:full # smoke + all extended ``` -**When**: after any change to `common/cpp/audioapi/core/`, `dsp/`, or `utils/` C++ files. Prefer this for a fast C++-only loop without running Jest; run `yarn validate:fast` before opening a PR. +**When**: after any change to `common/cpp/audioapi/core/`, `dsp/`, or `utils/` C++ files. Prefer smoke for a fast C++-only loop; see `common/cpp/test/TESTING.md`. Run `yarn validate:fast` before opening a PR. ### Library unit tests (JS + C++) @@ -162,7 +168,7 @@ Later steps may surface issues caused by earlier ones — run in this order: 2. `yarn lint` — catch remaining code issues 3. `yarn typecheck` — catch TypeScript errors 4. `yarn validate:fast` — full CI-parity gate (or `yarn test` / `test:cpp` for a quick local loop; always run `--fast` before opening a PR) -5. `yarn validate:graph` — when graph / audio-thread code changed +5. `yarn validate:cpp-extended` / `yarn validate:graph` — when graph / audio-thread code changed 6. `yarn validate:android` / `yarn validate:ios` / `yarn validate:full` — when native code or build files changed (see decision table above) --- diff --git a/.claude/skills/post-work-checks/maintenance.md b/.claude/skills/post-work-checks/maintenance.md index 1073cb524..bdcdcdb5b 100644 --- a/.claude/skills/post-work-checks/maintenance.md +++ b/.claude/skills/post-work-checks/maintenance.md @@ -11,4 +11,4 @@ Review this skill when `pre-push-update` reports changes in: | `lefthook.yml` | Pre-commit / commit-msg hook changes | | `scripts/validate.sh` | Tier behavior (`--fast` / `--graph` / `--android` / `--ios` / `--full`), skip rules | | `scripts/check-audio-enum-sync*` or `packages/react-native-audio-api/scripts/check-audio-events-sync.sh` | Enum sync check details | -| `.github/workflows/ci.yml`, `tests.yml`, `graph-tests.yml` | What CI covers vs local validation tiers | +| `.github/workflows/ci.yml`, `tests.yml`, `cpp-extended-job.yml` | What CI covers vs local validation tiers | diff --git a/.github/workflows/cpp-extended-job.yml b/.github/workflows/cpp-extended-job.yml new file mode 100644 index 000000000..a33a80c2a --- /dev/null +++ b/.github/workflows/cpp-extended-job.yml @@ -0,0 +1,78 @@ +name: C++ Extended Job + +# Reusable runner for one (or more) C++ extended categories. +# Path filtering and setup live here so tests.yml only declares a thin per-category entry. + +on: + workflow_call: + inputs: + name: + description: Job display name + required: true + type: string + categories: + description: Space-separated extended categories (e.g. graph) + required: true + type: string + force: + description: Skip path filter and always run (manual workflow_dispatch) + required: false + type: boolean + default: false + path_filters: + description: > + dorny/paths-filter YAML document with a single top-level key `run` + listing globs that should trigger this category on pull_request. + required: true + type: string + +jobs: + run: + name: ${{ inputs.name }} + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + defaults: + run: + working-directory: packages/react-native-audio-api/common/cpp/test + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Path filter + if: ${{ inputs.force == false }} + uses: dorny/paths-filter@v3 + id: filter + with: + filters: ${{ inputs.path_filters }} + + - name: Decide whether to run + id: decide + working-directory: . + run: | + if [[ "${{ inputs.force }}" == "true" ]]; then + echo "run=true" >> "$GITHUB_OUTPUT" + elif [[ "${{ steps.filter.outputs.run }}" == "true" ]]; then + echo "run=true" >> "$GITHUB_OUTPUT" + else + echo "run=false" >> "$GITHUB_OUTPUT" + echo "No matching path changes; skipping ${{ inputs.name }}." + fi + + - name: Checkout with Node + if: steps.decide.outputs.run == 'true' + uses: ./.github/actions/checkout-with-node + + - name: Setup Yarn + if: steps.decide.outputs.run == 'true' + uses: ./.github/actions/setup-yarn + + - name: Setup CMake + if: steps.decide.outputs.run == 'true' + uses: ./.github/actions/setup-cmake + + - name: ${{ inputs.name }} + if: steps.decide.outputs.run == 'true' + run: bash RunTests.sh extended ${{ inputs.categories }} diff --git a/.github/workflows/graph-tests.yml b/.github/workflows/graph-tests.yml deleted file mode 100644 index 011cb0f74..000000000 --- a/.github/workflows/graph-tests.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Graph Tests - -on: - pull_request: - paths: - - 'packages/react-native-audio-api/common/cpp/audioapi/core/utils/graph/**' - - 'packages/react-native-audio-api/common/cpp/test/src/graph/**' - -jobs: - graph-test: - uses: ./.github/workflows/cpp-job.yml - with: - name: Graph tests - working-directory: packages/react-native-audio-api/common/cpp/test - run: bash RunTestsGraph.sh diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 599ee43e9..1fa225118 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,24 +5,28 @@ on: workflow_dispatch: inputs: run_cpp_tests: - description: Run C++ tests (GCC) + description: Run C++ smoke tests (GCC) type: boolean default: true run_cpp_coverage: - description: Run C++ coverage (Clang / llvm-cov) + description: Run C++ coverage (Clang / llvm-cov, smoke) type: boolean default: true run_js_tests: description: Run JS integration tests type: boolean default: true + run_cpp_extended_graph: + description: Run C++ extended category graph + type: boolean + default: false jobs: cpp-tests: if: github.event_name == 'pull_request' || inputs.run_cpp_tests uses: ./.github/workflows/cpp-job.yml with: - name: C++ tests + name: C++ smoke working-directory: packages/react-native-audio-api run: yarn test:cpp @@ -33,3 +37,19 @@ jobs: js-tests: if: github.event_name == 'pull_request' || inputs.run_js_tests uses: ./.github/workflows/js-job.yml + + # One thin entry per extended category: paths + categories stay here; + # filter/setup/run logic lives in cpp-extended-job.yml. + cpp-extended-graph: + if: github.event_name == 'pull_request' || inputs.run_cpp_extended_graph + uses: ./.github/workflows/cpp-extended-job.yml + with: + name: C++ extended (graph) + categories: graph + force: ${{ github.event_name == 'workflow_dispatch' }} + path_filters: | + run: + - 'packages/react-native-audio-api/common/cpp/audioapi/core/utils/graph/**' + - 'packages/react-native-audio-api/common/cpp/test/src/graph/**' + - 'packages/react-native-audio-api/common/cpp/test/filters.sh' + - 'packages/react-native-audio-api/common/cpp/test/RunTests.sh' diff --git a/package.json b/package.json index 7c4aff502..3a5643453 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,9 @@ "test": "yarn workspace react-native-audio-api run test", "check-audio-enum-sync": "bash packages/react-native-audio-api/scripts/check-audio-events-sync.sh", "validate:fast": "bash scripts/validate.sh --fast", + "validate:cpp": "bash scripts/validate.sh --cpp", + "validate:cpp-extended": "bash scripts/validate.sh --cpp-extended", + "validate:cpp-full": "bash scripts/validate.sh --cpp-full", "validate:graph": "bash scripts/validate.sh --graph", "validate:android": "bash scripts/validate.sh --android", "validate:ios": "bash scripts/validate.sh --ios", diff --git a/packages/react-native-audio-api/common/cpp/test/RunCoverage.sh b/packages/react-native-audio-api/common/cpp/test/RunCoverage.sh index cd9da290c..beff85750 100755 --- a/packages/react-native-audio-api/common/cpp/test/RunCoverage.sh +++ b/packages/react-native-audio-api/common/cpp/test/RunCoverage.sh @@ -1,21 +1,47 @@ #!/bin/bash -# Build the gtest suite with Clang LLVM source-based coverage and emit an -# llvm-cov HTML report. Uses Xcode llvm-profdata/llvm-cov on macOS (no gcovr). -# -# From packages/react-native-audio-api: -# yarn test:cpp:coverage +print_help() { + cat <<'EOF' +Usage: RunCoverage.sh + +Build the C++ gtest suite with Clang LLVM source-based coverage and emit an +llvm-cov HTML report under coverage-html/. Always uses the smoke filter +(unsanitized). Override with GTEST_FILTER if needed. + + yarn test:cpp:coverage + +Options: + --help, -h Show this help. +EOF +} set -euo pipefail +if [[ $# -gt 0 ]]; then + case "$1" in + --help|-h) + print_help + exit 0 + ;; + *) + echo "error: unexpected argument '$1'" >&2 + print_help >&2 + exit 1 + ;; + esac +fi + SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$SCRIPT_DIR" +# shellcheck source=filters.sh +source "${SCRIPT_DIR}/filters.sh" + readonly BUILD_DIR="${SCRIPT_DIR}/build-coverage" readonly COVERAGE_HTML_DIR="${SCRIPT_DIR}/coverage-html" readonly PROFDATA_FILE="${BUILD_DIR}/coverage.profdata" -readonly GRAPH_FILTER="AudioGraphTest.*:AudioGraphFuzzTest.*:GraphTest.*:GraphFuzzTest.*:GraphCycleDebugTest.*:HostGraphTest.*:Seeds/*" readonly IGNORE_FILENAME_REGEX='(/common/cpp/test/|/_deps/|/googletest|/gmock|/audioapi/libs/|/r8brain/|/jsi/|/HostObjects/)' +readonly FILTER="${GTEST_FILTER:-$(cpp_test_smoke_filter)}" resolve_llvm_tool() { local tool_name="$1" @@ -57,7 +83,8 @@ rm -rf "$COVERAGE_HTML_DIR" ( cd "$BUILD_DIR" export LLVM_PROFILE_FILE="${BUILD_DIR}/default-%p.profraw" - ./tests --gtest_print_time=1 --gtest_filter="-${GRAPH_FILTER}" + echo "=== Coverage run (smoke filter=${FILTER}) ===" + ./tests --gtest_print_time=1 --gtest_filter="${FILTER}" ) shopt -s nullglob diff --git a/packages/react-native-audio-api/common/cpp/test/RunTests.sh b/packages/react-native-audio-api/common/cpp/test/RunTests.sh index b6e33a639..972347c95 100755 --- a/packages/react-native-audio-api/common/cpp/test/RunTests.sh +++ b/packages/react-native-audio-api/common/cpp/test/RunTests.sh @@ -1,13 +1,222 @@ #!/bin/bash -set -e +print_help() { + cat <<'EOF' +Usage: RunTests.sh [smoke|extended|full] [category…] [options] -cd common/cpp/test +Modes (default: smoke): + smoke Fast suites — PR default and coverage. Disjoint from extended. + extended Slow suites for the given categories (default: all registered). + full smoke, then extended for all categories (each mode’s defaults). -cmake -S . -B build -Wno-dev +Categories (extended only): + graph Slow graph suites (see filters.sh). GraphNodeGrowthTest is smoke. + +Sanitizer options (choose at most one; --ubasan and --tsan are incompatible): + --ubasan AddressSanitizer + UndefinedBehaviorSanitizer (tests_asan). + Default for extended. + --no-ubasan Plain tests binary (no sanitizers). Default for smoke. + --tsan ThreadSanitizer (tests_tsan). + Incompatible with --ubasan (ASan and TSan cannot run together). + +Other: + --help, -h Show this help. + --gtest_* Forwarded to the gtest binary. + GTEST_FILTER If set, overrides the mode/category gtest filter. + +Examples: + RunTests.sh + RunTests.sh smoke --ubasan + RunTests.sh extended graph + RunTests.sh extended graph --no-ubasan + RunTests.sh extended graph --tsan + RunTests.sh full + +See TESTING.md. +EOF +} + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$SCRIPT_DIR" + +# shellcheck source=filters.sh +source "${SCRIPT_DIR}/filters.sh" + +MODE="" +SANITIZER="" # empty = mode default; none|ubasan|tsan +CATEGORIES=() +PASSTHROUGH=() + +while [[ $# -gt 0 ]]; do + case "$1" in + --help|-h) + print_help + exit 0 + ;; + smoke|extended|full) + if [[ -n "$MODE" ]]; then + echo "error: mode already set to '${MODE}', got '$1'" >&2 + exit 1 + fi + MODE="$1" + shift + ;; + --ubasan) + if [[ "$SANITIZER" == "tsan" ]]; then + echo "error: --ubasan is incompatible with --tsan (AddressSanitizer and ThreadSanitizer cannot be combined)" >&2 + exit 1 + fi + SANITIZER=ubasan + shift + ;; + --tsan) + if [[ "$SANITIZER" == "ubasan" ]]; then + echo "error: --tsan is incompatible with --ubasan (AddressSanitizer and ThreadSanitizer cannot be combined)" >&2 + exit 1 + fi + SANITIZER=tsan + shift + ;; + --no-ubasan) + if [[ "$SANITIZER" == "ubasan" || "$SANITIZER" == "tsan" ]]; then + echo "error: --no-ubasan conflicts with a sanitizer flag already set (${SANITIZER})" >&2 + exit 1 + fi + SANITIZER=none + shift + ;; + # Yarn forwards a literal "--" before script args (`yarn cmd -- graph`). + --) + shift + ;; + --gtest_*) + PASSTHROUGH+=("$1") + shift + ;; + -*) + echo "error: unknown option '$1'" >&2 + print_help >&2 + exit 1 + ;; + *) + CATEGORIES+=("$1") + shift + ;; + esac +done + +MODE="${MODE:-smoke}" -cd build -make -j10 +if [[ "$MODE" != "extended" && "$MODE" != "full" && ${#CATEGORIES[@]} -gt 0 ]]; then + echo "error: categories are only valid with extended (or full); got mode=${MODE}" >&2 + exit 1 +fi + +if [[ "$MODE" == "full" && ${#CATEGORIES[@]} -gt 0 ]]; then + echo "error: full always runs all extended categories; omit category args" >&2 + exit 1 +fi + +resolve_sanitizer_for_mode() { + local mode="$1" + if [[ -n "$SANITIZER" ]]; then + printf '%s' "$SANITIZER" + return + fi + case "$mode" in + smoke) printf 'none' ;; + extended) printf 'ubasan' ;; + *) + echo "error: internal: no sanitizer default for mode '${mode}'" >&2 + return 1 + ;; + esac +} + +binary_for_sanitizer() { + case "$1" in + none) printf 'tests' ;; + ubasan) printf 'tests_asan' ;; + tsan) printf 'tests_tsan' ;; + *) + echo "error: unknown sanitizer '$1'" >&2 + return 1 + ;; + esac +} + +label_for_sanitizer() { + case "$1" in + none) printf 'tests (normal)' ;; + ubasan) printf 'tests with AddressSanitizer + UndefinedBehaviorSanitizer' ;; + tsan) printf 'tests with ThreadSanitizer' ;; + esac +} + +parallel_job_count() { + sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 10 +} + +filter_for_mode() { + local mode="$1" + shift + if [[ -n "${GTEST_FILTER:-}" ]]; then + printf '%s' "$GTEST_FILTER" + return + fi + case "$mode" in + smoke) + cpp_test_smoke_filter + ;; + extended) + cpp_test_extended_filter "$@" + ;; + *) + echo "error: internal: no filter for mode '${mode}'" >&2 + return 1 + ;; + esac +} + +run_mode() { + local mode="$1" + shift + local categories=("$@") + local sanitizer binary filter label + sanitizer="$(resolve_sanitizer_for_mode "$mode")" + binary="$(binary_for_sanitizer "$sanitizer")" + label="$(label_for_sanitizer "$sanitizer")" + filter="$(filter_for_mode "$mode" "${categories[@]+"${categories[@]}"}")" + + cmake --build build --target "$binary" -j "$(parallel_job_count)" + + echo "" + echo "=== ${label} (mode=${mode}, filter=${filter}) ===" + echo "" + "./build/${binary}" --gtest_print_time=1 --gtest_filter="${filter}" \ + ${PASSTHROUGH[@]+"${PASSTHROUGH[@]}"} +} + +cmake -S . -B build -Wno-dev -GRAPH_FILTER="AudioGraphTest.*:AudioGraphFuzzTest.*:GraphTest.*:GraphFuzzTest.*:GraphCycleDebugTest.*:HostGraphTest.*:Seeds/*" -./tests --gtest_print_time=1 --gtest_filter="-${GRAPH_FILTER}" \ No newline at end of file +case "$MODE" in + smoke) + run_mode smoke + ;; + extended) + run_mode extended "${CATEGORIES[@]+"${CATEGORIES[@]}"}" + ;; + full) + # Each sub-mode uses its own default sanitizer (ignore flags for the pair). + SANITIZER="" + run_mode smoke + SANITIZER="" + run_mode extended + ;; + *) + echo "error: unknown mode '${MODE}'" >&2 + exit 1 + ;; +esac diff --git a/packages/react-native-audio-api/common/cpp/test/RunTestsGraph.sh b/packages/react-native-audio-api/common/cpp/test/RunTestsGraph.sh index 658fc72c9..a1dd1ac2a 100755 --- a/packages/react-native-audio-api/common/cpp/test/RunTestsGraph.sh +++ b/packages/react-native-audio-api/common/cpp/test/RunTestsGraph.sh @@ -1,36 +1,29 @@ #!/bin/bash -set -e +print_help() { + cat <<'EOF' +Usage: RunTestsGraph.sh [options] -cleanup() { - echo "Cleaning up..." - rm -rf build/ -} - -trap cleanup EXIT +Legacy alias for: + RunTests.sh extended graph [options] +Prefer: yarn test:cpp:extended -- graph -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -cd "$SCRIPT_DIR" - -# Allow override of GRAPH_FILTER via environment variable -GRAPH_FILTER="${GRAPH_FILTER:-AudioGraphTest.*:AudioGraphFuzzTest.*:GraphTest.*:GraphFuzzTest.*:GraphCycleDebugTest.*:HostGraphTest.*:GraphNodeGrowthTest.*:Seeds/*}" - -cmake -S . -B build -Wno-dev +GRAPH_FILTER (legacy) is mapped to GTEST_FILTER when unset. +EOF +} -cd build -make tests_asan tests -j10 +set -euo pipefail -echo "" -echo "=== Running graph tests with AddressSanitizer + UndefinedBehaviorSanitizer ===" -echo "" -./tests_asan --gtest_print_time=1 --gtest_filter="${GRAPH_FILTER}" "$@" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -echo "" -echo "=== Running graph tests (normal) ===" -echo "" -./tests --gtest_print_time=1 --gtest_filter="${GRAPH_FILTER}" "$@" +if [[ $# -eq 1 && ( "$1" == "--help" || "$1" == "-h" ) ]]; then + print_help + exit 0 +fi -cd .. +if [[ -n "${GRAPH_FILTER:-}" && -z "${GTEST_FILTER:-}" ]]; then + export GTEST_FILTER="$GRAPH_FILTER" +fi -rm -rf build/ +exec bash "${SCRIPT_DIR}/RunTests.sh" extended graph "$@" diff --git a/packages/react-native-audio-api/common/cpp/test/RunTestsGraphDocker.sh b/packages/react-native-audio-api/common/cpp/test/RunTestsGraphDocker.sh index 3f341a7d3..fd3803e58 100755 --- a/packages/react-native-audio-api/common/cpp/test/RunTestsGraphDocker.sh +++ b/packages/react-native-audio-api/common/cpp/test/RunTestsGraphDocker.sh @@ -1,26 +1,48 @@ #!/bin/bash -# This script builds and runs the AddressSanitizer-enabled tests in a Linux Docker container from macOS. -# Usage: ./run_graph_tests_in_docker.sh -# Make sure to run from the root of your repo or adjust paths accordingly. +print_help() { + cat <<'EOF' +Usage: RunTestsGraphDocker.sh [RunTests.sh args…] -set -e +Thin Docker wrapper around RunTests.sh (Linux leak/ASan parity from macOS). +Forwards all arguments into the container. If none are given, runs: + extended graph -# Absolute path to the repo root on the host (macOS) -REPO_ROOT=$(cd "$(dirname "$0")/../../../../.." && pwd) +Examples: + RunTestsGraphDocker.sh + RunTestsGraphDocker.sh extended graph --tsan + RunTestsGraphDocker.sh --help # this help (container not started) + GTEST_FILTER='GraphTest.*' RunTestsGraphDocker.sh extended graph + +See RunTests.sh --help and TESTING.md. +EOF +} + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../../../../.." && pwd)" -# Name for the Docker image/container IMAGE_NAME=asan-graph-test CONTAINER_NAME=asan-graph-test-container -# Build the Docker image (Dockerfile must be in the test dir) -docker build -t $IMAGE_NAME "${REPO_ROOT}/packages/react-native-audio-api/common/cpp/test" +if [[ $# -eq 1 && ( "$1" == "--help" || "$1" == "-h" ) ]]; then + print_help + exit 0 +fi + +if [[ $# -eq 0 ]]; then + set -- extended graph +fi + +docker build -t "$IMAGE_NAME" "${SCRIPT_DIR}" -# Run the container, mounting the entire repo for source access docker run --rm -it \ - --name $CONTAINER_NAME \ + --name "$CONTAINER_NAME" \ -v "$REPO_ROOT:/workspace" \ -w /workspace/packages/react-native-audio-api/common/cpp/test \ -e ASAN_OPTIONS=detect_leaks=1:verbosity=2 \ - $IMAGE_NAME \ - bash RunTestsGraph.sh + ${GTEST_FILTER:+-e GTEST_FILTER="$GTEST_FILTER"} \ + ${GRAPH_FILTER:+-e GRAPH_FILTER="$GRAPH_FILTER"} \ + "$IMAGE_NAME" \ + bash RunTests.sh "$@" diff --git a/packages/react-native-audio-api/common/cpp/test/TESTING.md b/packages/react-native-audio-api/common/cpp/test/TESTING.md new file mode 100644 index 000000000..5bea1a685 --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/test/TESTING.md @@ -0,0 +1,39 @@ +# C++ tests + +`common/cpp/test/` — Google Test, modes by **runtime cost**. + +| Mode | What | Default binary | +| --- | --- | --- | +| **smoke** | Fast suites (PR + coverage). Disjoint from extended. | `tests` | +| **extended** | Slow suites by **category** | `tests_asan` (ASan+UBSan) | +| **full** | smoke, then all extended categories | each mode’s default | + +```bash +yarn test:cpp # smoke +yarn test:cpp:extended # all categories +yarn test:cpp:extended -- graph +yarn test:cpp:full +yarn test:cpp:coverage # smoke + llvm-cov HTML +yarn test:cpp:smoke --ubasan # Address + UndefinedBehavior sanitizers +yarn test:cpp:extended -- graph --tsan +yarn test:cpp:extended -- graph --no-ubasan +bash common/cpp/test/RunTests.sh --help +``` + +`--ubasan` = AddressSanitizer + UndefinedBehaviorSanitizer. Incompatible with `--tsan` (ASan and TSan cannot run together). + +Filters: [`filters.sh`](filters.sh). Override: `GTEST_FILTER=...`. + +### Categories + +| Category | Contents | CI | +| --- | --- | --- | +| `graph` | Slow graph (`AudioGraph*`, `Graph*`, `HostGraph*`, `Seeds/*`, …) | path filter + manual dispatch in `tests.yml` | + +**`GraphNodeGrowthTest` is smoke**, not `graph`: it is short (~100–200 ms) and needs unsanitized `AudioThreadGuard` (asserts `GTEST_SKIP` under ASan/TSan). + +**Add a category:** (1) filter in `filters.sh`, (2) append name to `CPP_TEST_EXTENDED_CATEGORIES`, (3) in `tests.yml` add a `workflow_dispatch` boolean and one `cpp-extended-*` job that calls `cpp-extended-job.yml` with `categories`, `force`, and that category’s `path_filters`. + +### Legacy aliases + +`yarn test:graph` → `extended graph`. Docker: `yarn test:graph:docker` forwards args to `RunTests.sh` (default `extended graph`). `yarn validate:graph` → extended category `graph` only. diff --git a/packages/react-native-audio-api/common/cpp/test/filters.sh b/packages/react-native-audio-api/common/cpp/test/filters.sh new file mode 100755 index 000000000..0bddb74cb --- /dev/null +++ b/packages/react-native-audio-api/common/cpp/test/filters.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Gtest filters for C++ test modes (smoke / extended-by-category / full). +# Sourced by RunTests.sh and RunCoverage.sh. +# +# Invariant: smoke and extended are disjoint. Extended lists only slow suites. +# Override any computed filter with GTEST_FILTER=... + +# Slow graph suites only. GraphNodeGrowthTest stays in smoke (short; needs +# unsanitized AudioThreadGuard — see TESTING.md). +CPP_TEST_EXTENDED_GRAPH_FILTER="AudioGraphTest.*:AudioGraphFuzzTest.*:GraphTest.*:GraphFuzzTest.*:GraphCycleDebugTest.*:HostGraphTest.*:Seeds/*" + +# Space-separated registered extended categories (add new names here). +CPP_TEST_EXTENDED_CATEGORIES="graph" + +cpp_test_extended_filter_for_category() { + local category="$1" + case "$category" in + graph) + printf '%s' "${CPP_TEST_EXTENDED_GRAPH_FILTER}" + ;; + *) + echo "error: unknown extended category '${category}' (registered: ${CPP_TEST_EXTENDED_CATEGORIES})" >&2 + return 1 + ;; + esac +} + +# Join category filters with ':'. Args = category names (default: all registered). +cpp_test_extended_filter() { + local categories=("$@") + if [[ ${#categories[@]} -eq 0 ]]; then + # shellcheck disable=SC2206 + categories=(${CPP_TEST_EXTENDED_CATEGORIES}) + fi + + local parts=() + local category filter + for category in "${categories[@]}"; do + filter="$(cpp_test_extended_filter_for_category "$category")" || return 1 + parts+=("$filter") + done + + local IFS=':' + printf '%s' "${parts[*]}" +} + +cpp_test_smoke_filter() { + local extended + extended="$(cpp_test_extended_filter)" || return 1 + printf '%s' "-${extended}" +} diff --git a/packages/react-native-audio-api/common/cpp/test/graph_tests_docs.md b/packages/react-native-audio-api/common/cpp/test/graph_tests_docs.md index ea10ebdbc..9dcc38487 100644 --- a/packages/react-native-audio-api/common/cpp/test/graph_tests_docs.md +++ b/packages/react-native-audio-api/common/cpp/test/graph_tests_docs.md @@ -1,33 +1,11 @@ +# Graph / extended tests (legacy note) -Here is the guide on how to run the graph tests locally with some tips and tricks to make it easier. - - -## Running it normally -``` -yarn test:graph -``` -> This is most common way to run the tests, but it has subtle difference on macos - -## Running on docker -``` -yarn test:graph:docker -``` -> This way we ensure that the test enviroment is simmilar to the one used in CI, it is much slower and requires docker to be installed - - -## Tips and tricks -As running docker tests takes forevewer it is recommended to relly on CI/CD. Tests without docker does not have ASAN and may not catch memory leaks or address realated issues. So if any of these issues occur in CI/CD here is how you can run single test with docker to debug it locally: -add the following line to the `RunTestsGraphDocker.sh` file in docker command: +Canonical docs: [`TESTING.md`](TESTING.md). ```bash -docker run --rm -it \ - --name $CONTAINER_NAME \ - -v "$REPO_ROOT:/workspace" \ - -w /workspace/packages/react-native-audio-api/common/cpp/test \ - -e ASAN_OPTIONS=detect_leaks=1:verbosity=2 \ - -e GRAPH_FILTER="" \ # Add this line to set the filter for the tests - $IMAGE_NAME \ - bash RunTestsGraph.sh +yarn test:cpp:extended -- graph # preferred +yarn test:graph # legacy alias +yarn test:graph:docker # Docker → RunTests.sh (default: extended graph) ``` -This will add enviromental variable `GRAPH_FILTER` which will limit the tests cases to only ones matching the filter. This way you can run single test case or a group instead of running all the tests all the time. +Narrow with `GTEST_FILTER` (legacy `GRAPH_FILTER` still mapped by `RunTestsGraph.sh`). diff --git a/packages/react-native-audio-api/package.json b/packages/react-native-audio-api/package.json index aaa09c3f2..d1003cf83 100644 --- a/packages/react-native-audio-api/package.json +++ b/packages/react-native-audio-api/package.json @@ -47,9 +47,12 @@ "test": "yarn test:js && yarn test:cpp", "test:js": "jest", "test:cpp": "bash common/cpp/test/RunTests.sh", + "test:cpp:smoke": "bash common/cpp/test/RunTests.sh smoke", + "test:cpp:extended": "bash common/cpp/test/RunTests.sh extended", + "test:cpp:full": "bash common/cpp/test/RunTests.sh full", "test:cpp:coverage": "bash common/cpp/test/RunCoverage.sh", - "test:full": "yarn test && yarn test:graph", - "test:graph": "bash common/cpp/test/RunTestsGraph.sh", + "test:full": "yarn test:js && yarn test:cpp:full", + "test:graph": "bash common/cpp/test/RunTests.sh extended graph", "test:graph:docker": "bash common/cpp/test/RunTestsGraphDocker.sh", "build:android": "cd ../../apps/fabric-example/android && ./gradlew :react-native-audio-api:assembleDebug", "build:ios": "cd ../../apps/fabric-example/ios && pod install && xcodebuild build -workspace FabricExample.xcworkspace -scheme FabricExample -destination 'generic/platform=iOS Simulator' -quiet", diff --git a/scripts/validate.sh b/scripts/validate.sh index 391e59ba3..94d5afce7 100755 --- a/scripts/validate.sh +++ b/scripts/validate.sh @@ -1,14 +1,35 @@ #!/usr/bin/env bash -# validate.sh — tiered local validation for react-native-audio-api -# -# Usage: -# ./scripts/validate.sh --fast # CI parity (format, lint, typecheck, tests, build) -# ./scripts/validate.sh --graph # graph tests (optional, graph changes) -# ./scripts/validate.sh --android # Android native build (requires Android SDK) -# ./scripts/validate.sh --ios # iOS native build (macOS only) -# ./scripts/validate.sh --full # --fast + --android + --ios (with graceful skips) -# -# Local-only — not wired into CI. + +print_help() { + cat <<'EOF' +Usage: ./scripts/validate.sh [tiers…] + +Local-only validation (not run in CI). Combine flags as needed. + +Tiers: + --fast CI parity: format, lint, typecheck, enum sync, build, C++ smoke + JS + --cpp C++ smoke only + --cpp-extended C++ extended (all registered categories) + --cpp-full C++ full (smoke, then all extended categories) + --android Android native build (requires ANDROID_HOME) + --ios iOS native build (macOS only) + --full --fast + C++ extended (all categories) + --android + --ios + (C++ full = smoke from --fast + extended; skips unavailable platforms) + +Legacy aliases: + --graph Same as C++ extended category graph only + (prefer --cpp-extended, or yarn test:cpp:extended -- graph) + +Examples: + yarn validate:fast + yarn validate:cpp + yarn validate:cpp-extended + yarn validate:full + +Options: + --help, -h Show this help. +EOF +} set -euo pipefail @@ -18,6 +39,9 @@ LIBRARY_DIR="$REPO_ROOT/packages/react-native-audio-api" SCRIPTS_DIR="$LIBRARY_DIR/scripts" RUN_FAST=false +RUN_CPP=false +RUN_CPP_EXTENDED=false +RUN_CPP_FULL=false RUN_GRAPH=false RUN_ANDROID=false RUN_IOS=false @@ -59,7 +83,7 @@ run_prebuild_core() { log_step "Prebuild: yarn build" (cd "$REPO_ROOT" && yarn build) - log_step "Prebuild: C++ tests (shared layer compile check)" + log_step "Prebuild: C++ smoke (shared layer compile check)" (cd "$REPO_ROOT" && yarn workspace react-native-audio-api test:cpp) PREBUILD_CORE_DONE=true @@ -90,7 +114,7 @@ EOF } run_fast() { - log_step "Tier 0 (--fast): CI parity checks" + log_step "Tier (--fast): CI parity checks" log_step "yarn install --immutable" (cd "$REPO_ROOT" && yarn install --immutable) @@ -119,10 +143,29 @@ run_fast() { PREBUILD_CORE_DONE=true } +run_cpp() { + log_step "C++ smoke (--cpp)" + run_prebuild_core + (cd "$REPO_ROOT" && yarn workspace react-native-audio-api test:cpp:smoke) +} + +run_cpp_extended() { + log_step "C++ extended all categories (--cpp-extended)" + run_prebuild_core + (cd "$REPO_ROOT" && yarn workspace react-native-audio-api test:cpp:extended) +} + +run_cpp_full() { + log_step "C++ full (--cpp-full)" + run_prebuild_core + (cd "$REPO_ROOT" && yarn workspace react-native-audio-api test:cpp:full) +} + +# Legacy alias: extended category graph only. run_graph() { - log_step "Tier 1 (--graph): graph tests" + log_step "C++ extended category graph (--graph, legacy alias)" run_prebuild_core - (cd "$REPO_ROOT" && yarn workspace react-native-audio-api test:graph) + (cd "$REPO_ROOT" && yarn workspace react-native-audio-api test:cpp:extended -- graph) } run_android() { @@ -141,7 +184,7 @@ run_android() { exit 1 fi - log_step "Tier 2 (--android): Android native build" + log_step "Tier (--android): Android native build" run_prebuild_for_platform android @@ -169,7 +212,7 @@ run_ios() { exit 1 fi - log_step "Tier 3 (--ios): iOS native build" + log_step "Tier (--ios): iOS native build" run_prebuild_for_platform ios @@ -180,36 +223,29 @@ run_ios() { run_full() { log_step "Full local validation (--full)" run_fast + # --fast already ran C++ smoke; extended completes C++ full without re-running smoke. + log_step "C++ extended all categories (remainder of C++ full)" + (cd "$REPO_ROOT" && yarn workspace react-native-audio-api test:cpp:extended) run_android true run_ios true } -usage() { - cat <<'EOF' -Usage: ./scripts/validate.sh [--fast] [--graph] [--android] [--ios] [--full] - -Tiers: - --fast CI parity: format, lint, typecheck, enum sync, build, C++ + JS tests - --graph Graph tests (optional; run when graph/audio-thread code changes) - --android Android native build via yarn workspace … build:android (requires ANDROID_HOME) - --ios iOS native build via yarn workspace … build:ios (macOS only) - --full --fast + --android + --ios (skips unavailable platforms with a warning) - -Examples: - yarn validate:fast - yarn validate:android - yarn validate:full - -Local-only — not run in CI. -EOF -} - while [[ $# -gt 0 ]]; do case "$1" in --fast) RUN_FAST=true ;; + --cpp) + RUN_CPP=true + ;; + --cpp-extended) + RUN_CPP_EXTENDED=true + ;; + --cpp-full) + RUN_CPP_FULL=true + ;; --graph) + # Legacy alias for extended category graph only. RUN_GRAPH=true ;; --android) @@ -219,28 +255,29 @@ while [[ $# -gt 0 ]]; do RUN_IOS=true ;; --full) - RUN_FULL=true + RUN_FULL=true ;; --help|-h) - usage + print_help exit 0 ;; *) echo "Unknown option: $1" >&2 - usage >&2 + print_help >&2 exit 1 ;; esac shift done -if [[ "$RUN_FAST" == false && "$RUN_GRAPH" == false && "$RUN_ANDROID" == false && "$RUN_IOS" == false && "$RUN_FULL" == false ]]; then - usage >&2 +if [[ "$RUN_FAST" == false && "$RUN_CPP" == false && "$RUN_CPP_EXTENDED" == false && "$RUN_CPP_FULL" == false && "$RUN_GRAPH" == false && "$RUN_ANDROID" == false && "$RUN_IOS" == false && "$RUN_FULL" == false ]]; then + print_help >&2 exit 1 fi cd "$REPO_ROOT" +enable_ccache_if_available if [[ "$RUN_FULL" == true ]]; then run_full @@ -248,6 +285,15 @@ fi if [[ "$RUN_FAST" == true && "$RUN_FULL" == false ]]; then run_fast fi +if [[ "$RUN_CPP" == true ]]; then + run_cpp +fi +if [[ "$RUN_CPP_EXTENDED" == true ]]; then + run_cpp_extended +fi +if [[ "$RUN_CPP_FULL" == true ]]; then + run_cpp_full +fi if [[ "$RUN_GRAPH" == true ]]; then run_graph fi