diff --git a/.gitignore b/.gitignore
index def066fe7a..614098c887 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,6 @@
/.build
/.swiftpm
xcuserdata/
+
+# SPM-generated .xcodedproj
+Datadog.xcodeproj
diff --git a/Datadog.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Datadog.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000000..18d981003d
--- /dev/null
+++ b/Datadog.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/Datadog/Datadog.xcodeproj/project.pbxproj b/Datadog/Datadog.xcodeproj/project.pbxproj
index 9c30fc8ec8..2c6316d17f 100644
--- a/Datadog/Datadog.xcodeproj/project.pbxproj
+++ b/Datadog/Datadog.xcodeproj/project.pbxproj
@@ -87,6 +87,11 @@
61133C6E2423990D00786299 /* DatadogExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61133C472423990D00786299 /* DatadogExtensions.swift */; };
61133C702423993200786299 /* Datadog.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61133B82242393DE00786299 /* Datadog.framework */; };
61133C712423993200786299 /* Datadog.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 61133B82242393DE00786299 /* Datadog.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 616A62D024349BA700D1BE12 /* ObjcExceptionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 616A626924335D4900D1BE12 /* ObjcExceptionHandler.m */; };
+ 616A62D62434A3C500D1BE12 /* ObjcExceptionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 616A626A24335D4900D1BE12 /* ObjcExceptionHandler.h */; };
+ 61C363802436164B00C4D4E6 /* ObjcExceptionHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C3637F2436164B00C4D4E6 /* ObjcExceptionHandlerTests.swift */; };
+ 61C3638324361BE200C4D4E6 /* DatadogPrivateMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C3638224361BE200C4D4E6 /* DatadogPrivateMocks.swift */; };
+ 61C3638524361E9200C4D4E6 /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C3638424361E9200C4D4E6 /* Globals.swift */; };
9E08587A242519FF001A3583 /* NetworkPathMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E085879242519FF001A3583 /* NetworkPathMonitor.swift */; };
/* End PBXBuildFile section */
@@ -212,6 +217,12 @@
61133C452423990D00786299 /* SwiftExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftExtensions.swift; sourceTree = ""; };
61133C462423990D00786299 /* TestsDirectory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestsDirectory.swift; sourceTree = ""; };
61133C472423990D00786299 /* DatadogExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DatadogExtensions.swift; sourceTree = ""; };
+ 616A626924335D4900D1BE12 /* ObjcExceptionHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjcExceptionHandler.m; sourceTree = ""; };
+ 616A626A24335D4900D1BE12 /* ObjcExceptionHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjcExceptionHandler.h; sourceTree = ""; };
+ 616A62DF2434BEF200D1BE12 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; };
+ 61C3637F2436164B00C4D4E6 /* ObjcExceptionHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjcExceptionHandlerTests.swift; sourceTree = ""; };
+ 61C3638224361BE200C4D4E6 /* DatadogPrivateMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatadogPrivateMocks.swift; sourceTree = ""; };
+ 61C3638424361E9200C4D4E6 /* Globals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = ""; };
9E085879242519FF001A3583 /* NetworkPathMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkPathMonitor.swift; sourceTree = ""; };
/* End PBXFileReference section */
@@ -247,6 +258,7 @@
children = (
61133B9C2423979B00786299 /* Datadog */,
61133C082423983800786299 /* DatadogObjc */,
+ 616A626824335D4900D1BE12 /* DatadogPrivate */,
61133C122423990D00786299 /* DatadogTests */,
61133C07242397F200786299 /* TargetSupport */,
61133B83242393DE00786299 /* Products */,
@@ -363,6 +375,7 @@
61133BB72423979B00786299 /* Utils */ = {
isa = PBXGroup;
children = (
+ 61C3638424361E9200C4D4E6 /* Globals.swift */,
61133BB82423979B00786299 /* InternalLoggers.swift */,
61133BB92423979B00786299 /* CompilationConditions.swift */,
61133BBA2423979B00786299 /* SwiftExtensions.swift */,
@@ -455,6 +468,7 @@
children = (
61133C182423990D00786299 /* Datadog */,
61133C132423990D00786299 /* DatadogObjc */,
+ 61C3637E2436163400C4D4E6 /* DatadogPrivate */,
61133C422423990D00786299 /* Matchers */,
61133C442423990D00786299 /* Helpers */,
);
@@ -495,6 +509,7 @@
61133C1C2423990D00786299 /* UIKitMocks.swift */,
61133C1D2423990D00786299 /* DatadogObjcMocks.swift */,
61133C1F2423990D00786299 /* DatadogMocks.swift */,
+ 61C3638224361BE200C4D4E6 /* DatadogPrivateMocks.swift */,
61133C202423990D00786299 /* FoundationMocks.swift */,
);
path = Mocks;
@@ -615,6 +630,24 @@
name = Frameworks;
sourceTree = "";
};
+ 616A626824335D4900D1BE12 /* DatadogPrivate */ = {
+ isa = PBXGroup;
+ children = (
+ 616A62DF2434BEF200D1BE12 /* module.modulemap */,
+ 616A626A24335D4900D1BE12 /* ObjcExceptionHandler.h */,
+ 616A626924335D4900D1BE12 /* ObjcExceptionHandler.m */,
+ );
+ path = DatadogPrivate;
+ sourceTree = "";
+ };
+ 61C3637E2436163400C4D4E6 /* DatadogPrivate */ = {
+ isa = PBXGroup;
+ children = (
+ 61C3637F2436164B00C4D4E6 /* ObjcExceptionHandlerTests.swift */,
+ );
+ path = DatadogPrivate;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -623,6 +656,7 @@
buildActionMask = 2147483647;
files = (
61133B93242393DE00786299 /* Datadog.h in Headers */,
+ 616A62D62434A3C500D1BE12 /* ObjcExceptionHandler.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -795,6 +829,8 @@
61133BCC2423979B00786299 /* MobileDevice.swift in Sources */,
9E08587A242519FF001A3583 /* NetworkPathMonitor.swift in Sources */,
61133BCA2423979B00786299 /* EncodableValue.swift in Sources */,
+ 61C3638524361E9200C4D4E6 /* Globals.swift in Sources */,
+ 616A62D024349BA700D1BE12 /* ObjcExceptionHandler.m in Sources */,
61133BE62423979B00786299 /* LogSanitizer.swift in Sources */,
61133BDF2423979B00786299 /* SwiftExtensions.swift in Sources */,
61133BEA2423979B00786299 /* LogConsoleOutput.swift in Sources */,
@@ -836,9 +872,11 @@
61133C622423990D00786299 /* InternalLoggersTests.swift in Sources */,
61133C582423990D00786299 /* FileWriterTests.swift in Sources */,
61133C672423990D00786299 /* LogConsoleOutputTests.swift in Sources */,
+ 61C3638324361BE200C4D4E6 /* DatadogPrivateMocks.swift in Sources */,
61133C4C2423990D00786299 /* LogsMocks.swift in Sources */,
61133C542423990D00786299 /* NetworkConnectionInfoProviderTests.swift in Sources */,
61133C4A2423990D00786299 /* DDConfigurationTests.swift in Sources */,
+ 61C363802436164B00C4D4E6 /* ObjcExceptionHandlerTests.swift in Sources */,
61133C602423990D00786299 /* HTTPHeadersTests.swift in Sources */,
61133C632423990D00786299 /* DatadogConfigurationTests.swift in Sources */,
61133C572423990D00786299 /* FileReaderTests.swift in Sources */,
@@ -1042,6 +1080,7 @@
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = NO;
+ SWIFT_INCLUDE_PATHS = "$(SRCROOT)/DatadogPrivate";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@@ -1066,6 +1105,7 @@
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = NO;
+ SWIFT_INCLUDE_PATHS = "$(SRCROOT)/DatadogPrivate";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
diff --git a/Datadog/DatadogPrivate/ObjcExceptionHandler.h b/Datadog/DatadogPrivate/ObjcExceptionHandler.h
new file mode 100644
index 0000000000..bf5a9e3e75
--- /dev/null
+++ b/Datadog/DatadogPrivate/ObjcExceptionHandler.h
@@ -0,0 +1,18 @@
+/*
+* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
+* This product includes software developed at Datadog (https://www.datadoghq.com/).
+* Copyright 2019-2020 Datadog, Inc.
+*/
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ObjcExceptionHandler : NSObject
+
+- (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error
+ NS_SWIFT_NAME(rethrowToSwift(tryBlock:));
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Datadog/DatadogPrivate/ObjcExceptionHandler.m b/Datadog/DatadogPrivate/ObjcExceptionHandler.m
new file mode 100644
index 0000000000..61a0c28ea7
--- /dev/null
+++ b/Datadog/DatadogPrivate/ObjcExceptionHandler.m
@@ -0,0 +1,23 @@
+/*
+* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
+* This product includes software developed at Datadog (https://www.datadoghq.com/).
+* Copyright 2019-2020 Datadog, Inc.
+*/
+
+#import
+#import "ObjcExceptionHandler.h"
+
+@implementation ObjcExceptionHandler
+
+- (BOOL)catchException:(void(^)(void))tryBlock error:(__autoreleasing NSError **)error {
+ @try {
+ tryBlock();
+ return YES;
+ }
+ @catch (NSException *exception) {
+ *error = [[NSError alloc] initWithDomain:exception.name code:0 userInfo:exception.userInfo];
+ return NO;
+ }
+}
+
+@end
diff --git a/Datadog/DatadogPrivate/include/SPMHeaders.h b/Datadog/DatadogPrivate/include/SPMHeaders.h
new file mode 100644
index 0000000000..bc3e3ebc33
--- /dev/null
+++ b/Datadog/DatadogPrivate/include/SPMHeaders.h
@@ -0,0 +1,9 @@
+/*
+* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
+* This product includes software developed at Datadog (https://www.datadoghq.com/).
+* Copyright 2019-2020 Datadog, Inc.
+*/
+
+
+// List of headers for SPM to include for `_Datadog_Private` module.
+#import "../ObjcExceptionHandler.h"
diff --git a/Datadog/DatadogPrivate/module.modulemap b/Datadog/DatadogPrivate/module.modulemap
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/Datadog/DatadogPrivate/module.modulemap
@@ -0,0 +1 @@
+
diff --git a/Datadog/DatadogPrivate/module.private.modulemap b/Datadog/DatadogPrivate/module.private.modulemap
new file mode 100644
index 0000000000..c3ae441654
--- /dev/null
+++ b/Datadog/DatadogPrivate/module.private.modulemap
@@ -0,0 +1,14 @@
+/*
+ Module Map Language reference: https://clang.llvm.org/docs/Modules.html#module-map-language
+ */
+module _Datadog_Private {
+ /*
+ Each header exported from here must be also exposed to each dependency manager separately:
+ - For Carthage, add it to "Datadog > Build Phases > Headers > Project".
+ - For SPM, import it from `include/SPMHeaders.h`.
+ - Cocoapods `.podspec` is already configured to read this `module.modulemap`.
+ */
+
+ header "ObjcExceptionHandler.h"
+ export *
+}
diff --git a/DatadogSDK.podspec b/DatadogSDK.podspec
index 185dca817c..92a82db894 100644
--- a/DatadogSDK.podspec
+++ b/DatadogSDK.podspec
@@ -16,7 +16,11 @@ Pod::Spec.new do |s|
s.swift_version = '5.1'
s.ios.deployment_target = '11.0'
- s.source = { :git => 'https://github.com/DataDog/dd-sdk-ios.git', :tag => s.version.to_s }
+ s.source = { :git => "https://github.com/DataDog/dd-sdk-ios.git", :tag => s.version.to_s }
- s.source_files = "Sources/Datadog/**/*.swift"
+ s.source_files = "Sources/Datadog/**/*.swift", "Datadog/DatadogPrivate/*.m"
+ s.preserve_paths = "Datadog/DatadogPrivate/*.{modulemap,h}"
+ s.pod_target_xcconfig = {
+ "SWIFT_INCLUDE_PATHS" => "$(PODS_ROOT)/DatadogSDK/Datadog/DatadogPrivate/** $(PODS_TARGET_SRCROOT)/DatadogSDK/Datadog/DatadogPrivate/**"
+ }
end
diff --git a/Package.swift b/Package.swift
index 6abe78fdaf..38502fb642 100644
--- a/Package.swift
+++ b/Package.swift
@@ -20,10 +20,14 @@ let package = Package(
targets: [
.target(
name: "Datadog",
- dependencies: []),
+ dependencies: ["_Datadog_Private"]),
.target(
name: "DatadogObjc",
dependencies: ["Datadog"]),
+ .target(
+ name: "_Datadog_Private",
+ path: "Datadog/DatadogPrivate"
+ ),
.testTarget(
name: "DatadogTests",
dependencies: ["Datadog", "DatadogObjc"]),
diff --git a/Sources/Datadog/Core/Persistence/FileWriter.swift b/Sources/Datadog/Core/Persistence/FileWriter.swift
index 03e3c24cc6..e20f11c2ea 100644
--- a/Sources/Datadog/Core/Persistence/FileWriter.swift
+++ b/Sources/Datadog/Core/Persistence/FileWriter.swift
@@ -51,13 +51,13 @@ internal final class FileWriter {
let file = try orchestrator.getWritableFile(writeSize: UInt64(data.count))
if try file.size() == 0 {
- try file.append { write in
- write(data)
+ try file.append { (write: (Data) throws -> Void) in
+ try write(data)
}
} else {
try file.append { write in
- write(commaSeparatorData)
- write(data)
+ try write(commaSeparatorData)
+ try write(data)
}
}
} catch {
diff --git a/Sources/Datadog/Core/Persistence/Files/File.swift b/Sources/Datadog/Core/Persistence/Files/File.swift
index 3fcf2cc24b..70e05b9551 100644
--- a/Sources/Datadog/Core/Persistence/Files/File.swift
+++ b/Sources/Datadog/Core/Persistence/Files/File.swift
@@ -5,6 +5,7 @@
*/
import Foundation
+import _Datadog_Private
/// Provides convenient interface for reading metadata and appending data to the file.
internal protocol WritableFile {
@@ -15,7 +16,7 @@ internal protocol WritableFile {
func size() throws -> UInt64
/// Synchronously appends given data at the end of this file.
- func append(transaction: ((Data) -> Void) -> Void) throws
+ func append(transaction: ((Data) throws -> Void) throws -> Void) throws
}
/// Provides convenient interface for reading contents and metadata of the file.
@@ -42,27 +43,24 @@ internal struct File: WritableFile, ReadableFile {
}
/// Appends given data at the end of this file.
- func append(transaction: ((Data) -> Void) -> Void) throws {
+ func append(transaction: ((Data) throws -> Void) throws -> Void) throws {
let fileHandle = try FileHandle(forWritingTo: url)
defer { fileHandle.closeFile() }
- fileHandle.seekToEndOfFile()
+
+ try objcExceptionHandler.rethrowToSwift {
+ fileHandle.seekToEndOfFile()
+ }
// Writes given data at the end of the file.
- func appendData(_ data: Data) {
- /*
- Apple documentation https://developer.apple.com/documentation/foundation/filehandle/1410936-write says
- that `fileHandle.write()` raises an exception if no free space is left on the file system,
- or if any other writing error occurs. Those are unchecked exceptions impossible to handle in Swift.
-
- It was already escalated to Apple in Swift open source project discussion:
- https://forums.swift.org/t/pitch-replacement-for-filehandle/5177
-
- Until better replacement is provided by Apple, the SDK sticks to this API. To mitigate the risk of
- crashing client applications, other precautions are implemented carefuly.
- */
- fileHandle.write(data)
+ func appendData(_ data: Data) throws {
+ try objcExceptionHandler.rethrowToSwift {
+ fileHandle.write(data)
+ }
+ }
+
+ try transaction { chunkOfData in
+ try appendData(chunkOfData)
}
- transaction(appendData)
}
func read() throws -> Data {
diff --git a/Sources/Datadog/Logs/LogOutputs/LogConsoleOutput.swift b/Sources/Datadog/Logs/LogOutputs/LogConsoleOutput.swift
index f5a3802022..b54fefb1ec 100644
--- a/Sources/Datadog/Logs/LogOutputs/LogConsoleOutput.swift
+++ b/Sources/Datadog/Logs/LogOutputs/LogConsoleOutput.swift
@@ -11,11 +11,6 @@ internal protocol ConsoleLogFormatter {
func format(log: Log) -> String
}
-/// Function printing `String` content to console.
-internal var consolePrint: (String) -> Void = { content in
- print(content)
-}
-
/// `LogOutput` which prints logs to console.
internal struct LogConsoleOutput: LogOutput {
/// Time formatter used for `.short` output format.
diff --git a/Sources/Datadog/Utils/Globals.swift b/Sources/Datadog/Utils/Globals.swift
new file mode 100644
index 0000000000..a9f1e68bbd
--- /dev/null
+++ b/Sources/Datadog/Utils/Globals.swift
@@ -0,0 +1,15 @@
+/*
+ * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
+ * This product includes software developed at Datadog (https://www.datadoghq.com/).
+ * Copyright 2019-2020 Datadog, Inc.
+ */
+
+import _Datadog_Private
+
+/// Function printing `String` content to console.
+internal var consolePrint: (String) -> Void = { content in
+ print(content)
+}
+
+/// Exception handler rethrowing `NSExceptions` to Swift `NSError`.
+internal var objcExceptionHandler = ObjcExceptionHandler()
diff --git a/Tests/DatadogTests/Datadog/Core/Persistence/FileReaderTests.swift b/Tests/DatadogTests/Datadog/Core/Persistence/FileReaderTests.swift
index d5c859d60c..ab3ea0a9a3 100644
--- a/Tests/DatadogTests/Datadog/Core/Persistence/FileReaderTests.swift
+++ b/Tests/DatadogTests/Datadog/Core/Persistence/FileReaderTests.swift
@@ -27,7 +27,7 @@ class FileReaderTests: XCTestCase {
)
_ = try temporaryDirectory
.createFile(named: .mockAnyFileName())
- .append { write in write("ABCD".utf8Data) }
+ .append { write in try write("ABCD".utf8Data) }
let batch = reader.readNextBatch()
@@ -46,13 +46,13 @@ class FileReaderTests: XCTestCase {
queue: queue
)
let file1 = try temporaryDirectory.createFile(named: dateProvider.currentDate().toFileName)
- try file1.append { write in write("1".utf8Data) }
+ try file1.append { write in try write("1".utf8Data) }
let file2 = try temporaryDirectory.createFile(named: dateProvider.currentDate().toFileName)
- try file2.append { write in write("2".utf8Data) }
+ try file2.append { write in try write("2".utf8Data) }
let file3 = try temporaryDirectory.createFile(named: dateProvider.currentDate().toFileName)
- try file3.append { write in write("3".utf8Data) }
+ try file3.append { write in try write("3".utf8Data) }
var batch: Batch
batch = try reader.readNextBatch().unwrapOrThrow()
diff --git a/Tests/DatadogTests/Datadog/Core/Persistence/FileWriterTests.swift b/Tests/DatadogTests/Datadog/Core/Persistence/FileWriterTests.swift
index 7db124d515..a2d03f8f67 100644
--- a/Tests/DatadogTests/Datadog/Core/Persistence/FileWriterTests.swift
+++ b/Tests/DatadogTests/Datadog/Core/Persistence/FileWriterTests.swift
@@ -63,7 +63,7 @@ class FileWriterTests: XCTestCase {
XCTAssertEqual(try temporaryDirectory.files()[0].read(), #"{"key1":"value1"}"#.utf8Data) // same content as before
}
- func testGivenErrorVerbosity_whenLogCannotBeEncoded_itPrintsError() throws {
+ func testGivenErrorVerbosity_whenDataCannotBeEncoded_itPrintsError() throws {
let expectation = self.expectation(description: "write completed")
let previousUserLogger = userLogger
defer { userLogger = previousUserLogger }
@@ -86,6 +86,32 @@ class FileWriterTests: XCTestCase {
XCTAssertEqual(output.recordedLog?.message, "🔥 Failed to write log: failed to encode `FailingEncodable`.")
}
+ func testGivenErrorVerbosity_whenIOExceptionIsThrown_itPrintsError() throws {
+ let expectation = self.expectation(description: "write completed")
+ let previousUserLogger = userLogger
+ defer { userLogger = previousUserLogger }
+ let previousObjcExceptionHandler = objcExceptionHandler
+ defer { objcExceptionHandler = previousObjcExceptionHandler }
+
+ let output = LogOutputMock()
+ userLogger = Logger(logOutput: output, identifier: "sdk-user")
+ objcExceptionHandler = ObjcExceptionHandlerMock(throwingError: ErrorMock("I/O exception"))
+
+ let writer = FileWriter(
+ orchestrator: .mockWriteToSingleFile(in: temporaryDirectory),
+ queue: queue,
+ maxWriteSize: .max
+ )
+
+ writer.write(value: ["whatever"])
+
+ waitForWritesCompletion(on: queue, thenFulfill: expectation)
+ waitForExpectations(timeout: 1, handler: nil)
+
+ XCTAssertEqual(output.recordedLog?.level, .error)
+ XCTAssertEqual(output.recordedLog?.message, "🔥 Failed to write log: I/O exception")
+ }
+
private func waitForWritesCompletion(on queue: DispatchQueue, thenFulfill expectation: XCTestExpectation) {
queue.async { expectation.fulfill() }
}
diff --git a/Tests/DatadogTests/Datadog/Core/Persistence/Files/FileTests.swift b/Tests/DatadogTests/Datadog/Core/Persistence/Files/FileTests.swift
index 9d6d31f049..9f50b0a258 100644
--- a/Tests/DatadogTests/Datadog/Core/Persistence/Files/FileTests.swift
+++ b/Tests/DatadogTests/Datadog/Core/Persistence/Files/FileTests.swift
@@ -24,7 +24,7 @@ class FileTests: XCTestCase {
let file = try temporaryDirectory.createFile(named: "file")
try file.append { write in
- write(Data([0x41, 0x41, 0x41, 0x41, 0x41])) // 5 bytes
+ try write(Data([0x41, 0x41, 0x41, 0x41, 0x41])) // 5 bytes
}
XCTAssertEqual(
@@ -33,8 +33,8 @@ class FileTests: XCTestCase {
)
try file.append { write in
- write(Data([0x42, 0x42, 0x42, 0x42, 0x42])) // 5 bytes
- write(Data([0x41, 0x41, 0x41, 0x41, 0x41])) // 5 bytes
+ try write(Data([0x42, 0x42, 0x42, 0x42, 0x42])) // 5 bytes
+ try write(Data([0x41, 0x41, 0x41, 0x41, 0x41])) // 5 bytes
}
XCTAssertEqual(
@@ -51,7 +51,7 @@ class FileTests: XCTestCase {
func testItReadsDataFromFile() throws {
let file = try temporaryDirectory.createFile(named: "file")
- try file.append { write in write("Hello 👋".utf8Data) }
+ try file.append { write in try write("Hello 👋".utf8Data) }
XCTAssertEqual(try file.read().utf8String, "Hello 👋")
}
@@ -68,10 +68,10 @@ class FileTests: XCTestCase {
func testItReturnsFileSize() throws {
let file = try temporaryDirectory.createFile(named: "file")
- try file.append { write in write(.mock(ofSize: 5)) }
+ try file.append { write in try write(.mock(ofSize: 5)) }
XCTAssertEqual(try file.size(), 5)
- try file.append { write in write(.mock(ofSize: 10)) }
+ try file.append { write in try write(.mock(ofSize: 10)) }
XCTAssertEqual(try file.size(), 15)
}
}
diff --git a/Tests/DatadogTests/Datadog/Core/Persistence/FilesOrchestratorTests.swift b/Tests/DatadogTests/Datadog/Core/Persistence/FilesOrchestratorTests.swift
index 4dc6f719fb..988621933c 100644
--- a/Tests/DatadogTests/Datadog/Core/Persistence/FilesOrchestratorTests.swift
+++ b/Tests/DatadogTests/Datadog/Core/Persistence/FilesOrchestratorTests.swift
@@ -73,7 +73,7 @@ class FilesOrchestratorTests: XCTestCase {
let chunkedData: [Data] = .mockChunksOf(totalSize: defaultWriteConditions.maxFileSize)
let file1 = try orchestrator.getWritableFile(writeSize: defaultWriteConditions.maxFileSize)
- try file1.append { write in chunkedData.forEach { chunk in write(chunk) } }
+ try file1.append { write in try chunkedData.forEach { chunk in try write(chunk) } }
let file2 = try orchestrator.getWritableFile(writeSize: 1)
XCTAssertNotEqual(file1.name, file2.name)
@@ -132,15 +132,15 @@ class FilesOrchestratorTests: XCTestCase {
// write 1MB to first file (1MB of directory size in total)
let file1 = try orchestrator.getWritableFile(writeSize: oneMB)
- try file1.append { write in write(.mock(ofSize: oneMB)) }
+ try file1.append { write in try write(.mock(ofSize: oneMB)) }
// write 1MB to second file (2MB of directory size in total)
let file2 = try orchestrator.getWritableFile(writeSize: oneMB)
- try file2.append { write in write(.mock(ofSize: oneMB)) }
+ try file2.append { write in try write(.mock(ofSize: oneMB)) }
// write 1MB to third file (3MB of directory size in total)
let file3 = try orchestrator.getWritableFile(writeSize: oneMB + 1) // +1 byte to exceed the limit
- try file3.append { write in write(.mock(ofSize: oneMB + 1)) }
+ try file3.append { write in try write(.mock(ofSize: oneMB + 1)) }
XCTAssertEqual(try temporaryDirectory.files().count, 3)
@@ -149,7 +149,7 @@ class FilesOrchestratorTests: XCTestCase {
let file4 = try orchestrator.getWritableFile(writeSize: oneMB)
XCTAssertEqual(try temporaryDirectory.files().count, 3)
XCTAssertNil(try? temporaryDirectory.file(named: file1.name))
- try file4.append { write in write(.mock(ofSize: oneMB + 1)) }
+ try file4.append { write in try write(.mock(ofSize: oneMB + 1)) }
_ = try orchestrator.getWritableFile(writeSize: oneMB)
XCTAssertEqual(try temporaryDirectory.files().count, 3)
diff --git a/Tests/DatadogTests/Datadog/Mocks/DatadogPrivateMocks.swift b/Tests/DatadogTests/Datadog/Mocks/DatadogPrivateMocks.swift
new file mode 100644
index 0000000000..6480151157
--- /dev/null
+++ b/Tests/DatadogTests/Datadog/Mocks/DatadogPrivateMocks.swift
@@ -0,0 +1,23 @@
+/*
+ * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
+ * This product includes software developed at Datadog (https://www.datadoghq.com/).
+ * Copyright 2019-2020 Datadog, Inc.
+ */
+
+import _Datadog_Private
+
+/*
+ A collection of mocks for `_Datadog_Private` module.
+ */
+
+class ObjcExceptionHandlerMock: ObjcExceptionHandler {
+ let error: Error
+
+ init(throwingError: Error) {
+ self.error = throwingError
+ }
+
+ override func rethrowToSwift(tryBlock: @escaping () -> Void) throws {
+ throw error
+ }
+}
diff --git a/Tests/DatadogTests/DatadogPrivate/ObjcExceptionHandlerTests.swift b/Tests/DatadogTests/DatadogPrivate/ObjcExceptionHandlerTests.swift
new file mode 100644
index 0000000000..dcbb1cc88b
--- /dev/null
+++ b/Tests/DatadogTests/DatadogPrivate/ObjcExceptionHandlerTests.swift
@@ -0,0 +1,32 @@
+/*
+ * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
+ * This product includes software developed at Datadog (https://www.datadoghq.com/).
+ * Copyright 2019-2020 Datadog, Inc.
+ */
+
+import XCTest
+import _Datadog_Private
+
+class ObjcExceptionHandlerTests: XCTestCase {
+ private let exceptionHandler = ObjcExceptionHandler()
+
+ func testGivenNonThrowingCode_itDoesNotThrow() throws {
+ var counter = 0
+ try exceptionHandler.rethrowToSwift { counter += 1 }
+ XCTAssertEqual(counter, 1)
+ }
+
+ func testGivenThrowingCode_itThrowsNSErrorToSwift() {
+ let nsException = NSException(
+ name: NSExceptionName(rawValue: "name"),
+ reason: "reason",
+ userInfo: ["user-info": "some"]
+ )
+
+ XCTAssertThrowsError(try exceptionHandler.rethrowToSwift { nsException.raise() }) { error in
+ XCTAssertEqual((error as NSError).domain, "name")
+ XCTAssertEqual((error as NSError).code, 0)
+ XCTAssertEqual((error as NSError).userInfo as? [String: String], ["user-info": "some"])
+ }
+ }
+}
diff --git a/instrumented-tests/Benchmark/Benchmark.xcodeproj/project.pbxproj b/instrumented-tests/Benchmark/Benchmark.xcodeproj/project.pbxproj
index e2da86bcdf..2e39a28e60 100644
--- a/instrumented-tests/Benchmark/Benchmark.xcodeproj/project.pbxproj
+++ b/instrumented-tests/Benchmark/Benchmark.xcodeproj/project.pbxproj
@@ -17,6 +17,8 @@
61999EC924071A760094866C /* LoggingBenchmarkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61999EC824071A760094866C /* LoggingBenchmarkTests.swift */; };
61AEBF062423D2AE00A8CB51 /* Datadog.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61AEBF052423D2AE00A8CB51 /* Datadog.framework */; };
61AEBF072423D2AE00A8CB51 /* Datadog.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 61AEBF052423D2AE00A8CB51 /* Datadog.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 61C363CB2436674B00C4D4E6 /* _Datadog_Private.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61C363C22436650C00C4D4E6 /* _Datadog_Private.framework */; };
+ 61C363CC2436674B00C4D4E6 /* _Datadog_Private.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 61C363C22436650C00C4D4E6 /* _Datadog_Private.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -37,6 +39,7 @@
dstSubfolderSpec = 10;
files = (
61AEBF072423D2AE00A8CB51 /* Datadog.framework in Embed Frameworks */,
+ 61C363CC2436674B00C4D4E6 /* _Datadog_Private.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -57,6 +60,7 @@
613D7F5C240938560013B7DF /* LoggingIOBenchmarkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingIOBenchmarkTests.swift; sourceTree = ""; };
61999EC824071A760094866C /* LoggingBenchmarkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingBenchmarkTests.swift; sourceTree = ""; };
61AEBF052423D2AE00A8CB51 /* Datadog.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Datadog.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 61C363C22436650C00C4D4E6 /* _Datadog_Private.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = _Datadog_Private.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -65,6 +69,7 @@
buildActionMask = 2147483647;
files = (
61AEBF062423D2AE00A8CB51 /* Datadog.framework in Frameworks */,
+ 61C363CB2436674B00C4D4E6 /* _Datadog_Private.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -141,6 +146,7 @@
61800F732405411400420E0D /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 61C363C22436650C00C4D4E6 /* _Datadog_Private.framework */,
61AEBF052423D2AE00A8CB51 /* Datadog.framework */,
);
name = Frameworks;
@@ -493,6 +499,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
+ SWIFT_INCLUDE_PATHS = "$(SRCROOT)/../../Datadog/DatadogPrivate";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Benchmark.app/Benchmark";
@@ -520,6 +527,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
+ SWIFT_INCLUDE_PATHS = "$(SRCROOT)/../../Datadog/DatadogPrivate";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Benchmark.app/Benchmark";