Updated on 2026-08-14
This commit is contained in:
parent
820578708c
commit
83d291d7d0
8 changed files with 422 additions and 323 deletions
|
|
@ -2,7 +2,8 @@ package com.tangem.blockchainsdk.providers
|
|||
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.blockchainsdk.BlockchainProvidersResponse
|
||||
import com.tangem.blockchainsdk.providers.BlockchainProvidersResponseMergerTest.Companion.localResponse
|
||||
import com.tangem.blockchainsdk.providers.BlockchainProvidersResponseMergerTest.Companion.remoteResponse
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.config.providers.BlockchainProvidersStorage
|
||||
import com.tangem.datasource.local.config.providers.models.ProviderModel
|
||||
|
|
@ -17,229 +18,71 @@ import org.junit.Test
|
|||
*/
|
||||
internal class BlockchainProvidersResponseLoaderTest {
|
||||
|
||||
private val tangemTechServiceApi = mockk<TangemTechApi>()
|
||||
private val tangemTechApi = mockk<TangemTechApi>()
|
||||
private val blockchainProvidersStorage = mockk<BlockchainProvidersStorage>()
|
||||
|
||||
private val loader = BlockchainProvidersResponseLoader(
|
||||
tangemTechServiceApi = tangemTechServiceApi,
|
||||
tangemTechApi = tangemTechApi,
|
||||
blockchainProvidersStorage = blockchainProvidersStorage,
|
||||
dispatchers = TestingCoroutineDispatcherProvider(),
|
||||
)
|
||||
|
||||
private val firebaseCrashlytics = mockk<FirebaseCrashlytics>()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkStatic(FirebaseCrashlytics::class)
|
||||
val firebaseCrashlytics = mockk<FirebaseCrashlytics>()
|
||||
every { FirebaseCrashlytics.getInstance() } returns firebaseCrashlytics
|
||||
every { firebaseCrashlytics.recordException(any()) } just Runs
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_local_config_is_empty() = runTest {
|
||||
fun test_if_local_config_is_empty() = runTest {
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns emptyMap()
|
||||
|
||||
val expected = null
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder { blockchainProvidersStorage.getConfigSync() }
|
||||
coVerify(inverse = true) { tangemTechServiceApi.getBlockchainProviders() }
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_remote_config_loading_is_loaded_failure() = runTest {
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localProviders
|
||||
coEvery { tangemTechServiceApi.getBlockchainProviders() } throws IllegalStateException("Test exception")
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder {
|
||||
blockchainProvidersStorage.getConfigSync()
|
||||
tangemTechServiceApi.getBlockchainProviders()
|
||||
}
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(localProviders)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_remote_config_loading_is_loaded_successful() = runTest {
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localProviders
|
||||
coEvery { tangemTechServiceApi.getBlockchainProviders() } returns remoteProviders
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder {
|
||||
blockchainProvidersStorage.getConfigSync()
|
||||
tangemTechServiceApi.getBlockchainProviders()
|
||||
}
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(remoteProviders)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_remote_config_is_the_same_as_local() = runTest {
|
||||
val remoteProviders = localProviders
|
||||
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localProviders
|
||||
coEvery { tangemTechServiceApi.getBlockchainProviders() } returns remoteProviders
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder {
|
||||
blockchainProvidersStorage.getConfigSync()
|
||||
tangemTechServiceApi.getBlockchainProviders()
|
||||
}
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(remoteProviders)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_remote_config_has_empty_providers() = runTest {
|
||||
val ethProvider = "ethereum" to emptyList<ProviderModel>()
|
||||
val remoteProvidersWithEth = remoteProviders + ethProvider
|
||||
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localProviders
|
||||
coEvery { tangemTechServiceApi.getBlockchainProviders() } returns remoteProvidersWithEth
|
||||
everyCrashlyticsRecording() just Runs
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder {
|
||||
blockchainProvidersStorage.getConfigSync()
|
||||
tangemTechServiceApi.getBlockchainProviders()
|
||||
firebaseCrashlytics.recordException(any())
|
||||
}
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(remoteProviders)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_local_config_has_empty_providers() = runTest {
|
||||
val localProvidersWithEmptyApt = localProviders.mapValues { if (it.key == "aptos") emptyList() else it.value }
|
||||
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localProvidersWithEmptyApt
|
||||
coEvery { tangemTechServiceApi.getBlockchainProviders() } returns remoteProviders
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder {
|
||||
blockchainProvidersStorage.getConfigSync()
|
||||
tangemTechServiceApi.getBlockchainProviders()
|
||||
}
|
||||
|
||||
val expected = localProvidersWithEmptyApt + remoteProviders
|
||||
coVerify(inverse = true) { tangemTechApi.getBlockchainProviders() }
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_remote_config_doesnt_contain_local_providers() = runTest {
|
||||
val remoteProvidersWithoutLocal: BlockchainProvidersResponse = remoteProviders - localProviders.keys
|
||||
fun test_if_remote_config_loading_is_failed() = runTest {
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localResponse
|
||||
coEvery { tangemTechApi.getBlockchainProviders() } throws IllegalStateException("Test exception")
|
||||
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localProviders
|
||||
coEvery { tangemTechServiceApi.getBlockchainProviders() } returns remoteProvidersWithoutLocal
|
||||
everyCrashlyticsRecording() just Runs
|
||||
val expected = localResponse
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder {
|
||||
blockchainProvidersStorage.getConfigSync()
|
||||
tangemTechServiceApi.getBlockchainProviders()
|
||||
firebaseCrashlytics.recordException(any())
|
||||
tangemTechApi.getBlockchainProviders()
|
||||
}
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(remoteProviders)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_remote_config_contains_unsupported_types() = runTest {
|
||||
val ethProvider = "ethereum" to listOf(ProviderModel.UnsupportedType, ProviderModel.Private(name = "nownodes"))
|
||||
val remoteProvidersWithEth = remoteProviders + ethProvider
|
||||
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localProviders
|
||||
coEvery { tangemTechServiceApi.getBlockchainProviders() } returns remoteProvidersWithEth
|
||||
everyCrashlyticsRecording() just Runs
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder {
|
||||
blockchainProvidersStorage.getConfigSync()
|
||||
tangemTechServiceApi.getBlockchainProviders()
|
||||
firebaseCrashlytics.recordException(any())
|
||||
}
|
||||
|
||||
val expected = remoteProviders + ("ethereum" to listOf(ProviderModel.Private(name = "nownodes")))
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_remote_config_contains_invalid_public_providers() = runTest {
|
||||
val localEthProvider = "ethereum" to listOf(ProviderModel.Private(name = "nownodes"))
|
||||
val localProvidersWithEth = localProviders + localEthProvider
|
||||
fun test_if_remote_config_is_loaded_successfully() = runTest {
|
||||
val eth = "ethereum" to listOf(ProviderModel.Private(name = "nownodes"))
|
||||
|
||||
val remoteEthProvider = "ethereum" to listOf(ProviderModel.UnsupportedType, ProviderModel.Public("adbw2138"))
|
||||
val remoteProvidersWithEth = remoteProviders + remoteEthProvider
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localResponse + eth
|
||||
coEvery { tangemTechApi.getBlockchainProviders() } returns remoteResponse
|
||||
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localProvidersWithEth
|
||||
coEvery { tangemTechServiceApi.getBlockchainProviders() } returns remoteProvidersWithEth
|
||||
everyCrashlyticsRecording() just Runs
|
||||
// Because configs are merged in BlockchainProvidersResponseMerger
|
||||
val expected = remoteResponse + eth
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder {
|
||||
blockchainProvidersStorage.getConfigSync()
|
||||
tangemTechServiceApi.getBlockchainProviders()
|
||||
firebaseCrashlytics.recordException(any())
|
||||
tangemTechApi.getBlockchainProviders()
|
||||
}
|
||||
|
||||
val expected = remoteProviders + localEthProvider
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_load_if_configs_contain_public_providers_without_slash_in_the_end() = runTest {
|
||||
val localPublicProviderUrl = "https://qwe.com"
|
||||
val localEthProvider = "ethereum" to listOf(ProviderModel.Public(url = localPublicProviderUrl))
|
||||
val localProvidersWithEth = localProviders + localEthProvider
|
||||
|
||||
val remotePublicProviderUrl = "https://rty.com"
|
||||
val remoteDogeProvider = "dogecoin" to listOf(ProviderModel.Public(url = remotePublicProviderUrl))
|
||||
val remoteProvidersWithDoge = remoteProviders + remoteDogeProvider
|
||||
|
||||
coEvery { blockchainProvidersStorage.getConfigSync() } returns localProvidersWithEth
|
||||
coEvery { tangemTechServiceApi.getBlockchainProviders() } returns remoteProvidersWithDoge
|
||||
everyCrashlyticsRecording() just Runs
|
||||
|
||||
val actual = loader.load()
|
||||
|
||||
coVerifyOrder {
|
||||
blockchainProvidersStorage.getConfigSync()
|
||||
tangemTechServiceApi.getBlockchainProviders()
|
||||
firebaseCrashlytics.recordException(any())
|
||||
}
|
||||
|
||||
val expected = remoteProviders +
|
||||
localEthProvider.copy(second = listOf(ProviderModel.Public(url = "$localPublicProviderUrl/"))) +
|
||||
remoteDogeProvider.copy(second = listOf(ProviderModel.Public(url = "$remotePublicProviderUrl/")))
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
private fun everyCrashlyticsRecording() = every { firebaseCrashlytics.recordException(any()) }
|
||||
|
||||
private companion object {
|
||||
val localProviders: BlockchainProvidersResponse = mapOf(
|
||||
"aptos" to listOf(ProviderModel.Private(name = "nownodes")),
|
||||
"algorand" to listOf(
|
||||
ProviderModel.Private(name = "nownodes"),
|
||||
ProviderModel.Public(url = "https://public_alg.com/"),
|
||||
),
|
||||
)
|
||||
|
||||
val remoteProviders: BlockchainProvidersResponse = localProviders + mapOf(
|
||||
"bitcoin" to listOf(ProviderModel.Private(name = "blockchair")),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
package com.tangem.blockchainsdk.providers
|
||||
|
||||
import com.google.common.truth.Truth
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.blockchainsdk.BlockchainProvidersResponse
|
||||
import com.tangem.datasource.local.config.providers.models.ProviderModel
|
||||
import io.mockk.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class BlockchainProvidersResponseMergerTest {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkStatic(FirebaseCrashlytics::class)
|
||||
val firebaseCrashlytics = mockk<FirebaseCrashlytics>()
|
||||
every { FirebaseCrashlytics.getInstance() } returns firebaseCrashlytics
|
||||
every { firebaseCrashlytics.recordException(any()) } just Runs
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_both_configs_are_empty() {
|
||||
val expected = emptyMap<String, List<ProviderModel>>()
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = emptyMap(),
|
||||
remote = emptyMap(),
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_local_config_is_empty() {
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = emptyMap(),
|
||||
remote = remoteResponse,
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_remote_config_is_empty() {
|
||||
val expected = localResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = emptyMap(),
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_both_configs_are_not_empty() {
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteResponse,
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_configs_are_equal() {
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = remoteResponse,
|
||||
remote = remoteResponse,
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_local_config_has_blockchain_with_empty_providers() {
|
||||
val eth = "ethereum" to emptyList<ProviderModel>()
|
||||
val localResponseWithEth = localResponse + eth
|
||||
|
||||
val expected = localResponseWithEth + remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = localResponseWithEth,
|
||||
remote = remoteResponse,
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_remote_config_has_blockchain_with_empty_providers() {
|
||||
val expected = remoteResponse
|
||||
|
||||
val eth = "ethereum" to emptyList<ProviderModel>()
|
||||
val remoteWithEth = remoteResponse + eth
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteWithEth,
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_remote_config_doesnt_contain_local_providers() {
|
||||
val remoteWithoutLocal = remoteResponse - localResponse.keys
|
||||
|
||||
/**
|
||||
* The expected result does not contain local blockchains, since they can be disabled remotely.
|
||||
* For the opposite case, see [test_if_both_configs_are_not_empty].
|
||||
*/
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteWithoutLocal,
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_remote_config_contains_unsupported_providers() {
|
||||
val nowNodesProvider = ProviderModel.Private(name = "nownodes")
|
||||
val eth = "ethereum" to listOf(ProviderModel.UnsupportedType, nowNodesProvider)
|
||||
val remoteWithEth = remoteResponse + eth
|
||||
|
||||
val expected = remoteResponse + ("ethereum" to listOf(nowNodesProvider))
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteWithEth,
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_remote_config_contains_invalid_public_providers() {
|
||||
val eth = "ethereum" to listOf(ProviderModel.UnsupportedType, ProviderModel.Public("adbw2138"))
|
||||
val remoteWithEth = remoteResponse + eth
|
||||
|
||||
val expected = remoteResponse
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = localResponse,
|
||||
remote = remoteWithEth,
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_if_configs_contain_public_providers_without_slash_in_the_end() {
|
||||
val eth = "ethereum" to listOf(ProviderModel.Public("https://qwe.com"))
|
||||
val kaspa = "kaspa" to listOf(ProviderModel.Public("https://qwe.com"))
|
||||
|
||||
val localWithKaspa = localResponse + kaspa
|
||||
val remoteWithEth = remoteResponse + eth
|
||||
|
||||
val expected = remoteResponse + eth.addSlash() + kaspa.addSlash()
|
||||
|
||||
val actual = BlockchainProvidersResponseMerger.merge(
|
||||
local = localWithKaspa,
|
||||
remote = remoteWithEth,
|
||||
)
|
||||
|
||||
Truth.assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val localResponse: BlockchainProvidersResponse = mapOf(
|
||||
"aptos" to listOf(ProviderModel.Private(name = "nownodes")),
|
||||
"algorand" to listOf(
|
||||
ProviderModel.Private(name = "nownodes"),
|
||||
ProviderModel.Public(url = "https://public_alg.com/"),
|
||||
),
|
||||
)
|
||||
|
||||
// local + bitcoin
|
||||
val remoteResponse: BlockchainProvidersResponse = mapOf(
|
||||
"aptos" to listOf(ProviderModel.Private(name = "nownodes")),
|
||||
"algorand" to listOf(
|
||||
ProviderModel.Private(name = "nownodes"),
|
||||
ProviderModel.Public(url = "https://public_alg.com/"),
|
||||
),
|
||||
"bitcoin" to listOf(ProviderModel.Private(name = "blockchair")),
|
||||
)
|
||||
|
||||
private fun Pair<String, List<ProviderModel.Public>>.addSlash(): Pair<String, List<ProviderModel.Public>> {
|
||||
return first to second.map { it.copy(url = "${it.url}/") }
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue