react-native-image-stitcher 0.15.2 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +171 -1
- package/README.md +131 -5
- package/android/src/main/cpp/image_stitcher_jni.cpp +154 -13
- package/android/src/main/cpp/keyframe_gate_jni.cpp +15 -8
- package/android/src/main/java/io/imagestitcher/rn/BatchStitcher.kt +223 -1
- package/android/src/main/java/io/imagestitcher/rn/IncrementalStitcher.kt +220 -87
- package/android/src/main/java/io/imagestitcher/rn/KeyframeGate.kt +1 -1
- package/android/src/main/java/io/imagestitcher/rn/RNSARCameraView.kt +7 -36
- package/android/src/main/java/io/imagestitcher/rn/RNSARSession.kt +14 -8
- package/android/src/main/java/io/imagestitcher/rn/ar/YuvImageConverter.kt +39 -1
- package/cpp/crop_quad.cpp +162 -0
- package/cpp/crop_quad.hpp +163 -0
- package/cpp/keyframe_gate.cpp +54 -15
- package/cpp/keyframe_gate.hpp +33 -0
- package/cpp/stitcher.cpp +1122 -132
- package/cpp/stitcher.hpp +62 -0
- package/cpp/warp_guard.hpp +212 -0
- package/dist/camera/Camera.d.ts +209 -12
- package/dist/camera/Camera.js +575 -36
- package/dist/camera/CameraView.js +35 -16
- package/dist/camera/CaptureCountdownOverlay.d.ts +70 -0
- package/dist/camera/CaptureCountdownOverlay.js +239 -0
- package/dist/camera/CaptureFrameCounterOverlay.d.ts +58 -0
- package/dist/camera/CaptureFrameCounterOverlay.js +153 -0
- package/dist/camera/CaptureMemoryPill.d.ts +24 -8
- package/dist/camera/CaptureMemoryPill.js +37 -12
- package/dist/camera/CapturePreview.js +2 -1
- package/dist/camera/CaptureStatusOverlay.d.ts +11 -4
- package/dist/camera/CaptureStatusOverlay.js +22 -5
- package/dist/camera/CaptureThumbnailStrip.js +2 -1
- package/dist/camera/LateralMotionModal.d.ts +85 -0
- package/dist/camera/LateralMotionModal.js +134 -0
- package/dist/camera/PanHowToOverlay.d.ts +76 -0
- package/dist/camera/PanHowToOverlay.js +222 -0
- package/dist/camera/PanoramaBandOverlay.d.ts +2 -1
- package/dist/camera/PanoramaBandOverlay.js +9 -3
- package/dist/camera/PanoramaSettings.d.ts +8 -6
- package/dist/camera/PanoramaSettings.js +19 -1
- package/dist/camera/PanoramaSettingsModal.js +4 -4
- package/dist/camera/RectCropPreview.d.ts +135 -0
- package/dist/camera/RectCropPreview.js +370 -0
- package/dist/camera/RotateToLandscapePrompt.d.ts +87 -0
- package/dist/camera/RotateToLandscapePrompt.js +138 -0
- package/dist/camera/buildPanoramaInitialSettings.d.ts +19 -2
- package/dist/camera/buildPanoramaInitialSettings.js +9 -0
- package/dist/camera/cameraErrorMessages.d.ts +30 -1
- package/dist/camera/cameraErrorMessages.js +26 -10
- package/dist/camera/cameraGuidanceCopy.d.ts +87 -0
- package/dist/camera/cameraGuidanceCopy.js +80 -0
- package/dist/camera/captureCountdown.d.ts +52 -0
- package/dist/camera/captureCountdown.js +76 -0
- package/dist/camera/captureWarnings.d.ts +90 -0
- package/dist/camera/captureWarnings.js +108 -0
- package/dist/camera/classifyStitchError.d.ts +30 -0
- package/dist/camera/classifyStitchError.js +42 -0
- package/dist/camera/cropGeometry.d.ts +136 -0
- package/dist/camera/cropGeometry.js +223 -0
- package/dist/camera/displayDecodeImageProps.d.ts +25 -0
- package/dist/camera/displayDecodeImageProps.js +29 -0
- package/dist/camera/guidanceGraphics.d.ts +58 -0
- package/dist/camera/guidanceGraphics.js +280 -0
- package/dist/camera/guidanceTokens.d.ts +54 -0
- package/dist/camera/guidanceTokens.js +58 -0
- package/dist/camera/panModeGate.d.ts +54 -0
- package/dist/camera/panModeGate.js +62 -0
- package/dist/camera/pickCaptureFormat.d.ts +71 -0
- package/dist/camera/pickCaptureFormat.js +85 -0
- package/dist/camera/stitchDebugInfo.d.ts +27 -0
- package/dist/camera/stitchDebugInfo.js +55 -0
- package/dist/camera/usePanMotion.d.ts +250 -0
- package/dist/camera/usePanMotion.js +451 -0
- package/dist/index.d.ts +24 -3
- package/dist/index.js +33 -2
- package/dist/stitching/computeInscribedRect.d.ts +40 -0
- package/dist/stitching/computeInscribedRect.js +55 -0
- package/dist/stitching/cropQuad.d.ts +78 -0
- package/dist/stitching/cropQuad.js +116 -0
- package/dist/stitching/incremental.d.ts +74 -0
- package/dist/stitching/useIncrementalStitcher.d.ts +7 -1
- package/dist/stitching/useIncrementalStitcher.js +7 -1
- package/ios/Sources/RNImageStitcher/IncrementalStitcher.swift +154 -29
- package/ios/Sources/RNImageStitcher/IncrementalStitcherBridge.m +4 -0
- package/ios/Sources/RNImageStitcher/IncrementalStitcherBridge.swift +15 -0
- package/ios/Sources/RNImageStitcher/KeyframeGate.swift +2 -2
- package/ios/Sources/RNImageStitcher/OpenCVKeyframeCollector.mm +48 -5
- package/ios/Sources/RNImageStitcher/OpenCVStitcher.h +27 -0
- package/ios/Sources/RNImageStitcher/OpenCVStitcher.mm +211 -7
- package/ios/Sources/RNImageStitcher/RNSARSession.swift +25 -1
- package/ios/Sources/RNImageStitcher/Stitcher.swift +34 -1
- package/ios/Sources/RNImageStitcher/StitcherBridge.m +5 -0
- package/ios/Sources/RNImageStitcher/StitcherBridge.swift +56 -0
- package/package.json +5 -1
- package/src/camera/Camera.tsx +945 -47
- package/src/camera/CameraView.tsx +48 -16
- package/src/camera/CaptureCountdownOverlay.tsx +272 -0
- package/src/camera/CaptureFrameCounterOverlay.tsx +197 -0
- package/src/camera/CaptureMemoryPill.tsx +50 -12
- package/src/camera/CapturePreview.tsx +5 -0
- package/src/camera/CaptureStatusOverlay.tsx +35 -7
- package/src/camera/CaptureThumbnailStrip.tsx +4 -0
- package/src/camera/LateralMotionModal.tsx +199 -0
- package/src/camera/PanHowToOverlay.tsx +246 -0
- package/src/camera/PanoramaBandOverlay.tsx +9 -1
- package/src/camera/PanoramaSettings.ts +27 -7
- package/src/camera/PanoramaSettingsModal.tsx +4 -4
- package/src/camera/RectCropPreview.tsx +638 -0
- package/src/camera/RotateToLandscapePrompt.tsx +188 -0
- package/src/camera/buildPanoramaInitialSettings.ts +30 -1
- package/src/camera/cameraErrorMessages.ts +39 -2
- package/src/camera/cameraGuidanceCopy.ts +145 -0
- package/src/camera/captureCountdown.ts +83 -0
- package/src/camera/captureWarnings.ts +190 -0
- package/src/camera/classifyStitchError.ts +68 -0
- package/src/camera/cropGeometry.ts +268 -0
- package/src/camera/displayDecodeImageProps.ts +25 -0
- package/src/camera/guidanceGraphics.tsx +347 -0
- package/src/camera/guidanceTokens.ts +57 -0
- package/src/camera/panModeGate.ts +81 -0
- package/src/camera/pickCaptureFormat.ts +130 -0
- package/src/camera/stitchDebugInfo.ts +71 -0
- package/src/camera/usePanMotion.ts +667 -0
- package/src/index.ts +66 -3
- package/src/stitching/computeInscribedRect.ts +81 -0
- package/src/stitching/cropQuad.ts +167 -0
- package/src/stitching/incremental.ts +74 -0
- package/src/stitching/useIncrementalStitcher.ts +13 -0
- package/android/src/main/java/io/imagestitcher/rn/TransferredNV21.kt +0 -100
- package/cpp/tests/CMakeLists.txt +0 -104
- package/cpp/tests/README.md +0 -86
- package/cpp/tests/keyframe_timebudget_test.cpp +0 -65
- package/cpp/tests/pose_test.cpp +0 -74
- package/cpp/tests/stitcher_frame_data_test.cpp +0 -132
- package/cpp/tests/stubs/jsi/jsi.h +0 -33
- package/cpp/tests/stubs/react-native-worklets-core/WKTJsiWorklet.h +0 -34
- package/cpp/tests/warp_guard_test.cpp +0 -48
- package/src/camera/__tests__/PanoramaSettingsBridge.test.ts +0 -190
- package/src/camera/__tests__/bandThumbRotation.test.ts +0 -120
- package/src/camera/__tests__/buildPanoramaInitialSettings.test.ts +0 -160
- package/src/camera/__tests__/cameraErrorMessages.test.ts +0 -76
- package/src/camera/__tests__/homeIndicatorEdge.test.ts +0 -116
- package/src/camera/__tests__/lowMemDevice.test.ts +0 -52
- package/src/camera/__tests__/selectCaptureDevice.test.ts +0 -210
- package/src/camera/__tests__/useContentRotation.test.ts +0 -89
- package/src/camera/__tests__/useOrientationDrift.test.ts +0 -169
- package/src/stitching/__tests__/subscribeIncrementalState.refine.test.ts +0 -276
- package/src/stitching/__tests__/useStitcherWorklet.test.ts +0 -202
package/cpp/tests/CMakeLists.txt
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
#
|
|
3
|
-
# cpp/tests/CMakeLists.txt — v0.10.0 audit #9A
|
|
4
|
-
#
|
|
5
|
-
# Standalone Google Test runner for the shared C++ port under `cpp/`.
|
|
6
|
-
# Build + run via:
|
|
7
|
-
#
|
|
8
|
-
# cmake -S cpp/tests -B build/cpp-tests
|
|
9
|
-
# cmake --build build/cpp-tests
|
|
10
|
-
# (cd build/cpp-tests && ctest --output-on-failure)
|
|
11
|
-
#
|
|
12
|
-
# Or, from the repo root: `scripts/run-cpp-tests.sh`.
|
|
13
|
-
#
|
|
14
|
-
# What this DOES test:
|
|
15
|
-
# - Pure-C++ types in cpp/: `Pose`, `PlaneTransform`,
|
|
16
|
-
# `StitcherFrameData`, `PixelBufferReader` interface contract.
|
|
17
|
-
# - `timeBudgetCrossed` — the keyframe gate's OpenCV-free time-budget
|
|
18
|
-
# force-accept predicate (keyframe_timebudget_test.cpp).
|
|
19
|
-
# - `warpRoiExceedsGuard` — the OpenCV-free warp-canvas size guard that
|
|
20
|
-
# triggers the cylindrical-fallback pre-pass (warp_guard_test.cpp).
|
|
21
|
-
# (The StitcherWorkletRegistry test was removed when that source was
|
|
22
|
-
# archived in the Phase-3 cleanup — its CMake entries had gone stale
|
|
23
|
-
# and broke the whole suite's configure step.)
|
|
24
|
-
#
|
|
25
|
-
# What this DOES NOT test yet (deferred to v0.11.0+):
|
|
26
|
-
# - `KeyframeGate` (the full gate) — depends on OpenCV. Will need an
|
|
27
|
-
# OpenCV-aware CMake config (link the same opencv_world the prod
|
|
28
|
-
# build uses). NOTE: the OpenCV-free `timeBudgetCrossed` predicate
|
|
29
|
-
# (the time-budget force-accept boundary logic) IS covered, via
|
|
30
|
-
# keyframe_timebudget_test.cpp — it's an inline header-only function.
|
|
31
|
-
# - JSI host-object dispatch — needs a real Hermes runtime.
|
|
32
|
-
# - Anything in `stitcher.cpp` (uses OpenCV stitching pipeline).
|
|
33
|
-
|
|
34
|
-
cmake_minimum_required(VERSION 3.20)
|
|
35
|
-
project(stitcher_cpp_tests CXX)
|
|
36
|
-
|
|
37
|
-
set(CMAKE_CXX_STANDARD 17)
|
|
38
|
-
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
39
|
-
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
40
|
-
|
|
41
|
-
# Must precede `gtest_discover_tests` — without this the discovered
|
|
42
|
-
# cases aren't registered into a CTestTestfile.cmake at this directory
|
|
43
|
-
# level, and `ctest` reports "No tests were found".
|
|
44
|
-
enable_testing()
|
|
45
|
-
|
|
46
|
-
# Fetch GoogleTest pinned to v1.14.0. Pin matches what the AOSP /
|
|
47
|
-
# Android NDK test ecosystem uses today; bumps should be deliberate.
|
|
48
|
-
include(FetchContent)
|
|
49
|
-
FetchContent_Declare(
|
|
50
|
-
googletest
|
|
51
|
-
GIT_REPOSITORY https://github.com/google/googletest.git
|
|
52
|
-
GIT_TAG v1.14.0
|
|
53
|
-
)
|
|
54
|
-
# Prevent GoogleTest from overriding our compiler/linker options
|
|
55
|
-
# (Windows-only quirk; harmless on macOS/Linux).
|
|
56
|
-
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
|
57
|
-
FetchContent_MakeAvailable(googletest)
|
|
58
|
-
|
|
59
|
-
# ─────────────────────────────────────────────────────────────────────
|
|
60
|
-
# Include paths
|
|
61
|
-
# ─────────────────────────────────────────────────────────────────────
|
|
62
|
-
# Order matters: stubs/ comes FIRST so `#include <jsi/jsi.h>` and
|
|
63
|
-
# `#include <react-native-worklets-core/WKTJsiWorklet.h>` resolve to
|
|
64
|
-
# the test-only stubs before any system header. The production cpp/
|
|
65
|
-
# directory comes after so retailens:: headers (e.g. ar_frame_pose.h,
|
|
66
|
-
# stitcher_frame_data.hpp) are found as the production code expects.
|
|
67
|
-
include_directories(
|
|
68
|
-
${CMAKE_CURRENT_SOURCE_DIR}/stubs
|
|
69
|
-
${CMAKE_CURRENT_SOURCE_DIR}/..
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
# ─────────────────────────────────────────────────────────────────────
|
|
73
|
-
# Test executable
|
|
74
|
-
# ─────────────────────────────────────────────────────────────────────
|
|
75
|
-
add_executable(stitcher_cpp_tests
|
|
76
|
-
# Test sources. All subjects are header-only (Pose / PlaneTransform,
|
|
77
|
-
# StitcherFrameData, and the gate's inline `timeBudgetCrossed`
|
|
78
|
-
# predicate), so no production .cpp needs linking here.
|
|
79
|
-
${CMAKE_CURRENT_SOURCE_DIR}/pose_test.cpp
|
|
80
|
-
${CMAKE_CURRENT_SOURCE_DIR}/stitcher_frame_data_test.cpp
|
|
81
|
-
${CMAKE_CURRENT_SOURCE_DIR}/keyframe_timebudget_test.cpp
|
|
82
|
-
${CMAKE_CURRENT_SOURCE_DIR}/warp_guard_test.cpp
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
target_link_libraries(stitcher_cpp_tests
|
|
86
|
-
PRIVATE
|
|
87
|
-
GTest::gtest_main
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
# Treat warnings as errors in the test build to catch the kind of
|
|
91
|
-
# silent regressions (unused variables, signed/unsigned comparisons,
|
|
92
|
-
# narrowing conversions) that production cross-compilation flags would
|
|
93
|
-
# otherwise suppress.
|
|
94
|
-
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
|
95
|
-
target_compile_options(stitcher_cpp_tests PRIVATE
|
|
96
|
-
-Wall -Wextra -Wpedantic -Werror
|
|
97
|
-
)
|
|
98
|
-
endif()
|
|
99
|
-
|
|
100
|
-
# Register with CTest so `ctest --output-on-failure` picks up the
|
|
101
|
-
# individual TEST() cases (gtest_discover_tests scans the binary at
|
|
102
|
-
# build time, no manual ADD_TEST per case).
|
|
103
|
-
include(GoogleTest)
|
|
104
|
-
gtest_discover_tests(stitcher_cpp_tests)
|
package/cpp/tests/README.md
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# `cpp/tests/` — shared C++ unit test suite
|
|
2
|
-
|
|
3
|
-
v0.10.0 audit `#9A` introduced this directory to give the cross-platform
|
|
4
|
-
shared C++ code under `cpp/` a Google Test harness that runs on the
|
|
5
|
-
developer's host machine (not on a device or emulator). Pairs with the
|
|
6
|
-
Android-side JUnit suite added in `#11A` (see
|
|
7
|
-
`android/src/test/java/io/imagestitcher/rn/`).
|
|
8
|
-
|
|
9
|
-
## Run
|
|
10
|
-
|
|
11
|
-
```sh
|
|
12
|
-
scripts/run-cpp-tests.sh # configure + build + ctest
|
|
13
|
-
scripts/run-cpp-tests.sh --clean # nuke build/cpp-tests/ first
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Requires `cmake ≥ 3.20` and a C++17 toolchain (the macOS AppleClang
|
|
17
|
-
shipped with Xcode 14+ is fine; Linux GCC 9+ / Clang 10+ also work).
|
|
18
|
-
|
|
19
|
-
Build artefacts land under `build/cpp-tests/` (gitignored). Google
|
|
20
|
-
Test is fetched at configure time via CMake `FetchContent` pinned to
|
|
21
|
-
`v1.14.0`; no system-wide install required.
|
|
22
|
-
|
|
23
|
-
## Scope (v0.10.0)
|
|
24
|
-
|
|
25
|
-
Covered:
|
|
26
|
-
|
|
27
|
-
- `Pose`, `PlaneTransform` (POD layout / size / field offsets — pinned
|
|
28
|
-
to the cross-platform marshalling contract documented in
|
|
29
|
-
`cpp/ar_frame_pose.h`).
|
|
30
|
-
- `StitcherFrameData` (default-construction invariants the JSI host
|
|
31
|
-
object's `get()` dispatch relies on).
|
|
32
|
-
- `PixelBufferReader` interface contract (clipping behaviour of
|
|
33
|
-
`copyTo` — validated via the `FakePixelBufferReader` test helper).
|
|
34
|
-
- `StitcherWorkletRegistry` storage lifecycle: shared-instance,
|
|
35
|
-
install/uninstall/count/snapshot, snapshot independence, concurrent
|
|
36
|
-
installs yield unique IDs (16 threads × 32 installs).
|
|
37
|
-
|
|
38
|
-
Not yet covered (intentional deferrals):
|
|
39
|
-
|
|
40
|
-
- `KeyframeGate` (`cpp/keyframe_gate.cpp`) — depends on OpenCV
|
|
41
|
-
(`opencv2/imgproc.hpp`, `opencv2/video.hpp` for `calcOpticalFlowPyrLK`).
|
|
42
|
-
Linking the production OpenCV xcframework / Android SDK into the
|
|
43
|
-
host-side test target would balloon CI time and disk usage; the
|
|
44
|
-
alternative is to land a stripped-down `libopencv-core` host build
|
|
45
|
-
just for tests. Deferred — comes with the v0.11.0 cross-platform
|
|
46
|
-
parity suite (`#2C`).
|
|
47
|
-
- `stitcher.cpp` — uses the full OpenCV stitching pipeline; same
|
|
48
|
-
reason as above.
|
|
49
|
-
- JSI host-object dispatch (`stitcher_frame_jsi.cpp`,
|
|
50
|
-
`stitcher_proxy_jsi.cpp`, `stitcher_worklet_dispatch.cpp`) — needs
|
|
51
|
-
a real Hermes runtime. The `StitcherWorkletRegistry` tests sidestep
|
|
52
|
-
this via the `_installEntryForTests` seam + JSI stubs under
|
|
53
|
-
`stubs/`; the JSI dispatch paths can't be similarly stubbed because
|
|
54
|
-
they actively call into the runtime.
|
|
55
|
-
|
|
56
|
-
## How the JSI-dependent registry tests work without a real JSI
|
|
57
|
-
|
|
58
|
-
`stitcher_worklet_registry.cpp` `#include`s
|
|
59
|
-
`<jsi/jsi.h>` and `<react-native-worklets-core/WKTJsiWorklet.h>` to
|
|
60
|
-
construct `WorkletInvoker` instances from a real JS runtime. The test
|
|
61
|
-
target sidesteps both by:
|
|
62
|
-
|
|
63
|
-
1. Putting `cpp/tests/stubs/` first on the compiler's include path so
|
|
64
|
-
`#include <jsi/jsi.h>` resolves to `stubs/jsi/jsi.h` (which declares
|
|
65
|
-
`facebook::jsi::Runtime` / `Value` as empty classes — enough for
|
|
66
|
-
the registry's reference-only usage), and
|
|
67
|
-
`#include <react-native-worklets-core/WKTJsiWorklet.h>` resolves to
|
|
68
|
-
`stubs/react-native-worklets-core/WKTJsiWorklet.h` (which declares
|
|
69
|
-
`RNWorklet::WorkletInvoker` with a no-op constructor).
|
|
70
|
-
2. Calling `_installEntryForTests(nullptr)` instead of the production
|
|
71
|
-
`install(runtime, value)` path. The registry stores the
|
|
72
|
-
`shared_ptr<WorkletInvoker>` but never dereferences it (it only
|
|
73
|
-
hands it back via `snapshot`), so `nullptr` is safe.
|
|
74
|
-
|
|
75
|
-
The stubs live exclusively under `cpp/tests/stubs/`; production
|
|
76
|
-
builds never see them. See `stubs/jsi/jsi.h`'s docstring for the
|
|
77
|
-
guard-rails.
|
|
78
|
-
|
|
79
|
-
## When NOT to add a test here
|
|
80
|
-
|
|
81
|
-
- If the test needs a real JSI runtime, real OpenCV operations, or
|
|
82
|
-
real-device sensor data, it belongs in `android/src/androidTest/`
|
|
83
|
-
(instrumented), the iOS Swift test target, or the v0.11.0 parity
|
|
84
|
-
harness — NOT here.
|
|
85
|
-
- If the test verifies TypeScript/JS-side behaviour, it belongs under
|
|
86
|
-
`src/**/__tests__/` (Jest).
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
//
|
|
3
|
-
// keyframe_timebudget_test.cpp — host unit tests for the pure
|
|
4
|
-
// `retailens::timeBudgetCrossed` predicate (the keyframe gate's
|
|
5
|
-
// time-budget force-accept decision).
|
|
6
|
-
//
|
|
7
|
-
// The full KeyframeGate depends on OpenCV and cannot run in this
|
|
8
|
-
// harness (see CMakeLists.txt). The time-budget boundary logic was
|
|
9
|
-
// therefore deliberately extracted into an inline, OpenCV-free
|
|
10
|
-
// predicate in keyframe_gate.hpp precisely so it CAN be unit-tested
|
|
11
|
-
// here without linking the gate's OpenCV-dependent .cpp.
|
|
12
|
-
|
|
13
|
-
#include <gtest/gtest.h>
|
|
14
|
-
|
|
15
|
-
#include "keyframe_gate.hpp"
|
|
16
|
-
|
|
17
|
-
using retailens::timeBudgetCrossed;
|
|
18
|
-
|
|
19
|
-
// intervalMs <= 0 disables the budget entirely (opt-out path).
|
|
20
|
-
TEST(TimeBudgetCrossed, DisabledWhenIntervalNonPositive) {
|
|
21
|
-
EXPECT_FALSE(timeBudgetCrossed(0.0, 1000, 999999));
|
|
22
|
-
EXPECT_FALSE(timeBudgetCrossed(-5.0, 1000, 999999));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Never fires before the first accept (lastAcceptMs sentinel -1),
|
|
26
|
-
// regardless of how large `nowMs` is.
|
|
27
|
-
TEST(TimeBudgetCrossed, NeverFiresBeforeFirstAccept) {
|
|
28
|
-
EXPECT_FALSE(timeBudgetCrossed(2000.0, -1, 1000000));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Fires exactly at the boundary (elapsed == interval) and beyond.
|
|
32
|
-
TEST(TimeBudgetCrossed, FiresAtAndAfterBoundary) {
|
|
33
|
-
EXPECT_TRUE(timeBudgetCrossed(2000.0, 1000, 3000)); // elapsed == 2000
|
|
34
|
-
EXPECT_TRUE(timeBudgetCrossed(2000.0, 1000, 5000)); // elapsed > 2000
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Does NOT fire just under the boundary.
|
|
38
|
-
TEST(TimeBudgetCrossed, DoesNotFireJustUnderBoundary) {
|
|
39
|
-
EXPECT_FALSE(timeBudgetCrossed(2000.0, 1000, 2999)); // elapsed == 1999
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// A backwards or equal clock must never fire. A monotonic source
|
|
43
|
-
// should prevent now < lastAccept, but the predicate must be robust.
|
|
44
|
-
TEST(TimeBudgetCrossed, BackwardsOrEqualClockDoesNotFire) {
|
|
45
|
-
EXPECT_FALSE(timeBudgetCrossed(2000.0, 5000, 4000)); // now < lastAccept
|
|
46
|
-
EXPECT_FALSE(timeBudgetCrossed(2000.0, 5000, 5000)); // elapsed 0 < 2000
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Sub-millisecond budget must NOT collapse to "accept every frame":
|
|
50
|
-
// the predicate compares elapsed in double, so a 0.5 ms budget needs
|
|
51
|
-
// ~1 ms elapsed (not 0). Guards the truncation regression.
|
|
52
|
-
TEST(TimeBudgetCrossed, SubMillisecondBudgetDoesNotAcceptEveryFrame) {
|
|
53
|
-
EXPECT_FALSE(timeBudgetCrossed(0.5, 1000, 1000)); // elapsed 0.0 < 0.5
|
|
54
|
-
EXPECT_TRUE(timeBudgetCrossed(0.5, 1000, 1001)); // elapsed 1.0 >= 0.5
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Realistic 2 s budget across a slow pan: a keyframe accepted at t,
|
|
58
|
-
// the next force-accept lands at t + 2000 ms, not before.
|
|
59
|
-
TEST(TimeBudgetCrossed, TwoSecondBudgetTypicalUse) {
|
|
60
|
-
const int64_t lastAccept = 10000;
|
|
61
|
-
EXPECT_FALSE(timeBudgetCrossed(2000.0, lastAccept, lastAccept + 1500));
|
|
62
|
-
EXPECT_FALSE(timeBudgetCrossed(2000.0, lastAccept, lastAccept + 1999));
|
|
63
|
-
EXPECT_TRUE(timeBudgetCrossed(2000.0, lastAccept, lastAccept + 2000));
|
|
64
|
-
EXPECT_TRUE(timeBudgetCrossed(2000.0, lastAccept, lastAccept + 2001));
|
|
65
|
-
}
|
package/cpp/tests/pose_test.cpp
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
//
|
|
3
|
-
// pose_test.cpp — v0.10.0 audit #9A
|
|
4
|
-
//
|
|
5
|
-
// Layout / size invariants for the cross-platform POD structs that
|
|
6
|
-
// marshal AR-frame pose data between Swift/Kotlin and shared C++.
|
|
7
|
-
// The Pose / PlaneTransform structs MUST stay binary-compatible
|
|
8
|
-
// across iOS (Swift → C++) and Android (Kotlin → JNI → C++) — any
|
|
9
|
-
// silent field reorder, padding shift, or size change would diverge
|
|
10
|
-
// gate decisions between platforms.
|
|
11
|
-
//
|
|
12
|
-
// These are pinned to the contract in `cpp/ar_frame_pose.h`'s
|
|
13
|
-
// docstring; if the struct shape evolves intentionally, update both
|
|
14
|
-
// the docstring and these tests in the same commit.
|
|
15
|
-
|
|
16
|
-
#include "ar_frame_pose.h"
|
|
17
|
-
|
|
18
|
-
#include <gtest/gtest.h>
|
|
19
|
-
|
|
20
|
-
#include <cstddef>
|
|
21
|
-
#include <type_traits>
|
|
22
|
-
|
|
23
|
-
using retailens::Pose;
|
|
24
|
-
using retailens::PlaneTransform;
|
|
25
|
-
|
|
26
|
-
TEST(PoseLayoutTest, IsStandardLayoutPod) {
|
|
27
|
-
// Required for `memcpy` marshalling and for the iOS Obj-C++ /
|
|
28
|
-
// Android JNI bridges to write into the struct directly.
|
|
29
|
-
EXPECT_TRUE(std::is_standard_layout<Pose>::value);
|
|
30
|
-
EXPECT_TRUE(std::is_trivially_copyable<Pose>::value);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
TEST(PoseLayoutTest, SizeMatchesExpectedFields) {
|
|
34
|
-
// 11 floats (tx, ty, tz, qx, qy, qz, qw, fx, fy, cx, cy) + 2 int32_t
|
|
35
|
-
// (imageWidth, imageHeight) = 11*4 + 2*4 = 52 bytes. No padding
|
|
36
|
-
// expected: every field is 4-byte aligned and the struct contains
|
|
37
|
-
// only 4-byte primitives.
|
|
38
|
-
EXPECT_EQ(sizeof(Pose), static_cast<std::size_t>(11 * 4 + 2 * 4));
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
TEST(PoseLayoutTest, FieldOrderMatchesContract) {
|
|
42
|
-
// Translation comes before rotation; rotation before intrinsics;
|
|
43
|
-
// intrinsics before image dimensions. Swift / Kotlin marshallers
|
|
44
|
-
// assume this order — flipping any pair silently breaks the
|
|
45
|
-
// memcpy-based bridge.
|
|
46
|
-
EXPECT_EQ(offsetof(Pose, tx), 0u);
|
|
47
|
-
EXPECT_EQ(offsetof(Pose, ty), sizeof(float) * 1);
|
|
48
|
-
EXPECT_EQ(offsetof(Pose, tz), sizeof(float) * 2);
|
|
49
|
-
EXPECT_EQ(offsetof(Pose, qx), sizeof(float) * 3);
|
|
50
|
-
EXPECT_EQ(offsetof(Pose, qy), sizeof(float) * 4);
|
|
51
|
-
EXPECT_EQ(offsetof(Pose, qz), sizeof(float) * 5);
|
|
52
|
-
EXPECT_EQ(offsetof(Pose, qw), sizeof(float) * 6);
|
|
53
|
-
EXPECT_EQ(offsetof(Pose, fx), sizeof(float) * 7);
|
|
54
|
-
EXPECT_EQ(offsetof(Pose, fy), sizeof(float) * 8);
|
|
55
|
-
EXPECT_EQ(offsetof(Pose, cx), sizeof(float) * 9);
|
|
56
|
-
EXPECT_EQ(offsetof(Pose, cy), sizeof(float) * 10);
|
|
57
|
-
EXPECT_EQ(offsetof(Pose, imageWidth), sizeof(float) * 11);
|
|
58
|
-
EXPECT_EQ(offsetof(Pose, imageHeight),
|
|
59
|
-
sizeof(float) * 11 + sizeof(int32_t));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
TEST(PlaneTransformLayoutTest, IsStandardLayoutPod) {
|
|
63
|
-
EXPECT_TRUE(std::is_standard_layout<PlaneTransform>::value);
|
|
64
|
-
EXPECT_TRUE(std::is_trivially_copyable<PlaneTransform>::value);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
TEST(PlaneTransformLayoutTest, SixteenFloatsContiguous) {
|
|
68
|
-
// The `m[16]` array MUST be a contiguous 64-byte block — both
|
|
69
|
-
// bridges call `memcpy(planeTransform.m, source, 64)`. No leading
|
|
70
|
-
// padding, no field reorder (there's only one field, but pinning the
|
|
71
|
-
// size catches any accidental wrapper/struct change).
|
|
72
|
-
EXPECT_EQ(sizeof(PlaneTransform), static_cast<std::size_t>(16 * 4));
|
|
73
|
-
EXPECT_EQ(offsetof(PlaneTransform, m), 0u);
|
|
74
|
-
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
//
|
|
3
|
-
// stitcher_frame_data_test.cpp — v0.10.0 audit #9A
|
|
4
|
-
//
|
|
5
|
-
// Sanity coverage for the `StitcherFrameData` POD payload + the
|
|
6
|
-
// `PixelBufferReader` interface contract. The shared C++
|
|
7
|
-
// `StitcherFrameData` is constructed by both the iOS Obj-C++ side
|
|
8
|
-
// (`StitcherFrameHostObject.mm`) and the Android JNI side
|
|
9
|
-
// (`stitcher_frame_jni.cpp`); these tests pin the default-construction
|
|
10
|
-
// invariants both sides depend on (e.g. `hasTranslation=false`,
|
|
11
|
-
// `qw=1.0`).
|
|
12
|
-
//
|
|
13
|
-
// The `PixelBufferReader` tests use a fake-buffer implementation
|
|
14
|
-
// (`FakePixelBufferReader`) to validate the `copyTo` clipping
|
|
15
|
-
// behaviour the docstring promises.
|
|
16
|
-
|
|
17
|
-
#include "stitcher_frame_data.hpp"
|
|
18
|
-
|
|
19
|
-
#include <gtest/gtest.h>
|
|
20
|
-
|
|
21
|
-
#include <cstdint>
|
|
22
|
-
#include <cstring>
|
|
23
|
-
#include <memory>
|
|
24
|
-
#include <vector>
|
|
25
|
-
|
|
26
|
-
using retailens::PixelBufferReader;
|
|
27
|
-
using retailens::StitcherFrameData;
|
|
28
|
-
|
|
29
|
-
namespace {
|
|
30
|
-
|
|
31
|
-
/// Minimal fake reader — backs a fixed byte vector. Used by the
|
|
32
|
-
/// `PixelBufferReader` contract tests below to verify
|
|
33
|
-
/// `copyTo` clips at the smaller of (maxBytes, byteSize).
|
|
34
|
-
class FakePixelBufferReader : public PixelBufferReader {
|
|
35
|
-
public:
|
|
36
|
-
explicit FakePixelBufferReader(std::vector<uint8_t> bytes)
|
|
37
|
-
: _bytes(std::move(bytes)) {}
|
|
38
|
-
|
|
39
|
-
std::size_t byteSize() const override { return _bytes.size(); }
|
|
40
|
-
|
|
41
|
-
std::size_t copyTo(uint8_t* dst, std::size_t maxBytes) override {
|
|
42
|
-
const std::size_t n =
|
|
43
|
-
maxBytes < _bytes.size() ? maxBytes : _bytes.size();
|
|
44
|
-
std::memcpy(dst, _bytes.data(), n);
|
|
45
|
-
return n;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private:
|
|
49
|
-
std::vector<uint8_t> _bytes;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
} // namespace
|
|
53
|
-
|
|
54
|
-
// ─── StitcherFrameData default-construction invariants ─────────────
|
|
55
|
-
|
|
56
|
-
TEST(StitcherFrameDataTest, DefaultsAreSafeForJSIDispatch) {
|
|
57
|
-
// The JSI host object's `get()` dispatch keys off these defaults to
|
|
58
|
-
// expose `undefined` for unset fields. In particular:
|
|
59
|
-
// - `hasTranslation == false` → pose.translation === undefined
|
|
60
|
-
// - `arTrackingState.empty()` → arTrackingState === undefined
|
|
61
|
-
// - `qw == 1.0` with rest zero → identity rotation (safe default
|
|
62
|
-
// for non-AR mode where rotation is unknown)
|
|
63
|
-
StitcherFrameData d;
|
|
64
|
-
EXPECT_EQ(d.width, 0);
|
|
65
|
-
EXPECT_EQ(d.height, 0);
|
|
66
|
-
EXPECT_TRUE(d.source.empty());
|
|
67
|
-
EXPECT_TRUE(d.pixelFormat.empty());
|
|
68
|
-
EXPECT_TRUE(d.orientation.empty());
|
|
69
|
-
EXPECT_DOUBLE_EQ(d.timestampNs, 0.0);
|
|
70
|
-
EXPECT_DOUBLE_EQ(d.qx, 0.0);
|
|
71
|
-
EXPECT_DOUBLE_EQ(d.qy, 0.0);
|
|
72
|
-
EXPECT_DOUBLE_EQ(d.qz, 0.0);
|
|
73
|
-
EXPECT_DOUBLE_EQ(d.qw, 1.0); // identity rotation
|
|
74
|
-
EXPECT_DOUBLE_EQ(d.tx, 0.0);
|
|
75
|
-
EXPECT_DOUBLE_EQ(d.ty, 0.0);
|
|
76
|
-
EXPECT_DOUBLE_EQ(d.tz, 0.0);
|
|
77
|
-
EXPECT_FALSE(d.hasTranslation);
|
|
78
|
-
EXPECT_TRUE(d.arTrackingState.empty());
|
|
79
|
-
EXPECT_EQ(d.pixelReader, nullptr);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
TEST(StitcherFrameDataTest, IsCopyable) {
|
|
83
|
-
// `StitcherFrameData` is documented as "value-typed (cheap to copy;
|
|
84
|
-
// ~100 bytes)". Copy needs to deep-copy the strings + bump the
|
|
85
|
-
// pixelReader shared_ptr refcount.
|
|
86
|
-
StitcherFrameData a;
|
|
87
|
-
a.source = "ar";
|
|
88
|
-
a.width = 1920;
|
|
89
|
-
a.height = 1080;
|
|
90
|
-
a.pixelReader = std::make_shared<FakePixelBufferReader>(
|
|
91
|
-
std::vector<uint8_t>{1, 2, 3});
|
|
92
|
-
|
|
93
|
-
StitcherFrameData b = a;
|
|
94
|
-
EXPECT_EQ(b.source, "ar");
|
|
95
|
-
EXPECT_EQ(b.width, 1920);
|
|
96
|
-
EXPECT_EQ(b.height, 1080);
|
|
97
|
-
ASSERT_NE(b.pixelReader, nullptr);
|
|
98
|
-
EXPECT_EQ(b.pixelReader.use_count(), 2); // both a and b hold a ref
|
|
99
|
-
EXPECT_EQ(b.pixelReader->byteSize(), 3u);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ─── PixelBufferReader contract ────────────────────────────────────
|
|
103
|
-
|
|
104
|
-
TEST(PixelBufferReaderTest, CopyToReturnsAllBytesWhenMaxBytesExceedsSize) {
|
|
105
|
-
FakePixelBufferReader reader({0x11, 0x22, 0x33});
|
|
106
|
-
uint8_t buf[8] = {0};
|
|
107
|
-
const std::size_t written = reader.copyTo(buf, sizeof(buf));
|
|
108
|
-
EXPECT_EQ(written, 3u);
|
|
109
|
-
EXPECT_EQ(buf[0], 0x11);
|
|
110
|
-
EXPECT_EQ(buf[1], 0x22);
|
|
111
|
-
EXPECT_EQ(buf[2], 0x33);
|
|
112
|
-
EXPECT_EQ(buf[3], 0u); // untouched tail
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
TEST(PixelBufferReaderTest, CopyToClipsWhenMaxBytesIsSmaller) {
|
|
116
|
-
// Contract per stitcher_frame_data.hpp: "Implementations MUST handle
|
|
117
|
-
// the case where maxBytes < byteSize() (clip silently)."
|
|
118
|
-
FakePixelBufferReader reader({0xAA, 0xBB, 0xCC, 0xDD});
|
|
119
|
-
uint8_t buf[2] = {0};
|
|
120
|
-
const std::size_t written = reader.copyTo(buf, sizeof(buf));
|
|
121
|
-
EXPECT_EQ(written, 2u);
|
|
122
|
-
EXPECT_EQ(buf[0], 0xAA);
|
|
123
|
-
EXPECT_EQ(buf[1], 0xBB);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
TEST(PixelBufferReaderTest, CopyToWithZeroMaxBytesReturnsZero) {
|
|
127
|
-
FakePixelBufferReader reader({0x01, 0x02, 0x03});
|
|
128
|
-
uint8_t dummy = 0xFF;
|
|
129
|
-
const std::size_t written = reader.copyTo(&dummy, 0);
|
|
130
|
-
EXPECT_EQ(written, 0u);
|
|
131
|
-
EXPECT_EQ(dummy, 0xFF); // dst untouched when maxBytes == 0
|
|
132
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
//
|
|
3
|
-
// jsi.h — TEST-ONLY stub of facebook::jsi types.
|
|
4
|
-
//
|
|
5
|
-
// The real jsi.h ships with React Native and pulls in a large surface
|
|
6
|
-
// area (Runtime, Value, Object, Function, HostObject, HostFunction,
|
|
7
|
-
// Array, ArrayBuffer, PropNameID, …) along with the build infra to
|
|
8
|
-
// link them. For pure-C++ unit tests that exercise data-structure
|
|
9
|
-
// invariants of code that REFERENCES jsi types but never CALLS into
|
|
10
|
-
// them (e.g. `StitcherWorkletRegistry` storing a `shared_ptr` and
|
|
11
|
-
// forwarding `Runtime&` to a constructor stub), we only need the
|
|
12
|
-
// types to be NAMED so headers compile.
|
|
13
|
-
//
|
|
14
|
-
// Pattern: this stub is placed first on the test target's include
|
|
15
|
-
// path so `#include <jsi/jsi.h>` resolves here instead of to RN's
|
|
16
|
-
// real header. Production builds NEVER see this file — it lives
|
|
17
|
-
// only under `cpp/tests/stubs/`, which is referenced exclusively by
|
|
18
|
-
// `cpp/tests/CMakeLists.txt`.
|
|
19
|
-
//
|
|
20
|
-
// Tests that need to actually CONSTRUCT or CALL into JSI types should
|
|
21
|
-
// not use this stub — they should run against a real JSI runtime (a
|
|
22
|
-
// future v0.11.0+ test target that links Hermes).
|
|
23
|
-
|
|
24
|
-
#pragma once
|
|
25
|
-
|
|
26
|
-
namespace facebook {
|
|
27
|
-
namespace jsi {
|
|
28
|
-
|
|
29
|
-
class Runtime {};
|
|
30
|
-
class Value {};
|
|
31
|
-
|
|
32
|
-
} // namespace jsi
|
|
33
|
-
} // namespace facebook
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
//
|
|
3
|
-
// WKTJsiWorklet.h — TEST-ONLY stub of RNWorklet::WorkletInvoker.
|
|
4
|
-
//
|
|
5
|
-
// `cpp/stitcher_worklet_registry.cpp` constructs a
|
|
6
|
-
// `std::make_shared<RNWorklet::WorkletInvoker>(runtime, value)` inside
|
|
7
|
-
// `install`. The real WorkletInvoker (from react-native-worklets-core)
|
|
8
|
-
// captures the worklet's source / closure / runtime affinity and is
|
|
9
|
-
// non-trivial to stand up in a unit-test context.
|
|
10
|
-
//
|
|
11
|
-
// This stub provides JUST the symbols needed for the registry to
|
|
12
|
-
// compile and link. The constructor and destructor are no-ops; calling
|
|
13
|
-
// methods on a stub invoker is undefined behaviour, but the registry
|
|
14
|
-
// itself never does (it only stores the shared_ptr and hands it out
|
|
15
|
-
// via `snapshot`). Tests construct entries directly via
|
|
16
|
-
// `_installEntryForTests(nullptr)` to avoid even the trivial
|
|
17
|
-
// allocation.
|
|
18
|
-
//
|
|
19
|
-
// See cpp/tests/stubs/jsi/jsi.h for the parallel stub of facebook::jsi.
|
|
20
|
-
|
|
21
|
-
#pragma once
|
|
22
|
-
|
|
23
|
-
#include <jsi/jsi.h>
|
|
24
|
-
|
|
25
|
-
namespace RNWorklet {
|
|
26
|
-
|
|
27
|
-
class WorkletInvoker {
|
|
28
|
-
public:
|
|
29
|
-
WorkletInvoker(facebook::jsi::Runtime& /*runtime*/,
|
|
30
|
-
const facebook::jsi::Value& /*workletValue*/) {}
|
|
31
|
-
~WorkletInvoker() = default;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
} // namespace RNWorklet
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
/**
|
|
3
|
-
* Unit tests for the warp-canvas size guard (cpp/warp_guard.hpp).
|
|
4
|
-
*
|
|
5
|
-
* The guard decides when a warp ROI is "degenerate" — the trigger for
|
|
6
|
-
* both the cylindrical-fallback pre-pass and the in-loop final safety net.
|
|
7
|
-
* The cases that matter: normal ROIs pass, non-positive dims fail, the
|
|
8
|
-
* 100 MP boundary is inclusive, the real observed divergence (8171×12336)
|
|
9
|
-
* is caught, and a ROI whose int32 area would overflow is still caught.
|
|
10
|
-
*/
|
|
11
|
-
#include "warp_guard.hpp"
|
|
12
|
-
|
|
13
|
-
#include <gtest/gtest.h>
|
|
14
|
-
|
|
15
|
-
using retailens::warpRoiExceedsGuard;
|
|
16
|
-
|
|
17
|
-
TEST(WarpGuard, AcceptsNormalRoi) {
|
|
18
|
-
EXPECT_FALSE(warpRoiExceedsGuard(4000, 2000)); // 8 MP
|
|
19
|
-
EXPECT_FALSE(warpRoiExceedsGuard(1, 1));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
TEST(WarpGuard, RejectsNonPositiveDims) {
|
|
23
|
-
EXPECT_TRUE(warpRoiExceedsGuard(0, 1000));
|
|
24
|
-
EXPECT_TRUE(warpRoiExceedsGuard(1000, 0));
|
|
25
|
-
EXPECT_TRUE(warpRoiExceedsGuard(-5, 1000));
|
|
26
|
-
EXPECT_TRUE(warpRoiExceedsGuard(1000, -5));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
TEST(WarpGuard, BoundaryIsInclusive) {
|
|
30
|
-
EXPECT_FALSE(warpRoiExceedsGuard(100000, 1000)); // exactly 100 MP — allowed
|
|
31
|
-
EXPECT_TRUE(warpRoiExceedsGuard(100000, 1001)); // 100.1 MP — over
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
TEST(WarpGuard, RejectsTheObservedDivergence) {
|
|
35
|
-
// 8171×12336 = 100.8 MP — the exact STITCH_CAMERA_PARAMS_FAIL canvas.
|
|
36
|
-
EXPECT_TRUE(warpRoiExceedsGuard(8171, 12336));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
TEST(WarpGuard, RejectsInt32OverflowingRoi) {
|
|
40
|
-
// 65536×65536 = 2^32; an int32 area would wrap to 0 and slip past the
|
|
41
|
-
// guard. The int64 area math catches it.
|
|
42
|
-
EXPECT_TRUE(warpRoiExceedsGuard(65536, 65536));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
TEST(WarpGuard, HonoursCustomThreshold) {
|
|
46
|
-
EXPECT_FALSE(warpRoiExceedsGuard(1000, 1000, 2'000'000)); // 1 MP < 2 MP
|
|
47
|
-
EXPECT_TRUE(warpRoiExceedsGuard(2000, 1000, 1'000'000)); // 2 MP > 1 MP
|
|
48
|
-
}
|