From 41d2d21265565ea879f2ba5a9d304c8fa23db564 Mon Sep 17 00:00:00 2001 From: Muzahidul Islam <129880873+muzahidul-opti@users.noreply.github.com> Date: Wed, 1 Nov 2023 18:03:06 +0600 Subject: [PATCH 1/7] Upload task body issue fixed (#521) (cherry picked from commit a375e2b44b18b2d21bfcdc0a55e6a9bf53be05eb) --- Sources/Customization/DefaultEventDispatcher.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/Customization/DefaultEventDispatcher.swift b/Sources/Customization/DefaultEventDispatcher.swift index 68e93feae..0311f9d09 100644 --- a/Sources/Customization/DefaultEventDispatcher.swift +++ b/Sources/Customization/DefaultEventDispatcher.swift @@ -183,7 +183,6 @@ open class DefaultEventDispatcher: BackgroundingCallbacks, OPTEventDispatcher { var request = URLRequest(url: event.url) request.httpMethod = "POST" - request.httpBody = event.body request.addValue("application/json", forHTTPHeaderField: "Content-Type") // send notification BEFORE sending event to the server From 4690cbe9a069e45c91e4a6eeff6b3d321f6d6aa4 Mon Sep 17 00:00:00 2001 From: Muzahidul Islam <129880873+muzahidul-opti@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:48:57 +0600 Subject: [PATCH 2/7] [FSSDK-9776] handle duplicate experiment key (#523) Logged for Duplicate keys (cherry picked from commit c2af8fe55978942d9a005373b3ba7687092527da) --- Sources/Optimizely/OptimizelyClient.swift | 2 +- Sources/Optimizely/OptimizelyConfig.swift | 11 ++- ...timizelyClientTests_OptimizelyConfig.swift | 96 +++++++++++++++++++ 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/Sources/Optimizely/OptimizelyClient.swift b/Sources/Optimizely/OptimizelyClient.swift index a88fd9de0..0c32c7eb0 100644 --- a/Sources/Optimizely/OptimizelyClient.swift +++ b/Sources/Optimizely/OptimizelyClient.swift @@ -745,7 +745,7 @@ open class OptimizelyClient: NSObject { public func getOptimizelyConfig() throws -> OptimizelyConfig { guard let config = self.config else { throw OptimizelyError.sdkNotReady } - return OptimizelyConfigImp(projectConfig: config) + return OptimizelyConfigImp(projectConfig: config, logger: logger) } } diff --git a/Sources/Optimizely/OptimizelyConfig.swift b/Sources/Optimizely/OptimizelyConfig.swift index af590d31b..e04d3002c 100644 --- a/Sources/Optimizely/OptimizelyConfig.swift +++ b/Sources/Optimizely/OptimizelyConfig.swift @@ -95,8 +95,8 @@ struct OptimizelyConfigImp: OptimizelyConfig { var attributes: [OptimizelyAttribute] = [] var audiences: [OptimizelyAudience] = [] var events: [OptimizelyEvent] = [] - - init(projectConfig: ProjectConfig) { + + init(projectConfig: ProjectConfig, logger: OPTLogger = DefaultLogger()) { guard let project = projectConfig.project else { return } self.environmentKey = project.environmentKey ?? "" @@ -139,7 +139,7 @@ struct OptimizelyConfigImp: OptimizelyConfig { return updatedRollout } - self.experimentsMap = makeExperimentsMap(project: project, experiments: updatedExperiments) + self.experimentsMap = makeExperimentsMap(project: project, experiments: updatedExperiments, logger: logger) self.featuresMap = makeFeaturesMap(project: project, experiments: updatedExperiments, rollouts: updatedRollouts) } } @@ -148,9 +148,12 @@ struct OptimizelyConfigImp: OptimizelyConfig { extension OptimizelyConfigImp { - func makeExperimentsMap(project: Project, experiments: [Experiment]) -> [String: Experiment] { + func makeExperimentsMap(project: Project, experiments: [Experiment], logger: OPTLogger) -> [String: Experiment] { var map = [String: Experiment]() experiments.forEach { + if map.keys.contains($0.key) { + logger.w("Duplicate experiment keys found in datafile: \($0.key)") + } map[$0.key] = $0 } return map diff --git a/Tests/OptimizelyTests-APIs/OptimizelyClientTests_OptimizelyConfig.swift b/Tests/OptimizelyTests-APIs/OptimizelyClientTests_OptimizelyConfig.swift index 24880abfa..48891924d 100644 --- a/Tests/OptimizelyTests-APIs/OptimizelyClientTests_OptimizelyConfig.swift +++ b/Tests/OptimizelyTests-APIs/OptimizelyClientTests_OptimizelyConfig.swift @@ -263,6 +263,64 @@ class OptimizelyClientTests_OptimizelyConfig: XCTestCase { let result = try? self.optimizely.getOptimizelyConfig() XCTAssertNil(result) } + + func testOptimizelyConfigWithDuplicateKeys() { + let exp0: [String : Any] = [ + "id": "10001", + "key": "duplicate_key", + "status": "Running", + "layerId": "22222", + "variations": [], + "trafficAllocation": [], + "audienceIds": ["33333"], + "audienceConditions": [], + "forcedVariations": ["12345": "1234567890"] + ] + + let exp1: [String : Any] = [ + "id": "10005", + "key": "duplicate_key", + "status": "Running", + "layerId": "22222", + "variations": [], + "trafficAllocation": [], + "audienceIds": ["33333"], + "audienceConditions": [], + "forcedVariations": ["12345": "1234567890"] + ] + + var projectData: [String: Any] = [ + "version": "4", + "projectId": "11111", + "experiments": [], + "audiences": [], + "groups": [], + "attributes": [], + "accountId": "1234567890", + "events": [], + "revision": "5", + "anonymizeIP": true, + "rollouts": [], + "typedAudiences": [], + "integrations": [], + "featureFlags": [], + "botFiltering": false, + "sendFlagDecisions": true + ] + + projectData["experiments"] = [exp0, exp1] + let model: Project = try! OTUtils.model(from: projectData) + let projectConfig = ProjectConfig() + projectConfig.project = model + + let logger = TestLogger() + let optiConfigImpl = OptimizelyConfigImp(projectConfig: projectConfig, logger: logger) + let optimizelyExpMap: [String: OptimizelyExperiment] = optiConfigImpl.experimentsMap + XCTAssertEqual(logger.getMessages(.warning), ["Duplicate experiment keys found in datafile: duplicate_key"]) + + XCTAssertEqual(optimizelyExpMap.count, 1) + XCTAssertEqual(optimizelyExpMap["duplicate_key"]?.id, "10005") + } } @@ -371,3 +429,41 @@ extension OptimizelyEvent { } } +// MARK: - Mock Loggers + +fileprivate class TestLogger: OPTLogger { + private static var _logLevel: OptimizelyLogLevel? + public static var logLevel: OptimizelyLogLevel { + get { + return _logLevel ?? .info + } + set (newLevel) { + _logLevel = newLevel + } + } + + required public init() { + clearMessages() + } + + func log(level: OptimizelyLogLevel, message: String) { + logMessages[level.rawValue].append(message) + } + + // Utils + + var logMessages = [[String]]() + + var logCount: Int { + return logMessages.reduce(0) { $0 + $1.count } + } + + func getMessages(_ level: OptimizelyLogLevel) -> [String] { + return logMessages[level.rawValue] + } + + func clearMessages() { + logMessages = [[String]](repeating: [], count: OptimizelyLogLevel.debug.rawValue + 1) + } + +} From 9e1862ab4b419563c0071bebffa21071293820a3 Mon Sep 17 00:00:00 2001 From: Muzahidul Islam Date: Tue, 5 Dec 2023 23:33:38 +0600 Subject: [PATCH 3/7] [FSSDK-9709] feat: App privacy manifest file added (#522) --- OptimizelySwiftSDK.xcodeproj/project.pbxproj | 1 + Sources/Supporting Files/PrivacyInfo.xcprivacy | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 Sources/Supporting Files/PrivacyInfo.xcprivacy diff --git a/OptimizelySwiftSDK.xcodeproj/project.pbxproj b/OptimizelySwiftSDK.xcodeproj/project.pbxproj index ceb2e999a..2697b9739 100644 --- a/OptimizelySwiftSDK.xcodeproj/project.pbxproj +++ b/OptimizelySwiftSDK.xcodeproj/project.pbxproj @@ -2457,6 +2457,7 @@ children = ( 6E75167A22C520D400B2B157 /* Optimizely.h */, 6E75167B22C520D400B2B157 /* Info.plist */, + 987F11D92AF3F56F0083D3F9 /* PrivacyInfo.xcprivacy */, ); path = "Supporting Files"; sourceTree = ""; diff --git a/Sources/Supporting Files/PrivacyInfo.xcprivacy b/Sources/Supporting Files/PrivacyInfo.xcprivacy new file mode 100644 index 000000000..f6b5e1a82 --- /dev/null +++ b/Sources/Supporting Files/PrivacyInfo.xcprivacy @@ -0,0 +1,17 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPITypeReasons + + To store configuration and event data temporarily + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + + + + From beb1ae1332252de98a1deb04eb9d03adcf7d6f66 Mon Sep 17 00:00:00 2001 From: Muzahidul Islam <129880873+muzahidul-opti@users.noreply.github.com> Date: Tue, 5 Dec 2023 23:39:22 +0600 Subject: [PATCH 4/7] Update CHANGELOG.md --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a33d37ec..0ac463e4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Optimizely Swift SDK Changelog +## 3.10.3 +December 5, 2023 + +### Bug Fixes +* Remove redundant post request body in upload task. ([#521](https://github.com/optimizely/swift-sdk/pull/521/)). + +### Enhancement +* Add privacy manifest file ([#522](https://github.com/optimizely/swift-sdk/pull/522/)). +* Handle duplicate keys in experiment ([#523](https://github.com/optimizely/swift-sdk/pull/523/)). + ## 3.10.2 March 14, 2023 From abadb8667677142ef76ce62f5c831697ca966892 Mon Sep 17 00:00:00 2001 From: Muzahidul Islam <129880873+muzahidul-opti@users.noreply.github.com> Date: Tue, 5 Dec 2023 23:39:58 +0600 Subject: [PATCH 5/7] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bc1270ab9..f76aa9013 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Add the dependency on the Optimizely Swift SDK with Swift Package Manager in `Xc #### CocoaPods 1. Add the following lines to the _Podfile_:
 ```use_frameworks!```
-```pod 'OptimizelySwiftSDK', '~> 3.10.2'```
+```pod 'OptimizelySwiftSDK', '~> 3.10.3'```
 
2. Run the following command:
``` pod install ```
@@ -45,7 +45,7 @@ Add the dependency on the Optimizely Swift SDK with Swift Package Manager in `Xc Further installation instructions for Cocoapods: https://guides.cocoapods.org/using/getting-started.html #### Carthage -1. Add the following lines to the _Cartfile_:
```github "optimizely/swift-sdk" ~> 3.10.2```
+1. Add the following lines to the _Cartfile_:
```github "optimizely/swift-sdk" ~> 3.10.3```
2. Run the following command:
```carthage update```
From 8a40f2cfaf73acf264ac38f9b741394d0ad747a5 Mon Sep 17 00:00:00 2001 From: Muzahidul Islam <129880873+muzahidul-opti@users.noreply.github.com> Date: Tue, 5 Dec 2023 23:41:02 +0600 Subject: [PATCH 6/7] Update swift.yml --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index f22bcf8f6..bc64ab490 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -17,7 +17,7 @@ on: description: release env: - VERSION: 3.10.2 + VERSION: 3.10.3 jobs: From 06209076d5dd0e60e6d31f432870c31106b15fcd Mon Sep 17 00:00:00 2001 From: Muzahidul Islam <129880873+muzahidul-opti@users.noreply.github.com> Date: Wed, 6 Dec 2023 00:13:29 +0600 Subject: [PATCH 7/7] Update run_unit_tests.sh --- Scripts/run_unit_tests.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Scripts/run_unit_tests.sh b/Scripts/run_unit_tests.sh index 4541b6548..dd99210a2 100755 --- a/Scripts/run_unit_tests.sh +++ b/Scripts/run_unit_tests.sh @@ -7,7 +7,7 @@ # # unit tests for PR only -if [[ "$BRANCH" == "master" ]] -then +# if [[ "$BRANCH" == "master" ]] +# then xcodebuild test -derivedDataPath $COVERAGE_DIR -workspace OptimizelySwiftSDK.xcworkspace -scheme $SCHEME -configuration Release CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -sdk $TEST_SDK -destination "platform=$PLATFORM,OS=$OS,name=$NAME" ONLY_ACTIVE_ARCH=YES | tee buildoutput | xcpretty && test ${PIPESTATUS[0]} -eq 0 -fi +# fi