This commit is contained in:
Milos Kozak 2020-03-12 22:55:29 +01:00
parent 927e690f7f
commit cdda4caa07
6 changed files with 320 additions and 349 deletions

View file

@ -19,8 +19,6 @@ import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.logging.L.isEnabled
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
@ -33,6 +31,7 @@ import info.nightscout.androidaps.queue.commands.*
import info.nightscout.androidaps.queue.commands.Command.CommandType
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.util.*
import javax.inject.Inject
import javax.inject.Singleton
@ -87,7 +86,8 @@ class CommandQueue @Inject constructor(
val constraintChecker: ConstraintChecker,
val profileFunction: ProfileFunction,
val activePlugin: Lazy<ActivePluginProvider>,
val mainApp: MainApp
val context: Context,
val sp: SP
) : CommandQueueProvider {
private val queue = LinkedList<Command>()
@ -161,7 +161,7 @@ class CommandQueue @Inject constructor(
SystemClock.sleep(500)
}
if (thread == null || thread!!.state == Thread.State.TERMINATED) {
thread = QueueThread(this)
thread = QueueThread(this, context, aapsLogger, rxBus, activePlugin.get(), resourceHelper, sp)
thread!!.start()
aapsLogger.debug(LTag.PUMPQUEUE, "Starting new thread")
} else {
@ -171,7 +171,7 @@ class CommandQueue @Inject constructor(
override fun independentConnect(reason: String, callback: Callback?) {
aapsLogger.debug(LTag.PUMPQUEUE, "Starting new queue")
val tempCommandQueue = CommandQueue(injector, aapsLogger, rxBus, resourceHelper, constraintChecker, profileFunction, activePlugin, mainApp)
val tempCommandQueue = CommandQueue(injector, aapsLogger, rxBus, resourceHelper, constraintChecker, profileFunction, activePlugin, context, sp)
tempCommandQueue.readStatus(reason, callback)
}
@ -470,26 +470,24 @@ class CommandQueue @Inject constructor(
return if (current != null) {
val result = activePump.isThisProfileSet(profile)
if (!result) {
if (isEnabled(L.PUMPQUEUE)) {
aapsLogger.debug(LTag.PUMPQUEUE, "Current profile: $current")
aapsLogger.debug(LTag.PUMPQUEUE, "New profile: $profile")
}
aapsLogger.debug(LTag.PUMPQUEUE, "Current profile: $current")
aapsLogger.debug(LTag.PUMPQUEUE, "New profile: $profile")
}
result
} else true
}
private fun showBolusProgressDialog(insulin: Double, context: Context?) {
if (context != null) {
private fun showBolusProgressDialog(insulin: Double, ctx: Context?) {
if (ctx != null) {
val bolusProgressDialog = BolusProgressDialog()
bolusProgressDialog.setInsulin(insulin)
bolusProgressDialog.show((context as AppCompatActivity).supportFragmentManager, "BolusProgress")
bolusProgressDialog.show((ctx as AppCompatActivity).supportFragmentManager, "BolusProgress")
} else {
val i = Intent()
i.putExtra("insulin", insulin)
i.setClass(mainApp, BolusProgressHelperActivity::class.java)
i.setClass(context, BolusProgressHelperActivity::class.java)
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
mainApp.startActivity(i)
context.startActivity(i)
}
}
}

View file

@ -5,85 +5,78 @@ import android.content.Context;
import android.os.PowerManager;
import android.os.SystemClock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.logging.StacktraceLoggerWrapper;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning;
import info.nightscout.androidaps.queue.events.EventQueueChanged;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.resources.ResourceHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SP;
/**
* Created by mike on 09.11.2017.
*/
public class QueueThread extends Thread {
private Logger log = StacktraceLoggerWrapper.getLogger(L.PUMPQUEUE);
private CommandQueue queue;
private AAPSLogger aapsLogger;
private RxBusWrapper rxBus;
private ActivePluginProvider activePlugin;
private ResourceHelper resourceHelper;
private SP sp;
private boolean connectLogged = false;
boolean waitingForDisconnect = false;
private PowerManager.WakeLock mWakeLock;
QueueThread(CommandQueue queue) {
QueueThread(CommandQueue queue, Context context, AAPSLogger aapsLogger, RxBusWrapper rxBus, ActivePluginProvider activePlugin, ResourceHelper resourceHelper, SP sp) {
super();
this.queue = queue;
Context context = MainApp.instance().getApplicationContext();
if (context != null) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (powerManager != null)
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:QueueThread");
}
this.aapsLogger = aapsLogger;
this.rxBus = rxBus;
this.activePlugin = activePlugin;
this.resourceHelper = resourceHelper;
this.sp = sp;
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (powerManager != null)
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:QueueThread");
}
@Override
public final void run() {
if (mWakeLock != null)
mWakeLock.acquire(T.mins(10).msecs());
RxBus.Companion.getINSTANCE().send(new EventQueueChanged());
rxBus.send(new EventQueueChanged());
long lastCommandTime;
long connectionStartTime = lastCommandTime = System.currentTimeMillis();
try {
while (true) {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
if (pump == null) {
if (L.isEnabled(L.PUMPQUEUE))
log.debug("pump == null");
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(MainApp.gs(R.string.pumpNotInitialized)));
SystemClock.sleep(1000);
continue;
}
long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000;
PumpInterface pump = activePlugin.getActivePump();
if (!pump.isConnected() && secondsElapsed > Constants.PUMP_MAX_CONNECTION_TIME_IN_SECONDS) {
RxBus.Companion.getINSTANCE().send(new EventDismissBolusProgressIfRunning(null));
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(MainApp.gs(R.string.connectiontimedout)));
if (L.isEnabled(L.PUMPQUEUE))
log.debug("timed out");
rxBus.send(new EventDismissBolusProgressIfRunning(null));
rxBus.send(new EventPumpStatusChanged(resourceHelper.gs(R.string.connectiontimedout)));
aapsLogger.debug(LTag.PUMPQUEUE, "timed out");
pump.stopConnecting();
//BLUETOOTH-WATCHDOG
boolean watchdog = SP.getBoolean(R.string.key_btwatchdog, false);
long last_watchdog = SP.getLong(R.string.key_btwatchdog_lastbark, 0L);
boolean watchdog = sp.getBoolean(R.string.key_btwatchdog, false);
long last_watchdog = sp.getLong(R.string.key_btwatchdog_lastbark, 0L);
watchdog = watchdog && System.currentTimeMillis() - last_watchdog > (Constants.MIN_WATCHDOG_INTERVAL_IN_SECONDS * 1000);
if (watchdog) {
if (L.isEnabled(L.PUMPQUEUE))
log.debug("BT watchdog - toggeling the phonest bluetooth");
aapsLogger.debug(LTag.PUMPQUEUE, "BT watchdog - toggeling the phonest bluetooth");
//write time
SP.putLong(R.string.key_btwatchdog_lastbark, System.currentTimeMillis());
sp.putLong(R.string.key_btwatchdog_lastbark, System.currentTimeMillis());
//toggle BT
pump.stopConnecting();
pump.disconnect("watchdog");
@ -95,40 +88,36 @@ public class QueueThread extends Thread {
SystemClock.sleep(1000);
//start over again once after watchdog barked
//Notification notification = new Notification(Notification.OLD_NSCLIENT, "Watchdog", Notification.URGENT);
//RxBus.Companion.getINSTANCE().send(new EventNewNotification(notification));
//rxBus.send(new EventNewNotification(notification));
connectionStartTime = lastCommandTime = System.currentTimeMillis();
pump.connect("watchdog");
} else {
queue.clear();
if (L.isEnabled(L.PUMPQUEUE))
log.debug("no connection possible");
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
aapsLogger.debug(LTag.PUMPQUEUE, "no connection possible");
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
pump.disconnect("Queue empty");
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED));
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED));
return;
}
}
if (pump.isHandshakeInProgress()) {
if (L.isEnabled(L.PUMPQUEUE))
log.debug("handshaking " + secondsElapsed);
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.HANDSHAKING, (int) secondsElapsed));
aapsLogger.debug(LTag.PUMPQUEUE, "handshaking " + secondsElapsed);
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.HANDSHAKING, (int) secondsElapsed));
SystemClock.sleep(100);
continue;
}
if (pump.isConnecting()) {
if (L.isEnabled(L.PUMPQUEUE))
log.debug("connecting " + secondsElapsed);
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTING, (int) secondsElapsed));
aapsLogger.debug(LTag.PUMPQUEUE, "connecting " + secondsElapsed);
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTING, (int) secondsElapsed));
SystemClock.sleep(1000);
continue;
}
if (!pump.isConnected()) {
if (L.isEnabled(L.PUMPQUEUE))
log.debug("connect");
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTING, (int) secondsElapsed));
aapsLogger.debug(LTag.PUMPQUEUE, "connect");
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTING, (int) secondsElapsed));
pump.connect("Connection needed");
SystemClock.sleep(1000);
continue;
@ -137,19 +126,17 @@ public class QueueThread extends Thread {
if (queue.performing() == null) {
if (!connectLogged) {
connectLogged = true;
if (L.isEnabled(L.PUMPQUEUE))
log.debug("connection time " + secondsElapsed + "s");
aapsLogger.debug(LTag.PUMPQUEUE, "connection time " + secondsElapsed + "s");
}
// Pickup 1st command and set performing variable
if (queue.size() > 0) {
queue.pickup();
if (queue.performing() != null) {
if (L.isEnabled(L.PUMPQUEUE))
log.debug("performing " + queue.performing().status());
RxBus.Companion.getINSTANCE().send(new EventQueueChanged());
aapsLogger.debug(LTag.PUMPQUEUE, "performing " + queue.performing().status());
rxBus.send(new EventQueueChanged());
queue.performing().execute();
queue.resetPerforming();
RxBus.Companion.getINSTANCE().send(new EventQueueChanged());
rxBus.send(new EventQueueChanged());
lastCommandTime = System.currentTimeMillis();
SystemClock.sleep(100);
continue;
@ -161,17 +148,14 @@ public class QueueThread extends Thread {
long secondsFromLastCommand = (System.currentTimeMillis() - lastCommandTime) / 1000;
if (secondsFromLastCommand >= 5) {
waitingForDisconnect = true;
if (L.isEnabled(L.PUMPQUEUE))
log.debug("queue empty. disconnect");
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
aapsLogger.debug(LTag.PUMPQUEUE, "queue empty. disconnect");
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING));
pump.disconnect("Queue empty");
RxBus.Companion.getINSTANCE().send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED));
if (L.isEnabled(L.PUMPQUEUE))
log.debug("disconnected");
rxBus.send(new EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED));
aapsLogger.debug(LTag.PUMPQUEUE, "disconnected");
return;
} else {
if (L.isEnabled(L.PUMPQUEUE))
log.debug("waiting for disconnect");
aapsLogger.debug(LTag.PUMPQUEUE, "waiting for disconnect");
SystemClock.sleep(1000);
}
}
@ -179,8 +163,7 @@ public class QueueThread extends Thread {
} finally {
if (mWakeLock != null && mWakeLock.isHeld())
mWakeLock.release();
if (L.isEnabled(L.PUMPQUEUE))
log.debug("thread end");
aapsLogger.debug(LTag.PUMPQUEUE, "thread end");
}
}
}

