Skip to content

Commit cc1ae81

Browse files
mpangburnps2
authored andcommitted
Mock managers (#4)
* Move mock health data deletion to Loop * Fix mock data deletion section logic
1 parent 93c20c5 commit cc1ae81

File tree

7 files changed

+223
-11
lines changed

7 files changed

+223
-11
lines changed

Common/Models/PumpManager.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
import Foundation
99
import LoopKit
1010
import MinimedKit
11+
import MockKit
1112

1213

1314
let allPumpManagers: [PumpManager.Type] = [
14-
MinimedPumpManager.self
15+
MinimedPumpManager.self,
16+
MockPumpManager.self,
1517
]
1618

1719
private let managersByIdentifier: [String: PumpManager.Type] = allPumpManagers.reduce(into: [:]) { (map, Type) in

Loop.xcodeproj/project.pbxproj

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,11 @@
282282
7D70765E1FE06EE3004AC8EA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D7076601FE06EE3004AC8EA /* Localizable.strings */; };
283283
7D7076631FE06EE4004AC8EA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D7076651FE06EE4004AC8EA /* Localizable.strings */; };
284284
7D7076681FE0702F004AC8EA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D70766A1FE0702F004AC8EA /* InfoPlist.strings */; };
285+
892A5D2A222EF60A008961AB /* MockKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 892A5D29222EF60A008961AB /* MockKit.framework */; };
286+
892A5D2C222EF60A008961AB /* MockKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 892A5D2B222EF60A008961AB /* MockKitUI.framework */; };
287+
892A5D59222F0A27008961AB /* Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892A5D58222F0A27008961AB /* Debug.swift */; };
288+
892A5D5B222F0D7C008961AB /* LoopTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 892A5D5A222F0D7C008961AB /* LoopTestingKit.framework */; };
289+
892A5D692230C41D008961AB /* RangeReplaceableCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 892A5D682230C41D008961AB /* RangeReplaceableCollection.swift */; };
285290
894F71E21FFEC4D8007D365C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 894F71E11FFEC4D8007D365C /* Assets.xcassets */; };
286291
898ECA60218ABD17001E9D35 /* GlucoseChartScaler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898ECA5E218ABD17001E9D35 /* GlucoseChartScaler.swift */; };
287292
898ECA61218ABD17001E9D35 /* GlucoseChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898ECA5F218ABD17001E9D35 /* GlucoseChartData.swift */; };
@@ -819,6 +824,11 @@
819824
7DD382771F8DBFC60071272B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Main.strings; sourceTree = "<group>"; };
820825
7DD382781F8DBFC60071272B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/MainInterface.strings; sourceTree = "<group>"; };
821826
7DD382791F8DBFC60071272B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Interface.strings; sourceTree = "<group>"; };
827+
892A5D29222EF60A008961AB /* MockKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MockKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
828+
892A5D2B222EF60A008961AB /* MockKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MockKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
829+
892A5D58222F0A27008961AB /* Debug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Debug.swift; sourceTree = "<group>"; };
830+
892A5D5A222F0D7C008961AB /* LoopTestingKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopTestingKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
831+
892A5D682230C41D008961AB /* RangeReplaceableCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RangeReplaceableCollection.swift; sourceTree = "<group>"; };
822832
894F71E11FFEC4D8007D365C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
823833
898ECA5E218ABD17001E9D35 /* GlucoseChartScaler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseChartScaler.swift; sourceTree = "<group>"; };
824834
898ECA5F218ABD17001E9D35 /* GlucoseChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseChartData.swift; sourceTree = "<group>"; };
@@ -857,6 +867,9 @@
857867
isa = PBXFrameworksBuildPhase;
858868
buildActionMask = 2147483647;
859869
files = (
870+
892A5D5B222F0D7C008961AB /* LoopTestingKit.framework in Frameworks */,
871+
892A5D2A222EF60A008961AB /* MockKit.framework in Frameworks */,
872+
892A5D2C222EF60A008961AB /* MockKitUI.framework in Frameworks */,
860873
4F7528941DFE1E9500C322D6 /* LoopUI.framework in Frameworks */,
861874
434FB6461D68F1CD007B9C70 /* Amplitude.framework in Frameworks */,
862875
43A8EC6F210E622700A81379 /* CGMBLEKitUI.framework in Frameworks */,
@@ -1147,6 +1160,8 @@
11471160
437CEEE31CDE5C0A003C8C80 /* UIImage.swift */,
11481161
434FF1ED1CF27EEF000DB779 /* UITableViewCell.swift */,
11491162
430B29922041F5B200BA9F93 /* UserDefaults+Loop.swift */,
1163+
892A5D58222F0A27008961AB /* Debug.swift */,
1164+
892A5D682230C41D008961AB /* RangeReplaceableCollection.swift */,
11501165
);
11511166
path = Extensions;
11521167
sourceTree = "<group>";
@@ -1394,6 +1409,9 @@
13941409
968DCD53F724DE56FFE51920 /* Frameworks */ = {
13951410
isa = PBXGroup;
13961411
children = (
1412+
892A5D5A222F0D7C008961AB /* LoopTestingKit.framework */,
1413+
892A5D29222EF60A008961AB /* MockKit.framework */,
1414+
892A5D2B222EF60A008961AB /* MockKitUI.framework */,
13971415
C168C40521B0D53E00ADE90E /* MinimedKit.framework */,
13981416
C168C40721B0D53E00ADE90E /* MinimedKitUI.framework */,
13991417
C1C108C22152F46D00EA5165 /* CGMBLEKitUI.framework */,
@@ -1963,8 +1981,10 @@
19631981
4372E490213CFCE70068E043 /* LoopSettingsUserInfo.swift in Sources */,
19641982
43F78D261C8FC000002152D1 /* DoseMath.swift in Sources */,
19651983
438D42F91D7C88BC003244B0 /* PredictionInputEffect.swift in Sources */,
1984+
892A5D692230C41D008961AB /* RangeReplaceableCollection.swift in Sources */,
19661985
4F70C2101DE8FAC5006380B7 /* StatusExtensionDataManager.swift in Sources */,
19671986
43DFB62320D4CAE7008A7BAE /* PumpManager.swift in Sources */,
1987+
892A5D59222F0A27008961AB /* Debug.swift in Sources */,
19681988
435CB6291F37B01300C320C7 /* InsulinModelSettings.swift in Sources */,
19691989
431A8C401EC6E8AB00823B9C /* CircleMaskView.swift in Sources */,
19701990
439897371CD2F80600223065 /* AnalyticsManager.swift in Sources */,
@@ -2644,6 +2664,7 @@
26442664
DEVELOPMENT_TEAM = "";
26452665
INFOPLIST_FILE = Loop/Info.plist;
26462666
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
2667+
"OTHER_SWIFT_FLAGS[arch=*]" = "-DDEBUG";
26472668
"OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]" = "-D IOS_SIMULATOR";
26482669
PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)";
26492670
PRODUCT_NAME = "$(TARGET_NAME)";

Loop/Extensions/Debug.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// Debug.swift
3+
// Loop
4+
//
5+
// Created by Michael Pangburn on 3/5/19.
6+
// Copyright © 2019 LoopKit Authors. All rights reserved.
7+
//
8+
9+
func assertingDebugOnly(file: StaticString = #file, line: UInt = #line, _ doIt: () -> Void) {
10+
#if DEBUG || IOS_SIMULATOR
11+
doIt()
12+
#else
13+
fatalError("\(file):\(line) should never be invoked in release builds", file: file, line: line)
14+
#endif
15+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//
2+
// RangeReplaceableCollection.swift
3+
// Loop
4+
//
5+
// Created by Michael Pangburn on 3/6/19.
6+
// Copyright © 2019 LoopKit Authors. All rights reserved.
7+
//
8+
9+
extension RangeReplaceableCollection where Element: Equatable {
10+
/// Returns `true` if the element was removed, or `false` if it is not present in the collection.
11+
@discardableResult
12+
mutating func remove(_ element: Element) -> Bool {
13+
guard let index = self.index(of: element) else {
14+
return false
15+
}
16+
17+
remove(at: index)
18+
return true
19+
}
20+
}

Loop/Managers/CGMManager.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ import LoopKit
99
import CGMBLEKit
1010
import G4ShareSpy
1111
import ShareClient
12+
import MockKit
1213

1314

1415
let allCGMManagers: [CGMManager.Type] = [
1516
G6CGMManager.self,
1617
G5CGMManager.self,
1718
G4CGMManager.self,
1819
ShareClientManager.self,
20+
MockCGMManager.self,
1921
]
2022

2123

Loop/Managers/DeviceDataManager.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import HealthKit
1010
import LoopKit
1111
import LoopKitUI
12+
import LoopTestingKit
13+
1214

1315
final class DeviceDataManager {
1416

@@ -214,6 +216,10 @@ extension DeviceDataManager: CGMManagerDelegate {
214216
func startDateToFilterNewData(for manager: CGMManager) -> Date? {
215217
return loopManager.glucoseStore.latestGlucose?.startDate
216218
}
219+
220+
func cgmManagerDidUpdateState(_ manager: CGMManager) {
221+
UserDefaults.appGroup.cgmManager = manager
222+
}
217223
}
218224

219225

@@ -387,6 +393,43 @@ extension DeviceDataManager {
387393
}
388394
}
389395

396+
extension DeviceDataManager {
397+
func deleteTestingPumpData() {
398+
assertingDebugOnly {
399+
guard let testingPumpManager = pumpManager as? TestingPumpManager else {
400+
assertionFailure("\(#function) should be invoked only when a testing pump manager is in use")
401+
return
402+
}
403+
let devicePredicate = HKQuery.predicateForObjects(from: [testingPumpManager.testingDevice])
404+
405+
// DoseStore.deleteAllPumpEvents first syncs the events to the health store,
406+
// so HKHealthStore.deleteObjects catches any that were still in the cache.
407+
let doseStore = loopManager.doseStore
408+
let healthStore = doseStore.insulinDeliveryStore.healthStore
409+
doseStore.deleteAllPumpEvents { doseStoreError in
410+
if doseStoreError != nil {
411+
healthStore.deleteObjects(of: doseStore.sampleType!, predicate: devicePredicate) { success, deletedObjectCount, error in
412+
// errors are already logged through the store, so we'll ignore them here
413+
}
414+
}
415+
}
416+
}
417+
}
418+
419+
func deleteTestingCGMData() {
420+
assertingDebugOnly {
421+
guard let testingCGMManager = cgmManager as? TestingCGMManager else {
422+
assertionFailure("\(#function) should be invoked only when a testing CGM manager is in use")
423+
return
424+
}
425+
let predicate = HKQuery.predicateForObjects(from: [testingCGMManager.testingDevice])
426+
loopManager.glucoseStore.purgeGlucoseSamples(matchingCachePredicate: nil, healthKitPredicate: predicate) { success, count, error in
427+
// result already logged through the store, so ignore the error here
428+
}
429+
}
430+
}
431+
}
432+
390433
extension DeviceDataManager: LoopDataManagerDelegate {
391434
func loopDataManager(_ manager: LoopDataManager, roundBasalRate unitsPerHour: Double) -> Double {
392435
guard let pumpManager = pumpManager else {

0 commit comments

Comments
 (0)