problem: not subscribing to an address

This commit is contained in:
Igor Artamonov
2019-07-30 22:57:58 -04:00
parent 913ad6965a
commit fd8f558d64
6 changed files with 221 additions and 39 deletions

View File

@@ -0,0 +1,129 @@
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.upstream.Upstreams
import io.emeraldpay.grpc.Chain
import io.infinitape.etherjar.domain.Address
import io.infinitape.etherjar.domain.BlockHash
import io.infinitape.etherjar.rpc.RpcClient
import io.infinitape.etherjar.rpc.json.BlockJson
import reactor.core.publisher.Mono
import reactor.core.publisher.TopicProcessor
import reactor.core.scheduler.Schedulers
import reactor.test.StepVerifier
import spock.lang.Specification
import java.time.Duration
class TrackAddressSpec extends Specification {
AvailableChains availableChains = new AvailableChains()
Upstreams upstreams
TrackAddress trackAddress
def chain = Common.ChainRef.CHAIN_ETHEREUM
def address1 = "0xe2c8fa8120d813cd0b5e6add120295bf20cfa09f"
def address1Proto = Common.SingleAddress.newBuilder()
.setAddress(address1)
def etherAsset = Common.Asset.newBuilder()
.setChain(chain)
.setCode("ETHER")
def setup() {
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()
.setAsset(etherAsset)
.setAddress(Common.AnyAddress.newBuilder().setAddressSingle(address1Proto).build())
.build()
def exp = BlockchainOuterClass.AddressBalance.newBuilder()
.setAddress(address1Proto)
.setAsset(etherAsset)
.setBalance("1234567890")
.build()
def upstreamMock = Mock(AggregatedUpstreams)
def apiMock = new EthereumApiMock(Mock(RpcClient), TestingCommons.objectMapper(), Chain.ETHEREUM)
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:
StepVerifier.create(flux)
.expectNext(exp)
.expectComplete()
.verify(Duration.ofSeconds(3))
!trackAddress.isTracked(Chain.ETHEREUM, Address.from(address1))
}
def "recheck address after each block"() {
setup:
def req = BlockchainOuterClass.BalanceRequest.newBuilder()
.setAsset(etherAsset)
.setAddress(Common.AnyAddress.newBuilder().setAddressSingle(address1Proto).build())
.build()
def exp1 = BlockchainOuterClass.AddressBalance.newBuilder()
.setAddress(address1Proto)
.setAsset(etherAsset)
.setBalance("1234567890")
.build()
def exp2 = BlockchainOuterClass.AddressBalance.newBuilder()
.setAddress(address1Proto)
.setAsset(etherAsset)
.setBalance("65432")
.build()
def block2 = new BlockJson().with {
it.number = 1
it.totalDifficulty = 100
it.hash = BlockHash.from("0xa0e65cbc1b52a8ca60562112c6060552d882f16f34a9dba2ccdc05c0a6a27c22")
return it
}
def blocksBus = TopicProcessor.create()
def upstreamMock = Mock(AggregatedUpstreams)
def headMock = Mock(EthereumHead)
def apiMock = new EthereumApiMock(Mock(RpcClient), TestingCommons.objectMapper(), Chain.ETHEREUM)
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:
StepVerifier.create(flux)
.expectNext(exp1)
.then {
assert trackAddress.isTracked(Chain.ETHEREUM, Address.from(address1))
}
.then {
blocksBus.onNext(block2)
}
.expectNext(exp2)
.thenCancel()
.verify(Duration.ofSeconds(3))
!trackAddress.isTracked(Chain.ETHEREUM, Address.from(address1))
}
}

View File

@@ -25,8 +25,12 @@ class EthereumApiMock extends EthereumApi {
this.objectMapper = objectMapper
}
EthereumApiMock answer(@NotNull String method, List<Object> params, Object result) {
predefined << new PredefinedResponse(method: method, params: params, result: result)
EthereumApiMock answerOnce(@NotNull String method, List<Object> params, Object result) {
return answer(method, params, result, 1)
}
EthereumApiMock answer(@NotNull String method, List<Object> params, Object result, Integer limit = null) {
predefined << new PredefinedResponse(method: method, params: params, result: result, limit: limit)
return this
}
@@ -40,6 +44,8 @@ class EthereumApiMock extends EthereumApi {
log.error("Method ${method} with ${params} is not mocked")
json.error = new RpcResponseError(-32601, "Method ${method} with ${params} is not mocked")
}
predefined.onCalled()
predefined.print()
return Mono.just(objectMapper.writeValueAsBytes(json))
}
@@ -61,8 +67,14 @@ class EthereumApiMock extends EthereumApi {
String method
List params
Object result
Integer limit
boolean isSame(int id, String method, List<?> params) {
if (limit != null) {
if (limit <= 0) {
return false
}
}
if (method != this.method) {
return false
}
@@ -71,5 +83,15 @@ class EthereumApiMock extends EthereumApi {
}
return this.params == params
}
void onCalled() {
if (limit != null) {
limit--
}
}
void print() {
println "Execute API: $method ${params ? params : '_'} >> $result"
}
}
}