DetermineBasalSMBEnablementTests.swift 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import Foundation
  2. import Testing
  3. @testable import Trio
  4. @Suite("Determination: SMB Enablement Tests") struct SMBEnablementTests {
  5. /// Scheduled-off override window should always disable SMB
  6. @Test("should disable SMB during scheduled-off window") func disableDuringScheduledOff() async throws {
  7. let now = Calendar.current.date(from: DateComponents(hour: 10))!
  8. let override = Override(
  9. name: "scheduledOff",
  10. enabled: true,
  11. date: now,
  12. duration: 0,
  13. indefinite: false,
  14. percentage: 1,
  15. smbIsOff: false,
  16. isPreset: false,
  17. id: "",
  18. overrideTarget: false,
  19. target: 0,
  20. advancedSettings: false,
  21. isfAndCr: false,
  22. isf: false,
  23. cr: false,
  24. smbIsScheduledOff: true,
  25. start: 9,
  26. end: 17,
  27. smbMinutes: 0,
  28. uamMinutes: 0
  29. )
  30. var profile = Profile()
  31. profile.enableSMBAlways = true
  32. let bg = BloodGlucose(
  33. sgv: 120,
  34. date: Decimal(now.timeIntervalSince1970 * 1000),
  35. dateString: now
  36. )
  37. let autosens = Autosens(ratio: 1, newisf: nil)
  38. #expect(
  39. DeterminationGenerator.isSMBEnabled(
  40. glucose: bg,
  41. profile: profile,
  42. autosens: autosens,
  43. mealData: nil,
  44. override: override,
  45. shouldProtectDueToHIGH: false,
  46. currentTime: now
  47. ) == false
  48. )
  49. }
  50. /// A hard-off override should disable SMB immediately
  51. @Test("should disable SMB when override.smbIsOff") func disableWhenOverrideOff() async throws {
  52. let now = Date()
  53. let override = Override(
  54. name: "hardOff",
  55. enabled: true,
  56. date: now,
  57. duration: 0,
  58. indefinite: false,
  59. percentage: 1,
  60. smbIsOff: true,
  61. isPreset: false,
  62. id: "",
  63. overrideTarget: false,
  64. target: 0,
  65. advancedSettings: false,
  66. isfAndCr: false,
  67. isf: false,
  68. cr: false,
  69. smbIsScheduledOff: false,
  70. start: 0,
  71. end: 0,
  72. smbMinutes: 0,
  73. uamMinutes: 0
  74. )
  75. let profile = Profile()
  76. let bg = BloodGlucose(sgv: 100, date: Decimal(now.timeIntervalSince1970 * 1000), dateString: now)
  77. let autosens = Autosens(ratio: 1, newisf: nil)
  78. #expect(
  79. DeterminationGenerator.isSMBEnabled(
  80. glucose: bg,
  81. profile: profile,
  82. autosens: autosens,
  83. mealData: nil,
  84. override: override,
  85. shouldProtectDueToHIGH: false,
  86. currentTime: now
  87. ) == false
  88. )
  89. }
  90. /// Should disable if CGM reports “HIGH” protection
  91. @Test("should disable SMB when protectDueToHIGH") func disableWhenProtectDueToHIGH() async throws {
  92. let now = Date()
  93. let profile = Profile()
  94. let bg = BloodGlucose(sgv: 150, date: Decimal(now.timeIntervalSince1970 * 1000), dateString: now)
  95. let autosens = Autosens(ratio: 1, newisf: nil)
  96. #expect(
  97. DeterminationGenerator.isSMBEnabled(
  98. glucose: bg,
  99. profile: profile,
  100. autosens: autosens,
  101. mealData: nil,
  102. override: nil,
  103. shouldProtectDueToHIGH: true,
  104. currentTime: now
  105. ) == false
  106. )
  107. }
  108. /// Always-on preference should enable SMB
  109. @Test("should enable SMB when enableSMBAlways") func enableWhenAlwaysEnabled() async throws {
  110. let now = Date()
  111. var profile = Profile()
  112. profile.enableSMBAlways = true
  113. let bg = BloodGlucose(sgv: 80, date: Decimal(now.timeIntervalSince1970 * 1000), dateString: now)
  114. let autosens = Autosens(ratio: 1, newisf: nil)
  115. #expect(
  116. DeterminationGenerator.isSMBEnabled(
  117. glucose: bg,
  118. profile: profile,
  119. autosens: autosens,
  120. mealData: nil,
  121. override: nil,
  122. shouldProtectDueToHIGH: false,
  123. currentTime: now
  124. ) == true
  125. )
  126. }
  127. /// Low temp-target below 100 should enable SMB when allowed
  128. @Test("should enable SMB with active low temp target") func enableWithActiveLowTempTarget() async throws {
  129. let now = Date()
  130. var profile = Profile()
  131. profile.temptargetSet = true
  132. profile.enableSMBWithTemptarget = true
  133. profile.targetBg = 90
  134. let bg = BloodGlucose(sgv: 95, date: Decimal(now.timeIntervalSince1970 * 1000), dateString: now)
  135. let autosens = Autosens(ratio: 1, newisf: nil)
  136. #expect(
  137. DeterminationGenerator.isSMBEnabled(
  138. glucose: bg,
  139. profile: profile,
  140. autosens: autosens,
  141. mealData: nil,
  142. override: nil,
  143. shouldProtectDueToHIGH: false,
  144. currentTime: now
  145. ) == true
  146. )
  147. }
  148. /// High temp-target above 100 should disable SMB when not allowed
  149. @Test("should disable SMB with high temp target not allowed") func disableWhenHighTempTargetNotAllowed() async throws {
  150. let now = Date()
  151. var profile = Profile()
  152. profile.temptargetSet = true
  153. profile.allowSMBWithHighTemptarget = false
  154. profile.targetBg = 120
  155. let bg = BloodGlucose(sgv: 115, date: Decimal(now.timeIntervalSince1970 * 1000), dateString: now)
  156. let autosens = Autosens(ratio: 1, newisf: nil)
  157. #expect(
  158. DeterminationGenerator.isSMBEnabled(
  159. glucose: bg,
  160. profile: profile,
  161. autosens: autosens,
  162. mealData: nil,
  163. override: nil,
  164. shouldProtectDueToHIGH: false,
  165. currentTime: now
  166. ) == false
  167. )
  168. }
  169. /// Carbs-on-board should enable SMB when COB > 0
  170. @Test("should enable SMB with COB") func enableWithCOB() async throws {
  171. let now = Date()
  172. var profile = Profile()
  173. profile.enableSMBWithCOB = true
  174. let mealData = ComputedCarbs(
  175. carbs: 30,
  176. mealCOB: 10,
  177. currentDeviation: 0,
  178. maxDeviation: 0,
  179. minDeviation: 0,
  180. slopeFromMaxDeviation: 0,
  181. slopeFromMinDeviation: 0,
  182. allDeviations: [0],
  183. lastCarbTime: now.timeIntervalSince1970
  184. )
  185. let bg = BloodGlucose(sgv: 100, date: Decimal(now.timeIntervalSince1970 * 1000), dateString: now)
  186. let autosens = Autosens(ratio: 1, newisf: nil)
  187. #expect(
  188. DeterminationGenerator.isSMBEnabled(
  189. glucose: bg,
  190. profile: profile,
  191. autosens: autosens,
  192. mealData: mealData,
  193. override: nil,
  194. shouldProtectDueToHIGH: false,
  195. currentTime: now
  196. ) == true
  197. )
  198. }
  199. /// Any carb entry should enable SMB for the after-carbs window
  200. @Test("should enable SMB after carbs") func enableAfterCarbs() async throws {
  201. let now = Date()
  202. var profile = Profile()
  203. profile.enableSMBAfterCarbs = true
  204. let mealData = ComputedCarbs(
  205. carbs: 15,
  206. mealCOB: 0,
  207. currentDeviation: 0,
  208. maxDeviation: 0,
  209. minDeviation: 0,
  210. slopeFromMaxDeviation: 0,
  211. slopeFromMinDeviation: 0,
  212. allDeviations: [0],
  213. lastCarbTime: now.timeIntervalSince1970
  214. )
  215. let bg = BloodGlucose(sgv: 90, date: Decimal(now.timeIntervalSince1970 * 1000), dateString: now)
  216. let autosens = Autosens(ratio: 1, newisf: nil)
  217. #expect(
  218. DeterminationGenerator.isSMBEnabled(
  219. glucose: bg,
  220. profile: profile,
  221. autosens: autosens,
  222. mealData: mealData,
  223. override: nil,
  224. shouldProtectDueToHIGH: false,
  225. currentTime: now
  226. ) == true
  227. )
  228. }
  229. /// High-BG condition should enable SMB when above threshold
  230. @Test("should enable SMB for high BG") func enableWithHighBG() async throws {
  231. let now = Date()
  232. var profile = Profile()
  233. profile.enableSMBHighBg = true
  234. profile.enableSMBHighBgTarget = 130
  235. let bg = BloodGlucose(sgv: 135, date: Decimal(now.timeIntervalSince1970 * 1000), dateString: now)
  236. let autosens = Autosens(ratio: 1, newisf: nil)
  237. #expect(
  238. DeterminationGenerator.isSMBEnabled(
  239. glucose: bg,
  240. profile: profile,
  241. autosens: autosens,
  242. mealData: nil,
  243. override: nil,
  244. shouldProtectDueToHIGH: false,
  245. currentTime: now
  246. ) == true
  247. )
  248. }
  249. }