Upgrade robolectric to version 4.16 (#5923)
* Update dependency org.robolectric:robolectric to v4.16 * Fix file size formatter output on API 26+ * Use more realistic value for maxUploadSize * Update screenshots * Fix test issue: "java.security.KeyStoreException: AndroidKeyStore not found" * Add exceptions. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
commit
2a9765ad33
11 changed files with 127 additions and 30 deletions
|
|
@ -95,7 +95,7 @@ fun aMediaUploadInfo(
|
|||
)
|
||||
|
||||
fun aMediaOptimisationSelectorState(
|
||||
maxUploadSize: Long = 100,
|
||||
maxUploadSize: Long = 100 * 1024 * 1024,
|
||||
videoSizeEstimations: AsyncData<ImmutableList<VideoUploadEstimation>> = AsyncData.Success(persistentListOf()),
|
||||
isImageOptimizationEnabled: Boolean = true,
|
||||
selectedVideoPreset: VideoCompressionPreset = VideoCompressionPreset.STANDARD,
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ test_konsist = "com.lemonappdev:konsist:0.17.3"
|
|||
test_turbine = "app.cash.turbine:turbine:1.2.1"
|
||||
test_truth = "com.google.truth:truth:1.4.5"
|
||||
test_parameter_injector = "com.google.testparameterinjector:test-parameter-injector:1.20"
|
||||
test_robolectric = "org.robolectric:robolectric:4.15.1"
|
||||
test_robolectric = "org.robolectric:robolectric:4.16"
|
||||
test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "appyx" }
|
||||
test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.7.2"
|
||||
test_detekt_api = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" }
|
||||
|
|
|
|||
|
|
@ -24,12 +24,15 @@ class AndroidFileSizeFormatter(
|
|||
override fun format(fileSize: Long, useShortFormat: Boolean): String {
|
||||
// Since Android O, the system considers that 1kB = 1000 bytes instead of 1024 bytes.
|
||||
// We want to avoid that.
|
||||
// Sadly we do not have access to the flags values Formatter.FLAG_IEC_UNITS and Formatter.FLAG_SHORTER
|
||||
// nor the method Formatter.formatFileSize with the flags parameter.
|
||||
// So for Android 0 and more, first convert the fileSize to MB/GB/TB ourselves
|
||||
val normalizedSize = if (sdkIntProvider.get() <= Build.VERSION_CODES.N) {
|
||||
fileSize
|
||||
} else {
|
||||
// First convert the size
|
||||
when {
|
||||
fileSize < 1024 -> fileSize
|
||||
fileSize <= 1 -> fileSize
|
||||
fileSize < 1024 * 1024 -> fileSize * 1000 / 1024
|
||||
fileSize < 1024 * 1024 * 1024 -> fileSize * 1000 / 1024 * 1000 / 1024
|
||||
else -> fileSize * 1000 / 1024 * 1000 / 1024 * 1000 / 1024
|
||||
|
|
@ -40,6 +43,6 @@ class AndroidFileSizeFormatter(
|
|||
Formatter.formatShortFileSize(context, normalizedSize)
|
||||
} else {
|
||||
Formatter.formatFileSize(context, normalizedSize)
|
||||
}
|
||||
}.replace("kB", "KB")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,45 +15,59 @@ import org.junit.Test
|
|||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class AndroidFileSizeFormatterTest {
|
||||
@Config(sdk = [Build.VERSION_CODES.N])
|
||||
@Test
|
||||
fun `test api 24 long format`() {
|
||||
val sut = createAndroidFileSizeFormatter(sdkLevel = Build.VERSION_CODES.N)
|
||||
assertThat(sut.format(1, useShortFormat = false)).isEqualTo("1.00B")
|
||||
assertThat(sut.format(1000, useShortFormat = false)).isEqualTo("0.98KB")
|
||||
assertThat(sut.format(1024, useShortFormat = false)).isEqualTo("1.00KB")
|
||||
assertThat(sut.format(1024 * 1024, useShortFormat = false)).isEqualTo("1.00MB")
|
||||
assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = false)).isEqualTo("1.00GB")
|
||||
assertThat(sut.format(1, useShortFormat = false)).isEqualTo("1 B")
|
||||
assertThat(sut.format(1000, useShortFormat = false)).isEqualTo("0.98 KB")
|
||||
assertThat(sut.format(1024, useShortFormat = false)).isEqualTo("1.00 KB")
|
||||
assertThat(sut.format(1024 * 500, useShortFormat = false)).isEqualTo("500 KB")
|
||||
assertThat(sut.format(1024 * 1024, useShortFormat = false)).isEqualTo("1.00 MB")
|
||||
assertThat(sut.format(1024 * 1024 * 500, useShortFormat = false)).isEqualTo("500 MB")
|
||||
assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = false)).isEqualTo("1.00 GB")
|
||||
}
|
||||
|
||||
@Config(sdk = [Build.VERSION_CODES.O])
|
||||
@Test
|
||||
fun `test api 26 long format`() {
|
||||
val sut = createAndroidFileSizeFormatter(sdkLevel = Build.VERSION_CODES.O)
|
||||
assertThat(sut.format(1, useShortFormat = false)).isEqualTo("1.00B")
|
||||
assertThat(sut.format(1000, useShortFormat = false)).isEqualTo("0.98KB")
|
||||
assertThat(sut.format(1024 * 1024, useShortFormat = false)).isEqualTo("0.95MB")
|
||||
assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = false)).isEqualTo("0.93GB")
|
||||
assertThat(sut.format(1, useShortFormat = false)).isEqualTo("1 B")
|
||||
assertThat(sut.format(1000, useShortFormat = false)).isEqualTo("0.98 KB")
|
||||
assertThat(sut.format(1024, useShortFormat = false)).isEqualTo("1.00 KB")
|
||||
assertThat(sut.format(1024 * 500, useShortFormat = false)).isEqualTo("500 KB")
|
||||
assertThat(sut.format(1024 * 1024, useShortFormat = false)).isEqualTo("1.00 MB")
|
||||
assertThat(sut.format(1024 * 1024 * 500, useShortFormat = false)).isEqualTo("500 MB")
|
||||
assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = false)).isEqualTo("1.00 GB")
|
||||
}
|
||||
|
||||
@Config(sdk = [Build.VERSION_CODES.N])
|
||||
@Test
|
||||
fun `test api 24 short format`() {
|
||||
val sut = createAndroidFileSizeFormatter(sdkLevel = Build.VERSION_CODES.N)
|
||||
assertThat(sut.format(1, useShortFormat = true)).isEqualTo("1.0B")
|
||||
assertThat(sut.format(1000, useShortFormat = true)).isEqualTo("0.98KB")
|
||||
assertThat(sut.format(1024, useShortFormat = true)).isEqualTo("1.0KB")
|
||||
assertThat(sut.format(1024 * 1024, useShortFormat = true)).isEqualTo("1.0MB")
|
||||
assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = true)).isEqualTo("1.0GB")
|
||||
assertThat(sut.format(1, useShortFormat = true)).isEqualTo("1 B")
|
||||
assertThat(sut.format(1000, useShortFormat = true)).isEqualTo("0.98 KB")
|
||||
assertThat(sut.format(1024, useShortFormat = true)).isEqualTo("1.0 KB")
|
||||
assertThat(sut.format(1024 * 500, useShortFormat = true)).isEqualTo("500 KB")
|
||||
assertThat(sut.format(1024 * 1024, useShortFormat = true)).isEqualTo("1.0 MB")
|
||||
assertThat(sut.format(1024 * 1024 * 500, useShortFormat = true)).isEqualTo("500 MB")
|
||||
assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = true)).isEqualTo("1.0 GB")
|
||||
}
|
||||
|
||||
@Config(sdk = [Build.VERSION_CODES.O])
|
||||
@Test
|
||||
fun `test api 26 short format`() {
|
||||
val sut = createAndroidFileSizeFormatter(sdkLevel = Build.VERSION_CODES.O)
|
||||
assertThat(sut.format(1, useShortFormat = true)).isEqualTo("1.0B")
|
||||
assertThat(sut.format(1000, useShortFormat = true)).isEqualTo("0.98KB")
|
||||
assertThat(sut.format(1024 * 1024, useShortFormat = true)).isEqualTo("0.95MB")
|
||||
assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = true)).isEqualTo("0.93GB")
|
||||
assertThat(sut.format(1, useShortFormat = true)).isEqualTo("1 B")
|
||||
assertThat(sut.format(1000, useShortFormat = true)).isEqualTo("0.98 KB")
|
||||
assertThat(sut.format(1024, useShortFormat = true)).isEqualTo("1.0 KB")
|
||||
assertThat(sut.format(1024 * 500, useShortFormat = true)).isEqualTo("500 KB")
|
||||
assertThat(sut.format(1024 * 1024, useShortFormat = true)).isEqualTo("1.0 MB")
|
||||
assertThat(sut.format(1024 * 1024 * 1024, useShortFormat = true)).isEqualTo("1.0 GB")
|
||||
}
|
||||
|
||||
private fun createAndroidFileSizeFormatter(sdkLevel: Int) = AndroidFileSizeFormatter(
|
||||
|
|
|
|||
|
|
@ -15,16 +15,23 @@ import io.element.android.libraries.matrix.test.A_SECRET
|
|||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.registration.EndpointRegistrationHandler
|
||||
import io.element.android.libraries.pushproviders.unifiedpush.registration.RegistrationResult
|
||||
import io.element.android.tests.testutils.fake.FakeAndroidKeyStore
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class DefaultRegisterUnifiedPushUseCaseTest {
|
||||
@Before
|
||||
fun setup() {
|
||||
FakeAndroidKeyStore.setup
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test registration successful`() = runTest {
|
||||
val endpointRegistrationHandler = EndpointRegistrationHandler()
|
||||
|
|
|
|||
|
|
@ -99,8 +99,10 @@ class KonsistClassNameTest {
|
|||
.classes()
|
||||
.withNameContaining("Fake")
|
||||
.withoutName(
|
||||
"FakeAesKeyGenerator",
|
||||
"FakeFileSystem",
|
||||
"FakeImageLoader",
|
||||
"FakeKeyStore",
|
||||
"FakeListenableFuture",
|
||||
)
|
||||
.assertTrue {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.tests.testutils.fake
|
||||
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.security.Key
|
||||
import java.security.KeyStore
|
||||
import java.security.KeyStoreSpi
|
||||
import java.security.Provider
|
||||
import java.security.SecureRandom
|
||||
import java.security.Security
|
||||
import java.security.cert.Certificate
|
||||
import java.security.spec.AlgorithmParameterSpec
|
||||
import java.util.Date
|
||||
import java.util.Enumeration
|
||||
import javax.crypto.KeyGenerator
|
||||
import javax.crypto.KeyGeneratorSpi
|
||||
import javax.crypto.SecretKey
|
||||
|
||||
// Source - https://stackoverflow.com/questions/38213748/using-the-android-keystore-in-robolectric-tests/75763240#75763240
|
||||
// Posted by Victor Oliveira
|
||||
// Retrieved 2025-12-19, License - CC BY-SA 4.0
|
||||
|
||||
object FakeAndroidKeyStore {
|
||||
val setup by lazy {
|
||||
Security.addProvider(object : Provider("AndroidKeyStore", 1.0, "") {
|
||||
init {
|
||||
put("KeyStore.AndroidKeyStore", FakeKeyStore::class.java.name)
|
||||
put("KeyGenerator.AES", FakeAesKeyGenerator::class.java.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class FakeKeyStore : KeyStoreSpi() {
|
||||
private val wrapped = KeyStore.getInstance(KeyStore.getDefaultType())
|
||||
|
||||
override fun engineIsKeyEntry(alias: String?): Boolean = wrapped.isKeyEntry(alias)
|
||||
override fun engineIsCertificateEntry(alias: String?): Boolean = wrapped.isCertificateEntry(alias)
|
||||
override fun engineGetCertificate(alias: String?): Certificate = wrapped.getCertificate(alias)
|
||||
override fun engineGetCreationDate(alias: String?): Date = wrapped.getCreationDate(alias)
|
||||
override fun engineDeleteEntry(alias: String?) = wrapped.deleteEntry(alias)
|
||||
override fun engineSetKeyEntry(alias: String?, key: Key?, password: CharArray?, chain: Array<out Certificate>?) =
|
||||
wrapped.setKeyEntry(alias, key, password, chain)
|
||||
|
||||
override fun engineSetKeyEntry(alias: String?, key: ByteArray?, chain: Array<out Certificate>?) = wrapped.setKeyEntry(alias, key, chain)
|
||||
override fun engineStore(stream: OutputStream?, password: CharArray?) = wrapped.store(stream, password)
|
||||
override fun engineSize(): Int = wrapped.size()
|
||||
override fun engineAliases(): Enumeration<String> = wrapped.aliases()
|
||||
override fun engineContainsAlias(alias: String?): Boolean = wrapped.containsAlias(alias)
|
||||
override fun engineLoad(stream: InputStream?, password: CharArray?) = wrapped.load(stream, password)
|
||||
override fun engineGetCertificateChain(alias: String?): Array<Certificate> = wrapped.getCertificateChain(alias)
|
||||
override fun engineSetCertificateEntry(alias: String?, cert: Certificate?) = wrapped.setCertificateEntry(alias, cert)
|
||||
override fun engineGetCertificateAlias(cert: Certificate?): String = wrapped.getCertificateAlias(cert)
|
||||
override fun engineGetKey(alias: String?, password: CharArray?): Key = wrapped.getKey(alias, password)
|
||||
}
|
||||
|
||||
class FakeAesKeyGenerator : KeyGeneratorSpi() {
|
||||
private val wrapped = KeyGenerator.getInstance("AES")
|
||||
|
||||
override fun engineInit(random: SecureRandom?) = Unit
|
||||
override fun engineInit(params: AlgorithmParameterSpec?, random: SecureRandom?) = Unit
|
||||
override fun engineInit(keysize: Int, random: SecureRandom?) = Unit
|
||||
override fun engineGenerateKey(): SecretKey = wrapped.generateKey()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d3f18250226a6d8eb034b1de50531ad5b09c3da3020090a04d6064156d5aac35
|
||||
size 72811
|
||||
oid sha256:267c22669a6b79d3f2cf39307bab2bc9192c7d5426cd8967400ccb6422d3afee
|
||||
size 73059
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:787675a64260b3557948840d252836cd561814117e93dda41332af57ad54953a
|
||||
size 83474
|
||||
oid sha256:88539a3267facb99fdff7e49f6d554aca83d7fafa4896c27b1d5f5ab0dedfb32
|
||||
size 83677
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:521262df440dc94729863544f131f3b025057aa854f7b5d40490bbb24aafe45b
|
||||
size 56605
|
||||
oid sha256:17b4bfbf75f7999c39e32245ecfeb209524865a47d0d79b9249a2833d0988ffe
|
||||
size 56663
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:72132b0490257da50ca1a55599eff7f5c4bfdc0266d9d01c0822d51c728423f5
|
||||
size 54345
|
||||
oid sha256:724455c16cb39e9b532a57286c2a1a22d74930b5b06ff3e5b13771327545fa8f
|
||||
size 54404
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue