Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ extension CachedInsulinDeliveryObject {
self.endDate = entry.endDate
self.syncIdentifier = entry.syncIdentifier
self.deliveredUnits = entry.unitsInDeliverableIncrements
self.scheduledBasalRate = entry.scheduledBasalRate
// A `.basal` dose's rate is its `value`; preserve it as the rate field so the cache reports the exact rate instead of one derived from a quantized delivered total.
self.scheduledBasalRate = entry.scheduledBasalRate ?? (entry.type == .basal ? LoopQuantity(unit: .internationalUnitsPerHour, doubleValue: entry.unitsPerHour) : nil)
self.programmedTempBasalRate = (entry.type == .tempBasal) ? LoopQuantity(unit: .internationalUnitsPerHour, doubleValue: entry.unitsPerHour) : nil
self.programmedUnits = (entry.type == .bolus) ? entry.programmedUnits : nil
self.reason = (entry.type == .bolus) ? .bolus : .basal
Expand All @@ -302,7 +303,8 @@ extension CachedInsulinDeliveryObject {
self.endDate = entry.endDate
self.syncIdentifier = entry.syncIdentifier
self.deliveredUnits = entry.unitsInDeliverableIncrements
self.scheduledBasalRate = entry.scheduledBasalRate
// A `.basal` dose's rate is its `value`; preserve it as the rate field so the cache reports the exact rate instead of one derived from a quantized delivered total.
self.scheduledBasalRate = entry.scheduledBasalRate ?? (entry.type == .basal ? LoopQuantity(unit: .internationalUnitsPerHour, doubleValue: entry.unitsPerHour) : nil)
self.programmedTempBasalRate = (entry.type == .tempBasal) ? LoopQuantity(unit: .internationalUnitsPerHour, doubleValue: entry.unitsPerHour) : nil
self.programmedUnits = (entry.type == .bolus) ? entry.programmedUnits : nil
self.reason = (entry.type == .bolus) ? .bolus : .basal
Expand Down
14 changes: 7 additions & 7 deletions LoopKitHostedTests/InsulinDeliveryStoreTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class InsulinDeliveryStoreTestsBase: PersistenceControllerTestCase {
decisionId: nil,
deliveredUnits: 0.015,
syncIdentifier: "4B14522E-A7B5-4E73-B76B-5043CD7176B0",
scheduledBasalRate: nil)
scheduledBasalRate: LoopQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.8))
internal let entry2 = DoseEntry(type: .tempBasal,
startDate: Date(timeIntervalSinceNow: -.minutes(2)),
endDate: Date(timeIntervalSinceNow: -.minutes(1.5)),
Expand Down Expand Up @@ -202,8 +202,8 @@ class InsulinDeliveryStoreTests: InsulinDeliveryStoreTestsBase {
XCTAssertEqual(entries[0].type, self.entry1.type)
XCTAssertEqual(entries[0].startDate, self.entry1.startDate)
XCTAssertEqual(entries[0].endDate, self.entry1.endDate)
XCTAssertEqual(entries[0].value, 0.015)
XCTAssertEqual(entries[0].unit, .units)
XCTAssertEqual(entries[0].value, 1.8)
XCTAssertEqual(entries[0].unit, .unitsPerHour)
XCTAssertEqual(entries[0].deliveredUnits, 0.015)
XCTAssertEqual(entries[0].description, self.entry1.description)
XCTAssertEqual(entries[0].syncIdentifier, self.entry1.syncIdentifier)
Expand Down Expand Up @@ -282,8 +282,8 @@ class InsulinDeliveryStoreTests: InsulinDeliveryStoreTestsBase {
XCTAssertEqual(entries[0].type, self.entry1.type)
XCTAssertEqual(entries[0].startDate, self.entry1.startDate)
XCTAssertEqual(entries[0].endDate, self.entry1.endDate)
XCTAssertEqual(entries[0].value, 0.015)
XCTAssertEqual(entries[0].unit, .units)
XCTAssertEqual(entries[0].value, 1.8)
XCTAssertEqual(entries[0].unit, .unitsPerHour)
XCTAssertEqual(entries[0].deliveredUnits, 0.015)
XCTAssertEqual(entries[0].description, self.entry1.description)
XCTAssertEqual(entries[0].syncIdentifier, self.entry1.syncIdentifier)
Expand Down Expand Up @@ -314,8 +314,8 @@ class InsulinDeliveryStoreTests: InsulinDeliveryStoreTestsBase {
XCTAssertEqual(entries[0].type, self.entry1.type)
XCTAssertEqual(entries[0].startDate, self.entry1.startDate)
XCTAssertEqual(entries[0].endDate, self.entry1.endDate)
XCTAssertEqual(entries[0].value, 0.015)
XCTAssertEqual(entries[0].unit, .units)
XCTAssertEqual(entries[0].value, 1.8)
XCTAssertEqual(entries[0].unit, .unitsPerHour)
XCTAssertEqual(entries[0].deliveredUnits, 0.015)
XCTAssertEqual(entries[0].description, self.entry1.description)
XCTAssertEqual(entries[0].syncIdentifier, self.entry1.syncIdentifier)
Expand Down
28 changes: 28 additions & 0 deletions LoopKitTests/Persistence/CachedInsulinDeliveryObjectTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,34 @@ class CachedInsulinDeliveryObjectOperationsTests: PersistenceControllerTestCase
}
}

func testCreateFromScheduledBasalEntryPreservesRate() {
// A scheduled `.basal` reported without a scheduledBasalRate (e.g. after a PumpEvent
// round-trip, which doesn't persist it) must keep its exact rate. Without the fix the
// cache stores only the quantized delivered total and the read-back rate drifts.
let start = dateFormatter.date(from: "2020-01-02T03:04:05Z")!
let entry = DoseEntry(type: .basal,
startDate: start,
endDate: start.addingTimeInterval(180.2), // 3 min 0.2 s → quantized total would drift
value: 1.0,
unit: .unitsPerHour,
decisionId: nil,
deliveredUnits: nil,
syncIdentifier: "scheduled-basal",
scheduledBasalRate: nil,
isMutable: true)
cacheStore.managedObjectContext.performAndWait {
let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
object.create(from: entry, by: "Test Providence Identifier", at: start)

XCTAssertEqual(object.scheduledBasalRate, LoopQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0))

let dose = object.dose
XCTAssertNotNil(dose)
XCTAssertEqual(dose!.unit, .unitsPerHour)
XCTAssertEqual(dose!.unitsPerHour, 1.0, accuracy: 1e-9)
}
}

func testCreateAndUpdateFromEntry() {
let createEntry = DoseEntry(type: .tempBasal,
startDate: dateFormatter.date(from: "2020-02-03T04:05:06Z")!,
Expand Down