Improve basal schedule validation and add profile to basal schedule mapping tests
This commit is contained in:
parent
a399c24ccd
commit
0bcdf30a7e
|
@ -10,8 +10,10 @@ public class BasalSchedule {
|
||||||
private final List<BasalScheduleEntry> entries;
|
private final List<BasalScheduleEntry> entries;
|
||||||
|
|
||||||
public BasalSchedule(List<BasalScheduleEntry> entries) {
|
public BasalSchedule(List<BasalScheduleEntry> entries) {
|
||||||
if (entries == null) {
|
if (entries == null || entries.size() == 0) {
|
||||||
throw new IllegalArgumentException("Entries cannot be null");
|
throw new IllegalArgumentException("Entries can not be empty");
|
||||||
|
} else if (!entries.get(0).getStartTime().isEqual(Duration.ZERO)) {
|
||||||
|
throw new IllegalArgumentException("First basal schedule entry should have 0 offset");
|
||||||
}
|
}
|
||||||
this.entries = entries;
|
this.entries = entries;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,14 @@ public class BasalScheduleEntry {
|
||||||
private final Duration startTime;
|
private final Duration startTime;
|
||||||
|
|
||||||
public BasalScheduleEntry(double rate, Duration startTime) {
|
public BasalScheduleEntry(double rate, Duration startTime) {
|
||||||
if (rate < 0D) {
|
if (startTime.isLongerThan(Duration.standardHours(24).minus(Duration.standardSeconds(1))) || startTime.isShorterThan(Duration.ZERO)) {
|
||||||
|
throw new IllegalArgumentException("Invalid start time");
|
||||||
|
} else if (rate < 0D) {
|
||||||
throw new IllegalArgumentException("Rate should be >= 0");
|
throw new IllegalArgumentException("Rate should be >= 0");
|
||||||
} else if (rate > OmnipodConst.MAX_BASAL_RATE) {
|
} else if (rate > OmnipodConst.MAX_BASAL_RATE) {
|
||||||
throw new IllegalArgumentException("Rate exceeds max basal rate");
|
throw new IllegalArgumentException("Rate exceeds max basal rate");
|
||||||
|
} else if (rate % OmnipodConst.POD_PULSE_SIZE > 0.000001 && rate % OmnipodConst.POD_PULSE_SIZE - OmnipodConst.POD_PULSE_SIZE < -0.000001) {
|
||||||
|
throw new IllegalArgumentException("Unsupported basal rate precision");
|
||||||
}
|
}
|
||||||
this.rate = rate;
|
this.rate = rate;
|
||||||
this.startTime = startTime;
|
this.startTime = startTime;
|
||||||
|
|
|
@ -173,7 +173,13 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
|
||||||
}
|
}
|
||||||
} else if (PodInitActionType.FillCannulaSetBasalProfileWizardStep.equals(podInitActionType)) {
|
} else if (PodInitActionType.FillCannulaSetBasalProfileWizardStep.equals(podInitActionType)) {
|
||||||
try {
|
try {
|
||||||
Disposable disposable = delegate.insertCannula(mapProfileToBasalSchedule(profile)).subscribe(res -> //
|
BasalSchedule basalSchedule;
|
||||||
|
try {
|
||||||
|
basalSchedule = mapProfileToBasalSchedule(profile);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new CommandInitializationException("Basal profile mapping failed", ex);
|
||||||
|
}
|
||||||
|
Disposable disposable = delegate.insertCannula(basalSchedule).subscribe(res -> //
|
||||||
handleSetupActionResult(podInitActionType, podInitReceiver, res, time));
|
handleSetupActionResult(podInitActionType, podInitReceiver, res, time));
|
||||||
return new PumpEnactResult().success(true).enacted(true);
|
return new PumpEnactResult().success(true).enacted(true);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -222,11 +228,17 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PumpEnactResult setBasalProfile(Profile basalProfile) {
|
public PumpEnactResult setBasalProfile(Profile profile) {
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
delegate.setBasalSchedule(mapProfileToBasalSchedule(basalProfile), isBasalBeepsEnabled());
|
BasalSchedule basalSchedule;
|
||||||
addSuccessToHistory(time, PodHistoryEntryType.SetBasalSchedule, basalProfile);
|
try {
|
||||||
|
basalSchedule = mapProfileToBasalSchedule(profile);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new CommandInitializationException("Basal profile mapping failed", ex);
|
||||||
|
}
|
||||||
|
delegate.setBasalSchedule(basalSchedule, isBasalBeepsEnabled());
|
||||||
|
addSuccessToHistory(time, PodHistoryEntryType.SetBasalSchedule, profile);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
if ((ex instanceof OmnipodException) && !((OmnipodException) ex).isCertainFailure()) {
|
if ((ex instanceof OmnipodException) && !((OmnipodException) ex).isCertainFailure()) {
|
||||||
addToHistory(time, PodHistoryEntryType.SetBasalSchedule, "Uncertain failure", false);
|
addToHistory(time, PodHistoryEntryType.SetBasalSchedule, "Uncertain failure", false);
|
||||||
|
@ -623,9 +635,14 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
|
||||||
return L.isEnabled(L.PUMP);
|
return L.isEnabled(L.PUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO add tests
|
|
||||||
static BasalSchedule mapProfileToBasalSchedule(Profile profile) {
|
static BasalSchedule mapProfileToBasalSchedule(Profile profile) {
|
||||||
|
if (profile == null) {
|
||||||
|
throw new IllegalArgumentException("Profile can not be null");
|
||||||
|
}
|
||||||
Profile.ProfileValue[] basalValues = profile.getBasalValues();
|
Profile.ProfileValue[] basalValues = profile.getBasalValues();
|
||||||
|
if(basalValues == null) {
|
||||||
|
throw new IllegalArgumentException("Basal values can not be null");
|
||||||
|
}
|
||||||
List<BasalScheduleEntry> entries = new ArrayList<>();
|
List<BasalScheduleEntry> entries = new ArrayList<>();
|
||||||
for (Profile.ProfileValue basalValue : basalValues) {
|
for (Profile.ProfileValue basalValue : basalValues) {
|
||||||
entries.add(new BasalScheduleEntry(basalValue.value, Duration.standardSeconds(basalValue.timeAsSeconds)));
|
entries.add(new BasalScheduleEntry(basalValue.value, Duration.standardSeconds(basalValue.timeAsSeconds)));
|
||||||
|
|
|
@ -4,4 +4,8 @@ public class CommandInitializationException extends OmnipodException {
|
||||||
public CommandInitializationException(String message) {
|
public CommandInitializationException(String message) {
|
||||||
super(message, true);
|
super(message, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommandInitializationException(String message, Throwable cause) {
|
||||||
|
super(message, cause, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.driver.comm;
|
||||||
|
|
||||||
|
import org.joda.time.Duration;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalScheduleEntry;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.powermock.api.mockito.PowerMockito.when;
|
||||||
|
|
||||||
|
public class AapsOmnipodManagerTest {
|
||||||
|
@Rule
|
||||||
|
public ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validProfile() {
|
||||||
|
Profile profile = mock(Profile.class);
|
||||||
|
|
||||||
|
Profile.ProfileValue value1 = mock(Profile.ProfileValue.class);
|
||||||
|
value1.timeAsSeconds = 0;
|
||||||
|
value1.value = 0.5D;
|
||||||
|
|
||||||
|
Profile.ProfileValue value2 = mock(Profile.ProfileValue.class);
|
||||||
|
value2.timeAsSeconds = 18000;
|
||||||
|
value2.value = 1.0D;
|
||||||
|
|
||||||
|
Profile.ProfileValue value3 = mock(Profile.ProfileValue.class);
|
||||||
|
value3.timeAsSeconds = 50400;
|
||||||
|
value3.value = 3.05D;
|
||||||
|
|
||||||
|
when(profile.getBasalValues()).thenReturn(new Profile.ProfileValue[]{
|
||||||
|
value1,
|
||||||
|
value2,
|
||||||
|
value3
|
||||||
|
});
|
||||||
|
|
||||||
|
BasalSchedule basalSchedule = AapsOmnipodManager.mapProfileToBasalSchedule(profile);
|
||||||
|
|
||||||
|
List<BasalScheduleEntry> entries = basalSchedule.getEntries();
|
||||||
|
assertEquals(3, entries.size());
|
||||||
|
|
||||||
|
BasalScheduleEntry entry1 = entries.get(0);
|
||||||
|
assertEquals(Duration.standardSeconds(0), entry1.getStartTime());
|
||||||
|
assertEquals(0.5D, entry1.getRate(), 0.000001);
|
||||||
|
|
||||||
|
BasalScheduleEntry entry2 = entries.get(1);
|
||||||
|
assertEquals(Duration.standardSeconds(18000), entry2.getStartTime());
|
||||||
|
assertEquals(1.0D, entry2.getRate(), 0.000001);
|
||||||
|
|
||||||
|
BasalScheduleEntry entry3 = entries.get(2);
|
||||||
|
assertEquals(Duration.standardSeconds(50400), entry3.getStartTime());
|
||||||
|
assertEquals(3.05D, entry3.getRate(), 0.000001);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidProfileNullProfile() {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
thrown.expectMessage("Profile can not be null");
|
||||||
|
AapsOmnipodManager.mapProfileToBasalSchedule(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidProfileNullEntries() {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
thrown.expectMessage("Basal values can not be null");
|
||||||
|
AapsOmnipodManager.mapProfileToBasalSchedule(mock(Profile.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidProfileZeroEntries() {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
thrown.expectMessage("Entries can not be empty");
|
||||||
|
Profile profile = mock(Profile.class);
|
||||||
|
|
||||||
|
when(profile.getBasalValues()).thenReturn(new Profile.ProfileValue[0]);
|
||||||
|
|
||||||
|
AapsOmnipodManager.mapProfileToBasalSchedule(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidProfileNonZeroOffset() {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
thrown.expectMessage("First basal schedule entry should have 0 offset");
|
||||||
|
|
||||||
|
Profile profile = mock(Profile.class);
|
||||||
|
|
||||||
|
Profile.ProfileValue value = mock(Profile.ProfileValue.class);
|
||||||
|
value.timeAsSeconds = 500;
|
||||||
|
value.value = 0.5D;
|
||||||
|
|
||||||
|
when(profile.getBasalValues()).thenReturn(new Profile.ProfileValue[]{
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
|
||||||
|
AapsOmnipodManager.mapProfileToBasalSchedule(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidProfileMoreThan24Hours() {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
thrown.expectMessage("Invalid start time");
|
||||||
|
|
||||||
|
Profile profile = mock(Profile.class);
|
||||||
|
|
||||||
|
Profile.ProfileValue value1 = mock(Profile.ProfileValue.class);
|
||||||
|
value1.timeAsSeconds = 0;
|
||||||
|
value1.value = 0.5D;
|
||||||
|
|
||||||
|
Profile.ProfileValue value2 = mock(Profile.ProfileValue.class);
|
||||||
|
value2.timeAsSeconds = 86400;
|
||||||
|
value2.value = 0.5D;
|
||||||
|
|
||||||
|
when(profile.getBasalValues()).thenReturn(new Profile.ProfileValue[]{
|
||||||
|
value1,
|
||||||
|
value2
|
||||||
|
});
|
||||||
|
|
||||||
|
AapsOmnipodManager.mapProfileToBasalSchedule(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidProfileNegativeOffset() {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
thrown.expectMessage("Invalid start time");
|
||||||
|
|
||||||
|
Profile profile = mock(Profile.class);
|
||||||
|
|
||||||
|
Profile.ProfileValue value = mock(Profile.ProfileValue.class);
|
||||||
|
value.timeAsSeconds = -1;
|
||||||
|
value.value = 0.5D;
|
||||||
|
|
||||||
|
when(profile.getBasalValues()).thenReturn(new Profile.ProfileValue[]{
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
|
||||||
|
AapsOmnipodManager.mapProfileToBasalSchedule(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void invalidProfileUnsupportedPrecision() {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
thrown.expectMessage("Unsupported basal rate precision");
|
||||||
|
|
||||||
|
Profile profile = mock(Profile.class);
|
||||||
|
|
||||||
|
Profile.ProfileValue value = mock(Profile.ProfileValue.class);
|
||||||
|
value.timeAsSeconds = 500;
|
||||||
|
value.value = 0.04D;
|
||||||
|
|
||||||
|
when(profile.getBasalValues()).thenReturn(new Profile.ProfileValue[]{
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
|
||||||
|
AapsOmnipodManager.mapProfileToBasalSchedule(profile);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue