merge master
This commit is contained in:
@@ -166,7 +166,7 @@ class UpstreamsConfigReaderSpec extends Specification {
|
||||
with((UpstreamsConfig.EthereumPosConnection) connection) {
|
||||
execution.rpc != null
|
||||
execution.rpc.url == new URI("http://34.106.60.110:8545")
|
||||
blockPriority == 100
|
||||
upstreamRating == 100
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.emeraldpay.dshackle.test.MockWSServer
|
||||
import io.emeraldpay.dshackle.upstream.DefaultUpstream
|
||||
import io.emeraldpay.dshackle.upstream.UpstreamAvailability
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
||||
import io.emeraldpay.grpc.Chain
|
||||
import reactor.test.StepVerifier
|
||||
import spock.lang.Shared
|
||||
import spock.lang.Specification
|
||||
@@ -30,7 +31,7 @@ class WsConnectionRealSpec extends Specification {
|
||||
server = new MockWSServer(port)
|
||||
server.start()
|
||||
Thread.sleep(SLEEP)
|
||||
conn = new EthereumWsFactory("ws://localhost:${port}".toURI(), "http://localhost:${port}".toURI()).create(null, null, null)
|
||||
conn = new EthereumWsFactory("test", Chain.ETHEREUM, "ws://localhost:${port}".toURI(), "http://localhost:${port}".toURI()).create(null, null)
|
||||
}
|
||||
|
||||
def cleanup() {
|
||||
@@ -93,10 +94,26 @@ class WsConnectionRealSpec extends Specification {
|
||||
act[0].value.contains("\"params\":[\"newHeads\"]")
|
||||
}
|
||||
|
||||
def "Error on request when server disconnects"() {
|
||||
when:
|
||||
conn.connect()
|
||||
conn.reconnectIntervalSeconds = 2
|
||||
|
||||
def resp = conn.call(new JsonRpcRequest("foo_bar", []))
|
||||
|
||||
then:
|
||||
StepVerifier.create(resp)
|
||||
.then { server.stop() }
|
||||
.expectError()
|
||||
.verify(Duration.ofSeconds(1))
|
||||
}
|
||||
|
||||
def "Gets UNAVAIL status right after disconnect"() {
|
||||
setup:
|
||||
def up = Mock(DefaultUpstream)
|
||||
conn = new EthereumWsFactory("ws://localhost:${port}".toURI(), "http://localhost:${port}".toURI()).create(up, null, null)
|
||||
def up = Mock(DefaultUpstream) {
|
||||
_ * getId() >> "test"
|
||||
}
|
||||
conn = new EthereumWsFactory("test", Chain.ETHEREUM, "ws://localhost:${port}".toURI(), "http://localhost:${port}".toURI()).create(up, null)
|
||||
when:
|
||||
conn.connect()
|
||||
conn.reconnectIntervalSeconds = 10
|
||||
@@ -111,7 +128,7 @@ class WsConnectionRealSpec extends Specification {
|
||||
def "Validates after connect"() {
|
||||
setup:
|
||||
def validator = Mock(EthereumUpstreamValidator)
|
||||
conn = new EthereumWsFactory("ws://localhost:${port}".toURI(), "http://localhost:${port}".toURI()).create(null, validator, null)
|
||||
conn = new EthereumWsFactory("test", Chain.ETHEREUM, "ws://localhost:${port}".toURI(), "http://localhost:${port}".toURI()).create(null, validator)
|
||||
when:
|
||||
conn.connect()
|
||||
Thread.sleep(100)
|
||||
|
||||
@@ -25,6 +25,7 @@ import io.emeraldpay.etherjar.rpc.RpcResponseError
|
||||
import io.emeraldpay.etherjar.rpc.json.BlockJson
|
||||
import io.emeraldpay.etherjar.rpc.json.TransactionJson
|
||||
import io.emeraldpay.etherjar.rpc.json.TransactionRefJson
|
||||
import io.emeraldpay.grpc.Chain
|
||||
import reactor.core.publisher.Flux
|
||||
import reactor.test.StepVerifier
|
||||
import spock.lang.Specification
|
||||
@@ -37,7 +38,7 @@ class WsConnectionSpec extends Specification {
|
||||
|
||||
def "Fetch block"() {
|
||||
setup:
|
||||
def wsf = new EthereumWsFactory(new URI("http://localhost"), new URI("http://localhost"))
|
||||
def wsf = new EthereumWsFactory("test", Chain.ETHEREUM, new URI("http://localhost"), new URI("http://localhost"))
|
||||
|
||||
def block = new BlockJson<TransactionRefJson>()
|
||||
block.number = 100
|
||||
@@ -53,7 +54,7 @@ class WsConnectionSpec extends Specification {
|
||||
|
||||
def apiMock = TestingCommons.api()
|
||||
def wsApiMock = apiMock.asWebsocket()
|
||||
def ws = wsf.create(null, null, null)
|
||||
def ws = wsf.create(null, null)
|
||||
|
||||
apiMock.answerOnce("eth_getBlockByHash", ["0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200", false], block)
|
||||
|
||||
@@ -71,10 +72,10 @@ class WsConnectionSpec extends Specification {
|
||||
|
||||
def "Makes a RPC call"() {
|
||||
setup:
|
||||
def wsf = new EthereumWsFactory(new URI("http://localhost"), new URI("http://localhost"))
|
||||
def wsf = new EthereumWsFactory("test", Chain.ETHEREUM, new URI("http://localhost"), new URI("http://localhost"))
|
||||
def apiMock = TestingCommons.api()
|
||||
def wsApiMock = apiMock.asWebsocket()
|
||||
def ws = wsf.create(null, null, null)
|
||||
def ws = wsf.create(null, null)
|
||||
|
||||
def tx = new TransactionJson().tap {
|
||||
hash = TransactionId.from("0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200")
|
||||
@@ -96,10 +97,10 @@ class WsConnectionSpec extends Specification {
|
||||
|
||||
def "Makes a RPC call - return null"() {
|
||||
setup:
|
||||
def wsf = new EthereumWsFactory(new URI("http://localhost"), new URI("http://localhost"))
|
||||
def wsf = new EthereumWsFactory("test", Chain.ETHEREUM, new URI("http://localhost"), new URI("http://localhost"))
|
||||
def apiMock = TestingCommons.api()
|
||||
def wsApiMock = apiMock.asWebsocket()
|
||||
def ws = wsf.create(null, null, null)
|
||||
def ws = wsf.create(null, null)
|
||||
|
||||
apiMock.answerOnce("eth_getTransactionByHash", ["0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200"], null)
|
||||
|
||||
@@ -119,10 +120,10 @@ class WsConnectionSpec extends Specification {
|
||||
|
||||
def "Makes a RPC call - return error"() {
|
||||
setup:
|
||||
def wsf = new EthereumWsFactory(new URI("http://localhost"), new URI("http://localhost"))
|
||||
def wsf = new EthereumWsFactory("test", Chain.ETHEREUM, new URI("http://localhost"), new URI("http://localhost"))
|
||||
def apiMock = TestingCommons.api()
|
||||
def wsApiMock = apiMock.asWebsocket()
|
||||
def ws = wsf.create(null, null, null)
|
||||
def ws = wsf.create(null, null)
|
||||
|
||||
apiMock.answerOnce("eth_getTransactionByHash", ["0x3ec2ebf5d0ec474d0ac6bc50d2770d8409ad76e119968e7919f85d5ec8915200"],
|
||||
new RpcResponseError(RpcResponseError.CODE_METHOD_NOT_EXIST, "test"))
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package io.emeraldpay.dshackle.upstream.rpcclient
|
||||
|
||||
import io.emeraldpay.dshackle.reader.Reader
|
||||
import reactor.core.publisher.Mono
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.time.Duration
|
||||
|
||||
class JsonRpcSwitchClientSpec extends Specification {
|
||||
|
||||
def "Uses primary response if it works"() {
|
||||
setup:
|
||||
def primaryCalled = false
|
||||
def secondaryCalled = false
|
||||
def request = new JsonRpcRequest("eth_test", [])
|
||||
def response = JsonRpcResponse.ok("test".bytes, new JsonRpcResponse.NumberId(100))
|
||||
def primary = Mock(Reader<JsonRpcRequest, JsonRpcResponse>) {
|
||||
1 * read(request) >> Mono.fromCallable {
|
||||
primaryCalled = true
|
||||
response
|
||||
}
|
||||
}
|
||||
def secondary = Mock(Reader<JsonRpcRequest, JsonRpcResponse>) {
|
||||
_ * read(request) >> Mono.fromCallable {
|
||||
secondaryCalled = true
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
def client = new JsonRpcSwitchClient(primary, secondary)
|
||||
|
||||
when:
|
||||
def act = client.read(request).block(Duration.ofSeconds(1))
|
||||
|
||||
then:
|
||||
act == response
|
||||
primaryCalled
|
||||
!secondaryCalled
|
||||
}
|
||||
|
||||
def "Uses secondary response if primary fails"() {
|
||||
setup:
|
||||
def primaryCalled = false
|
||||
def secondaryCalled = false
|
||||
def request = new JsonRpcRequest("eth_test", [])
|
||||
def response = JsonRpcResponse.ok("test".bytes, new JsonRpcResponse.NumberId(100))
|
||||
def primary = Mock(Reader<JsonRpcRequest, JsonRpcResponse>) {
|
||||
1 * read(request) >> Mono.fromCallable {
|
||||
primaryCalled = true
|
||||
throw new IllegalStateException("Primary Fail")
|
||||
}
|
||||
}
|
||||
def secondary = Mock(Reader<JsonRpcRequest, JsonRpcResponse>) {
|
||||
1 * read(request) >> Mono.fromCallable {
|
||||
secondaryCalled = true
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
def client = new JsonRpcSwitchClient(primary, secondary)
|
||||
|
||||
when:
|
||||
def act = client.read(request).block(Duration.ofSeconds(1))
|
||||
|
||||
then:
|
||||
act == response
|
||||
primaryCalled
|
||||
secondaryCalled
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package io.emeraldpay.dshackle.upstream.rpcclient
|
||||
|
||||
import io.emeraldpay.dshackle.upstream.ethereum.WsConnection
|
||||
import reactor.core.Exceptions
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.time.Duration
|
||||
|
||||
class JsonRpcWsClientSpec extends Specification {
|
||||
|
||||
def "Produce error if WS is not connected"() {
|
||||
setup:
|
||||
def ws = Mock(WsConnection)
|
||||
def client = new JsonRpcWsClient(ws)
|
||||
when:
|
||||
client.read(new JsonRpcRequest("foo_bar", [], 1))
|
||||
.block(Duration.ofSeconds(1))
|
||||
then:
|
||||
def t = thrown(Exceptions.ReactiveException)
|
||||
t.cause instanceof JsonRpcException
|
||||
1 * ws.isConnected() >> false
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,4 @@
|
||||
execution:
|
||||
rpc:
|
||||
url: "http://34.106.60.110:8545"
|
||||
block-priority: 100
|
||||
upstream-rating: 100
|
||||
Reference in New Issue
Block a user