Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #1359 from corona-warn-app/fix/3297-Reset_Diagnosi…
Browse files Browse the repository at this point in the history
…s_Key_Cache_on_EN_Error_Code_2

Clear the key packages and app config on ENError = 2
  • Loading branch information
marcussc authored Oct 16, 2020
2 parents 09bd038 + a4cce7a commit 48ece41
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 10 deletions.
9 changes: 2 additions & 7 deletions src/xcode/ENA/ENA/Source/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import UIKit
protocol CoronaWarnAppDelegate: AnyObject {
var client: HTTPClient { get }
var downloadedPackagesStore: DownloadedPackagesStore { get }
var store: Store { get }
var store: Store & AppConfigCaching { get }
var appConfigurationProvider: AppConfigurationProviding { get }
var riskProvider: RiskProvider { get }
var exposureManager: ExposureManager { get }
Expand Down Expand Up @@ -99,7 +99,7 @@ extension AppDelegate: ExposureSummaryProvider {
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

let store: Store
let store: Store & AppConfigCaching
let serverEnvironment: ServerEnvironment

private let consumer = RiskConsumer()
Expand All @@ -109,11 +109,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// use a custom http client that uses/recognized caching mechanisms
let appFetchingClient = CachingHTTPClient(clientConfiguration: client.configuration)

// we currently use the store as common place for temporal persistency
guard let store = store as? AppConfigCaching else {
preconditionFailure("Ensure to provide a proper app config cache")
}

return CachedAppConfiguration(client: appFetchingClient, store: store)
}()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,4 +235,39 @@ final class DownloadedPackagesSQLLiteStoreTests: XCTestCase {
XCTAssertEqual(store.allDays(country: "DE").count, 7)
XCTAssertEqual(store.allDays(country: "IT").count, 2)
}

func test_ResetRemovesAllKeys() {
let database = FMDatabase.inMemory()
let store = DownloadedPackagesSQLLiteStore(database: database, migrator: SerialMigratorFake(), latestVersion: 0)
store.open()

let keysBin = Data("keys".utf8)
let signature = Data("sig".utf8)

let package = SAPDownloadedPackage(
keysBin: keysBin,
signature: signature
)

// Add days
store.set(country: "DE", day: "2020-06-01", package: package)
store.set(country: "DE", day: "2020-06-02", package: package)
store.set(country: "DE", day: "2020-06-03", package: package)
store.set(country: "IT", day: "2020-06-03", package: package)
store.set(country: "DE", day: "2020-06-04", package: package)
store.set(country: "DE", day: "2020-06-05", package: package)
store.set(country: "DE", day: "2020-06-06", package: package)
store.set(country: "IT", day: "2020-06-06", package: package)
store.set(country: "DE", day: "2020-06-07", package: package)

XCTAssertEqual(store.allDays(country: "DE").count, 7)
XCTAssertEqual(store.allDays(country: "IT").count, 2)

store.reset()
store.open()

XCTAssertEqual(store.allDays(country: "DE").count, 0)
XCTAssertEqual(store.allDays(country: "IT").count, 0)
XCTAssertEqual(database.lastErrorCode(), 0)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ final class ExposureDetectionExecutor: ExposureDetectionDelegate {
private let client: Client

private let downloadedPackagesStore: DownloadedPackagesStore
private let store: Store
private let store: Store & AppConfigCaching
private let exposureDetector: ExposureDetector

init(
client: Client,
downloadedPackagesStore: DownloadedPackagesStore,
store: Store,
store: Store & AppConfigCaching,
exposureDetector: ExposureDetector
) {
self.client = client
Expand Down Expand Up @@ -168,11 +168,28 @@ final class ExposureDetectionExecutor: ExposureDetectionDelegate {
writtenPackages: WrittenPackages,
completion: @escaping (Result<ENExposureDetectionSummary, Error>) -> Void
) -> Progress {

// Clear the key packages and app config on ENError = 2 = .badParameter
// For more details, see: https://jira.itc.sap.com/browse/EXPOSUREAPP-3297
func clearCacheOnErrorBadParameter(error: Error) {
if let enError = error as? ENError, enError.code == .badParameter {
// Clear the key packages
downloadedPackagesStore.reset()
downloadedPackagesStore.open()

// Clear the app config
store.appConfig = nil
store.lastAppConfigETag = nil
store.lastAppConfigFetch = nil
}
}

func withResultFrom(
summary: ENExposureDetectionSummary?,
error: Error?
) -> Result<ENExposureDetectionSummary, Error> {
if let error = error {
clearCacheOnErrorBadParameter(error: error)
return .failure(error)
}
if let summary = summary {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,55 @@ final class ExposureDetectionExecutorTests: XCTestCase {
)
waitForExpectations(timeout: 2.0)
}

func testDetectSummaryWithConfiguration_Error2BadParameter_ClearsCache() throws {
// Test the case where the exector is asked to run an exposure detection
// We provide an `MockExposureDetector` with an error, and expect this to be returned
let completionExpectation = expectation(description: "Expect that the completion handler is called.")
let expectedError = ENError(.badParameter)

let keysBin = Data("keys".utf8)
let signature = Data("sig".utf8)
let package = SAPDownloadedPackage(
keysBin: keysBin,
signature: signature
)
let packageStore = DownloadedPackagesSQLLiteStore.inMemory()
packageStore.open()
packageStore.set(country: "DE", day: "SomeDay", package: package)

let store = MockTestStore()
store.appConfig = SAP_ApplicationConfiguration()

let sut = ExposureDetectionExecutor.makeWith(
packageStore: packageStore,
store: store,
exposureDetector: MockExposureDetector((nil, expectedError))
)
let exposureDetection = ExposureDetection(
delegate: sut,
appConfigurationProvider: AppConfigurationProviderFake()
)

XCTAssertNotEqual(packageStore.allDays(country: "DE").count, 0)
XCTAssertNotNil(store.appConfig)

sut.exposureDetection(
exposureDetection,
detectSummaryWithConfiguration: ENExposureConfiguration(),
writtenPackages: WrittenPackages(urls: []),
completion: { result in

XCTAssertEqual(packageStore.allDays(country: "DE").count, 0)
XCTAssertNil(store.appConfig)
XCTAssertNil(store.lastAppConfigETag)
XCTAssertNil(store.lastAppConfigFetch)

completionExpectation.fulfill()
}
)
waitForExpectations(timeout: 2.0)
}
}

// MARK: - Private Helper Extensions
Expand All @@ -377,7 +426,7 @@ private extension ExposureDetectionExecutor {
static func makeWith(
client: Client = ClientMock(),
packageStore: DownloadedPackagesStore = DownloadedPackagesSQLLiteStore.inMemory(),
store: Store = MockTestStore(),
store: Store & AppConfigCaching = MockTestStore(),
exposureDetector: MockExposureDetector = MockExposureDetector()
) -> ExposureDetectionExecutor {
ExposureDetectionExecutor(
Expand Down

0 comments on commit 48ece41

Please sign in to comment.