diff --git a/tests/eventparser/test_from_json.py b/tests/eventparser/test_from_json.py index 6b5bb10..fa782c0 100644 --- a/tests/eventparser/test_from_json.py +++ b/tests/eventparser/test_from_json.py @@ -31,6 +31,40 @@ ALARM_5 = { "estimatedDateTime": "2026-04-30T01:00:00Z", } +# Real LID_CGM_DATA_G7 event: enum (glucoseValueStatus), ratio (rate ×0.1), +# raw egv seconds (egvTimeStamp), and bitmask arrays (cgmDataType, egvInfoBitmask). +CGM_399 = { + "deviceAssignmentId": "4ff6bebc-d4d6-4423-b123-eecfcf5a4238", + "eventCode": 399, + "sequenceGroup": 0, + "sequenceNumber": 441314, + "pumpDateTime": "2026-05-14T00:01:31", + "eventProperties": { + "glucoseValueStatus": 0, "cgmDataType": [0], "rate": -6, + "algorithmState": 32, "rssi": -78, "currentGlucoseDisplayValue": 167, + "egvTimeStamp": 579571288, "egvInfoBitmask": [0, 5, 6, 7, 8, 11, 12], + "interval": 0, "reservedD15": 0, + }, + "estimatedDateTime": "2026-05-14T00:01:31Z", +} + +# Real LID_AA_USER_MODE_CHANGE event: enum (requestedAction) and a bitmask +# array (activeSleepSchedule). +UMC_229 = { + "deviceAssignmentId": "4ff6bebc-d4d6-4423-b123-eecfcf5a4238", + "eventCode": 229, + "sequenceGroup": 0, + "sequenceNumber": 456851, + "pumpDateTime": "2026-05-18T10:15:53", + "eventProperties": { + "currentUserMode": 0, "previousUserMode": 1, "requestedAction": 2, + "spareA3": 0, "sleepStartedByGui": 1, "activeSleepSchedule": [0], + "spareB6": 0, "exerciseStoppedByTimer": 0, "exerciseChoice": 0, + "exerciseTime": 0, "eatingSoonStoppedByTimer": 0, + }, + "estimatedDateTime": "2026-05-18T10:15:53Z", +} + class TestBuildFromJson(unittest.TestCase): maxDiff = None @@ -87,5 +121,100 @@ class TestBuildFromJson(unittest.TestCase): self.assertEqual(ev.eventTimestamp.format('YYYY-MM-DDTHH:mm:ss'), "2026-04-30T00:00:00") +class TestEnumAndRatioFields(unittest.TestCase): + """#13: enum/dictionary fields arrive as raw ints and resolve through the + generated {field}Raw attr; ratio fields (×0.1) still compute.""" + maxDiff = None + + def test_enum_resolves_from_raw_int(self): + # commandedRateSource:3 -> Algorithm + ev = Event_from_json(BASAL_279) + self.assertEqual(ev.commandedRateSourceRaw, 3) + self.assertEqual(ev.commandedRateSource, + eventtypes.LidBasalDelivery.CommandedratesourceEnum.Algorithm) + + def test_dictionary_enum_resolves_from_raw_int(self): + # alarmId:18 -> ResumePumpAlarm (stored on the alarmidRaw attr) + ev = Event_from_json(ALARM_5) + self.assertEqual(ev.alarmidRaw, 18) + self.assertEqual(ev.alarmid, + eventtypes.LidAlarmActivated.AlarmidEnum.ResumePumpAlarm) + + def test_multiple_enums_on_one_event(self): + # requestedAction:2 -> StopSleep; previousUserMode:1 -> Sleeping + ev = Event_from_json(UMC_229) + self.assertEqual(ev.requestedaction, + eventtypes.LidAaUserModeChange.RequestedactionEnum.StopSleep) + self.assertEqual(ev.previoususermode, + eventtypes.LidAaUserModeChange.PrevioususermodeEnum.Sleeping) + + def test_ratio_field_scales(self): + # rate:-6 -> -0.6 mg/dL/min (rateRaw ×0.1) + ev = Event_from_json(CGM_399) + self.assertEqual(ev.rateRaw, -6) + self.assertAlmostEqual(ev.rate, -0.6) + + def test_enum_zero_value_resolves(self): + # glucoseValueStatus:0 -> PreciseValue (0 must not be treated as missing) + ev = Event_from_json(CGM_399) + self.assertEqual(ev.glucosevaluestatusRaw, 0) + self.assertEqual(ev.glucosevaluestatus, + eventtypes.LidCgmDataG7.GlucosevaluestatusEnum.PreciseValue) + + +class TestBitmaskFields(unittest.TestCase): + """#14: bitmask fields arrive as arrays of set-bit indices and must be + folded back into the raw int the {field}Raw attr / IntFlag expects.""" + maxDiff = None + + def test_single_bit_array(self): + # activeSleepSchedule:[0] -> 1<<0 == 1 + ev = Event_from_json(UMC_229) + self.assertEqual(ev.activesleepscheduleRaw, 1) + self.assertEqual(ev.activesleepschedule, + eventtypes.LidAaUserModeChange.ActivesleepscheduleBitmask.SleepSchedule1IsActive) + + def test_cgm_datatype_array(self): + # cgmDataType:[0] -> 1<<0 == 1 -> Fmr + ev = Event_from_json(CGM_399) + self.assertEqual(ev.cgmDataTypeRaw, 1) + self.assertEqual(ev.cgmDataType, + eventtypes.LidCgmDataG7.CgmdatatypeBitmask.Fmr) + + def test_multi_bit_array_round_trips_to_int(self): + # egvInfoBitmask:[0,5,6,7,8,11,12] -> sum(1<