isClosedLoopAllowed & isLoopInvokationAllowed tests

This commit is contained in:
Milos Kozak 2018-03-19 22:20:42 +01:00
parent 3a85a6f319
commit f6fdef7986
4 changed files with 189 additions and 30 deletions

View file

@ -3,9 +3,9 @@ package info.nightscout.androidaps.data;
import java.util.ArrayList;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.utils.SP;
/**

View file

@ -15,9 +15,9 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.interfaces.APSInterface;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.Loop.LoopPlugin;
@ -67,7 +67,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
@Override
public String getNameShort() {
String name = MainApp.sResources.getString(R.string.objectives_shortname);
String name = MainApp.gs(R.string.objectives_shortname);
if (!name.trim().isEmpty()) {
//only if translation exists
return name;
@ -115,7 +115,7 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
return -1;
}
class Objective {
public class Objective {
Integer num;
String objective;
String gate;
@ -131,6 +131,10 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
this.durationInDays = durationInDays;
this.accomplished = accomplished;
}
public void setStarted(Date started) {
this.started = started;
}
}
// Objective 0
@ -169,27 +173,27 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
apsEnabled = true;
return new RequirementResult(hasBGData && bgIsAvailableInNS && pumpStatusIsAvailableInNS && NSClientInternalPlugin.getPlugin().hasWritePermission() && LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP) && apsEnabled && vpUploadNeeded,
MainApp.sResources.getString(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
+ "\n" + MainApp.sResources.getString(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission())
+ (isVirtualPump ? "\n" + MainApp.sResources.getString(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
+ "\n" + MainApp.sResources.getString(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS)
+ "\n" + MainApp.sResources.getString(R.string.hasbgdata) + ": " + yesOrNo(hasBGData)
+ "\n" + MainApp.sResources.getString(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP))
+ "\n" + MainApp.sResources.getString(R.string.apsselected) + ": " + yesOrNo(apsEnabled)
MainApp.gs(R.string.objectives_bgavailableinns) + ": " + yesOrNo(bgIsAvailableInNS)
+ "\n" + MainApp.gs(R.string.nsclienthaswritepermission) + ": " + yesOrNo(NSClientInternalPlugin.getPlugin().hasWritePermission())
+ (isVirtualPump ? "\n" + MainApp.gs(R.string.virtualpump_uploadstatus_title) + ": " + yesOrNo(vpUploadEnabled) : "")
+ "\n" + MainApp.gs(R.string.objectives_pumpstatusavailableinns) + ": " + yesOrNo(pumpStatusIsAvailableInNS)
+ "\n" + MainApp.gs(R.string.hasbgdata) + ": " + yesOrNo(hasBGData)
+ "\n" + MainApp.gs(R.string.loopenabled) + ": " + yesOrNo(LoopPlugin.getPlugin().isEnabled(PluginBase.LOOP))
+ "\n" + MainApp.gs(R.string.apsselected) + ": " + yesOrNo(apsEnabled)
);
case 1:
return new RequirementResult(manualEnacts >= manualEnactsNeeded,
MainApp.sResources.getString(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded);
MainApp.gs(R.string.objectives_manualenacts) + ": " + manualEnacts + "/" + manualEnactsNeeded);
case 2:
return new RequirementResult(true, "");
case 3:
Constraint<Boolean> closedLoopEnabled = new Constraint<>(true);
SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled);
return new RequirementResult(closedLoopEnabled.get(), MainApp.sResources.getString(R.string.closedmodeenabled) + ": " + yesOrNo(closedLoopEnabled.get()));
return new RequirementResult(closedLoopEnabled.get(), MainApp.gs(R.string.closedmodeenabled) + ": " + yesOrNo(closedLoopEnabled.get()));
case 4:
double maxIOB = MainApp.getConstraintChecker().applyMaxIOBConstraints(1000d);
boolean maxIobSet = maxIOB > 0;
return new RequirementResult(maxIobSet, MainApp.sResources.getString(R.string.maxiobset) + ": " + yesOrNo(maxIobSet));
return new RequirementResult(maxIobSet, MainApp.gs(R.string.maxiobset) + ": " + yesOrNo(maxIobSet));
default:
return new RequirementResult(true, "");
}
@ -203,49 +207,49 @@ public class ObjectivesPlugin implements PluginBase, ConstraintsInterface {
objectives = new ArrayList<>();
objectives.add(new Objective(0,
MainApp.sResources.getString(R.string.objectives_0_objective),
MainApp.sResources.getString(R.string.objectives_0_gate),
MainApp.gs(R.string.objectives_0_objective),
MainApp.gs(R.string.objectives_0_gate),
new Date(0),
0, // 0 day
new Date(0)));
objectives.add(new Objective(1,
MainApp.sResources.getString(R.string.objectives_1_objective),
MainApp.sResources.getString(R.string.objectives_1_gate),
MainApp.gs(R.string.objectives_1_objective),
MainApp.gs(R.string.objectives_1_gate),
new Date(0),
7, // 7 days
new Date(0)));
objectives.add(new Objective(2,
MainApp.sResources.getString(R.string.objectives_2_objective),
MainApp.sResources.getString(R.string.objectives_2_gate),
MainApp.gs(R.string.objectives_2_objective),
MainApp.gs(R.string.objectives_2_gate),
new Date(0),
0, // 0 days
new Date(0)));
objectives.add(new Objective(3,
MainApp.sResources.getString(R.string.objectives_3_objective),
MainApp.sResources.getString(R.string.objectives_3_gate),
MainApp.gs(R.string.objectives_3_objective),
MainApp.gs(R.string.objectives_3_gate),
new Date(0),
5, // 5 days
new Date(0)));
objectives.add(new Objective(4,
MainApp.sResources.getString(R.string.objectives_4_objective),
MainApp.sResources.getString(R.string.objectives_4_gate),
MainApp.gs(R.string.objectives_4_objective),
MainApp.gs(R.string.objectives_4_gate),
new Date(0),
1,
new Date(0)));
objectives.add(new Objective(5,
MainApp.sResources.getString(R.string.objectives_5_objective),
MainApp.sResources.getString(R.string.objectives_5_gate),
MainApp.gs(R.string.objectives_5_objective),
MainApp.gs(R.string.objectives_5_gate),
new Date(0),
7,
new Date(0)));
objectives.add(new Objective(6,
MainApp.sResources.getString(R.string.objectives_6_objective),
MainApp.gs(R.string.objectives_6_objective),
"",
new Date(0),
28,
new Date(0)));
objectives.add(new Objective(7,
MainApp.sResources.getString(R.string.objectives_7_objective),
MainApp.gs(R.string.objectives_7_objective),
"",
new Date(0),
28,

View file

@ -424,7 +424,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
return;
}
pump.basalProfile = readBasalResult.basalProfile;
validBasalRateProfileSelectedOnPump = true;
setValidBasalRateProfileSelectedOnPump(true);
pump.initialized = true;
MainApp.bus().post(new EventInitializationChanged());
@ -925,7 +925,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
if (commandResult.success) {
pump.lastSuccessfulCmdTime = System.currentTimeMillis();
if (validBasalRateProfileSelectedOnPump && commandResult.state.unsafeUsageDetected == PumpState.UNSUPPORTED_BASAL_RATE_PROFILE) {
validBasalRateProfileSelectedOnPump = false;
setValidBasalRateProfileSelectedOnPump(false);
Notification n = new Notification(Notification.COMBO_PUMP_ALARM,
MainApp.gs(R.string.combo_force_disabled_notification),
Notification.URGENT);
@ -945,6 +945,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf
return commandResult;
}
public void setValidBasalRateProfileSelectedOnPump(boolean value) {
validBasalRateProfileSelectedOnPump = value;
}
/**
* Returns the command result of running ReadPumpState if it wasn't successful, indicating
* an error condition. Returns null otherwise.

View file

@ -0,0 +1,151 @@
package info.nightscout.androidaps.interfaces;
import com.squareup.otto.Bus;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.util.ArrayList;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ConstraintChecker;
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.ConstraintsObjectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.ConstraintsSafety.SafetyPlugin;
import info.nightscout.androidaps.plugins.PumpCombo.ComboPlugin;
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
import info.nightscout.utils.FabricPrivacy;
import info.nightscout.utils.SP;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Created by mike on 18.03.2018.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, FabricPrivacy.class, SP.class})
public class ConstraintsCheckerTest {
PumpInterface pump = new VirtualPumpPlugin();
ConstraintChecker constraintChecker;
ConfigBuilderPlugin configBuilderPlugin = mock(ConfigBuilderPlugin.class);
MainApp mainApp = mock(MainApp.class);
MockedBus bus = new MockedBus();
//PumpDescription pumpDescription = new PumpDescription();
SafetyPlugin safetyPlugin;
ObjectivesPlugin objectivesPlugin;
ComboPlugin comboPlugin;
boolean notificationSent = false;
// isLoopInvokationAllowed tests
@Test
public void pumpDescriptionShouldLimitLoopInvokation() throws Exception {
pump.getPumpDescription().isTempBasalCapable = false;
Constraint<Boolean> c = constraintChecker.isLoopInvokationAllowed();
Assert.assertEquals(true, c.getReasons().contains("Pump is not temp basal capable"));
Assert.assertEquals(Boolean.FALSE, c.get());
}
@Test
public void notStartedObjectivesShouldLimitLoopInvokation() throws Exception {
objectivesPlugin.objectives.get(0).setStarted(new Date(0));
Constraint<Boolean> c = constraintChecker.isLoopInvokationAllowed();
Assert.assertEquals(true, c.getReasons().contains("Objective 1 not started"));
Assert.assertEquals(Boolean.FALSE, c.get());
}
@Test
public void invalidBasalRateOnComboPumpShouldLimitLoopInvokation() throws Exception {
comboPlugin.setFragmentEnabled(PluginBase.PUMP, true);
comboPlugin.setValidBasalRateProfileSelectedOnPump(false);
Constraint<Boolean> c = constraintChecker.isLoopInvokationAllowed();
Assert.assertEquals(true, c.getReasons().contains("No valid basal rate read from pump"));
Assert.assertEquals(Boolean.FALSE, c.get());
}
// isClosedLoopAllowed tests
@Test
public void disabledEngineeringModeShouldLimitClosedLoop() throws Exception {
when(SP.getString("aps_mode", "open")).thenReturn("closed");
when(MainApp.isEngineeringModeOrRelease()).thenReturn(false);
Constraint<Boolean> c = constraintChecker.isClosedLoopAllowed();
Assert.assertEquals(true, c.getReasons().contains("Running dev version. Closed loop is disabled."));
Assert.assertEquals(Boolean.FALSE, c.get());
}
@Test
public void setOpenLoopInPreferencesShouldLimitClosedLoop() throws Exception {
when(SP.getString("aps_mode", "open")).thenReturn("open");
Constraint<Boolean> c = constraintChecker.isClosedLoopAllowed();
Assert.assertEquals(true, c.getReasons().contains("Closed loop mode disabled in preferences"));
Assert.assertEquals(Boolean.FALSE, c.get());
}
@Test
public void notStartedObjective4ShouldLimitClosedLoop() throws Exception {
when(SP.getString("aps_mode", "open")).thenReturn("closed");
objectivesPlugin.objectives.get(3).setStarted(new Date(0));
Constraint<Boolean> c = constraintChecker.isClosedLoopAllowed();
Assert.assertEquals(true, c.getReasons().contains("Objective 4 not started"));
Assert.assertEquals(Boolean.FALSE, c.get());
}
@Before
public void prepareMock() throws Exception {
PowerMockito.mockStatic(ConfigBuilderPlugin.class);
PowerMockito.mockStatic(MainApp.class);
when(MainApp.instance()).thenReturn(mainApp);
when(MainApp.getConfigBuilder()).thenReturn(configBuilderPlugin);
when(MainApp.getConfigBuilder().getActivePump()).thenReturn(pump);
constraintChecker = new ConstraintChecker(mainApp);
PowerMockito.mockStatic(FabricPrivacy.class);
when(MainApp.bus()).thenReturn(bus);
when(MainApp.gs(R.string.pumpisnottempbasalcapable)).thenReturn("Pump is not temp basal capable");
when(MainApp.gs(R.string.closed_loop_disabled_on_dev_branch)).thenReturn("Running dev version. Closed loop is disabled.");
when(MainApp.gs(R.string.closedmodedisabledinpreferences)).thenReturn("Closed loop mode disabled in preferences");
when(MainApp.gs(R.string.objectivenotstarted)).thenReturn("Objective %d not started");
when(MainApp.gs(R.string.novalidbasalrate)).thenReturn("No valid basal rate read from pump");
safetyPlugin = SafetyPlugin.getPlugin();
objectivesPlugin = ObjectivesPlugin.getPlugin();
comboPlugin = ComboPlugin.getPlugin();
ArrayList<PluginBase> constraintsPluginsList = new ArrayList<>();
constraintsPluginsList.add(safetyPlugin);
constraintsPluginsList.add(objectivesPlugin);
constraintsPluginsList.add(comboPlugin);
when(mainApp.getSpecificPluginsListByInterface(ConstraintsInterface.class)).thenReturn(constraintsPluginsList);
PowerMockito.mockStatic(SP.class);
}
class MockedBus extends Bus {
@Override
public void post(Object event) {
notificationSent = true;
}
}
}