problem: doesn't update head subscription through remote dshackle, because upstream becomes ready later after chain setup
solution: fix and refactor to avoid such situation in code
This commit is contained in:
@@ -27,14 +27,13 @@ class NativeCallSpec extends Specification {
|
||||
def quorum = Spy(new AlwaysQuorum())
|
||||
def upstreams = Stub(Upstreams)
|
||||
RpcClient rpcClient = Stub(RpcClient)
|
||||
def upstream = Stub(Upstream)
|
||||
def apiMock = TestingCommons.api(rpcClient, upstream)
|
||||
def apiMock = TestingCommons.api(rpcClient)
|
||||
apiMock.upstream = Stub(Upstream)
|
||||
|
||||
apiMock.answer("eth_test", [], "foo")
|
||||
|
||||
def nativeCall = new NativeCall(upstreams, TestingCommons.objectMapper())
|
||||
def call = new NativeCall.CallContext(1, [apiMock].multiply(5).iterator(), quorum, Tuples.of("eth_test", []))
|
||||
|
||||
def call = new NativeCall.CallContext(1, [apiMock].multiply(59).iterator(), quorum, Tuples.of("eth_test", []))
|
||||
|
||||
when:
|
||||
def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(2))
|
||||
@@ -52,8 +51,8 @@ class NativeCallSpec extends Specification {
|
||||
|
||||
def upstreams = Stub(Upstreams)
|
||||
RpcClient rpcClient = Stub(RpcClient)
|
||||
def upstream = Stub(Upstream)
|
||||
def apiMock = TestingCommons.api(rpcClient, upstream)
|
||||
def apiMock = TestingCommons.api(rpcClient)
|
||||
apiMock.upstream = Stub(Upstream)
|
||||
|
||||
apiMock.answerOnce("eth_test", [], null)
|
||||
apiMock.answerOnce("eth_test", [], "bar")
|
||||
@@ -79,8 +78,8 @@ class NativeCallSpec extends Specification {
|
||||
|
||||
def upstreams = Stub(Upstreams)
|
||||
RpcClient rpcClient = Stub(RpcClient)
|
||||
def upstream = Stub(Upstream)
|
||||
def apiMock = TestingCommons.api(rpcClient, upstream)
|
||||
def apiMock = TestingCommons.api(rpcClient)
|
||||
apiMock.upstream = Stub(Upstream)
|
||||
|
||||
apiMock.answer("eth_test", [], null, 3)
|
||||
apiMock.answerOnce("eth_test", [], "foo")
|
||||
|
||||
@@ -2,11 +2,8 @@ package io.emeraldpay.dshackle.rpc
|
||||
|
||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||
import io.emeraldpay.api.proto.Common
|
||||
import io.emeraldpay.dshackle.test.EthereumApiMock
|
||||
import io.emeraldpay.dshackle.test.TestingCommons
|
||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstreams
|
||||
import io.emeraldpay.dshackle.upstream.AvailableChains
|
||||
import io.emeraldpay.dshackle.upstream.EthereumHead
|
||||
import io.emeraldpay.dshackle.test.UpstreamsMock
|
||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
||||
import io.emeraldpay.grpc.Chain
|
||||
import io.infinitape.etherjar.domain.Address
|
||||
@@ -23,10 +20,6 @@ import java.time.Duration
|
||||
|
||||
class TrackAddressSpec extends Specification {
|
||||
|
||||
AvailableChains availableChains
|
||||
Upstreams upstreams
|
||||
TrackAddress trackAddress
|
||||
|
||||
def chain = Common.ChainRef.CHAIN_ETHEREUM
|
||||
def address1 = "0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f"
|
||||
def address1Proto = Common.SingleAddress.newBuilder()
|
||||
@@ -36,18 +29,6 @@ class TrackAddressSpec extends Specification {
|
||||
.setCode("ETHER")
|
||||
|
||||
|
||||
def setup() {
|
||||
availableChains = new AvailableChains(TestingCommons.objectMapper())
|
||||
upstreams = Mock(Upstreams)
|
||||
trackAddress = new TrackAddress(upstreams, availableChains, Schedulers.immediate())
|
||||
}
|
||||
|
||||
def start() {
|
||||
trackAddress.init()
|
||||
availableChains.add(Chain.ETHEREUM)
|
||||
availableChains.add(Chain.TESTNET_KOVAN)
|
||||
}
|
||||
|
||||
def "get balance"() {
|
||||
setup:
|
||||
def req = BlockchainOuterClass.BalanceRequest.newBuilder()
|
||||
@@ -60,12 +41,13 @@ class TrackAddressSpec extends Specification {
|
||||
.setBalance("1234567890")
|
||||
.build()
|
||||
|
||||
def upstreamMock = Mock(AggregatedUpstreams)
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient), upstreamMock)
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient))
|
||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
||||
TrackAddress trackAddress = new TrackAddress(upstreams, Schedulers.immediate())
|
||||
trackAddress.init()
|
||||
|
||||
apiMock.answer("eth_getBalance", ["0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f", "latest"], "0x499602D2")
|
||||
_ * upstreams.getUpstream(Chain.ETHEREUM) >> upstreamMock
|
||||
_ * upstreamMock.getApi(_) >> apiMock
|
||||
start()
|
||||
when:
|
||||
def flux = trackAddress.getBalance(Mono.just(req))
|
||||
then:
|
||||
@@ -101,16 +83,14 @@ class TrackAddressSpec extends Specification {
|
||||
}
|
||||
|
||||
def blocksBus = TopicProcessor.create()
|
||||
def upstreamMock = Mock(AggregatedUpstreams)
|
||||
def headMock = Mock(EthereumHead)
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient), upstreamMock)
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient))
|
||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
||||
TrackAddress trackAddress = new TrackAddress(upstreams, Schedulers.immediate())
|
||||
trackAddress.init()
|
||||
|
||||
apiMock.answerOnce("eth_getBalance", ["0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f", "latest"], "0x499602D2")
|
||||
apiMock.answerOnce("eth_getBalance", ["0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f", "latest"], "0xff98")
|
||||
_ * upstreams.getUpstream(Chain.ETHEREUM) >> upstreamMock
|
||||
_ * upstreamMock.getApi(_) >> apiMock
|
||||
_ * upstreamMock.getHead() >> headMock
|
||||
_ * headMock.getFlux() >> blocksBus
|
||||
start()
|
||||
when:
|
||||
def flux = trackAddress.subscribe(Mono.just(req))
|
||||
then:
|
||||
@@ -120,7 +100,7 @@ class TrackAddressSpec extends Specification {
|
||||
assert trackAddress.isTracked(Chain.ETHEREUM, Address.from(address1))
|
||||
}
|
||||
.then {
|
||||
blocksBus.onNext(block2)
|
||||
upstreamMock.nextBlock(block2)
|
||||
}
|
||||
.expectNext(exp2)
|
||||
.thenCancel()
|
||||
|
||||
@@ -4,9 +4,7 @@ import com.google.protobuf.ByteString
|
||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||
import io.emeraldpay.api.proto.Common
|
||||
import io.emeraldpay.dshackle.test.TestingCommons
|
||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstreams
|
||||
import io.emeraldpay.dshackle.upstream.AvailableChains
|
||||
import io.emeraldpay.dshackle.upstream.EthereumHead
|
||||
import io.emeraldpay.dshackle.test.UpstreamsMock
|
||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
||||
import io.emeraldpay.grpc.Chain
|
||||
import io.infinitape.etherjar.domain.BlockHash
|
||||
@@ -15,7 +13,6 @@ import io.infinitape.etherjar.rpc.RpcClient
|
||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||
import io.infinitape.etherjar.rpc.json.TransactionJson
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.core.publisher.TopicProcessor
|
||||
import reactor.core.scheduler.Schedulers
|
||||
import reactor.test.StepVerifier
|
||||
import spock.lang.Specification
|
||||
@@ -25,23 +22,9 @@ import java.time.Instant
|
||||
|
||||
class TrackTxSpec extends Specification {
|
||||
|
||||
AvailableChains availableChains = new AvailableChains(TestingCommons.objectMapper())
|
||||
Upstreams upstreams
|
||||
TrackTx trackTx
|
||||
|
||||
def chain = Common.ChainRef.CHAIN_ETHEREUM
|
||||
def txId = "0xba61ce4672751fd6086a9ac2b55547a5555af17535b6c0334ede2ecb6d64070a"
|
||||
|
||||
def setup() {
|
||||
upstreams = Mock(Upstreams)
|
||||
trackTx = new TrackTx(upstreams, availableChains, Schedulers.immediate())
|
||||
}
|
||||
|
||||
def startTrackTxService() {
|
||||
trackTx.init()
|
||||
availableChains.add(Chain.ETHEREUM)
|
||||
availableChains.add(Chain.TESTNET_KOVAN)
|
||||
}
|
||||
|
||||
def "Gives details for an old transaction"() {
|
||||
setup:
|
||||
@@ -89,21 +72,15 @@ class TrackTxSpec extends Specification {
|
||||
.setTimestamp(blockJson.timestamp.getTime())
|
||||
).build()
|
||||
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient))
|
||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
||||
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
|
||||
trackTx.init()
|
||||
|
||||
def upstreamMock = Mock(AggregatedUpstreams)
|
||||
def blocksBus = TopicProcessor.create()
|
||||
def headMock = Mock(EthereumHead)
|
||||
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient), upstreamMock)
|
||||
apiMock.answer("eth_getTransactionByHash", [txId], txJson)
|
||||
apiMock.answer("eth_getBlockByHash", [blockJson.hash.toHex(), false], blockJson)
|
||||
|
||||
_ * upstreams.getUpstream(Chain.ETHEREUM) >> upstreamMock
|
||||
_ * upstreamMock.getApi(_) >> apiMock
|
||||
_ * upstreamMock.getHead() >> headMock
|
||||
_ * headMock.getFlux() >> blocksBus
|
||||
_ * headMock.getHead() >> Mono.just(blockHeadJson)
|
||||
startTrackTxService()
|
||||
upstreamMock.nextBlock(blockHeadJson)
|
||||
|
||||
when:
|
||||
def flux = trackTx.add(Mono.just(req))
|
||||
@@ -127,13 +104,13 @@ class TrackTxSpec extends Specification {
|
||||
.setMined(false)
|
||||
.build()
|
||||
|
||||
def upstreamMock = Mock(AggregatedUpstreams)
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient), upstreamMock)
|
||||
apiMock.answer("eth_getTransactionByHash", [txId], null)
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient))
|
||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
||||
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
|
||||
trackTx.init()
|
||||
|
||||
_ * upstreams.getUpstream(Chain.ETHEREUM) >> upstreamMock
|
||||
_ * upstreamMock.getApi(_) >> apiMock
|
||||
startTrackTxService()
|
||||
apiMock.answer("eth_getTransactionByHash", [txId], null)
|
||||
|
||||
when:
|
||||
def act = StepVerifier.withVirtualTime {
|
||||
@@ -184,15 +161,15 @@ class TrackTxSpec extends Specification {
|
||||
it
|
||||
}
|
||||
|
||||
def upstreamMock = Mock(AggregatedUpstreams)
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient), upstreamMock)
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient))
|
||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
||||
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
|
||||
trackTx.init()
|
||||
|
||||
apiMock.answerOnce("eth_getTransactionByHash", [txId], null)
|
||||
apiMock.answer("eth_getTransactionByHash", [txId], txJson)
|
||||
|
||||
_ * upstreams.getUpstream(Chain.ETHEREUM) >> upstreamMock
|
||||
_ * upstreamMock.getApi(_) >> apiMock
|
||||
startTrackTxService()
|
||||
|
||||
when:
|
||||
def act = StepVerifier.withVirtualTime {
|
||||
return trackTx.add(Mono.just(req))
|
||||
@@ -283,11 +260,12 @@ class TrackTxSpec extends Specification {
|
||||
)
|
||||
|
||||
|
||||
def upstreamMock = Mock(AggregatedUpstreams)
|
||||
def blocksBus = TopicProcessor.create()
|
||||
def headMock = Mock(EthereumHead)
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient))
|
||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
||||
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
|
||||
trackTx.init()
|
||||
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient), upstreamMock)
|
||||
apiMock.answerOnce("eth_getTransactionByHash", [txId], null)
|
||||
apiMock.answerOnce("eth_getTransactionByHash", [txId], txJsonBroadcasted)
|
||||
apiMock.answer("eth_getTransactionByHash", [txId], txJsonMined)
|
||||
@@ -295,20 +273,10 @@ class TrackTxSpec extends Specification {
|
||||
apiMock.answer("eth_getBlockByHash", [block.hash.toHex(), false], block)
|
||||
}
|
||||
|
||||
def headBlock = blocks[0]
|
||||
|
||||
_ * upstreams.getUpstream(Chain.ETHEREUM) >> upstreamMock
|
||||
_ * upstreamMock.getApi(_) >> apiMock
|
||||
_ * upstreamMock.getHead() >> headMock
|
||||
_ * headMock.getFlux() >> blocksBus
|
||||
_ * headMock.getHead() >> { return Mono.just(headBlock) }
|
||||
startTrackTxService()
|
||||
|
||||
def nextBlock = { int i ->
|
||||
return {
|
||||
println("block $i");
|
||||
headBlock = blocks[i];
|
||||
blocksBus.onNext(blocks[i])
|
||||
upstreamMock.nextBlock(blocks[i])
|
||||
} as Runnable
|
||||
}
|
||||
|
||||
@@ -333,7 +301,11 @@ class TrackTxSpec extends Specification {
|
||||
|
||||
def "Tracked after first load"() {
|
||||
setup:
|
||||
startTrackTxService()
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient))
|
||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
||||
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
|
||||
trackTx.init()
|
||||
|
||||
def req = BlockchainOuterClass.TxStatusRequest.newBuilder()
|
||||
.setChain(chain)
|
||||
@@ -350,7 +322,12 @@ class TrackTxSpec extends Specification {
|
||||
|
||||
def "Update of last notified keeps everything else"() {
|
||||
setup:
|
||||
startTrackTxService()
|
||||
def apiMock = TestingCommons.api(Stub(RpcClient))
|
||||
def upstreamMock = TestingCommons.upstream(apiMock)
|
||||
Upstreams upstreams = new UpstreamsMock(Chain.ETHEREUM, upstreamMock)
|
||||
TrackTx trackTx = new TrackTx(upstreams, Schedulers.immediate())
|
||||
trackTx.init()
|
||||
|
||||
def req = BlockchainOuterClass.TxStatusRequest.newBuilder()
|
||||
.setChain(chain)
|
||||
.setConfirmationLimit(6)
|
||||
|
||||
@@ -3,10 +3,10 @@ package io.emeraldpay.dshackle.test
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.google.protobuf.ByteString
|
||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||
import io.emeraldpay.dshackle.upstream.DirectCallMethods
|
||||
import io.emeraldpay.dshackle.upstream.EthereumApi
|
||||
import io.emeraldpay.dshackle.upstream.EthereumTargets
|
||||
import io.emeraldpay.dshackle.upstream.QuorumBasedMethods
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
||||
import io.emeraldpay.grpc.Chain
|
||||
import io.grpc.stub.StreamObserver
|
||||
import io.infinitape.etherjar.rpc.RpcClient
|
||||
@@ -23,8 +23,8 @@ class EthereumApiMock extends EthereumApi {
|
||||
List<PredefinedResponse> predefined = []
|
||||
private ObjectMapper objectMapper
|
||||
|
||||
EthereumApiMock(@NotNull RpcClient rpcClient, @NotNull ObjectMapper objectMapper, @NotNull Chain chain, Upstream upstream) {
|
||||
super(rpcClient, objectMapper, chain, new EthereumTargets(objectMapper, chain), upstream)
|
||||
EthereumApiMock(@NotNull RpcClient rpcClient, @NotNull ObjectMapper objectMapper, @NotNull Chain chain) {
|
||||
super(rpcClient, objectMapper, chain, new DirectCallMethods())
|
||||
this.objectMapper = objectMapper
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package io.emeraldpay.dshackle.test
|
||||
|
||||
import io.emeraldpay.dshackle.upstream.EthereumHead
|
||||
import io.infinitape.etherjar.domain.TransactionId
|
||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||
import reactor.core.publisher.Flux
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.core.publisher.TopicProcessor
|
||||
|
||||
class EthereumHeadMock implements EthereumHead {
|
||||
|
||||
private TopicProcessor<BlockJson<TransactionId>> bus = TopicProcessor.create()
|
||||
private BlockJson<TransactionId> latest
|
||||
|
||||
void nextBlock(BlockJson<TransactionId> block) {
|
||||
assert block != null
|
||||
latest = block
|
||||
bus.onNext(block)
|
||||
}
|
||||
|
||||
@Override
|
||||
Mono<BlockJson<TransactionId>> getHead() {
|
||||
return latest != null ? Mono.just(latest) : Mono.from(bus)
|
||||
}
|
||||
|
||||
@Override
|
||||
Flux<BlockJson<TransactionId>> getFlux() {
|
||||
return Flux.concat(getHead(), bus).distinctUntilChanged()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.emeraldpay.dshackle.test
|
||||
|
||||
import io.emeraldpay.dshackle.upstream.EthereumApi
|
||||
import io.emeraldpay.dshackle.upstream.EthereumHead
|
||||
import io.emeraldpay.dshackle.upstream.EthereumUpstream
|
||||
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
||||
import io.emeraldpay.grpc.Chain
|
||||
import io.infinitape.etherjar.domain.TransactionId
|
||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||
import org.jetbrains.annotations.NotNull
|
||||
|
||||
class EthereumUpstreamMock extends EthereumUpstream {
|
||||
|
||||
EthereumHeadMock ethereumHeadMock = new EthereumHeadMock()
|
||||
|
||||
EthereumUpstreamMock(@NotNull Chain chain, @NotNull EthereumApi api) {
|
||||
super(chain, api)
|
||||
setLag(0)
|
||||
setStatus(UpstreamAvailability.OK)
|
||||
}
|
||||
|
||||
void nextBlock(BlockJson<TransactionId> block) {
|
||||
ethereumHeadMock.nextBlock(block)
|
||||
}
|
||||
|
||||
@Override
|
||||
EthereumHead createHead() {
|
||||
return ethereumHeadMock
|
||||
}
|
||||
|
||||
@Override
|
||||
EthereumHead getHead() {
|
||||
return ethereumHeadMock
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import com.fasterxml.jackson.core.Version
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||
import io.emeraldpay.dshackle.upstream.EthereumApi
|
||||
import io.emeraldpay.dshackle.upstream.EthereumUpstream
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.grpc.Chain
|
||||
import io.infinitape.etherjar.rpc.Batch
|
||||
@@ -32,11 +34,15 @@ class TestingCommons {
|
||||
return objectMapper
|
||||
}
|
||||
|
||||
static EthereumApiMock api(RpcClient rpcClient, Upstream upstream) {
|
||||
return new EthereumApiMock(rpcClient, objectMapper(), Chain.ETHEREUM, upstream)
|
||||
static EthereumApiMock api(RpcClient rpcClient) {
|
||||
return new EthereumApiMock(rpcClient, objectMapper(), Chain.ETHEREUM)
|
||||
}
|
||||
|
||||
static JacksonRpcConverter rpcConverter() {
|
||||
return new JacksonRpcConverter(objectMapper())
|
||||
}
|
||||
|
||||
static EthereumUpstreamMock upstream(EthereumApi api) {
|
||||
return new EthereumUpstreamMock(Chain.ETHEREUM, api)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package io.emeraldpay.dshackle.test
|
||||
|
||||
|
||||
import io.emeraldpay.dshackle.upstream.AggregatedUpstream
|
||||
import io.emeraldpay.dshackle.upstream.ChainUpstreams
|
||||
import io.emeraldpay.dshackle.upstream.QuorumBasedMethods
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.upstream.Upstreams
|
||||
import io.emeraldpay.grpc.Chain
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import reactor.core.publisher.Flux
|
||||
|
||||
class UpstreamsMock implements Upstreams {
|
||||
|
||||
private Map<Chain, QuorumBasedMethods> target = [:]
|
||||
private Map<Chain, AggregatedUpstream> upstreams = [:]
|
||||
|
||||
UpstreamsMock(Chain chain, Upstream up) {
|
||||
addUpstream(chain, up)
|
||||
}
|
||||
UpstreamsMock(Chain chain1, Upstream up1, Chain chain2, Upstream up2) {
|
||||
addUpstream(chain1, up1)
|
||||
addUpstream(chain2, up2)
|
||||
}
|
||||
|
||||
@Override
|
||||
AggregatedUpstream addUpstream(@NotNull Chain chain, @NotNull Upstream up) {
|
||||
if (!upstreams.containsKey(chain)) {
|
||||
upstreams[chain] = new ChainUpstreams(chain, [up], targetFor(chain))
|
||||
} else {
|
||||
upstreams[chain].addUpstream(up)
|
||||
}
|
||||
return upstreams[chain]
|
||||
}
|
||||
|
||||
@Override
|
||||
AggregatedUpstream getUpstream(@NotNull Chain chain) {
|
||||
return upstreams[chain]
|
||||
}
|
||||
|
||||
@Override
|
||||
List<Chain> getAvailable() {
|
||||
return upstreams.keySet().toList()
|
||||
}
|
||||
|
||||
@Override
|
||||
Flux<Chain> observeChains() {
|
||||
return Flux.fromIterable(getAvailable())
|
||||
}
|
||||
|
||||
@Override
|
||||
QuorumBasedMethods targetFor(@NotNull Chain chain) {
|
||||
if (target[chain] == null) {
|
||||
QuorumBasedMethods targets = new QuorumBasedMethods(TestingCommons.objectMapper(), chain)
|
||||
target[chain] = targets
|
||||
}
|
||||
return target[chain]
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isAvailable(@NotNull Chain chain) {
|
||||
return upstreams.containsKey(chain)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,15 +19,16 @@ class EthereumGrpcTransportSpec extends Specification {
|
||||
|
||||
MockServer mockServer = new MockServer()
|
||||
ObjectMapper objectMapper = TestingCommons.objectMapper()
|
||||
def ethereumTargets = new EthereumTargets(objectMapper, Chain.ETHEREUM)
|
||||
def ethereumTargets = new QuorumBasedMethods(objectMapper, Chain.ETHEREUM)
|
||||
|
||||
def "Make simple call"() {
|
||||
setup:
|
||||
def callData = [:]
|
||||
def otherSideUpstreams = Mock(Upstreams)
|
||||
def otherSideAggr = Mock(AggregatedUpstreams)
|
||||
def otherSideAggr = Mock(AggregatedUpstream)
|
||||
def otherSideNativeCall = new NativeCall(otherSideUpstreams, objectMapper)
|
||||
def otherSideApi = new EthereumApiMock(Mock(RpcClient), objectMapper, Chain.ETHEREUM, otherSideAggr)
|
||||
def otherSideApi = new EthereumApiMock(Mock(RpcClient), objectMapper, Chain.ETHEREUM)
|
||||
otherSideApi.upstream = otherSideAggr
|
||||
|
||||
def client = mockServer.clientForServer(new ReactorBlockchainGrpc.BlockchainImplBase() {
|
||||
@Override
|
||||
@@ -68,9 +69,10 @@ class EthereumGrpcTransportSpec extends Specification {
|
||||
setup:
|
||||
def callData = [:]
|
||||
def otherSideUpstreams = Mock(Upstreams)
|
||||
def otherSideAggr = Mock(AggregatedUpstreams)
|
||||
def otherSideAggr = Mock(AggregatedUpstream)
|
||||
def otherSideNativeCall = new NativeCall(otherSideUpstreams, objectMapper)
|
||||
def otherSideApi = new EthereumApiMock(Mock(RpcClient), objectMapper, Chain.ETHEREUM, otherSideAggr)
|
||||
def otherSideApi = new EthereumApiMock(Mock(RpcClient), objectMapper, Chain.ETHEREUM)
|
||||
otherSideApi.upstream = otherSideAggr
|
||||
|
||||
def client = mockServer.clientForServer(new ReactorBlockchainGrpc.BlockchainImplBase() {
|
||||
@Override
|
||||
|
||||
@@ -10,7 +10,7 @@ class FilteringApiIteratorSpec extends Specification {
|
||||
|
||||
def rpcClient = new DefaultRpcClient(null)
|
||||
def objectMapper = TestingCommons.objectMapper()
|
||||
def ethereumTargets = new EthereumTargets(objectMapper, Chain.ETHEREUM)
|
||||
def ethereumTargets = new QuorumBasedMethods(objectMapper, Chain.ETHEREUM)
|
||||
|
||||
def "Verifies labels"() {
|
||||
setup:
|
||||
@@ -23,7 +23,7 @@ class FilteringApiIteratorSpec extends Specification {
|
||||
].collect {
|
||||
new EthereumUpstream(
|
||||
Chain.ETHEREUM,
|
||||
new EthereumApi(rpcClient, objectMapper, Chain.ETHEREUM, ethereumTargets, null),
|
||||
new EthereumApi(rpcClient, objectMapper, Chain.ETHEREUM, ethereumTargets),
|
||||
(EthereumWs) null,
|
||||
new UpstreamsConfig.Options(),
|
||||
new NodeDetailsList.NodeDetails(1, UpstreamsConfig.Labels.fromMap(it)),
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.google.protobuf.ByteString
|
||||
import io.emeraldpay.api.proto.BlockchainGrpc
|
||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||
import io.emeraldpay.api.proto.Common
|
||||
import io.emeraldpay.dshackle.test.EthereumApiMock
|
||||
import io.emeraldpay.dshackle.test.MockServer
|
||||
import io.emeraldpay.dshackle.test.TestingCommons
|
||||
import io.emeraldpay.grpc.Chain
|
||||
@@ -13,7 +12,6 @@ import io.grpc.stub.StreamObserver
|
||||
import io.infinitape.etherjar.domain.BlockHash
|
||||
import io.infinitape.etherjar.rpc.RpcClient
|
||||
import io.infinitape.etherjar.rpc.json.BlockJson
|
||||
import org.apache.commons.codec.binary.Hex
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.time.Duration
|
||||
@@ -23,13 +21,13 @@ class GrpcUpstreamSpec extends Specification {
|
||||
|
||||
MockServer mockServer = new MockServer()
|
||||
ObjectMapper objectMapper = TestingCommons.objectMapper()
|
||||
def ethereumTargets = new EthereumTargets(objectMapper, Chain.ETHEREUM)
|
||||
def ethereumTargets = new QuorumBasedMethods(objectMapper, Chain.ETHEREUM)
|
||||
|
||||
def "Subscribe to head"() {
|
||||
setup:
|
||||
def callData = [:]
|
||||
def chain = Chain.ETHEREUM
|
||||
def api = TestingCommons.api(Stub(RpcClient), Stub(Upstream))
|
||||
def api = TestingCommons.api(Stub(RpcClient))
|
||||
def block1 = new BlockJson().with {
|
||||
it.number = 650246
|
||||
it.hash = BlockHash.from("0x50d26e119968e791970d84a7bf5d0ec474d3ec2ef85d5ec8915210ac6bc09ad7")
|
||||
@@ -71,7 +69,7 @@ class GrpcUpstreamSpec extends Specification {
|
||||
def callData = [:]
|
||||
def finished = new CompletableFuture<Boolean>()
|
||||
def chain = Chain.ETHEREUM
|
||||
def api = TestingCommons.api(Stub(RpcClient), Stub(Upstream))
|
||||
def api = TestingCommons.api(Stub(RpcClient))
|
||||
def block1 = new BlockJson().with {
|
||||
it.number = 650246
|
||||
it.hash = BlockHash.from("0x50d26e119968e791970d84a7bf5d0ec474d3ec2ef85d5ec8915210ac6bc09ad7")
|
||||
@@ -128,7 +126,7 @@ class GrpcUpstreamSpec extends Specification {
|
||||
def callData = [:]
|
||||
def finished = new CompletableFuture<Boolean>()
|
||||
def chain = Chain.ETHEREUM
|
||||
def api = TestingCommons.api(Stub(RpcClient), Stub(Upstream))
|
||||
def api = TestingCommons.api(Stub(RpcClient))
|
||||
def block1 = new BlockJson().with {
|
||||
it.number = 650246
|
||||
it.hash = BlockHash.from("0x50d26e119968e791970d84a7bf5d0ec474d3ec2ef85d5ec8915210ac6bc09ad7")
|
||||
|
||||
Reference in New Issue
Block a user