diff --git a/CHANGELOG.md b/CHANGELOG.md index 840c8655a37..df5ef6e6e7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Fixes +- Fix misleading duplicate SDK detection message: "same binary" → "same address space" (#8710) - Fix a race caused by mutating `URLSessionTask.currentRequest` during trace header propagation (#8650) ## 9.25.0 diff --git a/Sources/Swift/Tools/LoadValidator.swift b/Sources/Swift/Tools/LoadValidator.swift index 1a6ba6ce91f..d916f3652a9 100644 --- a/Sources/Swift/Tools/LoadValidator.swift +++ b/Sources/Swift/Tools/LoadValidator.swift @@ -67,7 +67,7 @@ import MachO continue } if name.contains(self.targetClassName) { - var message = ["❌ Sentry SDK was loaded multiple times in the same binary ❌"] + var message = ["❌ Sentry SDK was loaded multiple times in the same address space ❌"] message.append("⚠️ This can cause undefined behavior, crashes, or duplicate reporting.") message.append("Ensure the SDK is linked only once, found `\(self.targetClassName)` class in image path: \(imageName)") SentrySDKLog.error(message.joined(separator: "\n")) diff --git a/Tests/DuplicatedSDKTest/Unit Tests/Unit_Tests.swift b/Tests/DuplicatedSDKTest/Unit Tests/Unit_Tests.swift index 658e0ef6793..98f11e2ad0d 100644 --- a/Tests/DuplicatedSDKTest/Unit Tests/Unit_Tests.swift +++ b/Tests/DuplicatedSDKTest/Unit Tests/Unit_Tests.swift @@ -12,7 +12,9 @@ final class TestLog: XCTestCase { stopCapturingOutput() super.tearDown() } - + + private let loadedMultipleTimesMessage = "Sentry SDK was loaded multiple times in the same address space" + func testDuplicatedLoadMessageOnSDKInit() throws { let expectation = XCTestExpectation(description: "Wait for duplicated SDK load message") @@ -38,7 +40,7 @@ final class TestLog: XCTestCase { let checkQueue = DispatchQueue(label: "message.check") checkQueue.async { while self.isCapturing { - if self.capturedOutput.contains("Sentry SDK was loaded multiple times in the same binary") { + if self.capturedOutput.contains(self.loadedMultipleTimesMessage) { expectation.fulfill() break } @@ -49,7 +51,7 @@ final class TestLog: XCTestCase { // This expectation is fulfilled immediately on a mac, but takes way longer on CI wait(for: [expectation], timeout: 600.0) - XCTAssertTrue(capturedOutput.contains("Sentry SDK was loaded multiple times in the same binary")) + XCTAssertTrue(capturedOutput.contains(loadedMultipleTimesMessage)) } private func startCapturingOutput() { diff --git a/Tests/SentryTests/Swift/Core/Tools/LoadValidatorTests.swift b/Tests/SentryTests/Swift/Core/Tools/LoadValidatorTests.swift index 73c7e6a9c02..21fafd4abd4 100644 --- a/Tests/SentryTests/Swift/Core/Tools/LoadValidatorTests.swift +++ b/Tests/SentryTests/Swift/Core/Tools/LoadValidatorTests.swift @@ -12,7 +12,9 @@ class LoadValidatorTests: XCTestCase { private var dispatchQueueWrapper: TestSentryDispatchQueueWrapper! private var defaultImageAddress: UInt64 = 0x1000 private var defaultImageSize: UInt64 = 0x20 - + + private let loadedMultipleTimesMessage = "❌ Sentry SDK was loaded multiple times in the same address space ❌" + // MARK: - Setup and Teardown override func setUp() { @@ -58,7 +60,7 @@ class LoadValidatorTests: XCTestCase { // Assert XCTAssertFalse(validationResult, "Validation should return false for system libraries") XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a system library") - XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) }) XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0) } @@ -86,7 +88,7 @@ class LoadValidatorTests: XCTestCase { // Assert XCTAssertFalse(validationResult, "Validation should return false for simulator libraries") XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a simulator library") - XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) }) XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0) } @@ -114,7 +116,7 @@ class LoadValidatorTests: XCTestCase { // Assert XCTAssertFalse(validationResult, "Validation should return false for cryptex simulator libraries") XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a cryptex simulator library") - XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) }) XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0) } @@ -142,7 +144,7 @@ class LoadValidatorTests: XCTestCase { // Assert XCTAssertFalse(validationResult, "Validation should return false for system libraries") XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a simulator library") - XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) }) XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0) } @@ -170,7 +172,7 @@ class LoadValidatorTests: XCTestCase { // Assert XCTAssertFalse(validationResult, "Validation should return false") XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should be called for an app binary") - XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) }) XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) } @@ -201,7 +203,7 @@ class LoadValidatorTests: XCTestCase { // Assert XCTAssertTrue(validationResult, "Validation should skip for app binary") XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should be called for an app binary") - XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times in the same binary ❌") }) + XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) }) XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("⚠️ This can cause undefined behavior, crashes, or duplicate reporting.") }) XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("Ensure the SDK is linked only once, found `SentryDependencyContainerSwiftHelper` class in image path: \(imageName)") }) XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) @@ -234,7 +236,7 @@ class LoadValidatorTests: XCTestCase { // Assert XCTAssertTrue(validationResult, "Validation should return true for app") XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should be called for an app binary") - XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times in the same binary ❌") }) + XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) }) XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("⚠️ This can cause undefined behavior, crashes, or duplicate reporting.") }) XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("Ensure the SDK is linked only once, found `SentryDependencyContainerSwiftHelper` class in image path: \(imageName)") }) XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) @@ -271,7 +273,7 @@ class LoadValidatorTests: XCTestCase { // Assert XCTAssertFalse(validationResult, "Validation should skip for sentry framework") XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should not be called for an app binary") - XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains(loadedMultipleTimesMessage) }) XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) } }