Skip to content

Commit

Permalink
Trusted Entitlements: added tests to verify offerings and product e…
Browse files Browse the repository at this point in the history
…ntitlement mapping

These new integration tests verify that:
1. The response contains signature
2. In `enforced` mode, the signature must be valid
3. Response fails if it's not
4. In `informational` mode, no error is thrown
  • Loading branch information
NachoSoto committed Jul 6, 2023
1 parent 0cfec83 commit 49cae7c
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 5 deletions.
6 changes: 5 additions & 1 deletion Sources/Purchasing/OfferingsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,13 @@ class OfferingsManager {
return productIDsFromBackend.subtracting(productIDsFromStore)
}

func invalidateCachedOfferings(appUserID: String) {
self.deviceCache.clearOfferingsCache(appUserID: appUserID)
}

func invalidateAndReFetchCachedOfferingsIfAppropiate(appUserID: String) {
let cachedOfferings = self.deviceCache.cachedOfferings
self.deviceCache.clearOfferingsCache(appUserID: appUserID)
self.invalidateCachedOfferings(appUserID: appUserID)

if cachedOfferings != nil {
self.offerings(appUserID: appUserID, fetchPolicy: .ignoreNotFoundProducts) { @Sendable _ in }
Expand Down
9 changes: 7 additions & 2 deletions Sources/Purchasing/Purchases/Purchases.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1373,8 +1373,9 @@ extension Purchases: InternalPurchasesType {
@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
func productEntitlementMapping() async throws -> ProductEntitlementMapping {
let response = try await Async.call { completion in
self.backend.offlineEntitlements.getProductEntitlementMapping(withRandomDelay: false,
completion: completion)
self.backend.offlineEntitlements.getProductEntitlementMapping(withRandomDelay: false) { result in
completion(result.mapError(\.asPublicError))
}
}

return response.toMapping()
Expand Down Expand Up @@ -1472,6 +1473,10 @@ internal extension Purchases {
return self.receiptFetcher.receiptURL
}

func invalidateOfferingsCache() {
self.offeringsManager.invalidateCachedOfferings(appUserID: self.appUserID)
}

}

#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,26 @@ class InformationalSignatureVerificationIntegrationTests: BaseSignatureVerificat
expect(user.entitlements.verification) == .failed
}

func testOfferingsWithInvalidSignatureDontThrowError() async throws {
try AvailabilityChecks.iOS15APIAvailableOrSkipTest()

self.invalidSignature = true

Purchases.shared.invalidateOfferingsCache()

// Currently there's no API to detect signature failures
// See also `EnforcedSignatureVerificationIntegrationTests.testOfferingsWithInvalidSignature`
_ = try await Purchases.shared.offerings()
}

@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
func testEntitlementMappingWithInvalidSignatureDontThrowError() async throws {
try AvailabilityChecks.iOS15APIAvailableOrSkipTest()

self.invalidSignature = true
_ = try await Purchases.shared.productEntitlementMapping()
}

}

class EnforcedSignatureVerificationIntegrationTests: BaseSignatureVerificationIntegrationTests {
Expand All @@ -138,12 +158,29 @@ class EnforcedSignatureVerificationIntegrationTests: BaseSignatureVerificationIn
}
}

func testOfferingsWithInvalidSignature() async throws {
try AvailabilityChecks.iOS15APIAvailableOrSkipTest()

self.invalidSignature = true

Purchases.shared.invalidateOfferingsCache()

try await Self.verifyThrowsSignatureVerificationFailed {
_ = try await Purchases.shared.offerings()
}
}

func testOfferingsWithValidSignature() async throws {
try AvailabilityChecks.iOS15APIAvailableOrSkipTest()

Purchases.shared.invalidateOfferingsCache()
_ = try await Purchases.shared.offerings()
}

@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
func testEntitlementMappingWithInvalidSignature() async throws {
try AvailabilityChecks.iOS15APIAvailableOrSkipTest()

XCTExpectFailure("Not implemented yet")

self.invalidSignature = true

try await Self.verifyThrowsSignatureVerificationFailed {
Expand Down

0 comments on commit 49cae7c

Please sign in to comment.