Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

## Unreleased

### Features

- Add `enableTurboModuleTracking` opt-in experimental option to enable Turbo Module performance tracking in the New Architecture ([#6307](https://github.com/getsentry/sentry-react-native/pull/6307))

### Fixes

- Remove unused `React/RCTTextView.h` import that broke iOS builds on React Native 0.87, where the header was removed as part of the legacy architecture cleanup ([#6322](https://github.com/getsentry/sentry-react-native/pull/6322))
Expand Down
1 change: 1 addition & 0 deletions packages/core/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
!react-native.config.js
!/ios/**/*
!/android/**/*
!/cpp/**/*

# New Architecture Codegen
!src/js/NativeRNSentry.ts
Expand Down
6 changes: 5 additions & 1 deletion packages/core/RNSentry.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ Pod::Spec.new do |s|

s.preserve_paths = '*.js'

s.source_files = 'ios/**/*.{h,m,mm}'
# `cpp/` holds platform-agnostic C++ used by both iOS and Android. On iOS it
# is pulled in here; on Android it is compiled by the dedicated CMake target
# in `android/CMakeLists.txt`. The files are guarded with
# `RCT_NEW_ARCH_ENABLED` so they compile to empty TUs on Old Arch.
s.source_files = 'ios/**/*.{h,m,mm}', 'cpp/**/*.{h,cpp}'
s.public_header_files = 'ios/RNSentry.h', 'ios/RNSentrySDK.h', 'ios/RNSentryStart.h', 'ios/RNSentryVersion.h', 'ios/RNSentryBreadcrumb.h', 'ios/RNSentryReplay.h', 'ios/RNSentryReplayBreadcrumbConverter.h', 'ios/Replay/RNSentryReplayMask.h', 'ios/Replay/RNSentryReplayUnmask.h', 'ios/RNSentryTimeToDisplay.h'

s.compiler_flags = other_cflags
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package io.sentry.rnsentryandroidtester

import io.sentry.react.RNSentryTurboModulePerfTracker
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

/**
* Unit coverage for the JVM-side wrapper around the native perf-logger toggle.
*
* In a host JVM (where this test runs) there is no Android system loader for
* `libsentry-tm-perf-logger.so`, so any call into the native method must throw
* `UnsatisfiedLinkError`. The tracker is expected to swallow that error and
* flip an internal latch so subsequent calls short-circuit without retrying.
*
* Uses Robolectric so the `android.util.Log` call inside the tracker's `catch`
* branch resolves to a real implementation instead of the default-not-mocked
* stub the bare JUnit4 runner exposes.
*/
@RunWith(RobolectricTestRunner::class)
class RNSentryTurboModulePerfTrackerTest {
@Before
fun resetLatch() {
// Each test exercises the latch transition from scratch; without this
// reset the second test in execution order would see the latch already
// tripped from the previous one.
RNSentryTurboModulePerfTracker.resetNativeUnavailableForTests()
}

@After
fun cleanUp() {
RNSentryTurboModulePerfTracker.resetNativeUnavailableForTests()
}

@Test
fun setEnabledSwallowsUnsatisfiedLinkErrorOnFirstCall() {
// No `.so` loaded in the test JVM → the JNI symbol is missing. The
// tracker must absorb the resulting `UnsatisfiedLinkError` so the
// caller does not see a crash on a misconfigured host.
RNSentryTurboModulePerfTracker.setEnabled(true)
// Reaching this point means the error was caught, which is the contract.
assertTrue(
"after a failed link, the tracker must latch the failure",
RNSentryTurboModulePerfTracker.isNativeUnavailableForTests(),
)
}

@Test
fun subsequentCallsShortCircuitAfterLatchTrips() {
// Trip the latch via the first call.
RNSentryTurboModulePerfTracker.setEnabled(true)
assertTrue(RNSentryTurboModulePerfTracker.isNativeUnavailableForTests())

// The second call must not throw or attempt to relink. The contract is
// "exactly one UnsatisfiedLinkError per process lifetime" — anything
// else means the tracker is hammering the runtime on every setEnabled.
RNSentryTurboModulePerfTracker.setEnabled(false)
RNSentryTurboModulePerfTracker.setEnabled(true)
assertTrue(
"latch must stay tripped across repeated calls",
RNSentryTurboModulePerfTracker.isNativeUnavailableForTests(),
)
}

@Test
fun setEnabledFalseDoesNotLoadNativeLibrary() {
// The lazy-load contract: hosts that never opt in to
// `enableTurboModuleTracking` pay no shared-library cost. A bare
// `initNativeSdk` with the option absent or `false` calls
// `setEnabled(false)` from Java, and we expect this NOT to attempt
// `System.loadLibrary`. The proxy for "did we attempt the load?" is
// the `nativeUnavailable` latch — in the test JVM the load would
// fail, so if it ran we would see the latch tripped.
RNSentryTurboModulePerfTracker.setEnabled(false)
assertFalse(
"setEnabled(false) on a fresh tracker must not attempt to load the native library",
RNSentryTurboModulePerfTracker.isNativeUnavailableForTests(),
)
}

@Test
fun resetClearsTheLatch() {
RNSentryTurboModulePerfTracker.setEnabled(true)
assertTrue(RNSentryTurboModulePerfTracker.isNativeUnavailableForTests())

RNSentryTurboModulePerfTracker.resetNativeUnavailableForTests()
assertFalse(
"the @TestOnly reset must clear the latch so tests can re-exercise it",
RNSentryTurboModulePerfTracker.isNativeUnavailableForTests(),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
/* Begin PBXBuildFile section */
332D33472CDBDBB600547D76 /* RNSentryReplayOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 332D33462CDBDBB600547D76 /* RNSentryReplayOptionsTests.swift */; };
3339C4812D6625570088EB3A /* RNSentryUserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3339C4802D6625570088EB3A /* RNSentryUserTests.m */; };
B4DEB41739F14AA38202D4D4 /* RNSentryUriValidationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */; };
336084392C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */; };
3380C6C42CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3380C6C32CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift */; };
33AFDFED2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */; };
Expand All @@ -18,7 +17,9 @@
33DEDFED2D8DC825006066E4 /* RNSentryOnDrawReporter+Test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33DEDFEC2D8DC820006066E4 /* RNSentryOnDrawReporter+Test.mm */; };
33DEDFF02D9185EB006066E4 /* RNSentryTimeToDisplayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33DEDFEF2D9185E3006066E4 /* RNSentryTimeToDisplayTests.swift */; };
33F58AD02977037D008F60EA /* RNSentryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 33F58ACF2977037D008F60EA /* RNSentryTests.m */; };
A1B2C3D4E5F600000000001 /* RNSentryTurboModulePerfControllerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F600000000002 /* RNSentryTurboModulePerfControllerTests.mm */; };
AEFB00422CC90C4B00EC8A9A /* RNSentryBreadcrumbTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */; };
B4DEB41739F14AA38202D4D4 /* RNSentryUriValidationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */; };
B5859A50A3E865EF5E61465A /* libPods-RNSentryCocoaTesterTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 650CB718ACFBD05609BF2126 /* libPods-RNSentryCocoaTesterTests.a */; };
/* End PBXBuildFile section */

