SPImplementationTest

This commit is contained in:
Milos Kozak 2023-08-27 15:44:05 +02:00
parent 7eaf7c21f4
commit 7321284618
6 changed files with 383 additions and 38 deletions

View file

@ -8,6 +8,9 @@ plugins {
apply from: "${project.rootDir}/core/main/android_dependencies.gradle" apply from: "${project.rootDir}/core/main/android_dependencies.gradle"
apply from: "${project.rootDir}/core/main/android_module_dependencies.gradle" apply from: "${project.rootDir}/core/main/android_module_dependencies.gradle"
apply from: "${project.rootDir}/core/main/allopen_dependencies.gradle"
apply from: "${project.rootDir}/core/main/test_dependencies.gradle"
apply from: "${project.rootDir}/core/main/jacoco_global.gradle"
android { android {

View file

@ -27,6 +27,7 @@ class SPImplementation @Inject constructor(
override fun remove(@StringRes resourceID: Int) { override fun remove(@StringRes resourceID: Int) {
spEdit.remove(context.getString(resourceID)) spEdit.remove(context.getString(resourceID))
} }
override fun remove(key: String) { override fun remove(key: String) {
spEdit.remove(key) spEdit.remove(key)
} }
@ -34,30 +35,39 @@ class SPImplementation @Inject constructor(
override fun putBoolean(key: String, value: Boolean) { override fun putBoolean(key: String, value: Boolean) {
spEdit.putBoolean(key, value) spEdit.putBoolean(key, value)
} }
override fun putBoolean(@StringRes resourceID: Int, value: Boolean) { override fun putBoolean(@StringRes resourceID: Int, value: Boolean) {
spEdit.putBoolean(context.getString(resourceID), value) spEdit.putBoolean(context.getString(resourceID), value)
} }
override fun putDouble(key: String, value: Double) { override fun putDouble(key: String, value: Double) {
spEdit.putString(key, value.toString()) spEdit.putString(key, value.toString())
} }
override fun putDouble(@StringRes resourceID: Int, value: Double) { override fun putDouble(@StringRes resourceID: Int, value: Double) {
spEdit.putString(context.getString(resourceID), value.toString()) spEdit.putString(context.getString(resourceID), value.toString())
} }
override fun putLong(key: String, value: Long) { override fun putLong(key: String, value: Long) {
spEdit.putLong(key, value) spEdit.putLong(key, value)
} }
override fun putLong(@StringRes resourceID: Int, value: Long) { override fun putLong(@StringRes resourceID: Int, value: Long) {
spEdit.putLong(context.getString(resourceID), value) spEdit.putLong(context.getString(resourceID), value)
} }
override fun putInt(key: String, value: Int) { override fun putInt(key: String, value: Int) {
spEdit.putInt(key, value) spEdit.putInt(key, value)
} }
override fun putInt(@StringRes resourceID: Int, value: Int) { override fun putInt(@StringRes resourceID: Int, value: Int) {
spEdit.putInt(context.getString(resourceID), value) spEdit.putInt(context.getString(resourceID), value)
} }
override fun putString(key: String, value: String) { override fun putString(key: String, value: String) {
spEdit.putString(key, value) spEdit.putString(key, value)
} }
override fun putString(@StringRes resourceID: Int, value: String) { override fun putString(@StringRes resourceID: Int, value: String) {
spEdit.putString(context.getString(resourceID), value) spEdit.putString(context.getString(resourceID), value)
} }
@ -88,15 +98,15 @@ class SPImplementation @Inject constructor(
override fun getString(resourceID: Int, defaultValue: String): String = override fun getString(resourceID: Int, defaultValue: String): String =
sharedPreferences.getString(context.getString(resourceID), defaultValue) ?: defaultValue sharedPreferences.getString(context.getString(resourceID), defaultValue) ?: defaultValue
override fun getString(key: String, defaultValue: String): String =
sharedPreferences.getString(key, defaultValue) ?: defaultValue
override fun getStringOrNull(resourceID: Int, defaultValue: String?): String? = override fun getStringOrNull(resourceID: Int, defaultValue: String?): String? =
sharedPreferences.getString(context.getString(resourceID), defaultValue) ?: defaultValue sharedPreferences.getString(context.getString(resourceID), defaultValue) ?: defaultValue
override fun getStringOrNull(key: String, defaultValue: String?): String? = override fun getStringOrNull(key: String, defaultValue: String?): String? =
sharedPreferences.getString(key, defaultValue) sharedPreferences.getString(key, defaultValue)
override fun getString(key: String, defaultValue: String): String =
sharedPreferences.getString(key, defaultValue) ?: defaultValue
override fun getBoolean(resourceID: Int, defaultValue: Boolean): Boolean { override fun getBoolean(resourceID: Int, defaultValue: Boolean): Boolean {
return try { return try {
sharedPreferences.getBoolean(context.getString(resourceID), defaultValue) sharedPreferences.getBoolean(context.getString(resourceID), defaultValue)
@ -114,16 +124,16 @@ class SPImplementation @Inject constructor(
} }
override fun getDouble(resourceID: Int, defaultValue: Double): Double = override fun getDouble(resourceID: Int, defaultValue: Double): Double =
SafeParse.stringToDouble(sharedPreferences.getString(context.getString(resourceID), defaultValue.toString())) SafeParse.stringToDouble(sharedPreferences.getString(context.getString(resourceID), defaultValue.toString()), defaultValue)
override fun getDouble(key: String, defaultValue: Double): Double = override fun getDouble(key: String, defaultValue: Double): Double =
SafeParse.stringToDouble(sharedPreferences.getString(key, defaultValue.toString())) SafeParse.stringToDouble(sharedPreferences.getString(key, defaultValue.toString()), defaultValue)
override fun getInt(resourceID: Int, defaultValue: Int): Int { override fun getInt(resourceID: Int, defaultValue: Int): Int {
return try { return try {
sharedPreferences.getInt(context.getString(resourceID), defaultValue) sharedPreferences.getInt(context.getString(resourceID), defaultValue)
} catch (e: Exception) { } catch (e: Exception) {
SafeParse.stringToInt(sharedPreferences.getString(context.getString(resourceID), defaultValue.toString())) SafeParse.stringToInt(sharedPreferences.getString(context.getString(resourceID), defaultValue.toString()), defaultValue)
} }
} }
@ -131,7 +141,7 @@ class SPImplementation @Inject constructor(
return try { return try {
sharedPreferences.getInt(key, defaultValue) sharedPreferences.getInt(key, defaultValue)
} catch (e: Exception) { } catch (e: Exception) {
SafeParse.stringToInt(sharedPreferences.getString(key, defaultValue.toString())) SafeParse.stringToInt(sharedPreferences.getString(key, defaultValue.toString()), defaultValue)
} }
} }
@ -139,11 +149,7 @@ class SPImplementation @Inject constructor(
return try { return try {
sharedPreferences.getLong(context.getString(resourceID), defaultValue) sharedPreferences.getLong(context.getString(resourceID), defaultValue)
} catch (e: Exception) { } catch (e: Exception) {
try { SafeParse.stringToLong(sharedPreferences.getString(context.getString(resourceID), defaultValue.toString()), defaultValue)
SafeParse.stringToLong(sharedPreferences.getString(context.getString(resourceID), defaultValue.toString()))
} catch (e: Exception) {
defaultValue
}
} }
} }
@ -151,11 +157,7 @@ class SPImplementation @Inject constructor(
return try { return try {
sharedPreferences.getLong(key, defaultValue) sharedPreferences.getLong(key, defaultValue)
} catch (e: Exception) { } catch (e: Exception) {
try { SafeParse.stringToLong(sharedPreferences.getString(key, defaultValue.toString()), defaultValue)
SafeParse.stringToLong(sharedPreferences.getString(key, defaultValue.toString()))
} catch (e: Exception) {
defaultValue
}
} }
} }

View file

@ -0,0 +1,37 @@
package info.nightscout.androidaps
import info.nightscout.rx.AapsSchedulers
import info.nightscout.rx.TestAapsSchedulers
import info.nightscout.rx.logging.AAPSLoggerTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.Mockito
import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.junit.jupiter.MockitoSettings
import org.mockito.quality.Strictness
import java.util.Locale
@ExtendWith(MockitoExtension::class)
@MockitoSettings(strictness = Strictness.LENIENT)
open class TestBase {
val aapsLogger = AAPSLoggerTest()
val aapsSchedulers: AapsSchedulers = TestAapsSchedulers()
@BeforeEach
fun setupLocale() {
Locale.setDefault(Locale.ENGLISH)
System.setProperty("disableFirebase", "true")
}
// Workaround for Kotlin nullability.
// https://medium.com/@elye.project/befriending-kotlin-and-mockito-1c2e7b0ef791
// https://stackoverflow.com/questions/30305217/is-it-possible-to-use-mockito-in-kotlin
fun <T> anyObject(): T {
Mockito.any<T>()
return uninitialized()
}
@Suppress("Unchecked_Cast")
fun <T> uninitialized(): T = null as T
}

View file

@ -0,0 +1,123 @@
package info.nightscout.androidaps.mocks
import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
class SharedPreferencesMock : SharedPreferences {
private val editor = EditorInternals()
internal class EditorInternals : SharedPreferences.Editor {
var innerMap: MutableMap<String, Any?> = HashMap()
override fun putString(k: String, v: String?): SharedPreferences.Editor {
innerMap[k] = v
return this
}
override fun putStringSet(k: String, set: Set<String>?): SharedPreferences.Editor {
innerMap[k] = set
return this
}
override fun putInt(k: String, i: Int): SharedPreferences.Editor {
innerMap[k] = i
return this
}
override fun putLong(k: String, l: Long): SharedPreferences.Editor {
innerMap[k] = l
return this
}
override fun putFloat(k: String, v: Float): SharedPreferences.Editor {
innerMap[k] = v
return this
}
override fun putBoolean(k: String, b: Boolean): SharedPreferences.Editor {
innerMap[k] = b
return this
}
override fun remove(k: String): SharedPreferences.Editor {
innerMap.remove(k)
return this
}
override fun clear(): SharedPreferences.Editor {
innerMap.clear()
return this
}
override fun commit(): Boolean {
return true
}
override fun apply() {}
}
override fun getAll(): Map<String, *> {
return editor.innerMap
}
override fun getString(k: String, s: String?): String? {
return if (editor.innerMap.containsKey(k)) {
editor.innerMap[k] as String?
} else {
s
}
}
@Suppress("UNCHECKED_CAST")
override fun getStringSet(k: String, set: Set<String>?): Set<String>? {
return if (editor.innerMap.containsKey(k)) {
editor.innerMap[k] as Set<String>?
} else {
set
}
}
override fun getInt(k: String, i: Int): Int {
return if (editor.innerMap.containsKey(k)) {
editor.innerMap[k] as Int
} else {
i
}
}
override fun getLong(k: String, l: Long): Long {
return if (editor.innerMap.containsKey(k)) {
editor.innerMap[k] as Long
} else {
l
}
}
override fun getFloat(k: String, v: Float): Float {
return if (editor.innerMap.containsKey(k)) {
editor.innerMap[k] as Float
} else {
v
}
}
override fun getBoolean(k: String, b: Boolean): Boolean {
return if (editor.innerMap.containsKey(k)) {
editor.innerMap[k] as Boolean
} else {
b
}
}
override fun contains(k: String): Boolean {
return editor.innerMap.containsKey(k)
}
override fun edit(): SharedPreferences.Editor {
return editor
}
override fun registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener: OnSharedPreferenceChangeListener) {}
override fun unregisterOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener: OnSharedPreferenceChangeListener) {}
}

View file

@ -0,0 +1,181 @@
package info.nightscout.shared.impl.sharedPreferences
import android.content.Context
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.mocks.SharedPreferencesMock
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.Mock
import org.mockito.Mockito
class SPImplementationTest : TestBase() {
private val sharedPreferences: SharedPreferencesMock = SharedPreferencesMock()
@Mock lateinit var context: Context
private lateinit var sut: SPImplementation
private val someResource = 1
private val someResource2 = 2
@BeforeEach
fun setUp() {
sut = SPImplementation(sharedPreferences, context)
Mockito.`when`(context.getString(someResource)).thenReturn("some_resource")
Mockito.`when`(context.getString(someResource2)).thenReturn("some_resource_2")
}
@Test
fun edit() {
sut.edit { putBoolean("test", true) }
Assertions.assertTrue(sut.getBoolean("test", false))
sut.edit { remove("test") }
Assertions.assertFalse(sut.contains("test"))
sut.edit { putBoolean(someResource, true) }
Assertions.assertTrue(sut.getBoolean(someResource, false))
sut.edit { remove(someResource) }
Assertions.assertFalse(sut.contains(someResource))
sut.edit(commit = true) { putDouble("test", 1.0) }
Assertions.assertEquals(1.0, sut.getDouble("test", 2.0))
sut.edit { putDouble(someResource, 1.0) }
Assertions.assertEquals(1.0, sut.getDouble(someResource, 2.0))
sut.edit { clear() }
Assertions.assertFalse(sut.contains(someResource2))
sut.edit { putInt("test", 1) }
Assertions.assertEquals(1, sut.getInt("test", 2))
sut.edit { putInt(someResource, 1) }
Assertions.assertEquals(1, sut.getInt(someResource, 2))
sut.edit { clear() }
sut.edit { putLong("test", 1L) }
Assertions.assertEquals(1L, sut.getLong("test", 2L))
sut.edit { putLong(someResource, 1) }
Assertions.assertEquals(1L, sut.getLong(someResource, 2L))
sut.edit { clear() }
sut.edit { putString("test", "string") }
Assertions.assertEquals("string", sut.getString("test", "a"))
sut.edit { putString(someResource, "string") }
Assertions.assertEquals("string", sut.getString(someResource, "a"))
sut.edit { clear() }
}
@Test
fun clear() {
sut.putBoolean("test", true)
Assertions.assertTrue(sut.getAll().containsKey("test"))
sut.clear()
Assertions.assertFalse(sut.getAll().containsKey("test"))
}
@Test
fun contains() {
sut.putBoolean("test", true)
Assertions.assertTrue(sut.contains("test"))
sut.putBoolean(someResource, true)
Assertions.assertTrue(sut.contains(someResource))
}
@Test
fun remove() {
sut.putBoolean("test", true)
sut.remove("test")
Assertions.assertFalse(sut.contains("test"))
sut.putBoolean(someResource, true)
sut.remove(someResource)
Assertions.assertFalse(sut.contains(someResource))
}
@Test
fun getString() {
sut.putString("test", "string")
Assertions.assertTrue(sut.getString("test", "") == "string")
Assertions.assertTrue(sut.getString("test1", "") == "")
sut.putString(someResource, "string")
Assertions.assertTrue(sut.getString(someResource, "") == "string")
Assertions.assertTrue(sut.getString(someResource2, "") == "")
}
@Test
fun getStringOrNull() {
sut.putString("test", "string")
Assertions.assertTrue(sut.getStringOrNull("test", "") == "string")
Assertions.assertNull(sut.getStringOrNull("test1", null))
sut.putString(someResource, "string")
Assertions.assertTrue(sut.getStringOrNull(someResource, null) == "string")
Assertions.assertNull(sut.getStringOrNull(someResource2, null))
}
@Test
fun getBoolean() {
sut.putBoolean("test", true)
Assertions.assertTrue(sut.getBoolean("test", false))
sut.putBoolean(someResource, true)
Assertions.assertTrue(sut.getBoolean(someResource, false))
sut.putString("string_key", "a")
Assertions.assertTrue(sut.getBoolean("string_key", true))
sut.putString(someResource, "a")
Assertions.assertTrue(sut.getBoolean(someResource, true))
}
@Test
fun getDouble() {
sut.putDouble("test", 1.0)
Assertions.assertEquals(1.0, sut.getDouble("test", 2.0))
Assertions.assertEquals(2.0, sut.getDouble("test1", 2.0))
sut.putDouble(someResource, 1.0)
Assertions.assertEquals(1.0, sut.getDouble(someResource, 2.0))
Assertions.assertEquals(2.0, sut.getDouble(someResource2, 2.0))
sut.putString("string_key", "a")
Assertions.assertEquals(1.0, sut.getDouble("string_key", 1.0))
sut.putString(someResource, "a")
Assertions.assertEquals(1.0, sut.getDouble(someResource, 1.0))
}
@Test
fun getInt() {
sut.putInt("test", 1)
Assertions.assertEquals(1, sut.getInt("test", 2))
Assertions.assertEquals(2, sut.getInt("test1", 2))
sut.putInt(someResource, 1)
Assertions.assertEquals(1, sut.getInt(someResource, 2))
Assertions.assertEquals(2, sut.getInt(someResource2, 2))
sut.putString("string_key", "a")
Assertions.assertEquals(1, sut.getInt("string_key", 1))
sut.putString(someResource, "a")
Assertions.assertEquals(1, sut.getInt(someResource, 1))
}
@Test
fun getLong() {
sut.putLong("test", 1L)
Assertions.assertEquals(1L, sut.getLong("test", 2L))
Assertions.assertEquals(2L, sut.getLong("test1", 2L))
sut.putLong(someResource, 1L)
Assertions.assertEquals(1L, sut.getLong(someResource, 2L))
Assertions.assertEquals(2L, sut.getLong(someResource2, 2L))
sut.putString("string_key", "a")
Assertions.assertEquals(1L, sut.getLong("string_key", 1L))
sut.putString(someResource, "a")
Assertions.assertEquals(1L, sut.getLong(someResource, 1L))
}
@Test
fun incLong() {
sut.incLong(someResource)
Assertions.assertEquals(1L, sut.getLong(someResource, 3L))
sut.incLong(someResource)
Assertions.assertEquals(2L, sut.getLong(someResource, 3L))
}
@Test
fun incInt() {
sut.incInt(someResource)
Assertions.assertEquals(1, sut.getInt(someResource, 3))
sut.incInt(someResource)
Assertions.assertEquals(2, sut.getInt(someResource, 3))
}
}

View file

@ -2,7 +2,6 @@ package info.nightscout.shared
object SafeParse { object SafeParse {
// private static Logger log = StacktraceLoggerWrapper.getLogger(SafeParse.class);
fun stringToDouble(inputString: String?, defaultValue: Double = 0.0): Double { fun stringToDouble(inputString: String?, defaultValue: Double = 0.0): Double {
var input = inputString ?: return defaultValue var input = inputString ?: return defaultValue
var result = defaultValue var result = defaultValue
@ -11,50 +10,50 @@ object SafeParse {
if (input == "") return defaultValue if (input == "") return defaultValue
try { try {
result = input.toDouble() result = input.toDouble()
} catch (e: Exception) { } catch (ignored: Exception) {
// log.error("Error parsing " + input + " to double"); // fail over to default
} }
return result return result
} }
fun stringToFloat(inputString: String?): Float { fun stringToFloat(inputString: String?, defaultValue: Float = 0f): Float {
var input = inputString ?: return 0f var input = inputString ?: return defaultValue
var result = 0f var result = defaultValue
input = input.replace(",", ".") input = input.replace(",", ".")
input = input.replace("", "-") input = input.replace("", "-")
if (input == "") return 0f if (input == "") return defaultValue
try { try {
result = input.toFloat() result = input.toFloat()
} catch (e: Exception) { } catch (ignored: Exception) {
// log.error("Error parsing " + input + " to float"); // fail over to default
} }
return result return result
} }
fun stringToInt(inputString: String?): Int { fun stringToInt(inputString: String?, defaultValue: Int = 0): Int {
var input = inputString ?: return 0 var input = inputString ?: return defaultValue
var result = 0 var result = defaultValue
input = input.replace(",", ".") input = input.replace(",", ".")
input = input.replace("", "-") input = input.replace("", "-")
if (input == "") return 0 if (input == "") return defaultValue
try { try {
result = input.toInt() result = input.toInt()
} catch (e: Exception) { } catch (ignored: Exception) {
// log.error("Error parsing " + input + " to int"); // fail over to default
} }
return result return result
} }
fun stringToLong(inputString: String?): Long { fun stringToLong(inputString: String?, defaultValue: Long = 0L): Long {
var input = inputString ?: return 0L var input = inputString ?: return defaultValue
var result = 0L var result = defaultValue
input = input.replace(",", ".") input = input.replace(",", ".")
input = input.replace("", "-") input = input.replace("", "-")
if (input == "") return 0L if (input == "") return defaultValue
try { try {
result = input.toLong() result = input.toLong()
} catch (e: Exception) { } catch (ignored: Exception) {
// log.error("Error parsing " + input + " to long"); // fail over to default
} }
return result return result
} }