View file

@ -1,51 +0,0 @@
package info.nightscout.androidaps.plugins.configBuilder;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import info.AAPSMocker;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.utils.SP;
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, SP.class})
public class ConfigBuilderPluginTest {
@Test
@Ignore
public void getPluginTest() {
ConfigBuilderPlugin configBuilderPlugin = ConfigBuilderPlugin.getPlugin();
Assert.assertNotNull(configBuilderPlugin);
}
@Test
@Ignore
public void onStartTest() {
ConfigBuilderPlugin configBuilderPlugin = ConfigBuilderPlugin.getPlugin();
configBuilderPlugin.setPluginEnabled(PluginType.GENERAL, true);
}
@Test
@Ignore
public void onStopTest() {
ConfigBuilderPlugin configBuilderPlugin = ConfigBuilderPlugin.getPlugin();
configBuilderPlugin.setPluginEnabled(PluginType.GENERAL, true);
configBuilderPlugin.setPluginEnabled(PluginType.GENERAL, false);
}
@Before
public void prepareMock() {
AAPSMocker.mockMainApp();
AAPSMocker.mockApplicationContext();
AAPSMocker.mockSP();
}
}

View file

@ -0,0 +1,60 @@
package info.nightscout.androidaps.plugins.configBuilder
import dagger.Lazy
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.TestBase
import info.nightscout.androidaps.interfaces.CommandQueueProvider
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
@PrepareForTest(NSProfilePlugin::class)
class ConfigBuilderPluginTest : TestBase() {
@Mock lateinit var insulinOrefRapidActingPlugin: Lazy<InsulinOrefRapidActingPlugin>
@Mock lateinit var localProfilePlugin: Lazy<LocalProfilePlugin>
@Mock lateinit var virtualPumpPlugin: Lazy<VirtualPumpPlugin>
@Mock lateinit var treatmentsPlugin: Lazy<TreatmentsPlugin>
@Mock lateinit var sensitivityOref0Plugin: Lazy<SensitivityOref0Plugin>
@Mock lateinit var sensitivityOref1Plugin: Lazy<SensitivityOref1Plugin>
@Mock lateinit var sp: SP
@Mock lateinit var aapsLogger: AAPSLogger
@Mock lateinit var resourceHelper: ResourceHelper
@Mock lateinit var commandQueue: CommandQueueProvider
@Mock lateinit var nsProfilePlugin: NSProfilePlugin
lateinit var configBuilderPlugin: ConfigBuilderPlugin
val injector = HasAndroidInjector {
AndroidInjector {
}
}
@Test
fun dummy() {
}
@Before
fun prepareMock() {
configBuilderPlugin = ConfigBuilderPlugin(insulinOrefRapidActingPlugin, localProfilePlugin, virtualPumpPlugin, treatmentsPlugin, sensitivityOref0Plugin, sensitivityOref1Plugin, injector, sp, RxBusWrapper(), aapsLogger, resourceHelper, commandQueue, nsProfilePlugin)
}
}

View file

@ -1,217 +0,0 @@
package info.nightscout.androidaps.queue;
import android.content.Context;
import junit.framework.Assert;
import org.json.JSONException;
import org.json.JSONObject;
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.Date;
import info.AAPSMocker;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.androidaps.utils.ToastUtils;
import static info.nightscout.androidaps.utils.DateUtil.now;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Created by mike on 14.01.2018.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class, TreatmentsPlugin.class})
public class CommandQueueTest extends CommandQueue {
String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
Profile profile = new Profile(new JSONObject(validProfile), Constants.MGDL);
public CommandQueueTest() throws JSONException {
}
@Test
public void doTests() throws Exception {
prepareMock(0d, 0);
// start with empty queue
Assert.assertEquals(0, size());
// add bolus command
bolus(new DetailedBolusInfo(), null);
Assert.assertEquals(1, size());
// add READSTATUS
readStatus("anyString", null);
Assert.assertEquals(2, size());
// adding another bolus should remove the first one (size still == 2)
bolus(new DetailedBolusInfo(), null);
Assert.assertEquals(2, size());
// clear the queue should reset size
clear();
Assert.assertEquals(0, size());
// add tempbasal
tempBasalAbsolute(0, 30, true, profile, null);
Assert.assertEquals(1, size());
// add tempbasal percent. it should replace previous TEMPBASAL
tempBasalPercent(0, 30, true, profile, null);
Assert.assertEquals(1, size());
// add extended bolus
extendedBolus(1, 30, null);
Assert.assertEquals(2, size());
// add cancel temp basal should remove previous 2 temp basal setting
extendedBolus(1, 30, null);
Assert.assertEquals(2, size());
// cancel extended bolus should replace previous extended
extendedBolus(1, 30, null);
Assert.assertEquals(2, size());
// add setProfile
setProfile(profile, null);
Assert.assertEquals(3, size());
// add loadHistory
loadHistory((byte) 0, null);
Assert.assertEquals(4, size());
// add loadEvents
loadEvents(null);
Assert.assertEquals(5, size());
clear();
tempBasalAbsolute(0, 30, true, profile, null);
pickup();
Assert.assertEquals(0, size());
Assert.assertNotNull(performing);
Assert.assertEquals(Command.CommandType.TEMPBASAL, performing.commandType);
resetPerforming();
Assert.assertNull(performing);
}
private void prepareMock(Double insulin, Integer carbs) throws Exception {
PowerMockito.mockStatic(ConstraintChecker.class);
ConstraintChecker constraintChecker = mock(ConstraintChecker.class);
AAPSMocker.mockMainApp();
AAPSMocker.mockConfigBuilder();
PumpInterface pump = VirtualPumpPlugin.getPlugin();
when(ConfigBuilderPlugin.getPlugin().getActivePump()).thenReturn(pump);
when(ConstraintChecker.getInstance()).thenReturn(constraintChecker);
when(MainApp.isEngineeringModeOrRelease()).thenReturn(true);
Constraint<Double> bolusConstraint = new Constraint<>(0d);
when(ConstraintChecker.getInstance().applyBolusConstraints(any())).thenReturn(bolusConstraint);
when(ConstraintChecker.getInstance().applyExtendedBolusConstraints(any())).thenReturn(bolusConstraint);
Constraint<Integer> carbsConstraint = new Constraint<>(0);
when(ConstraintChecker.getInstance().applyCarbsConstraints(any())).thenReturn(carbsConstraint);
Constraint<Double> rateConstraint = new Constraint<>(0d);
when(ConstraintChecker.getInstance().applyBasalConstraints(any(), any())).thenReturn(rateConstraint);
Constraint<Integer> percentageConstraint = new Constraint<>(0);
when(ConstraintChecker.getInstance().applyBasalPercentConstraints(any(), any())).thenReturn(percentageConstraint);
PowerMockito.mockStatic(ToastUtils.class);
Context context = mock(Context.class);
String message = null;
PowerMockito.doNothing().when(ToastUtils.class, "showToastInUiThread", context, message);
when(MainApp.gs(0)).thenReturn("");
PowerMockito.mockStatic(TreatmentsPlugin.class);
TreatmentsPlugin treatmentsPlugin = mock(TreatmentsPlugin.class);
when(TreatmentsPlugin.getPlugin()).thenReturn(treatmentsPlugin);
when(treatmentsPlugin.getLastBolusTime()).thenReturn(new Date(100, 0,1 ).getTime());
}
@Override
protected synchronized void notifyAboutNewCommand() {
}
@Override
protected void showBolusProgressDialog(Double insulin, Context context) {
}
@Override
public boolean isThisProfileSet(Profile profile) {
return false;
}
@Test
public void callingCancelAllBolusesClearsQueue() throws Exception {
// given
prepareMock(0d, 0);
Assert.assertEquals(0, size());
DetailedBolusInfo smb = new DetailedBolusInfo();
smb.lastKnownBolusTime = now();
smb.isSMB = true;
bolus(smb, null);
bolus(new DetailedBolusInfo(), null);
Assert.assertEquals(2, size());
// when
cancelAllBoluses();
// then
Assert.assertEquals(0, size());
}
@Test
public void smbIsRejectedIfABolusIsQueued() throws Exception {
// given
prepareMock(0d, 0);
Assert.assertEquals(0, size());
// when
bolus(new DetailedBolusInfo(), null);
DetailedBolusInfo smb = new DetailedBolusInfo();
smb.isSMB = true;
boolean queued = bolus(smb, null);
// then
Assert.assertFalse(queued);
Assert.assertEquals(size(), 1);
}
@Test
public void smbIsRejectedIfLastKnownBolusIsOutdated() throws Exception {
// given
prepareMock(0d, 0);
Assert.assertEquals(0, size());
// when
DetailedBolusInfo bolus = new DetailedBolusInfo();
bolus.isSMB = true;
bolus.lastKnownBolusTime = 0;
boolean queued = bolus(bolus, null);
// then
Assert.assertFalse(queued);
Assert.assertEquals(size(), 0);
}
}