Expand All @@ -31,7 +32,6 @@
332D334A2CDCC8EB00547D76 /* RNSentryCocoaTesterTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentryCocoaTesterTests-Bridging-Header.h"; sourceTree = "<group>"; };
3339C47F2D6625260088EB3A /* RNSentry+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNSentry+Test.h"; sourceTree = "<group>"; };
3339C4802D6625570088EB3A /* RNSentryUserTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUserTests.m; sourceTree = "<group>"; };
3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUriValidationTests.m; sourceTree = "<group>"; };
336084382C32E382008CC412 /* RNSentryReplayBreadcrumbConverterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RNSentryReplayBreadcrumbConverterTests.swift; sourceTree = "<group>"; };
3360843A2C32E3A8008CC412 /* RNSentryReplayBreadcrumbConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNSentryReplayBreadcrumbConverter.h; path = ../ios/RNSentryReplayBreadcrumbConverter.h; sourceTree = "<group>"; };
3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryBreadcrumbTests.swift; sourceTree = "<group>"; };
Expand All @@ -50,7 +50,9 @@
33DEDFEE2D8DD431006066E4 /* RNSentryTimeToDisplay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentryTimeToDisplay.h; path = ../ios/RNSentryTimeToDisplay.h; sourceTree = SOURCE_ROOT; };
33DEDFEF2D9185E3006066E4 /* RNSentryTimeToDisplayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNSentryTimeToDisplayTests.swift; sourceTree = "<group>"; };
33F58ACF2977037D008F60EA /* RNSentryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSentryTests.m; sourceTree = "<group>"; };
3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNSentryUriValidationTests.m; sourceTree = "<group>"; };
650CB718ACFBD05609BF2126 /* libPods-RNSentryCocoaTesterTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNSentryCocoaTesterTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A1B2C3D4E5F600000000002 /* RNSentryTurboModulePerfControllerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = RNSentryTurboModulePerfControllerTests.mm; sourceTree = "<group>"; };
E2321E7CFA55AB617247098E /* Pods-RNSentryCocoaTesterTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNSentryCocoaTesterTests.debug.xcconfig"; path = "Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests.debug.xcconfig"; sourceTree = "<group>"; };
F48F26542EA2A481008A185E /* RNSentryEmitNewFrameEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentryEmitNewFrameEvent.h; path = ../ios/RNSentryEmitNewFrameEvent.h; sourceTree = SOURCE_ROOT; };
F48F26552EA2A4D4008A185E /* RNSentryFramesTrackerListener.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNSentryFramesTrackerListener.h; path = ../ios/RNSentryFramesTrackerListener.h; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -111,6 +113,7 @@
33F58ACF2977037D008F60EA /* RNSentryTests.m */,
3339C4802D6625570088EB3A /* RNSentryUserTests.m */,
3E3742693F7643C2ADE1BDF2 /* RNSentryUriValidationTests.m */,
A1B2C3D4E5F600000000002 /* RNSentryTurboModulePerfControllerTests.mm */,
33AFDFEC2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m */,
33AFDFF02B8D15E500AAB120 /* RNSentryDependencyContainerTests.m */,
3360843C2C340C76008CC412 /* RNSentryBreadcrumbTests.swift */,
Expand Down Expand Up @@ -241,14 +244,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNSentryCocoaTesterTests/Pods-RNSentryCocoaTesterTests-resources.sh\"\n";
Expand All @@ -270,6 +269,7 @@
33F58AD02977037D008F60EA /* RNSentryTests.m in Sources */,
3339C4812D6625570088EB3A /* RNSentryUserTests.m in Sources */,
B4DEB41739F14AA38202D4D4 /* RNSentryUriValidationTests.m in Sources */,
A1B2C3D4E5F600000000001 /* RNSentryTurboModulePerfControllerTests.mm in Sources */,
33DEDFF02D9185EB006066E4 /* RNSentryTimeToDisplayTests.swift in Sources */,
3380C6C42CE25ECA0018B9B6 /* RNSentryReplayPostInitTests.swift in Sources */,
33AFDFED2B8D14B300AAB120 /* RNSentryFramesTrackerListenerTests.m in Sources */,
Expand Down
Loading
Loading