From f86b67c8f114f329aa3ded4b630c2fb7a842581f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20=C5=81yp?= Date: Sun, 1 Oct 2023 23:53:46 +0200 Subject: [PATCH] Add tests --- Core/UserAgentManager.swift | 36 ++++- DuckDuckGoTests/UserAgentTests.swift | 200 ++++++++++++++++++++++++++- 2 files changed, 233 insertions(+), 3 deletions(-) diff --git a/Core/UserAgentManager.swift b/Core/UserAgentManager.swift index 648ab08e49..7e3571c0b0 100644 --- a/Core/UserAgentManager.swift +++ b/Core/UserAgentManager.swift @@ -108,6 +108,12 @@ struct UserAgent { static let defaultPolicyConfigKey = "defaultPolicy" static let ddgDefaultSitesConfigKey = "ddgDefaultSites" static let ddgFixedSitesConfigKey = "ddgFixedSites" + + static let closestUserAgentConfigKey = "closestUserAgent" + static let ddgFixedUserAgentConfigKey = "ddgFixedUserAgent" + + static let uaVersionsKey = "versions" + static let uaStateKey = "state" // todo: do we need it? // swiftlint:enable line_length } @@ -122,6 +128,8 @@ struct UserAgent { private let versionComponent: String private let safariComponent: String private let applicationComponent = "DuckDuckGo/\(AppVersion.shared.majorVersionNumber)" + private let statistics: StatisticsUserDefaults = StatisticsUserDefaults() + private let isTesting: Bool = ProcessInfo().arguments.contains("testing") init(defaultAgent: String = Constants.fallbackDefaultAgent) { versionComponent = UserAgent.createVersionComponent(fromAgent: defaultAgent) @@ -158,6 +166,20 @@ struct UserAgent { return fixedSitesObjs.map { $0[Constants.uaOmitDomainConfigKey] ?? "" } } + private func closestUserAgentVersions(forConfig config: PrivacyConfiguration) -> [String] { + let uaSettings = config.settings(for: .customUserAgent) + let closestUserAgentObjs = uaSettings[Constants.closestUserAgentConfigKey] as? [[String: String]] ?? [] + return [""] +// return closestUserAgentObjs.map { $0[Constants.uaOmitDomainConfigKey] ?? "" } + } + + private func ddgFixedUserAgentVersions(forConfig config: PrivacyConfiguration) -> [String] { + let uaSettings = config.settings(for: .customUserAgent) + let closestUserAgentObjs = uaSettings[Constants.closestUserAgentConfigKey] as? [[String: String]] ?? [] + return [""] +// return closestUserAgentObjs.map { $0[Constants.uaOmitDomainConfigKey] ?? "" } + } + public func agent(forUrl url: URL?, isDesktop: Bool, privacyConfig: PrivacyConfiguration = ContentBlocking.shared.privacyConfigurationManager.privacyConfig) -> String { @@ -222,12 +244,12 @@ struct UserAgent { private func closestLogic(forUrl url: URL?, isDesktop: Bool, privacyConfig: PrivacyConfiguration) -> String { - guard #available(iOS 16.6, *) else { + guard shouldUseUpdateLogic else { return oldLogic(forUrl: url, isDesktop: isDesktop, privacyConfig: privacyConfig) } if isDesktop { - return "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_5_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15" + return "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15" } var deviceProfile = "iPhone; CPU iPhone OS 16_6 like Mac OS X" if baseAgent.contains("iPad") { @@ -237,6 +259,16 @@ struct UserAgent { } return "Mozilla/5.0 (" + deviceProfile + ") AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1" } + + private var shouldUseUpdateLogic: Bool { + // Unfortunately you can't combine #available with any other condition in the same line + if isTesting { + return true + } else if #available(iOS 16.6, *) { + return true + } + return false + } private func concatWithSpaces(_ elements: String?...) -> String { return elements diff --git a/DuckDuckGoTests/UserAgentTests.swift b/DuckDuckGoTests/UserAgentTests.swift index 86da0621c2..be7bb014fd 100644 --- a/DuckDuckGoTests/UserAgentTests.swift +++ b/DuckDuckGoTests/UserAgentTests.swift @@ -42,6 +42,14 @@ class UserAgentTests: XCTestCase { // Based on fallback constants in UserAgent static let mobileFallback = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.5 Mobile/15E148 DuckDuckGo/7 Safari/605.1.15" static let desktopFallback = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.5 DuckDuckGo/7 Safari/605.1.15" + + static let mobileFixed = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 DuckDuckGo/7 Safari/604.1" + static let tabletFixed = "Mozilla/5.0 (iPad; CPU OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 DuckDuckGo/7 Safari/604.1" + static let desktopFixed = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 DuckDuckGo/7 Safari/605.1.15" + + static let mobileClosest = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1" + static let tabletClosest = "Mozilla/5.0 (iPad; CPU OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Mobile/15E148 Safari/604.1" + static let desktopClosest = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15" // swiftlint:enable line_length } @@ -50,6 +58,8 @@ class UserAgentTests: XCTestCase { static let url = URL(string: "http://example.com/index.html") static let noAppUrl = URL(string: "http://cvs.com/index.html") static let noAppSubdomainUrl = URL(string: "http://subdomain.cvs.com/index.html") + static let ddgFixedUrl = URL(string: "http://test2.com/index.html") + static let ddgDefaultUrl = URL(string: "http://test3.com/index.html") } let testConfig = """ @@ -73,7 +83,7 @@ class UserAgentTests: XCTestCase { """.data(using: .utf8)! private var privacyConfig: PrivacyConfiguration! - + override func setUp() { super.setUp() @@ -164,4 +174,192 @@ class UserAgentTests: XCTestCase { XCTAssertEqual(ExpectedAgent.mobileNoApplication, testee.agent(forUrl: Constants.url, isDesktop: false, privacyConfig: manager.privacyConfig)) } + + /// Experimental config + + func makePrivacyConfig(from rawConfig: Data) -> PrivacyConfiguration { + let mockEmbeddedData = MockEmbeddedDataProvider(data: rawConfig, etag: "test") + let mockProtectionStore = MockDomainsProtectionStore() + + let manager = PrivacyConfigurationManager(fetchedETag: nil, + fetchedData: nil, + embeddedDataProvider: mockEmbeddedData, + localProtection: mockProtectionStore, + internalUserDecider: DefaultInternalUserDecider()) + return manager.privacyConfig + } + + let ddgConfig = """ + { + "features": { + "customUserAgent": { + "defaultPolicy": "ddg", + "state": "enabled", + "settings": { + "omitApplicationSites": [ + { + "domain": "cvs.com", + "reason": "Site reports browser not supported" + } + ], + "ddgFixedSites": [ + { + "domain": "test2.com" + } + ] + }, + "exceptions": [] + } + }, + "unprotectedTemporary": [] + } + """.data(using: .utf8)! + + func testWhenMobileUaAndDesktopFalseAndDomainSupportsFixedUAThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.mobile) + let config = makePrivacyConfig(from: ddgConfig) + XCTAssertEqual(ExpectedAgent.mobileFixed, testee.agent(forUrl: Constants.ddgFixedUrl, isDesktop: false, privacyConfig: config)) + } + + func testWhenMobileUaAndDesktopTrueAndDomainSupportsFixedUAThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.mobile) + let config = makePrivacyConfig(from: ddgConfig) + XCTAssertEqual(ExpectedAgent.desktopFixed, testee.agent(forUrl: Constants.ddgFixedUrl, isDesktop: true, privacyConfig: config)) + } + + func testWhenTabletUaAndDesktopFalseAndDomainSupportsFixedUAThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.tablet) + let config = makePrivacyConfig(from: ddgConfig) + XCTAssertEqual(ExpectedAgent.tabletFixed, testee.agent(forUrl: Constants.ddgFixedUrl, isDesktop: false, privacyConfig: config)) + } + + func testWhenTabletUaAndDesktopTrueAndDomainSupportsFixedUAThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.tablet) + let config = makePrivacyConfig(from: ddgConfig) + XCTAssertEqual(ExpectedAgent.desktopFixed, testee.agent(forUrl: Constants.ddgFixedUrl, isDesktop: true, privacyConfig: config)) + } + + let ddgFixedConfig = """ + { + "features": { + "customUserAgent": { + "state": "enabled", + "settings": { + "defaultPolicy": "ddgFixed", + "omitApplicationSites": [ + { + "domain": "cvs.com", + "reason": "Site reports browser not supported" + } + ], + "ddgDefaultSites": [ + { + "domain": "test3.com" + } + ] + }, + "exceptions": [] + } + }, + "unprotectedTemporary": [] + } + """.data(using: .utf8)! + + func testWhenMobileUaAndDesktopFalseAndDefaultPolicyFixedThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.mobile) + let config = makePrivacyConfig(from: ddgFixedConfig) + XCTAssertEqual(ExpectedAgent.mobileFixed, testee.agent(forUrl: Constants.url, isDesktop: false, privacyConfig: config)) + } + + func testWhenMobileUaAndDesktopTrueAndDefaultPolicyFixedThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.mobile) + let config = makePrivacyConfig(from: ddgFixedConfig) + XCTAssertEqual(ExpectedAgent.desktopFixed, testee.agent(forUrl: Constants.url, isDesktop: true, privacyConfig: config)) + } + + func testWhenTabletUaAndDesktopFalseAndDefaultPolicyFixedThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.tablet) + let config = makePrivacyConfig(from: ddgFixedConfig) + XCTAssertEqual(ExpectedAgent.tabletFixed, testee.agent(forUrl: Constants.url, isDesktop: false, privacyConfig: config)) + } + + func testWhenTabletUaAndDesktopTrueAndDefaultPolicyFixedThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.tablet) + let config = makePrivacyConfig(from: ddgFixedConfig) + XCTAssertEqual(ExpectedAgent.desktopFixed, testee.agent(forUrl: Constants.url, isDesktop: true, privacyConfig: config)) + } + + func testWhenDefaultPolicyFixedAndDomainIsOnDefaultListThenDefaultAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.mobile) + let config = makePrivacyConfig(from: ddgFixedConfig) + XCTAssertEqual(ExpectedAgent.mobile, testee.agent(forUrl: Constants.ddgDefaultUrl, isDesktop: false, privacyConfig: config)) + } + + let closestConfig = """ + { + "features": { + "customUserAgent": { + "state": "enabled", + "settings": { + "defaultPolicy": "closest", + "omitApplicationSites": [ + { + "domain": "cvs.com", + "reason": "Site reports browser not supported" + } + ], + "ddgFixedSites": [ + { + "domain": "test2.com" + } + ], + "ddgDefaultSites": [ + { + "domain": "test3.com" + } + ] + }, + "exceptions": [] + } + }, + "unprotectedTemporary": [] + } + """.data(using: .utf8)! + + func testWhenMobileUaAndDesktopFalseAndDefaultPolicyClosestThenClosestMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.mobile) + let config = makePrivacyConfig(from: closestConfig) + XCTAssertEqual(ExpectedAgent.mobileClosest, testee.agent(forUrl: Constants.url, isDesktop: false, privacyConfig: config)) + } + + func testWhenMobileUaAndDesktopTrueAndDefaultPolicyClosestThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.mobile) + let config = makePrivacyConfig(from: closestConfig) + XCTAssertEqual(ExpectedAgent.desktopClosest, testee.agent(forUrl: Constants.url, isDesktop: true, privacyConfig: config)) + } + + func testWhenTabletUaAndDesktopFalseAndDefaultPolicyClosestThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.tablet) + let config = makePrivacyConfig(from: closestConfig) + XCTAssertEqual(ExpectedAgent.tabletClosest, testee.agent(forUrl: Constants.url, isDesktop: false, privacyConfig: config)) + } + + func testWhenTabletUaAndDesktopTrueAndDefaultPolicyClosestThenFixedMobileAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.tablet) + let config = makePrivacyConfig(from: closestConfig) + XCTAssertEqual(ExpectedAgent.desktopClosest, testee.agent(forUrl: Constants.url, isDesktop: true, privacyConfig: config)) + } + + func testWhenDefaultPolicyClosestAndDomainIsOnDefaultListThenDefaultAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.mobile) + let config = makePrivacyConfig(from: closestConfig) + XCTAssertEqual(ExpectedAgent.mobile, testee.agent(forUrl: Constants.ddgDefaultUrl, isDesktop: false, privacyConfig: config)) + } + + func testWhenDefaultPolicyClosestAndDomainIsOnFixedListThenFixedAgentUsed() { + let testee = UserAgent(defaultAgent: DefaultAgent.mobile) + let config = makePrivacyConfig(from: closestConfig) + XCTAssertEqual(ExpectedAgent.mobileFixed, testee.agent(forUrl: Constants.ddgFixedUrl, isDesktop: false, privacyConfig: config)) + } + }