View file

@ -0,0 +1,198 @@
package info.nightscout.androidaps.queue
import android.content.Context
import dagger.Lazy
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.TestBase
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.interfaces.ActivePluginProvider
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.commands.Command
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import java.util.*
@RunWith(PowerMockRunner::class)
@PrepareForTest(ConstraintChecker::class, VirtualPumpPlugin::class, ToastUtils::class, Context::class, TreatmentsPlugin::class)
class CommandQueueTest : TestBase() {
@Mock lateinit var aapsLogger: AAPSLogger
@Mock lateinit var resourceHelper: ResourceHelper
@Mock lateinit var constraintChecker: ConstraintChecker
@Mock lateinit var profileFunction: ProfileFunction
@Mock lateinit var lazyActivePlugin: Lazy<ActivePluginProvider>
@Mock lateinit var activePlugin: ActivePluginProvider
@Mock lateinit var context: Context
@Mock lateinit var treatmentsPlugin: TreatmentsPlugin
@Mock lateinit var virtualPumpPlugin: VirtualPumpPlugin
@Mock lateinit var sp: SP
val rxBus = RxBusWrapper()
val injector = HasAndroidInjector {
AndroidInjector {
if (it is Command) {
it.aapsLogger = aapsLogger
it.resourceHelper = resourceHelper
}
}
}
lateinit var commandQueue: CommandQueue
@Before
fun prepareMock() {
commandQueue = CommandQueue(injector, aapsLogger, rxBus, resourceHelper, constraintChecker, profileFunction, lazyActivePlugin, context, sp)
val pumpDescription = PumpDescription()
pumpDescription.basalMinimumRate = 0.1
`when`(lazyActivePlugin.get()).thenReturn(activePlugin)
`when`(activePlugin.activePump).thenReturn(virtualPumpPlugin)
`when`(virtualPumpPlugin.pumpDescription).thenReturn(pumpDescription)
`when`(virtualPumpPlugin.isThisProfileSet(anyObject())).thenReturn(false)
`when`(activePlugin.activeTreatments).thenReturn(treatmentsPlugin)
`when`(treatmentsPlugin.lastBolusTime).thenReturn(Date(100, 0, 1).time)
`when`(profileFunction.getProfile()).thenReturn(validProfile)
val bolusConstraint = Constraint(0.0)
`when`(constraintChecker.applyBolusConstraints(anyObject())).thenReturn(bolusConstraint)
`when`(constraintChecker.applyExtendedBolusConstraints(anyObject())).thenReturn(bolusConstraint)
val carbsConstraint = Constraint(0)
`when`(constraintChecker.applyCarbsConstraints(anyObject())).thenReturn(carbsConstraint)
val rateConstraint = Constraint(0.0)
`when`(constraintChecker.applyBasalConstraints(anyObject(), anyObject())).thenReturn(rateConstraint)
val percentageConstraint = Constraint(0)
`when`(constraintChecker.applyBasalPercentConstraints(anyObject(), anyObject())).thenReturn(percentageConstraint)
}
@Test
fun doTests() {
// start with empty queue
Assert.assertEquals(0, commandQueue.size())
// add bolus command
commandQueue.bolus(DetailedBolusInfo(), null)
Assert.assertEquals(1, commandQueue.size())
// add READSTATUS
commandQueue.readStatus("anyString", null)
Assert.assertEquals(2, commandQueue.size())
// adding another bolus should remove the first one (size still == 2)
commandQueue.bolus(DetailedBolusInfo(), null)
Assert.assertEquals(2, commandQueue.size())
// clear the queue should reset size
commandQueue.clear()
Assert.assertEquals(0, commandQueue.size())
// add tempbasal
commandQueue.tempBasalAbsolute(0.0, 30, true, validProfile, null)
Assert.assertEquals(1, commandQueue.size())
// add tempbasal percent. it should replace previous TEMPBASAL
commandQueue.tempBasalPercent(0, 30, true, validProfile, null)
Assert.assertEquals(1, commandQueue.size())
// add extended bolus
commandQueue.extendedBolus(1.0, 30, null)
Assert.assertEquals(2, commandQueue.size())
// add cancel temp basal should remove previous 2 temp basal setting
commandQueue.extendedBolus(1.0, 30, null)
Assert.assertEquals(2, commandQueue.size())
// cancel extended bolus should replace previous extended
commandQueue.extendedBolus(1.0, 30, null)
Assert.assertEquals(2, commandQueue.size())
// add setProfile
commandQueue.setProfile(validProfile, null)
Assert.assertEquals(3, commandQueue.size())
// add loadHistory
commandQueue.loadHistory(0.toByte(), null)
Assert.assertEquals(4, commandQueue.size())
// add loadEvents
commandQueue.loadEvents(null)
Assert.assertEquals(5, commandQueue.size())
commandQueue.clear()
commandQueue.tempBasalAbsolute(0.0, 30, true, validProfile, null)
commandQueue.pickup()
Assert.assertEquals(0, commandQueue.size())
Assert.assertNotNull(commandQueue.performing)
Assert.assertEquals(Command.CommandType.TEMPBASAL, commandQueue.performing?.commandType)
commandQueue.resetPerforming()
Assert.assertNull(commandQueue.performing)
}
@Test
fun callingCancelAllBolusesClearsQueue() {
// given
Assert.assertEquals(0, commandQueue.size())
val smb = DetailedBolusInfo()
smb.lastKnownBolusTime = DateUtil.now()
smb.isSMB = true
commandQueue.bolus(smb, null)
commandQueue.bolus(DetailedBolusInfo(), null)
Assert.assertEquals(2, commandQueue.size())
// when
commandQueue.cancelAllBoluses()
// then
Assert.assertEquals(0, commandQueue.size())
}
@Test
fun smbIsRejectedIfABolusIsQueued() {
// given
Assert.assertEquals(0, commandQueue.size())
// when
commandQueue.bolus(DetailedBolusInfo(), null)
val smb = DetailedBolusInfo()
smb.isSMB = true
val queued: Boolean = commandQueue.bolus(smb, null)
// then
Assert.assertFalse(queued)
Assert.assertEquals(commandQueue.size(), 1)
}
@Test
fun smbIsRejectedIfLastKnownBolusIsOutdated() {
// given
Assert.assertEquals(0, commandQueue.size())
// when
val bolus = DetailedBolusInfo()
bolus.isSMB = true
bolus.lastKnownBolusTime = 0
val queued: Boolean = commandQueue.bolus(bolus, null)
// then
Assert.assertFalse(queued)
Assert.assertEquals(commandQueue.size(), 0)
}
}