diff --git a/Sources/Sentry/include/SentryFileManager.h b/Sources/Sentry/include/SentryFileManager.h index b66a8f81e5..1bdfef4b0b 100644 --- a/Sources/Sentry/include/SentryFileManager.h +++ b/Sources/Sentry/include/SentryFileManager.h @@ -15,6 +15,12 @@ NS_ASSUME_NONNULL_BEGIN @class SentryOptions; @class SentrySession; +#if SENTRY_TEST || SENTRY_TEST_CI +BOOL isErrorPathTooLong(NSError *error); + +BOOL createDirectoryIfNotExists(NSString *path, NSError **error); +#endif // SENTRY_TEST || SENTRY_TEST_CI + NS_SWIFT_NAME(SentryFileManager) @interface SentryFileManager : NSObject SENTRY_NO_INIT diff --git a/Tests/SentryTests/Helper/SentryFileManagerTests.swift b/Tests/SentryTests/Helper/SentryFileManagerTests.swift index 81df321cae..c07f024a32 100644 --- a/Tests/SentryTests/Helper/SentryFileManagerTests.swift +++ b/Tests/SentryTests/Helper/SentryFileManagerTests.swift @@ -1,3 +1,5 @@ +// swiftlint:disable file_length + @testable import Sentry import SentryTestUtils import XCTest @@ -723,6 +725,132 @@ class SentryFileManagerTests: XCTestCase { try "garbage".write(to: URL(fileURLWithPath: sut.timezoneOffsetFilePath), atomically: true, encoding: .utf8) XCTAssertNil(sut.readTimezoneOffset()) } + + func testIsErrorPathTooLong_underlyingErrorsAvailableAndMultipleErrorsGiven_shouldUseErrorInUserInfo() throws { + // -- Arrange -- + guard #available(macOS 11.0, iOS 14.5, watchOS 7.4, tvOS 14.5, *) else { + throw XCTSkip("This test is only for macOS 11 and above") + } + // When accessing via `underlyingErrors`, the first result is the error set with `NSUnderlyingErrorKey`. + // This test asserts if that behavior changes. + let error = NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [ + NSMultipleUnderlyingErrorsKey: [ + NSError(domain: NSCocoaErrorDomain, code: 2, userInfo: nil) + ], + NSUnderlyingErrorKey: NSError(domain: NSPOSIXErrorDomain, code: Int(ENAMETOOLONG), userInfo: nil) + ]) + // -- Act -- + let result = isErrorPathTooLong(error) + // -- Assert -- + XCTAssertTrue(result) + } + + func testIsErrorPathTooLong_underlyingErrorsAvailableAndMultipleErrorsEmpty_shouldUseErrorInUserInfo() throws { + // -- Arrange -- + guard #available(macOS 11.0, iOS 14.5, watchOS 7.4, tvOS 14.5, *) else { + throw XCTSkip("Test is disabled for this OS version") + } + // When accessing via `underlyingErrors`, the first result is the error set with `NSUnderlyingErrorKey`. + // This test asserts if that behavior changes. + let error = NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [ + NSMultipleUnderlyingErrorsKey: [], + NSUnderlyingErrorKey: NSError(domain: NSPOSIXErrorDomain, code: Int(ENAMETOOLONG), userInfo: nil) + ]) + // -- Act -- + let result = isErrorPathTooLong(error) + // -- Assert -- + XCTAssertTrue(result) + } + + func testIsErrorPathTooLong_underlyingErrorsAvailableAndMultipleErrorsNotSet_shouldUseErrorInUserInfo() throws { + // -- Arrange -- + guard #available(macOS 11.0, iOS 14.5, watchOS 7.4, tvOS 14.5, *) else { + throw XCTSkip("Test is disabled for this OS version") + } + // When accessing via `underlyingErrors`, the first result is the error set with `NSUnderlyingErrorKey`. + // This test asserts if that behavior changes. + let error = NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [ + NSUnderlyingErrorKey: NSError(domain: NSPOSIXErrorDomain, code: Int(ENAMETOOLONG), userInfo: nil) + ]) + // -- Act -- + let result = isErrorPathTooLong(error) + // -- Assert -- + XCTAssertTrue(result) + } + + func testIsErrorPathTooLong_underlyingErrorsAvailableAndOnlyMultipleErrorsGiven_shouldUseErrorFirstError() throws { + // -- Arrange -- + guard #available(macOS 11.0, iOS 14.5, watchOS 7.4, tvOS 14.5, *) else { + throw XCTSkip("Test is disabled for this OS version") + } + // When accessing via `underlyingErrors`, the first result is the error set with `NSUnderlyingErrorKey`. + // This test asserts if that behavior changes. + let error = NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [ + NSMultipleUnderlyingErrorsKey: [ + NSError(domain: NSPOSIXErrorDomain, code: Int(ENAMETOOLONG), userInfo: nil), + NSError(domain: NSCocoaErrorDomain, code: 2, userInfo: nil) + ] + ]) + // -- Act -- + let result = isErrorPathTooLong(error) + // -- Assert -- + XCTAssertTrue(result) + } + + func testIsErrorPathTooLong_underlyingErrorsNotAvailableAndErrorNotInUserInfo_shouldNotCheckError() throws { + // -- Arrange -- + guard #unavailable(macOS 11.0, iOS 14.5, watchOS 7.4, tvOS 14.5) else { + throw XCTSkip("Test is disabled for this OS version") + } + // When accessing via `underlyingErrors`, the first result is the error set with `NSUnderlyingErrorKey`. + // This test asserts if that behavior changes. + let error = NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [:]) + // -- Act -- + let result = isErrorPathTooLong(error) + // -- Assert -- + XCTAssertFalse(result) + } + + func testIsErrorPathTooLong_underlyingErrorsNotAvailableAndNonErrorInUserInfo_shouldNotCheckError() throws { + // -- Arrange -- + guard #unavailable(macOS 11.0, iOS 14.5, watchOS 7.4, tvOS 14.5) else { + throw XCTSkip("Test is disabled for this OS version") + } + // When accessing via `underlyingErrors`, the first result is the error set with `NSUnderlyingErrorKey`. + // This test asserts if that behavior changes. + let error = NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [ + NSUnderlyingErrorKey: "This is not an error" + ]) + // -- Act -- + let result = isErrorPathTooLong(error) + // -- Assert -- + XCTAssertFalse(result) + } + + func testIsErrorPathTooLong_underlyingErrorsNotAvailableAndErrorInUserInfo_shouldNotCheckError() throws { + // -- Arrange -- + guard #unavailable(macOS 11.0, iOS 14.5, watchOS 7.4, tvOS 14.5) else { + throw XCTSkip("Test is disabled for this OS version") + } + // When accessing via `underlyingErrors`, the first result is the error set with `NSUnderlyingErrorKey`. + // This test asserts if that behavior changes. + let error = NSError(domain: NSCocoaErrorDomain, code: 1, userInfo: [ + NSUnderlyingErrorKey: NSError(domain: NSPOSIXErrorDomain, code: Int(ENAMETOOLONG), userInfo: nil) + ]) + // -- Act -- + let result = isErrorPathTooLong(error) + // -- Assert -- + XCTAssertTrue(result) + } + + func testIsErrrorPathTooLong_errorIsEnameTooLong_shouldReturnTrue() throws { + // -- Arrange -- + let error = NSError(domain: NSPOSIXErrorDomain, code: Int(ENAMETOOLONG), userInfo: nil) + // -- Act -- + let result = isErrorPathTooLong(error) + // -- Assert -- + XCTAssertTrue(result) + } } #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst)