CachedInsulinDeliveryObjectTests.swift 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. //
  2. // CachedInsulinDeliveryObjectTests.swift
  3. // LoopKitTests
  4. //
  5. // Copyright © 2018 LoopKit Authors. All rights reserved.
  6. //
  7. import XCTest
  8. import HealthKit
  9. @testable import LoopKit
  10. class CachedInsulinDeliveryObjectTests: PersistenceControllerTestCase {
  11. func testReasonGet() {
  12. cacheStore.managedObjectContext.performAndWait {
  13. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  14. object.primitiveReason = NSNumber(integerLiteral: 2)
  15. XCTAssertEqual(object.reason, .bolus)
  16. }
  17. }
  18. func testReasonSet() {
  19. cacheStore.managedObjectContext.performAndWait {
  20. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  21. object.reason = .basal
  22. XCTAssertEqual(object.primitiveReason, NSNumber(integerLiteral: 1))
  23. }
  24. }
  25. func testScheduledBasalRateGet() {
  26. cacheStore.managedObjectContext.performAndWait {
  27. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  28. object.primitiveScheduledBasalRate = NSNumber(floatLiteral: 1.23)
  29. XCTAssertEqual(object.scheduledBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.23))
  30. }
  31. }
  32. func testScheduledBasalRateGetNil() {
  33. cacheStore.managedObjectContext.performAndWait {
  34. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  35. object.primitiveScheduledBasalRate = nil
  36. XCTAssertNil(object.scheduledBasalRate)
  37. }
  38. }
  39. func testScheduledBasalRateSet() {
  40. cacheStore.managedObjectContext.performAndWait {
  41. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  42. object.scheduledBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 2.34)
  43. XCTAssertEqual(object.primitiveScheduledBasalRate, NSNumber(floatLiteral: 2.34))
  44. }
  45. }
  46. func testScheduledBasalRateSetNil() {
  47. cacheStore.managedObjectContext.performAndWait {
  48. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  49. object.scheduledBasalRate = nil
  50. XCTAssertNil(object.primitiveScheduledBasalRate)
  51. }
  52. }
  53. func testPrimitiveProgrammedTempBasalRateGet() {
  54. cacheStore.managedObjectContext.performAndWait {
  55. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  56. object.primitiveProgrammedTempBasalRate = NSNumber(floatLiteral: 1.23)
  57. XCTAssertEqual(object.programmedTempBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.23))
  58. }
  59. }
  60. func testPrimitiveProgrammedTempBasalRateGetNil() {
  61. cacheStore.managedObjectContext.performAndWait {
  62. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  63. object.primitiveProgrammedTempBasalRate = nil
  64. XCTAssertNil(object.programmedTempBasalRate)
  65. }
  66. }
  67. func testPrimitiveProgrammedTempBasalRateSet() {
  68. cacheStore.managedObjectContext.performAndWait {
  69. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  70. object.programmedTempBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 2.34)
  71. XCTAssertEqual(object.primitiveProgrammedTempBasalRate, NSNumber(floatLiteral: 2.34))
  72. }
  73. }
  74. func testPrimitiveProgrammedTempBasalRateSetNil() {
  75. cacheStore.managedObjectContext.performAndWait {
  76. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  77. object.programmedTempBasalRate = nil
  78. XCTAssertNil(object.primitiveProgrammedTempBasalRate)
  79. }
  80. }
  81. }
  82. class CachedInsulinDeliveryObjectDoseTests: PersistenceControllerTestCase {
  83. func testDoseBasal() {
  84. cacheStore.managedObjectContext.performAndWait {
  85. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  86. object.provenanceIdentifier = Bundle.main.bundleIdentifier!
  87. object.hasLoopKitOrigin = true
  88. object.startDate = dateFormatter.date(from: "2020-01-02T03:04:05Z")!
  89. object.endDate = dateFormatter.date(from: "2020-01-02T04:04:05Z")!
  90. object.syncIdentifier = "876DDBF9-CC47-45ED-B0D7-AD77B77913C4"
  91. object.value = 0.5
  92. object.scheduledBasalRate = nil
  93. object.programmedTempBasalRate = nil
  94. object.reason = .basal
  95. object.createdAt = dateFormatter.date(from: "2020-01-02T04:04:06Z")!
  96. object.wasProgrammedByPumpUI = true
  97. let dose = object.dose
  98. XCTAssertNotNil(dose)
  99. XCTAssertEqual(dose!.type, .basal)
  100. XCTAssertEqual(dose!.startDate, dateFormatter.date(from: "2020-01-02T03:04:05Z")!)
  101. XCTAssertEqual(dose!.endDate, dateFormatter.date(from: "2020-01-02T04:04:05Z")!)
  102. XCTAssertEqual(dose!.value, 0.5)
  103. XCTAssertEqual(dose!.unit, .units)
  104. XCTAssertEqual(dose!.deliveredUnits, nil)
  105. XCTAssertEqual(dose!.description, nil)
  106. XCTAssertEqual(dose!.syncIdentifier, "876DDBF9-CC47-45ED-B0D7-AD77B77913C4")
  107. XCTAssertEqual(dose!.scheduledBasalRate, nil)
  108. XCTAssertFalse(dose!.isMutable)
  109. XCTAssertTrue(dose!.wasProgrammedByPumpUI)
  110. }
  111. }
  112. func testDoseTempBasal() {
  113. cacheStore.managedObjectContext.performAndWait {
  114. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  115. object.provenanceIdentifier = Bundle.main.bundleIdentifier!
  116. object.hasLoopKitOrigin = false
  117. object.startDate = dateFormatter.date(from: "2020-01-02T03:04:06Z")!
  118. object.endDate = dateFormatter.date(from: "2020-01-02T03:34:06Z")!
  119. object.syncIdentifier = nil
  120. object.value = 0.75
  121. object.scheduledBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0)
  122. object.programmedTempBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.5)
  123. object.reason = .basal
  124. object.createdAt = dateFormatter.date(from: "2020-01-02T04:04:07Z")!
  125. object.isSuspend = false
  126. object.wasProgrammedByPumpUI = true
  127. let dose = object.dose
  128. XCTAssertNotNil(dose)
  129. XCTAssertEqual(dose!.type, .tempBasal)
  130. XCTAssertEqual(dose!.startDate, dateFormatter.date(from: "2020-01-02T03:04:06Z")!)
  131. XCTAssertEqual(dose!.endDate, dateFormatter.date(from: "2020-01-02T03:34:06Z")!)
  132. XCTAssertEqual(dose!.value, 1.5)
  133. XCTAssertEqual(dose!.unit, .unitsPerHour)
  134. XCTAssertEqual(dose!.deliveredUnits, 0.75)
  135. XCTAssertEqual(dose!.description, nil)
  136. XCTAssertEqual(dose!.syncIdentifier, nil)
  137. XCTAssertEqual(dose!.scheduledBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0))
  138. XCTAssertFalse(dose!.isMutable)
  139. XCTAssertTrue(dose!.wasProgrammedByPumpUI)
  140. }
  141. }
  142. func testDoseTempBasalIsSuspend() {
  143. cacheStore.managedObjectContext.performAndWait {
  144. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  145. object.provenanceIdentifier = Bundle.main.bundleIdentifier!
  146. object.hasLoopKitOrigin = false
  147. object.startDate = dateFormatter.date(from: "2020-01-02T03:04:06Z")!
  148. object.endDate = dateFormatter.date(from: "2020-01-02T03:34:06Z")!
  149. object.syncIdentifier = nil
  150. object.value = 0.75
  151. object.scheduledBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0)
  152. object.programmedTempBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.5)
  153. object.reason = .basal
  154. object.createdAt = dateFormatter.date(from: "2020-01-02T04:04:07Z")!
  155. object.isSuspend = true
  156. object.wasProgrammedByPumpUI = true
  157. let dose = object.dose
  158. XCTAssertNotNil(dose)
  159. XCTAssertEqual(dose!.type, .suspend)
  160. XCTAssertEqual(dose!.startDate, dateFormatter.date(from: "2020-01-02T03:04:06Z")!)
  161. XCTAssertEqual(dose!.endDate, dateFormatter.date(from: "2020-01-02T03:34:06Z")!)
  162. XCTAssertEqual(dose!.value, 1.5)
  163. XCTAssertEqual(dose!.unit, .unitsPerHour)
  164. XCTAssertEqual(dose!.deliveredUnits, 0.75)
  165. XCTAssertEqual(dose!.description, nil)
  166. XCTAssertEqual(dose!.syncIdentifier, nil)
  167. XCTAssertEqual(dose!.scheduledBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0))
  168. XCTAssertFalse(dose!.isMutable)
  169. XCTAssertTrue(dose!.wasProgrammedByPumpUI)
  170. }
  171. }
  172. func testDoseTempBasalIsMutable() {
  173. cacheStore.managedObjectContext.performAndWait {
  174. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  175. object.provenanceIdentifier = Bundle.main.bundleIdentifier!
  176. object.hasLoopKitOrigin = false
  177. object.startDate = dateFormatter.date(from: "2020-01-02T03:04:06Z")!
  178. object.endDate = dateFormatter.date(from: "2020-01-02T03:34:06Z")!
  179. object.syncIdentifier = nil
  180. object.value = 0.75
  181. object.scheduledBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0)
  182. object.programmedTempBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.5)
  183. object.reason = .basal
  184. object.createdAt = dateFormatter.date(from: "2020-01-02T04:04:07Z")!
  185. object.isSuspend = false
  186. object.isMutable = true
  187. object.wasProgrammedByPumpUI = true
  188. let dose = object.dose
  189. XCTAssertNotNil(dose)
  190. XCTAssertEqual(dose!.type, .tempBasal)
  191. XCTAssertEqual(dose!.startDate, dateFormatter.date(from: "2020-01-02T03:04:06Z")!)
  192. XCTAssertEqual(dose!.endDate, dateFormatter.date(from: "2020-01-02T03:34:06Z")!)
  193. XCTAssertEqual(dose!.value, 1.5)
  194. XCTAssertEqual(dose!.unit, .unitsPerHour)
  195. XCTAssertNil(dose!.deliveredUnits)
  196. XCTAssertEqual(dose!.description, nil)
  197. XCTAssertEqual(dose!.syncIdentifier, nil)
  198. XCTAssertEqual(dose!.scheduledBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0))
  199. XCTAssertTrue(dose!.isMutable)
  200. XCTAssertTrue(dose!.wasProgrammedByPumpUI)
  201. }
  202. }
  203. func testDoseTempBasalDeleted() {
  204. cacheStore.managedObjectContext.performAndWait {
  205. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  206. object.provenanceIdentifier = Bundle.main.bundleIdentifier!
  207. object.hasLoopKitOrigin = false
  208. object.startDate = dateFormatter.date(from: "2020-01-02T03:04:06Z")!
  209. object.endDate = dateFormatter.date(from: "2020-01-02T03:34:06Z")!
  210. object.syncIdentifier = nil
  211. object.value = 0.75
  212. object.scheduledBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0)
  213. object.programmedTempBasalRate = HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.5)
  214. object.reason = .basal
  215. object.createdAt = dateFormatter.date(from: "2020-01-02T04:04:07Z")!
  216. object.deletedAt = dateFormatter.date(from: "2020-01-02T04:34:06Z")!
  217. object.isSuspend = false
  218. object.wasProgrammedByPumpUI = true
  219. let dose = object.dose
  220. XCTAssertNotNil(dose)
  221. XCTAssertEqual(dose!.type, .tempBasal)
  222. XCTAssertEqual(dose!.startDate, dateFormatter.date(from: "2020-01-02T03:04:06Z")!)
  223. XCTAssertEqual(dose!.endDate, dateFormatter.date(from: "2020-01-02T03:34:06Z")!)
  224. XCTAssertEqual(dose!.value, 1.5)
  225. XCTAssertEqual(dose!.unit, .unitsPerHour)
  226. XCTAssertEqual(dose!.deliveredUnits, 0.75)
  227. XCTAssertEqual(dose!.description, nil)
  228. XCTAssertEqual(dose!.syncIdentifier, nil)
  229. XCTAssertEqual(dose!.scheduledBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0))
  230. XCTAssertFalse(dose!.isMutable)
  231. XCTAssertTrue(dose!.wasProgrammedByPumpUI)
  232. }
  233. }
  234. func testDoseBolus() {
  235. cacheStore.managedObjectContext.performAndWait {
  236. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  237. object.provenanceIdentifier = Bundle.main.bundleIdentifier!
  238. object.hasLoopKitOrigin = true
  239. object.startDate = dateFormatter.date(from: "2020-01-02T05:04:05Z")!
  240. object.endDate = dateFormatter.date(from: "2020-01-02T05:05:05Z")!
  241. object.syncIdentifier = "9AA61454-EED5-476F-8E57-4BA63D0267C1"
  242. object.value = 2.25
  243. object.scheduledBasalRate = nil
  244. object.programmedTempBasalRate = nil
  245. object.reason = .bolus
  246. object.createdAt = dateFormatter.date(from: "2020-01-02T05:05:06Z")!
  247. object.wasProgrammedByPumpUI = true
  248. let dose = object.dose
  249. XCTAssertNotNil(dose)
  250. XCTAssertEqual(dose!.type, .bolus)
  251. XCTAssertEqual(dose!.startDate, dateFormatter.date(from: "2020-01-02T05:04:05Z")!)
  252. XCTAssertEqual(dose!.endDate, dateFormatter.date(from: "2020-01-02T05:05:05Z")!)
  253. XCTAssertEqual(dose!.value, 2.25)
  254. XCTAssertEqual(dose!.unit, .units)
  255. XCTAssertEqual(dose!.deliveredUnits, nil)
  256. XCTAssertEqual(dose!.description, nil)
  257. XCTAssertEqual(dose!.syncIdentifier, "9AA61454-EED5-476F-8E57-4BA63D0267C1")
  258. XCTAssertEqual(dose!.scheduledBasalRate, nil)
  259. XCTAssertFalse(dose!.isMutable)
  260. XCTAssertTrue(dose!.wasProgrammedByPumpUI)
  261. }
  262. }
  263. func testDoseBolusIsMutable() {
  264. cacheStore.managedObjectContext.performAndWait {
  265. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  266. object.provenanceIdentifier = Bundle.main.bundleIdentifier!
  267. object.hasLoopKitOrigin = true
  268. object.startDate = dateFormatter.date(from: "2020-01-02T05:04:05Z")!
  269. object.endDate = dateFormatter.date(from: "2020-01-02T05:05:05Z")!
  270. object.syncIdentifier = "9AA61454-EED5-476F-8E57-4BA63D0267C1"
  271. object.value = 2.25
  272. object.scheduledBasalRate = nil
  273. object.programmedTempBasalRate = nil
  274. object.reason = .bolus
  275. object.createdAt = dateFormatter.date(from: "2020-01-02T05:05:06Z")!
  276. object.isMutable = true
  277. object.wasProgrammedByPumpUI = true
  278. let dose = object.dose
  279. XCTAssertNotNil(dose)
  280. XCTAssertEqual(dose!.type, .bolus)
  281. XCTAssertEqual(dose!.startDate, dateFormatter.date(from: "2020-01-02T05:04:05Z")!)
  282. XCTAssertEqual(dose!.endDate, dateFormatter.date(from: "2020-01-02T05:05:05Z")!)
  283. XCTAssertEqual(dose!.value, 2.25)
  284. XCTAssertEqual(dose!.unit, .units)
  285. XCTAssertEqual(dose!.deliveredUnits, nil)
  286. XCTAssertEqual(dose!.description, nil)
  287. XCTAssertEqual(dose!.syncIdentifier, "9AA61454-EED5-476F-8E57-4BA63D0267C1")
  288. XCTAssertEqual(dose!.scheduledBasalRate, nil)
  289. XCTAssertTrue(dose!.isMutable)
  290. XCTAssertTrue(dose!.wasProgrammedByPumpUI)
  291. }
  292. }
  293. private let dateFormatter = ISO8601DateFormatter()
  294. }
  295. class CachedInsulinDeliveryObjectOperationsTests: PersistenceControllerTestCase {
  296. func testCreateWithUUIDAndWithoutOptional() {
  297. let metadata: [String: Any] = [
  298. HKMetadataKeyInsulinDeliveryReason: HKInsulinDeliveryReason.bolus.rawValue,
  299. ]
  300. let sample = HKQuantitySample(type: HKQuantityType.quantityType(forIdentifier: .insulinDelivery)!,
  301. quantity: HKQuantity(unit: .internationalUnit(), doubleValue: 2.25),
  302. start: dateFormatter.date(from: "2020-02-03T04:05:06Z")!,
  303. end: dateFormatter.date(from: "2020-02-03T04:05:36Z")!,
  304. metadata: metadata)
  305. cacheStore.managedObjectContext.performAndWait {
  306. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  307. object.create(fromExisting: sample, on: dateFormatter.date(from: "2020-02-03T04:05:37Z")!)
  308. XCTAssertEqual(object.uuid, sample.uuid)
  309. XCTAssertEqual(object.provenanceIdentifier, "") // Not yet persisted so HealthKit reports as empty string
  310. XCTAssertEqual(object.hasLoopKitOrigin, false)
  311. XCTAssertEqual(object.startDate, dateFormatter.date(from: "2020-02-03T04:05:06Z")!)
  312. XCTAssertEqual(object.endDate, dateFormatter.date(from: "2020-02-03T04:05:36Z")!)
  313. XCTAssertEqual(object.syncIdentifier, sample.uuid.uuidString)
  314. XCTAssertEqual(object.value, 2.25)
  315. XCTAssertNil(object.scheduledBasalRate)
  316. XCTAssertNil(object.programmedTempBasalRate)
  317. XCTAssertEqual(object.reason, .bolus)
  318. XCTAssertEqual(object.createdAt, dateFormatter.date(from: "2020-02-03T04:05:37Z")!)
  319. XCTAssertFalse(object.isSuspend)
  320. }
  321. }
  322. func testCreateAndUpdateFromEntry() {
  323. let createEntry = DoseEntry(type: .tempBasal,
  324. startDate: dateFormatter.date(from: "2020-02-03T04:05:06Z")!,
  325. endDate: dateFormatter.date(from: "2020-02-03T04:35:06Z")!,
  326. value: 1.5,
  327. unit: .unitsPerHour,
  328. deliveredUnits: nil,
  329. description: "Create Dose Entry",
  330. syncIdentifier: "A1F8E29B-33D6-4B38-B4CD-D84F14744871",
  331. scheduledBasalRate: HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0),
  332. insulinType: .apidra,
  333. automatic: true,
  334. manuallyEntered: true,
  335. isMutable: true)
  336. let updateEntry = DoseEntry(type: .tempBasal,
  337. startDate: dateFormatter.date(from: "2020-02-03T04:05:06Z")!,
  338. endDate: dateFormatter.date(from: "2020-02-03T04:10:06Z")!,
  339. value: 3.0,
  340. unit: .unitsPerHour,
  341. deliveredUnits: 0.25,
  342. description: "Update Dose Entry",
  343. syncIdentifier: "A1F8E29B-33D6-4B38-B4CD-D84F14744871",
  344. scheduledBasalRate: HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 0.5),
  345. insulinType: .fiasp,
  346. automatic: false,
  347. manuallyEntered: false,
  348. isMutable: false)
  349. cacheStore.managedObjectContext.performAndWait {
  350. let object = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  351. object.create(from: createEntry, by: "Test Providence Identifier", at: dateFormatter.date(from: "2020-02-03T04:06:06Z")!)
  352. XCTAssertNil(object.uuid)
  353. XCTAssertEqual(object.provenanceIdentifier, "Test Providence Identifier")
  354. XCTAssertTrue(object.hasLoopKitOrigin)
  355. XCTAssertEqual(object.startDate, dateFormatter.date(from: "2020-02-03T04:05:06Z")!)
  356. XCTAssertEqual(object.endDate, dateFormatter.date(from: "2020-02-03T04:35:06Z")!)
  357. XCTAssertEqual(object.syncIdentifier, "A1F8E29B-33D6-4B38-B4CD-D84F14744871")
  358. XCTAssertEqual(object.value, 0.75)
  359. XCTAssertEqual(object.scheduledBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.0))
  360. XCTAssertEqual(object.programmedTempBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 1.5))
  361. XCTAssertEqual(object.reason, .basal)
  362. XCTAssertEqual(object.createdAt, dateFormatter.date(from: "2020-02-03T04:06:06Z")!)
  363. XCTAssertNil(object.deletedAt)
  364. XCTAssertEqual(object.insulinType, .apidra)
  365. XCTAssertEqual(object.automaticallyIssued, true)
  366. XCTAssertEqual(object.manuallyEntered, true)
  367. XCTAssertEqual(object.isSuspend, false)
  368. XCTAssertEqual(object.isMutable, true)
  369. object.update(from: updateEntry)
  370. XCTAssertNil(object.uuid)
  371. XCTAssertEqual(object.provenanceIdentifier, "Test Providence Identifier")
  372. XCTAssertTrue(object.hasLoopKitOrigin)
  373. XCTAssertEqual(object.startDate, dateFormatter.date(from: "2020-02-03T04:05:06Z")!)
  374. XCTAssertEqual(object.endDate, dateFormatter.date(from: "2020-02-03T04:10:06Z")!)
  375. XCTAssertEqual(object.syncIdentifier, "A1F8E29B-33D6-4B38-B4CD-D84F14744871")
  376. XCTAssertEqual(object.value, 0.25)
  377. XCTAssertEqual(object.scheduledBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 0.5))
  378. XCTAssertEqual(object.programmedTempBasalRate, HKQuantity(unit: .internationalUnitsPerHour, doubleValue: 3.0))
  379. XCTAssertEqual(object.reason, .basal)
  380. XCTAssertEqual(object.createdAt, dateFormatter.date(from: "2020-02-03T04:06:06Z")!)
  381. XCTAssertNil(object.deletedAt)
  382. XCTAssertEqual(object.insulinType, .fiasp)
  383. XCTAssertEqual(object.automaticallyIssued, false)
  384. XCTAssertEqual(object.manuallyEntered, false)
  385. XCTAssertEqual(object.isSuspend, false)
  386. XCTAssertEqual(object.isMutable, false)
  387. }
  388. }
  389. private let dateFormatter = ISO8601DateFormatter()
  390. }
  391. class CachedInsulinDeliveryObjectConstraintTests: PersistenceControllerTestCase {
  392. func testUUIDUniqueConstraintPreSave() {
  393. cacheStore.managedObjectContext.performAndWait {
  394. let uuid = UUID()
  395. let object1 = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  396. object1.setDefaultValues()
  397. object1.uuid = uuid
  398. object1.syncIdentifier = "object1"
  399. let object2 = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  400. object2.setDefaultValues()
  401. object2.uuid = uuid
  402. object2.syncIdentifier = "object2"
  403. try! cacheStore.managedObjectContext.save()
  404. let objects: [CachedInsulinDeliveryObject] = cacheStore.managedObjectContext.all()
  405. XCTAssertEqual(1, objects.count)
  406. }
  407. }
  408. func testUUIDUniqueConstraintPostSave() {
  409. cacheStore.managedObjectContext.performAndWait {
  410. let uuid = UUID()
  411. let object1 = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  412. object1.setDefaultValues()
  413. object1.uuid = uuid
  414. try! cacheStore.managedObjectContext.save()
  415. let object2 = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  416. object2.setDefaultValues()
  417. object2.uuid = uuid
  418. try! cacheStore.managedObjectContext.save()
  419. let objects: [CachedInsulinDeliveryObject] = cacheStore.managedObjectContext.all()
  420. XCTAssertEqual(1, objects.count)
  421. }
  422. }
  423. func testSyncIdentifierUniqueConstraint() {
  424. cacheStore.managedObjectContext.performAndWait {
  425. let uuid = UUID()
  426. let object1 = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  427. object1.setDefaultValues()
  428. object1.syncIdentifier = uuid.uuidString
  429. try! cacheStore.managedObjectContext.save()
  430. let object2 = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  431. object2.setDefaultValues()
  432. object2.syncIdentifier = uuid.uuidString
  433. try! cacheStore.managedObjectContext.save()
  434. let objects: [CachedInsulinDeliveryObject] = cacheStore.managedObjectContext.all()
  435. XCTAssertEqual(1, objects.count)
  436. }
  437. }
  438. func testSaveWithDefaultValues() {
  439. cacheStore.managedObjectContext.performAndWait {
  440. let object1 = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  441. object1.setDefaultValues()
  442. try! cacheStore.managedObjectContext.save()
  443. let object2 = CachedInsulinDeliveryObject(context: cacheStore.managedObjectContext)
  444. object2.setDefaultValues()
  445. try! cacheStore.managedObjectContext.save()
  446. let objects: [CachedInsulinDeliveryObject] = cacheStore.managedObjectContext.all()
  447. XCTAssertEqual(2, objects.count)
  448. }
  449. }
  450. }
  451. extension CachedInsulinDeliveryObject {
  452. fileprivate func setDefaultValues() {
  453. self.uuid = UUID()
  454. self.provenanceIdentifier = "CachedInsulinDeliveryObjectTests"
  455. self.hasLoopKitOrigin = true
  456. self.startDate = Date()
  457. self.endDate = Date()
  458. self.syncIdentifier = UUID().uuidString
  459. self.value = 3.5
  460. self.scheduledBasalRate = nil
  461. self.programmedTempBasalRate = nil
  462. self.isSuspend = false
  463. self.reason = .basal
  464. self.createdAt = Date()
  465. }
  466. }