diff --git a/Sources/Clickstream/Dependency/Clickstream/ClickstreamContext.swift b/Sources/Clickstream/Dependency/Clickstream/ClickstreamContext.swift index 3d34cef..d6adc76 100644 --- a/Sources/Clickstream/Dependency/Clickstream/ClickstreamContext.swift +++ b/Sources/Clickstream/Dependency/Clickstream/ClickstreamContext.swift @@ -124,7 +124,7 @@ extension UserDefaults: UserDefaultsBehaviour { self.globalAttributes = globalAttributes return self } - + public func withInitialGlobalAttributesObjc(_ globalAttributes: NSDictionary) -> ClickstreamConfiguration { self.globalAttributes = ClickstreamObjc.getAttributes(globalAttributes) return self diff --git a/Sources/Clickstream/Dependency/Clickstream/Event/Event.swift b/Sources/Clickstream/Dependency/Clickstream/Event/Event.swift index 4fe2e1e..928caeb 100644 --- a/Sources/Clickstream/Dependency/Clickstream/Event/Event.swift +++ b/Sources/Clickstream/Dependency/Clickstream/Event/Event.swift @@ -93,6 +93,7 @@ enum Event { static let ATTRIBUTE_NAME_INVALID = 2_002 static let ATTRIBUTE_VALUE_LENGTH_EXCEED = 2_003 static let ATTRIBUTE_SIZE_EXCEED = 2_004 + static let ATTRIBUTE_VALUE_NOT_FINITE = 2_005 static let USER_ATTRIBUTE_SIZE_EXCEED = 3_001 static let USER_ATTRIBUTE_NAME_LENGTH_EXCEED = 3_002 static let USER_ATTRIBUTE_NAME_INVALID = 3_003 diff --git a/Sources/Clickstream/Dependency/Clickstream/Event/EventChecker.swift b/Sources/Clickstream/Dependency/Clickstream/Event/EventChecker.swift index 4e85c5c..1317db4 100644 --- a/Sources/Clickstream/Dependency/Clickstream/Event/EventChecker.swift +++ b/Sources/Clickstream/Dependency/Clickstream/Event/EventChecker.swift @@ -82,6 +82,14 @@ class EventChecker { error.errorCode = Event.ErrorCode.ATTRIBUTE_VALUE_LENGTH_EXCEED error.errorMessage = getErrorMessage(errorString) } + } else if !checkFinite(value) { + errorMsg = """ + the value for attribute : \(key), is not finite\ + and the attribute will not be recorded + """ + let errorString = "the value for attribute name: \(key) is not finite" + error.errorCode = Event.ErrorCode.ATTRIBUTE_VALUE_NOT_FINITE + error.errorMessage = getErrorMessage(errorString) } if errorMsg != nil { log.warn(errorMsg!) @@ -89,6 +97,20 @@ class EventChecker { return error } + /// Check the Dboule or Decimal whether is finite + /// - Parameters: + /// - value: attribute value + /// - Returns: the isFinite boolean result + static func checkFinite(_ value: Any) -> Bool { + if let value = value as? Double, !value.isFinite { + return false + } + if let value = value as? Decimal, !value.isFinite { + return false + } + return true + } + /// Check the user attribute error. /// - Parameters: /// - currentNumber: current attribute number diff --git a/Tests/ClickstreamTests/Clickstream/ClickstreamEventTest.swift b/Tests/ClickstreamTests/Clickstream/ClickstreamEventTest.swift index c5c5391..b2bb134 100644 --- a/Tests/ClickstreamTests/Clickstream/ClickstreamEventTest.swift +++ b/Tests/ClickstreamTests/Clickstream/ClickstreamEventTest.swift @@ -63,6 +63,24 @@ class ClickstreamEventTest: XCTestCase { XCTAssertTrue(errorValueString.contains("testKey")) } + func testAddAttributeErrorForDoubleValueisNotFinite() { + clickstreamEvent.addAttribute(Double.infinity, forKey: "testKey") + XCTAssertNil(clickstreamEvent.attribute(forKey: "testKey")) + let errorCode = clickstreamEvent.attribute(forKey: Event.ReservedAttribute.ERROR_CODE) as! Int + let errorValueString = clickstreamEvent.attribute(forKey: Event.ReservedAttribute.ERROR_MESSAGE) as! String + XCTAssertEqual(Event.ErrorCode.ATTRIBUTE_VALUE_NOT_FINITE, errorCode) + XCTAssertTrue(errorValueString.contains("testKey")) + } + + func testAddAttributeErrorForDecimalValueisNotFinite() { + clickstreamEvent.addAttribute(Decimal.nan, forKey: "testKey") + XCTAssertNil(clickstreamEvent.attribute(forKey: "testKey")) + let errorCode = clickstreamEvent.attribute(forKey: Event.ReservedAttribute.ERROR_CODE) as! Int + let errorValueString = clickstreamEvent.attribute(forKey: Event.ReservedAttribute.ERROR_MESSAGE) as! String + XCTAssertEqual(Event.ErrorCode.ATTRIBUTE_VALUE_NOT_FINITE, errorCode) + XCTAssertTrue(errorValueString.contains("testKey")) + } + func testAddItemWithCustomAttributeScuccess() { let item: ClickstreamAttribute = [ ClickstreamAnalytics.Item.ITEM_ID: 123, diff --git a/Tests/ClickstreamTests/EventCheckerTest.swift b/Tests/ClickstreamTests/EventCheckerTest.swift index 9e351b4..a524ff1 100644 --- a/Tests/ClickstreamTests/EventCheckerTest.swift +++ b/Tests/ClickstreamTests/EventCheckerTest.swift @@ -25,4 +25,27 @@ class EventCheckerTest: XCTestCase { XCTAssertFalse(EventChecker.checkEventType(eventType: "9Abc").errorCode == noError) XCTAssertTrue(EventChecker.checkEventType(eventType: "A9bc").errorCode == noError) } + + func testDoubleIsFinite() { + XCTAssertTrue(EventChecker.checkFinite(123.31)) + XCTAssertTrue(EventChecker.checkFinite(0)) + XCTAssertTrue(EventChecker.checkFinite(Double.pi)) + XCTAssertTrue(EventChecker.checkFinite(Double.leastNormalMagnitude)) + XCTAssertTrue(EventChecker.checkFinite(Double.leastNonzeroMagnitude)) + XCTAssertTrue(EventChecker.checkFinite(Double.ulpOfOne)) + XCTAssertFalse(EventChecker.checkFinite(Double.nan)) + XCTAssertFalse(EventChecker.checkFinite(Double.infinity)) + XCTAssertFalse(EventChecker.checkFinite(-Double.infinity)) + XCTAssertFalse(EventChecker.checkFinite(Double.signalingNaN)) + } + + func testDecimalIsFinite() { + XCTAssertTrue(EventChecker.checkFinite(Decimal.pi)) + XCTAssertTrue(EventChecker.checkFinite(Decimal.leastNormalMagnitude)) + XCTAssertTrue(EventChecker.checkFinite(Decimal.leastNonzeroMagnitude)) + XCTAssertTrue(EventChecker.checkFinite(Decimal.greatestFiniteMagnitude)) + XCTAssertTrue(EventChecker.checkFinite(Decimal.leastFiniteMagnitude)) + XCTAssertFalse(EventChecker.checkFinite(Decimal.nan)) + XCTAssertFalse(EventChecker.checkFinite(Decimal.quietNaN)) + } }