From 4829e8de19ad935d47371ee6e5f65d5c3f78249a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20W=C3=BCrl?= Date: Fri, 29 Mar 2024 07:26:16 +0100 Subject: [PATCH] simplified cache size calculation and tests for cache --- .../android/data/MainDataHandler.kt | 5 +- .../android/data/cache/DataCache.kt | 26 +++--- .../blitzortung/android/dialogs/LogDialog.kt | 5 +- .../android/data/cache/DataCacheTest.kt | 85 +++++++++++++++++++ 4 files changed, 102 insertions(+), 19 deletions(-) create mode 100644 app/src/test/java/org/blitzortung/android/data/cache/DataCacheTest.kt diff --git a/app/src/main/java/org/blitzortung/android/data/MainDataHandler.kt b/app/src/main/java/org/blitzortung/android/data/MainDataHandler.kt index 448a773d..b568c700 100644 --- a/app/src/main/java/org/blitzortung/android/data/MainDataHandler.kt +++ b/app/src/main/java/org/blitzortung/android/data/MainDataHandler.kt @@ -32,6 +32,7 @@ import org.blitzortung.android.app.R import org.blitzortung.android.app.view.OnSharedPreferenceChangeListener import org.blitzortung.android.app.view.PreferenceKey import org.blitzortung.android.app.view.get +import org.blitzortung.android.data.cache.CacheSize import org.blitzortung.android.data.cache.DataCache import org.blitzortung.android.data.provider.DataProviderFactory import org.blitzortung.android.data.provider.DataProviderType @@ -443,9 +444,7 @@ class MainDataHandler @Inject constructor( } } - fun calculateTotalCacheSize(): Int = cache.calculateTotalSize() - - + fun calculateTotalCacheSize(): CacheSize = cache.calculateTotalSize() } internal const val DEFAULT_RASTER_BASELENGTH = 10000 diff --git a/app/src/main/java/org/blitzortung/android/data/cache/DataCache.kt b/app/src/main/java/org/blitzortung/android/data/cache/DataCache.kt index c4dcec41..6de1a998 100644 --- a/app/src/main/java/org/blitzortung/android/data/cache/DataCache.kt +++ b/app/src/main/java/org/blitzortung/android/data/cache/DataCache.kt @@ -13,7 +13,7 @@ import javax.inject.Singleton @Singleton class DataCache @Inject constructor() { - private val cache = hashMapOf>() + val cache = hashMapOf>() fun get(parameters: Parameters, expiryTime: Long = DEFAULT_EXPIRY_TIME): ResultEvent? { val entry = cache[parameters] ?: return null @@ -28,18 +28,11 @@ class DataCache @Inject constructor() { cache[parameters] = Timestamped(dataEvent) } - fun calculateTotalSize(): Int = cache.entries.fold(0) { acc, entry -> - val size = determineObjectSize(entry.value) - Log.v(LOG_TAG, "${entry.key} -> ${size}") - acc + size - } - - private fun determineObjectSize(obj: Any): Int { - val baos = ByteArrayOutputStream() - val oos = ObjectOutputStream(baos) - oos.writeObject(obj) - oos.close() - return baos.size() + fun calculateTotalSize(): CacheSize = cache.entries.fold(CacheSize(0,0)) { acc, entry -> + val resultEvent = entry.value.value + val strikeCount = resultEvent.strikes?.size ?: 0 + Log.v(LOG_TAG, "${entry.key} -> ${strikeCount}") + CacheSize(acc.entries + 1, acc.strikes + strikeCount) } fun clear() { @@ -51,4 +44,9 @@ class DataCache @Inject constructor() { } } -data class Timestamped(val value: T, val timestamp: Long = System.currentTimeMillis()) : Serializable \ No newline at end of file +data class Timestamped(val value: T, val timestamp: Long = System.currentTimeMillis()) : Serializable + +data class CacheSize( + val entries: Int, + val strikes: Int, +) \ No newline at end of file diff --git a/app/src/main/java/org/blitzortung/android/dialogs/LogDialog.kt b/app/src/main/java/org/blitzortung/android/dialogs/LogDialog.kt index 7b1b9d13..b098c4ec 100644 --- a/app/src/main/java/org/blitzortung/android/dialogs/LogDialog.kt +++ b/app/src/main/java/org/blitzortung/android/dialogs/LogDialog.kt @@ -29,11 +29,12 @@ import android.widget.TextView import android.widget.Toast import org.blitzortung.android.app.R import org.blitzortung.android.app.components.BuildVersion +import org.blitzortung.android.data.cache.CacheSize import org.blitzortung.android.dialogs.log.LogProvider class LogDialog( context: Context, - private val cacheSize: Int, + private val cacheSize: CacheSize, private val buildVersion: BuildVersion, private val logProvider: LogProvider = LogProvider() ) : android.app.AlertDialog(context) { @@ -65,7 +66,7 @@ class LogDialog( } private fun getCacheString(): String { - return "Cache size: %.3f MB".format(cacheSize/1024f/1024f) + return "Cache size: %d entries, %d strikes".format(cacheSize.entries, cacheSize.strikes) } private fun getDeviceString(): String { diff --git a/app/src/test/java/org/blitzortung/android/data/cache/DataCacheTest.kt b/app/src/test/java/org/blitzortung/android/data/cache/DataCacheTest.kt new file mode 100644 index 00000000..bdf3758e --- /dev/null +++ b/app/src/test/java/org/blitzortung/android/data/cache/DataCacheTest.kt @@ -0,0 +1,85 @@ +package org.blitzortung.android.data.cache + +import io.mockk.MockKAnnotations +import org.assertj.core.api.Assertions.assertThat +import org.blitzortung.android.data.Flags +import org.blitzortung.android.data.Parameters +import org.blitzortung.android.data.TimeInterval +import org.blitzortung.android.data.beans.RasterElement +import org.blitzortung.android.data.provider.result.ResultEvent +import org.junit.Before +import org.junit.Test + +class DataCacheTest { + + private val parameters = Parameters(interval = TimeInterval(offset = 30)) + + private lateinit var uut: DataCache + + @Before + fun setUp() { + MockKAnnotations.init(this, relaxed = true) + + uut = DataCache() + } + + @Test + fun cacheMiss() { + val result = uut.get(parameters) + + assertThat(result).isNull() + } + + @Test + fun emptySize() { + val result = uut.calculateTotalSize() + + assertThat(result).isEqualTo(CacheSize(0,0)) + } + + @Test + fun cachePut() { + val dataEvent = ResultEvent(parameters = parameters, flags = Flags()) + uut.put(parameters, dataEvent) + + val result = uut.get(parameters) + + assertThat(result).isEqualTo(dataEvent) + } + + @Test + fun cacheClear() { + val dataEvent = ResultEvent(parameters = parameters, flags = Flags()) + uut.put(parameters, dataEvent) + uut.clear() + + val result = uut.get(parameters) + + assertThat(result).isNull() + } + + @Test + fun cachePutOutdated() { + val dataEvent = ResultEvent(parameters = parameters, flags = Flags()) + uut.cache[parameters] = Timestamped(dataEvent, System.currentTimeMillis() - DataCache.DEFAULT_EXPIRY_TIME - 1) + + val result = uut.get(parameters) + + assertThat(result).isNull() + } + + @Test + fun cacheSizeSimple() { + val strikes = listOf( + RasterElement(0, 1.0, 2.0, 3), + RasterElement(2, 3.0, 4.0, 2), + ) + val dataEvent = ResultEvent(parameters = parameters, flags = Flags(), strikes = strikes) + + uut.put(parameters, dataEvent) + + val result = uut.calculateTotalSize() + + assertThat(result).isEqualTo(CacheSize(1,2)) + } +} \ No newline at end of file