From 6e024eda887abaf731339afb5d7453ae89e8a812 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Thu, 23 Jan 2025 10:43:26 +0100 Subject: [PATCH] feat: Deserializing SentryMechanism (#4746) --- Sentry.xcodeproj/project.pbxproj | 4 ++ .../Codable/SentryMechanismCodable.swift | 31 ++++++++++++++++ .../Protocol/SentryMechanismTests.swift | 37 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 Sources/Swift/Protocol/Codable/SentryMechanismCodable.swift diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index cf365a07998..d88e448372e 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -143,6 +143,7 @@ 62F226B729A37C120038080D /* SentryBooleanSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F226B629A37C120038080D /* SentryBooleanSerialization.m */; }; 62F4DDA12C04CB9700588890 /* SentryBaggageSerializationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62F4DDA02C04CB9700588890 /* SentryBaggageSerializationTests.swift */; }; 62F70E932D4234B800634054 /* SentryMechanismMetaCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62F70E922D4234B100634054 /* SentryMechanismMetaCodable.swift */; }; + 62F70E952D423BCD00634054 /* SentryMechanismCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62F70E942D423BCA00634054 /* SentryMechanismCodable.swift */; }; 62FC18AF2C9D5FAC008803CD /* SentryANRTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FC18AE2C9D5FAC008803CD /* SentryANRTracker.swift */; }; 62FC69362BEDFF18002D3EF2 /* SentryLogExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FC69352BEDFF18002D3EF2 /* SentryLogExtensions.swift */; }; 630435FE1EBCA9D900C4D3FA /* SentryNSURLRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 630435FC1EBCA9D900C4D3FA /* SentryNSURLRequest.h */; }; @@ -1185,6 +1186,7 @@ 62F226B829A37C270038080D /* SentryBooleanSerialization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryBooleanSerialization.h; sourceTree = ""; }; 62F4DDA02C04CB9700588890 /* SentryBaggageSerializationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryBaggageSerializationTests.swift; sourceTree = ""; }; 62F70E922D4234B100634054 /* SentryMechanismMetaCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryMechanismMetaCodable.swift; sourceTree = ""; }; + 62F70E942D423BCA00634054 /* SentryMechanismCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryMechanismCodable.swift; sourceTree = ""; }; 62FC18AE2C9D5FAC008803CD /* SentryANRTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryANRTracker.swift; sourceTree = ""; }; 62FC69352BEDFF18002D3EF2 /* SentryLogExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogExtensions.swift; sourceTree = ""; }; 630435FC1EBCA9D900C4D3FA /* SentryNSURLRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryNSURLRequest.h; path = include/SentryNSURLRequest.h; sourceTree = ""; }; @@ -2194,6 +2196,7 @@ 623FD9012D3FA5DA00803EDA /* SentryFrameCodable.swift */, 6293F5742D422A8A002BC3BD /* SentryStacktraceCodable.swift */, 62F70E922D4234B100634054 /* SentryMechanismMetaCodable.swift */, + 62F70E942D423BCA00634054 /* SentryMechanismCodable.swift */, 620467AB2D3FFD1C0025F06C /* SentryNSErrorCodable.swift */, 620078712D38F00D0022CB67 /* SentryGeoCodable.swift */, 628094732D39584700B3F18B /* SentryUserCodable.swift */, @@ -4890,6 +4893,7 @@ 7DB3A687238EA75E00A2D442 /* SentryHttpTransport.m in Sources */, 63FE70D520DA4C1000CDBAE8 /* SentryCrashMonitor_NSException.m in Sources */, D80CD8D12B751442002F710B /* HTTPHeaderSanitizer.swift in Sources */, + 62F70E952D423BCD00634054 /* SentryMechanismCodable.swift in Sources */, 0AAE201E28ED9B9400D0CD80 /* SentryReachability.m in Sources */, 7B0A54282521C22C00A71716 /* SentryFrameRemover.m in Sources */, 7BC63F0A28081288009D9E37 /* SentrySwizzleWrapper.m in Sources */, diff --git a/Sources/Swift/Protocol/Codable/SentryMechanismCodable.swift b/Sources/Swift/Protocol/Codable/SentryMechanismCodable.swift new file mode 100644 index 00000000000..235e5506c93 --- /dev/null +++ b/Sources/Swift/Protocol/Codable/SentryMechanismCodable.swift @@ -0,0 +1,31 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +extension Mechanism: Decodable { + + enum CodingKeys: String, CodingKey { + case type + case handled + case synthetic + case desc = "description" + case data + case helpLink = "help_link" + case meta + } + + required convenience public init(from decoder: any Decoder) throws { + + let container = try decoder.container(keyedBy: CodingKeys.self) + + let type = try container.decode(String.self, forKey: .type) + self.init(type: type) + self.desc = try container.decodeIfPresent(String.self, forKey: .desc) + self.data = decodeArbitraryData { + try container.decodeIfPresent([String: ArbitraryData].self, forKey: .data) + } + self.handled = try container.decodeIfPresent(NSNumberDecodableWrapper.self, forKey: .handled)?.value + self.synthetic = try container.decodeIfPresent(NSNumberDecodableWrapper.self, forKey: .synthetic)?.value + self.helpLink = try container.decodeIfPresent(String.self, forKey: .helpLink) + self.meta = try container.decodeIfPresent(MechanismMeta.self, forKey: .meta) + } +} diff --git a/Tests/SentryTests/Protocol/SentryMechanismTests.swift b/Tests/SentryTests/Protocol/SentryMechanismTests.swift index 30cbf8bc439..432cd13bbb7 100644 --- a/Tests/SentryTests/Protocol/SentryMechanismTests.swift +++ b/Tests/SentryTests/Protocol/SentryMechanismTests.swift @@ -1,3 +1,4 @@ +@testable import Sentry import SentryTestUtils import XCTest @@ -43,4 +44,40 @@ class SentryMechanismTests: XCTestCase { func testSerialize_Bools() { SentryBooleanSerialization.test(Mechanism(type: ""), property: "handled") } + + func testDecode_WithAllProperties() throws { + // Arrange + let expected = TestData.mechanism + let data = try XCTUnwrap(SentrySerialization.data(withJSONObject: expected.serialize())) + + // Act + let decoded = try XCTUnwrap(decodeFromJSONData(jsonData: data) as Mechanism?) + + // Assert + XCTAssertEqual(expected.type, decoded.type) + XCTAssertEqual(expected.desc, decoded.desc) + XCTAssertEqual(expected.handled, decoded.handled) + XCTAssertEqual(expected.synthetic, decoded.synthetic) + XCTAssertEqual(expected.helpLink, decoded.helpLink) + + XCTAssertEqual(expected.meta?.error?.code, decoded.meta?.error?.code) + XCTAssertEqual(expected.meta?.error?.domain, decoded.meta?.error?.domain) + } + + func testDecode_WithAllPropertiesNil() throws { + // Arrange + let expected = Mechanism(type: "type") + let data = try XCTUnwrap(SentrySerialization.data(withJSONObject: expected.serialize())) + + // Act + let decoded = try XCTUnwrap(decodeFromJSONData(jsonData: data) as Mechanism?) + + // Assert + XCTAssertEqual(expected.type, decoded.type) + XCTAssertNil(decoded.desc) + XCTAssertNil(decoded.handled) + XCTAssertNil(decoded.synthetic) + XCTAssertNil(decoded.helpLink) + XCTAssertNil(decoded.meta?.error) + } }