Integration test to check tx quorum and reader (#702)

This commit is contained in:
KirillPamPam
2025-08-13 16:08:31 +04:00
committed by GitHub
parent cf2851201b
commit 4e80af7a0c
2 changed files with 55 additions and 44 deletions

View File

@@ -108,7 +108,7 @@ spring-security-config = { module = "org.springframework.security:spring-securit
spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test", version.ref = "spring-boot" } spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test", version.ref = "spring-boot" }
testcontainers = "org.testcontainers:testcontainers:1.17.5" testcontainers = "org.testcontainers:testcontainers:1.21.3"
testcontainers-ganache = "io.github.ganchix:testcontainers-java-module-ganache:0.0.4" testcontainers-ganache = "io.github.ganchix:testcontainers-java-module-ganache:0.0.4"
junit-jupiter = "org.junit.jupiter:junit-jupiter:5.9.1" junit-jupiter = "org.junit.jupiter:junit-jupiter:5.9.1"

View File

@@ -1,80 +1,91 @@
package io.emeraldpay.dshackle package io.emeraldpay.dshackle
import io.emeraldpay.api.proto.BlockchainGrpc
import io.emeraldpay.api.proto.BlockchainOuterClass
import io.emeraldpay.api.proto.Common.ChainRef
import io.emeraldpay.dshackle.config.MainConfig import io.emeraldpay.dshackle.config.MainConfig
import io.emeraldpay.dshackle.config.MainConfigReader import io.emeraldpay.dshackle.config.MainConfigReader
import io.emeraldpay.dshackle.config.UpstreamsConfig import io.emeraldpay.dshackle.config.UpstreamsConfig
import io.emeraldpay.dshackle.foundation.ChainOptions import io.emeraldpay.dshackle.foundation.ChainOptions
import io.github.ganchix.ganache.Account import io.emeraldpay.dshackle.quorum.BroadcastQuorum
import io.github.ganchix.ganache.GanacheContainer import io.emeraldpay.dshackle.quorum.MaximumValueQuorum
import io.emeraldpay.dshackle.reader.BroadcastReader
import io.emeraldpay.dshackle.reader.RequestReaderFactory
import io.emeraldpay.dshackle.upstream.MultistreamHolder
import io.emeraldpay.dshackle.upstream.Selector
import io.grpc.BindableService import io.grpc.BindableService
import io.grpc.inprocess.InProcessChannelBuilder import org.assertj.core.api.Assertions.assertThat
import io.grpc.inprocess.InProcessServerBuilder
import org.assertj.core.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import org.mockito.Mockito.mock
import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.TestConfiguration import org.springframework.boot.test.context.TestConfiguration
import org.springframework.cloud.sleuth.Tracer
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Import import org.springframework.context.annotation.Import
import org.springframework.context.annotation.Profile import org.springframework.context.annotation.Profile
import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.ActiveProfiles
import org.springframework.util.ResourceUtils import org.springframework.util.ResourceUtils
import java.math.BigInteger import org.testcontainers.containers.GenericContainer
import java.net.URI import java.net.URI
@SpringBootTest(properties = ["spring.main.allow-bean-definition-overriding=true"]) @SpringBootTest(properties = ["spring.main.allow-bean-definition-overriding=true"])
@Import(Config::class) @Import(Config::class)
@ActiveProfiles("integration-test") @ActiveProfiles("integration-test")
@Disabled
class IntegrationTest { class IntegrationTest {
@Autowired @Autowired
lateinit var services: List<BindableService> lateinit var services: List<BindableService>
lateinit var stub: BlockchainGrpc.BlockchainBlockingStub @Autowired
lateinit var multistreamHolder: MultistreamHolder
companion object { companion object {
var ganache: GenericContainer<*> = GenericContainer<Nothing>("trufflesuite/ganache:latest").apply {
val PRIVATE_KEY_0 = "ae020c8ddb6fbc24e167b011666639d2ce3d4aa0d9c13d02d726d6865618a781" withExposedPorts(8545)
val PRIVATE_KEY_1 = "81ad1ba5c4da47feb0f0163c0c61a66c4d0e6a66bd839827444b1e3362016140" withCommand(
"--server.host=0.0.0.0",
var ganacheContainer: GanacheContainer<*> = GanacheContainer<Nothing>().apply { "--server.port=8545",
withAccounts( "--chain.chainId=1",
listOf( "--chain.networkId=1", // alias: -i=80001
Account.builder().privateKey(PRIVATE_KEY_0).balance(BigInteger.valueOf(2000000000000000000)).build(),
Account.builder().privateKey(PRIVATE_KEY_1).balance(BigInteger.valueOf(2000000000000000000)).build(),
),
) )
} }
init { init {
ganacheContainer.start() ganache.start()
} }
} }
@BeforeEach
fun prepare() {
val serverName = InProcessServerBuilder.generateName()
val builder = InProcessServerBuilder.forName(serverName)
.directExecutor()
services.forEach { builder.addService(it) }
val managedChannel = InProcessChannelBuilder.forName(serverName).directExecutor().build()
val server = builder.build()
server.start()
stub = BlockchainGrpc.newBlockingStub(managedChannel)
}
@Test @Test
fun test() { fun testUpstreamTxMethodQuorumAndReader() {
val result = stub.describe(BlockchainOuterClass.DescribeRequest.newBuilder().build()) val ms = multistreamHolder.getUpstream(Chain.ETHEREUM__MAINNET)
Assertions.assertThat(result.chainsCount).isEqualTo(1) val ethUpstream = ms.getUpstreams()[0]
Assertions.assertThat(result.chainsList[0].chain).isEqualTo(ChainRef.CHAIN_ETHEREUM__MAINNET) val tracer = mock<Tracer>()
val reqReader = RequestReaderFactory.default()
val txQuorum = ethUpstream.getMethods().createQuorumFor("eth_sendRawTransaction")
val txCountQuorum = ethUpstream.getMethods().createQuorumFor("eth_getTransactionCount")
val txReader = reqReader.create(
RequestReaderFactory.ReaderData(
ms,
Selector.UpstreamFilter.default,
txQuorum,
null,
tracer,
),
)
val txCountReader = reqReader.create(
RequestReaderFactory.ReaderData(
ms,
Selector.UpstreamFilter.default,
txCountQuorum,
null,
tracer,
),
)
assertThat(txQuorum).isInstanceOf(BroadcastQuorum::class.java)
assertThat(txCountQuorum).isInstanceOf(MaximumValueQuorum::class.java)
assertThat(txReader).isInstanceOf(BroadcastReader::class.java)
assertThat(txCountReader).isInstanceOf(BroadcastReader::class.java)
} }
@TestConfiguration @TestConfiguration
@@ -105,7 +116,7 @@ class IntegrationTest {
execution = UpstreamsConfig.RpcConnection().apply { execution = UpstreamsConfig.RpcConnection().apply {
rpc = UpstreamsConfig.HttpEndpoint( rpc = UpstreamsConfig.HttpEndpoint(
URI.create( URI.create(
"http://" + ganacheContainer.getHost() + ":" + ganacheContainer.getMappedPort(8545) + "/", "http://" + ganache.host + ":" + ganache.getMappedPort(8545) + "/",
), ),
) )
} }