From 86d965a7f135e1bd8458605dc2538f52cc8e0574 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Sat, 27 Feb 2021 23:50:51 +0100 Subject: [PATCH 1/3] initial history database --- omnipod-dash/build.gradle | 7 +++ .../dash/dagger/OmnipodDashHistoryModule.kt | 33 +++++++++++ .../omnipod/dash/dagger/OmnipodDashModule.kt | 2 +- .../pump/omnipod/dash/history/DashHistory.kt | 55 +++++++++++++++++++ .../dash/history/data/HistoryRecord.kt | 13 +++++ .../pump/omnipod/dash/history/data/Record.kt | 11 ++++ .../omnipod/dash/history/data/ResultStates.kt | 9 +++ .../dash/history/database/Converters.kt | 34 ++++++++++++ .../history/database/DashHistoryDatabase.kt | 31 +++++++++++ .../dash/history/database/HistoryRecordDao.kt | 36 ++++++++++++ .../history/database/HistoryRecordEntity.kt | 22 ++++++++ .../dash/history/mapper/HistoryMapper.kt | 32 +++++++++++ 12 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/dagger/OmnipodDashHistoryModule.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/Record.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/ResultStates.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/Converters.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/DashHistoryDatabase.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordDao.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordEntity.kt create mode 100644 omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/mapper/HistoryMapper.kt diff --git a/omnipod-dash/build.gradle b/omnipod-dash/build.gradle index ea8c60af66..45c11a93bf 100644 --- a/omnipod-dash/build.gradle +++ b/omnipod-dash/build.gradle @@ -17,4 +17,11 @@ android { dependencies { implementation project(':core') implementation project(':omnipod-common') + + implementation "androidx.room:room-runtime:$room_version" + implementation "androidx.room:room-rxjava2:$room_version" + kapt "androidx.room:room-compiler:$room_version" + + implementation 'com.github.guepardoapps:kulid:1.1.2.0' + } \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/dagger/OmnipodDashHistoryModule.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/dagger/OmnipodDashHistoryModule.kt new file mode 100644 index 0000000000..172dd497b0 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/dagger/OmnipodDashHistoryModule.kt @@ -0,0 +1,33 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.dagger + +import android.content.Context +import dagger.Module +import dagger.Provides +import dagger.Reusable +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.DashHistoryDatabase +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordDao +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.mapper.HistoryMapper +import javax.inject.Singleton + +@Module +class OmnipodDashHistoryModule { + + @Provides + @Singleton + internal fun provideDatabase(context: Context): DashHistoryDatabase = DashHistoryDatabase.build(context) + + @Provides + @Singleton + internal fun provideHistoryRecordDao(dashHistoryDatabase: DashHistoryDatabase): HistoryRecordDao = dashHistoryDatabase.historyRecordDao() + + @Provides + @Reusable // no state, let system decide when to reuse or create new. + internal fun provideHistoryMapper() = HistoryMapper() + + @Provides + @Singleton + internal fun provideDashHistory(dao: HistoryRecordDao, historyMapper: HistoryMapper) = + DashHistory(dao, historyMapper) + +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/dagger/OmnipodDashModule.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/dagger/OmnipodDashModule.kt index a67a8dd570..98780b10d9 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/dagger/OmnipodDashModule.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/dagger/OmnipodDashModule.kt @@ -16,7 +16,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.OmnipodDashOvervi import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.activation.DashPodActivationWizardActivity import info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.deactivation.DashPodDeactivationWizardActivity -@Module +@Module(includes = [OmnipodDashHistoryModule::class]) @Suppress("unused") abstract class OmnipodDashModule { // ACTIVITIES diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt new file mode 100644 index 0000000000..98319550ed --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt @@ -0,0 +1,55 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history + +import com.github.guepardoapps.kulid.ULID +import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.HistoryRecord +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.ResolvedResult +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.TempBasalRecord +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordDao +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordEntity +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.mapper.HistoryMapper +import io.reactivex.Completable +import io.reactivex.Single +import java.lang.System.currentTimeMillis +import javax.inject.Inject + +class DashHistory @Inject constructor( + private val dao: HistoryRecordDao, + private val historyMapper: HistoryMapper +) { + + fun markSuccess(id: String): Completable = dao.markResolved(id, ResolvedResult.SUCCESS, currentTimeMillis()) + + fun markFailure(id: String): Completable = dao.markResolved(id, ResolvedResult.FAILURE, currentTimeMillis()) + + fun createRecord( + commandType: OmnipodCommandType, + initialResult: InitialResult = InitialResult.UNCONFIRMED, + tempBasalRecord: TempBasalRecord? = null, + bolusRecord: BolusRecord? = null, + resolveResult: ResolvedResult? = null, + resolvedAt: Long? = null + ): Single { + val id = ULID.random() + return dao.save( + HistoryRecordEntity( + id = id, + createdAt = currentTimeMillis(), + commandType = commandType, + tempBasalRecord = tempBasalRecord, + bolusRecord = bolusRecord, + initialResult = initialResult, + resolvedResult = resolveResult, + resolvedAt = resolvedAt, + ) + ).toSingle { id } + } + + fun getRecords(): Single> = + dao.all().map { list -> list.map(historyMapper::entityToDomain) } + + fun getRecordsAfter(time: Long): Single> = dao.allSince(time) + +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt new file mode 100644 index 0000000000..5229248a7e --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data + +import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType + +data class HistoryRecord( + val id: String, // ULID + val createdAt: Long, + val commandType: OmnipodCommandType, + val initialResult: InitialResult, + val record: Record?, + val resolvedResult: ResolvedResult?, + val resolvedAt: Long? +) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/Record.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/Record.kt new file mode 100644 index 0000000000..6344c9fcd7 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/Record.kt @@ -0,0 +1,11 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data + +sealed class Record + +data class BolusRecord(val amout: Double, val bolusType: BolusType): Record() + +data class TempBasalRecord(val duration: Long, val rate: Double): Record() + +enum class BolusType { + DEFAULT, SMB +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/ResultStates.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/ResultStates.kt new file mode 100644 index 0000000000..53dc608e60 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/ResultStates.kt @@ -0,0 +1,9 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data + +enum class InitialResult { + SUCCESS, FAILURE, UNCONFIRMED +} + +enum class ResolvedResult { + SUCCESS, FAILURE +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/Converters.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/Converters.kt new file mode 100644 index 0000000000..b37d71bf3f --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/Converters.kt @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database + +import androidx.room.TypeConverter +import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.ResolvedResult + +class Converters { + + @TypeConverter + fun toBolusType(s: String) = enumValueOf(s) + + @TypeConverter + fun fromBolusType(bolusType: BolusType) = bolusType.name + + @TypeConverter + fun toInitialResult(s: String) = enumValueOf(s) + + @TypeConverter + fun fromInitialResult(initialResult: InitialResult) = initialResult.name + + @TypeConverter + fun toResolvedResult(s: String) = enumValueOf(s) + + @TypeConverter + fun fromResolvedResult(resolvedResult: ResolvedResult) = resolvedResult.name + + @TypeConverter + fun toOmnipodCommandType(s: String) = enumValueOf(s) + + @TypeConverter + fun fromOmnipodCommandType(omnipodCommandType: OmnipodCommandType) = omnipodCommandType.name +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/DashHistoryDatabase.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/DashHistoryDatabase.kt new file mode 100644 index 0000000000..259447afb0 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/DashHistoryDatabase.kt @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import androidx.room.TypeConverters + +@Database( + entities = [HistoryRecordEntity::class], + exportSchema = false, + version = DashHistoryDatabase.VERSION +) +@TypeConverters(Converters::class) +abstract class DashHistoryDatabase : RoomDatabase() { + + abstract fun historyRecordDao() : HistoryRecordDao + + companion object { + + const val VERSION = 1 + + @Synchronized + fun build(context: Context) = + Room.databaseBuilder(context.applicationContext, DashHistoryDatabase::class.java, "omnipod_dash_history_database.db") + .fallbackToDestructiveMigration() + .build() + + } + +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordDao.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordDao.kt new file mode 100644 index 0000000000..e5c425dd24 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordDao.kt @@ -0,0 +1,36 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.ResolvedResult +import io.reactivex.Completable +import io.reactivex.Single + +@Dao +abstract class HistoryRecordDao { + + @Query("SELECT * from historyrecords") + abstract fun all(): Single> + + @Query("SELECT * from historyrecords") + abstract fun allBlocking(): List + + @Query("SELECT * from historyrecords WHERE createdAt <= :since") + abstract fun allSince(since: Long): Single> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun saveBlocking(historyRecordEntity: HistoryRecordEntity) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun save(historyRecordEntity: HistoryRecordEntity): Completable + + @Delete + abstract fun delete(historyRecordEntity: HistoryRecordEntity): Completable + + @Query("UPDATE historyrecords SET resolvedResult = :resolvedResult, resolvedAt = :resolvedAt WHERE id = :id ") + abstract fun markResolved(id: String, resolvedResult: ResolvedResult, resolvedAt: Long): Completable + +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordEntity.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordEntity.kt new file mode 100644 index 0000000000..6539009117 --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordEntity.kt @@ -0,0 +1,22 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database + +import androidx.room.Embedded +import androidx.room.Entity +import androidx.room.PrimaryKey +import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.ResolvedResult +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.TempBasalRecord + +@Entity(tableName = "historyrecords") +data class HistoryRecordEntity( + @PrimaryKey val id: String, // ULID + val createdAt: Long, + val commandType: OmnipodCommandType, + val initialResult: InitialResult, + @Embedded(prefix = "tempBasalRecord_") val tempBasalRecord: TempBasalRecord?, + @Embedded(prefix = "bolusRecord_") val bolusRecord: BolusRecord?, + val resolvedResult: ResolvedResult?, + val resolvedAt: Long?) + diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/mapper/HistoryMapper.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/mapper/HistoryMapper.kt new file mode 100644 index 0000000000..6ceeb6920c --- /dev/null +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/mapper/HistoryMapper.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history.mapper + +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.HistoryRecord +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.TempBasalRecord +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordEntity + +class HistoryMapper { + + fun domainToEntity(historyRecord: HistoryRecord): HistoryRecordEntity = + HistoryRecordEntity( + id = historyRecord.id, + createdAt = historyRecord.createdAt, + commandType = historyRecord.commandType, + initialResult = historyRecord.initialResult, + tempBasalRecord = historyRecord.record as? TempBasalRecord, + bolusRecord = historyRecord.record as? BolusRecord, + resolvedResult = historyRecord.resolvedResult, + resolvedAt = historyRecord.resolvedAt + ) + + fun entityToDomain(entity: HistoryRecordEntity): HistoryRecord = + HistoryRecord(id = entity.id, + createdAt = entity.createdAt, + initialResult = entity.initialResult, + commandType = entity.commandType, + record = entity.bolusRecord ?: entity.tempBasalRecord, + resolvedResult = entity.resolvedResult, + resolvedAt = entity.resolvedAt + ) + +} \ No newline at end of file From 2d0d38f70f20aa85ade4d914820d6ccd109a69d2 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Sun, 28 Feb 2021 03:30:13 +0100 Subject: [PATCH 2/3] database integration test working --- gradle/test_dependencies.gradle | 13 ++++- .../omnipod/dash/history/DashHistoryTest.kt | 58 +++++++++++++++++++ .../omnipod/dash/history/RxSchedulerRule.kt | 32 ++++++++++ .../pump/omnipod/dash/history/DashHistory.kt | 10 +++- .../dash/history/data/HistoryRecord.kt | 1 + .../dash/history/database/Converters.kt | 4 +- .../history/database/DashHistoryDatabase.kt | 3 +- 7 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt create mode 100644 omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/RxSchedulerRule.kt diff --git a/gradle/test_dependencies.gradle b/gradle/test_dependencies.gradle index 3a484c419c..881e535d9d 100644 --- a/gradle/test_dependencies.gradle +++ b/gradle/test_dependencies.gradle @@ -13,9 +13,16 @@ dependencies { testImplementation "org.skyscreamer:jsonassert:1.5.0" testImplementation "org.hamcrest:hamcrest-all:1.3" - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0-alpha04' - androidTestImplementation "androidx.test.ext:junit:$androidx_junit" - androidTestImplementation "androidx.test:rules:$androidx_rules" + + // newer integration test libraries might not work + // https://stackoverflow.com/questions/64700104/attribute-androidforcequeryable-not-found-in-android-studio-when-running-espres + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0' + + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test:rules:1.3.0' + androidTestImplementation 'androidx.test:runner:1.3.0' + androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' } diff --git a/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt b/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt new file mode 100644 index 0000000000..28467f7a59 --- /dev/null +++ b/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt @@ -0,0 +1,58 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history + +import android.content.Context +import androidx.room.Room +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.guepardoapps.kulid.ULID +import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.DashHistoryDatabase +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.HistoryRecordDao +import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.mapper.HistoryMapper +import io.reactivex.schedulers.Schedulers +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DashHistoryTest { + + private lateinit var dao: HistoryRecordDao + private lateinit var database: DashHistoryDatabase + private lateinit var dashHistory: DashHistory + + @get:Rule + val schedulerRule = RxSchedulerRule(Schedulers.trampoline()) + + @Before + fun setUp() { + val context = ApplicationProvider.getApplicationContext() + database = Room.inMemoryDatabaseBuilder( + context, DashHistoryDatabase::class.java).build() + dao = database.historyRecordDao() + dashHistory = DashHistory(dao, HistoryMapper()) + } + + @Test + fun testInsertSomething() { // needs to be camel case as runs on Android + dashHistory.getRecords().test().apply { + assertValue { it.isEmpty() } + } + + dashHistory.createRecord(commandType = OmnipodCommandType.SET_BOLUS).test().apply { + assertValue { ULID.isValid(it) } + } + + dashHistory.getRecords().test().apply { + assertValue { it.size == 1 } + } + + } + + @After + fun tearDown() { + database.close() + } +} \ No newline at end of file diff --git a/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/RxSchedulerRule.kt b/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/RxSchedulerRule.kt new file mode 100644 index 0000000000..6073957e5f --- /dev/null +++ b/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/RxSchedulerRule.kt @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.dash.history + +import io.reactivex.Scheduler +import io.reactivex.android.plugins.RxAndroidPlugins +import io.reactivex.plugins.RxJavaPlugins +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement + +// TODO: move to core before the big merge +class RxSchedulerRule(val scheduler: Scheduler) : TestRule { + + override fun apply(base: Statement, description: Description) = + object : Statement() { + override fun evaluate() { + RxAndroidPlugins.reset() + RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler } + RxJavaPlugins.reset() + RxJavaPlugins.setIoSchedulerHandler { scheduler } + RxJavaPlugins.setNewThreadSchedulerHandler { scheduler } + RxJavaPlugins.setComputationSchedulerHandler { scheduler } + + try { + base.evaluate() + } finally { + RxJavaPlugins.reset() + RxAndroidPlugins.reset() + } + + } + } +} \ No newline at end of file diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt index 98319550ed..e2ebf8f94d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt @@ -20,9 +20,9 @@ class DashHistory @Inject constructor( private val historyMapper: HistoryMapper ) { - fun markSuccess(id: String): Completable = dao.markResolved(id, ResolvedResult.SUCCESS, currentTimeMillis()) + fun markSuccess(id: String): Completable = dao.markResolved(id, ResolvedResult.SUCCESS, currentTimeMillis()) // TODO pass time - fun markFailure(id: String): Completable = dao.markResolved(id, ResolvedResult.FAILURE, currentTimeMillis()) + fun markFailure(id: String): Completable = dao.markResolved(id, ResolvedResult.FAILURE, currentTimeMillis()) // TODO pass time fun createRecord( commandType: OmnipodCommandType, @@ -33,10 +33,14 @@ class DashHistory @Inject constructor( resolvedAt: Long? = null ): Single { val id = ULID.random() + + // TODO: verify that on OmnipodCommandType.SET_BOLUS bolusRecord is not null? + // TODO: verify that on SET_TEMPORARY_BASAL tempBasalRecord is not null + return dao.save( HistoryRecordEntity( id = id, - createdAt = currentTimeMillis(), + createdAt = currentTimeMillis(), // TODO pass time (as date, keep createdAt) commandType = commandType, tempBasalRecord = tempBasalRecord, bolusRecord = bolusRecord, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt index 5229248a7e..3993d8de73 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt @@ -4,6 +4,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.Omnipod data class HistoryRecord( val id: String, // ULID + // TODO add date val createdAt: Long, val commandType: OmnipodCommandType, val initialResult: InitialResult, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/Converters.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/Converters.kt index b37d71bf3f..2395695f1e 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/Converters.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/Converters.kt @@ -21,10 +21,10 @@ class Converters { fun fromInitialResult(initialResult: InitialResult) = initialResult.name @TypeConverter - fun toResolvedResult(s: String) = enumValueOf(s) + fun toResolvedResult(s: String?) = s?.let { enumValueOf(it) } @TypeConverter - fun fromResolvedResult(resolvedResult: ResolvedResult) = resolvedResult.name + fun fromResolvedResult(resolvedResult: ResolvedResult?) = resolvedResult?.name @TypeConverter fun toOmnipodCommandType(s: String) = enumValueOf(s) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/DashHistoryDatabase.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/DashHistoryDatabase.kt index 259447afb0..75b21716ba 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/DashHistoryDatabase.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/DashHistoryDatabase.kt @@ -5,6 +5,7 @@ import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase import androidx.room.TypeConverters +import androidx.room.migration.Migration @Database( entities = [HistoryRecordEntity::class], @@ -20,12 +21,10 @@ abstract class DashHistoryDatabase : RoomDatabase() { const val VERSION = 1 - @Synchronized fun build(context: Context) = Room.databaseBuilder(context.applicationContext, DashHistoryDatabase::class.java, "omnipod_dash_history_database.db") .fallbackToDestructiveMigration() .build() - } } \ No newline at end of file From 6dce871ed459329545e86662eb0a0507fbc56568 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Sun, 28 Feb 2021 03:55:01 +0100 Subject: [PATCH 3/3] fix database --- .../omnipod/dash/history/DashHistoryTest.kt | 18 +++++++++++++++-- .../pump/omnipod/dash/history/DashHistory.kt | 20 ++++++++++++++----- .../dash/history/data/HistoryRecord.kt | 4 ++-- .../history/database/HistoryRecordEntity.kt | 3 ++- .../dash/history/mapper/HistoryMapper.kt | 4 +++- 5 files changed, 38 insertions(+), 11 deletions(-) diff --git a/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt b/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt index 28467f7a59..9edd38f85e 100644 --- a/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt +++ b/omnipod-dash/src/androidTest/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistoryTest.kt @@ -36,19 +36,33 @@ class DashHistoryTest { } @Test - fun testInsertSomething() { // needs to be camel case as runs on Android + fun testInsertionAndConverters() { dashHistory.getRecords().test().apply { assertValue { it.isEmpty() } } - dashHistory.createRecord(commandType = OmnipodCommandType.SET_BOLUS).test().apply { + dashHistory.createRecord(commandType = OmnipodCommandType.CANCEL_BOLUS, 0L).test().apply { assertValue { ULID.isValid(it) } } dashHistory.getRecords().test().apply { assertValue { it.size == 1 } } + } + @Test + fun testExceptionOnBolusWithoutRecord() { + dashHistory.getRecords().test().apply { + assertValue { it.isEmpty() } + } + + dashHistory.createRecord(commandType = OmnipodCommandType.SET_BOLUS, 0L).test().apply { + assertError(IllegalArgumentException::class.java) + } + + dashHistory.getRecords().test().apply { + assertValue { it.isEmpty() } + } } @After diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt index e2ebf8f94d..d02d1141f9 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/DashHistory.kt @@ -2,6 +2,8 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.history import com.github.guepardoapps.kulid.ULID import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType +import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType.SET_BOLUS +import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType.SET_TEMPORARY_BASAL import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BolusRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.HistoryRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult @@ -20,12 +22,13 @@ class DashHistory @Inject constructor( private val historyMapper: HistoryMapper ) { - fun markSuccess(id: String): Completable = dao.markResolved(id, ResolvedResult.SUCCESS, currentTimeMillis()) // TODO pass time + fun markSuccess(id: String, date: Long): Completable = dao.markResolved(id, ResolvedResult.SUCCESS, currentTimeMillis()) - fun markFailure(id: String): Completable = dao.markResolved(id, ResolvedResult.FAILURE, currentTimeMillis()) // TODO pass time + fun markFailure(id: String, date: Long): Completable = dao.markResolved(id, ResolvedResult.FAILURE, currentTimeMillis()) fun createRecord( commandType: OmnipodCommandType, + date: Long, initialResult: InitialResult = InitialResult.UNCONFIRMED, tempBasalRecord: TempBasalRecord? = null, bolusRecord: BolusRecord? = null, @@ -34,13 +37,20 @@ class DashHistory @Inject constructor( ): Single { val id = ULID.random() - // TODO: verify that on OmnipodCommandType.SET_BOLUS bolusRecord is not null? - // TODO: verify that on SET_TEMPORARY_BASAL tempBasalRecord is not null + when { + commandType == SET_BOLUS && bolusRecord == null -> + Single.error(IllegalArgumentException("bolusRecord missing on SET_BOLUS")) + commandType == SET_TEMPORARY_BASAL && tempBasalRecord == null -> + Single.error(IllegalArgumentException("tempBasalRecord missing on SET_TEMPORARY_BASAL")) + else -> null + }?.let { return it } + return dao.save( HistoryRecordEntity( id = id, - createdAt = currentTimeMillis(), // TODO pass time (as date, keep createdAt) + date = date, + createdAt = currentTimeMillis(), commandType = commandType, tempBasalRecord = tempBasalRecord, bolusRecord = bolusRecord, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt index 3993d8de73..56aa2dc6b2 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/data/HistoryRecord.kt @@ -4,8 +4,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.Omnipod data class HistoryRecord( val id: String, // ULID - // TODO add date - val createdAt: Long, + val createdAt: Long, // creation date of the record + val date: Long, // when event actually happened val commandType: OmnipodCommandType, val initialResult: InitialResult, val record: Record?, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordEntity.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordEntity.kt index 6539009117..4eea309c5a 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordEntity.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/database/HistoryRecordEntity.kt @@ -12,7 +12,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.TempBas @Entity(tableName = "historyrecords") data class HistoryRecordEntity( @PrimaryKey val id: String, // ULID - val createdAt: Long, + val createdAt: Long, // creation date of the record + val date: Long, // when event actually happened val commandType: OmnipodCommandType, val initialResult: InitialResult, @Embedded(prefix = "tempBasalRecord_") val tempBasalRecord: TempBasalRecord?, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/mapper/HistoryMapper.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/mapper/HistoryMapper.kt index 6ceeb6920c..e3eeb39320 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/mapper/HistoryMapper.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/history/mapper/HistoryMapper.kt @@ -11,17 +11,19 @@ class HistoryMapper { HistoryRecordEntity( id = historyRecord.id, createdAt = historyRecord.createdAt, + date = historyRecord.date, commandType = historyRecord.commandType, initialResult = historyRecord.initialResult, tempBasalRecord = historyRecord.record as? TempBasalRecord, bolusRecord = historyRecord.record as? BolusRecord, resolvedResult = historyRecord.resolvedResult, - resolvedAt = historyRecord.resolvedAt + resolvedAt = historyRecord.resolvedAt, ) fun entityToDomain(entity: HistoryRecordEntity): HistoryRecord = HistoryRecord(id = entity.id, createdAt = entity.createdAt, + date = entity.date, initialResult = entity.initialResult, commandType = entity.commandType, record = entity.bolusRecord ?: entity.tempBasalRecord,