@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.quorum
|
||||
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.quorum.NotLaggingQuorum
|
||||
import io.infinitape.etherjar.rpc.RpcException
|
||||
import spock.lang.Specification
|
||||
|
||||
class NotLaggingQuorumSpec extends Specification {
|
||||
@@ -33,6 +34,7 @@ class NotLaggingQuorumSpec extends Specification {
|
||||
then:
|
||||
1 * up.getLag() >> 0
|
||||
quorum.isResolved()
|
||||
!quorum.isFailed()
|
||||
quorum.result == value
|
||||
}
|
||||
|
||||
@@ -47,6 +49,7 @@ class NotLaggingQuorumSpec extends Specification {
|
||||
then:
|
||||
1 * up.getLag() >> 1
|
||||
quorum.isResolved()
|
||||
!quorum.isFailed()
|
||||
quorum.result == value
|
||||
}
|
||||
|
||||
@@ -61,5 +64,20 @@ class NotLaggingQuorumSpec extends Specification {
|
||||
then:
|
||||
1 * up.getLag() >> 2
|
||||
!quorum.isResolved()
|
||||
!quorum.isFailed()
|
||||
}
|
||||
|
||||
def "Fails if no lag and error response received"() {
|
||||
setup:
|
||||
def up = Mock(Upstream)
|
||||
def value = "foo".getBytes()
|
||||
def quorum = new NotLaggingQuorum(1)
|
||||
|
||||
when:
|
||||
quorum.record(new RpcException(-100, "test error"), up)
|
||||
then:
|
||||
1 * up.getLag() >> 1
|
||||
!quorum.isResolved()
|
||||
quorum.isFailed()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import io.emeraldpay.dshackle.upstream.Selector
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
||||
import io.infinitape.etherjar.rpc.RpcException
|
||||
import reactor.core.publisher.Mono
|
||||
import reactor.test.StepVerifier
|
||||
import spock.lang.Specification
|
||||
@@ -60,15 +61,16 @@ class QuorumRpcReaderSpec extends Specification {
|
||||
|
||||
def "always-quorum - retry upstream error"() {
|
||||
setup:
|
||||
def api = Mock(Reader) {
|
||||
2 * read(new JsonRpcRequest("eth_test", [])) >>> [
|
||||
Mono.just(JsonRpcResponse.error(1, "test")),
|
||||
Mono.just(JsonRpcResponse.ok("1"))
|
||||
]
|
||||
}
|
||||
def up = Mock(Upstream) {
|
||||
_ * isAvailable() >> true
|
||||
_ * getRole() >> UpstreamsConfig.UpstreamRole.STANDARD
|
||||
_ * getApi() >> Mock(Reader) {
|
||||
2 * read(new JsonRpcRequest("eth_test", [])) >>> [
|
||||
Mono.just(JsonRpcResponse.error(1, "test")),
|
||||
Mono.just(JsonRpcResponse.ok("1"))
|
||||
]
|
||||
}
|
||||
_ * getApi() >> api
|
||||
}
|
||||
def apis = new FilteredApis(
|
||||
[up], Selector.empty
|
||||
@@ -180,18 +182,19 @@ class QuorumRpcReaderSpec extends Specification {
|
||||
.verify(Duration.ofSeconds(1))
|
||||
}
|
||||
|
||||
def "non-empty-quorum - no result if all failed"() {
|
||||
def "non-empty-quorum - error if all failed"() {
|
||||
setup:
|
||||
def api = Mock(Reader) {
|
||||
3 * read(new JsonRpcRequest("eth_test", [])) >>> [
|
||||
Mono.just(JsonRpcResponse.ok("null")),
|
||||
Mono.just(JsonRpcResponse.error(1, "test")),
|
||||
Mono.just(JsonRpcResponse.ok("null"))
|
||||
]
|
||||
}
|
||||
def up = Mock(Upstream) {
|
||||
_ * isAvailable() >> true
|
||||
_ * getRole() >> UpstreamsConfig.UpstreamRole.STANDARD
|
||||
_ * getApi() >> Mock(Reader) {
|
||||
3 * read(new JsonRpcRequest("eth_test", [])) >>> [
|
||||
Mono.just(JsonRpcResponse.ok("null")),
|
||||
Mono.just(JsonRpcResponse.error(1, "test")),
|
||||
Mono.just(JsonRpcResponse.ok("null"))
|
||||
]
|
||||
}
|
||||
_ * getApi() >> api
|
||||
}
|
||||
def apis = new FilteredApis(
|
||||
[up], Selector.empty
|
||||
@@ -206,7 +209,35 @@ class QuorumRpcReaderSpec extends Specification {
|
||||
|
||||
then:
|
||||
StepVerifier.create(act)
|
||||
.expectComplete()
|
||||
.expectError()
|
||||
.verify(Duration.ofSeconds(2))
|
||||
}
|
||||
|
||||
def "Return error is upstream returned it"() {
|
||||
setup:
|
||||
def up = Mock(Upstream) {
|
||||
_ * getLag() >> 0
|
||||
_ * isAvailable() >> true
|
||||
_ * getRole() >> UpstreamsConfig.UpstreamRole.STANDARD
|
||||
_ * getApi() >> Mock(Reader) {
|
||||
_ * read(new JsonRpcRequest("eth_test", [])) >>> [
|
||||
Mono.just(JsonRpcResponse.error(-3010, "test")),
|
||||
]
|
||||
}
|
||||
}
|
||||
def apis = new FilteredApis(
|
||||
[up], Selector.empty
|
||||
)
|
||||
def reader = new QuorumRpcReader(apis, new NotLaggingQuorum(1))
|
||||
|
||||
when:
|
||||
def act = reader.read(new JsonRpcRequest("eth_test", []))
|
||||
|
||||
then:
|
||||
StepVerifier.create(act)
|
||||
.expectError()
|
||||
//TODO verify
|
||||
//.expectErrorMatches { t -> t instanceof RpcException && t.code == -3010}
|
||||
.verify(Duration.ofSeconds(1))
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class NativeCallSpec extends Specification {
|
||||
when:
|
||||
def act = nativeCall.fetch(ctx).block(Duration.ofSeconds(1))
|
||||
then:
|
||||
act.payload == "1".bytes
|
||||
act.result == "1".bytes
|
||||
}
|
||||
|
||||
def "Return error if router denied the requests"() {
|
||||
@@ -85,12 +85,10 @@ class NativeCallSpec extends Specification {
|
||||
def act = nativeCall.fetch(ctx) //.block(Duration.ofSeconds(1))
|
||||
then:
|
||||
StepVerifier.create(act)
|
||||
.expectErrorMatches { t ->
|
||||
t instanceof NativeCall.CallFailure &&
|
||||
t.id == 15 &&
|
||||
t.reason instanceof RpcException &&
|
||||
t.reason.rpcMessage == "Test message"
|
||||
.expectNextMatches { result ->
|
||||
result.id == 15 && result.isError()
|
||||
}
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(1))
|
||||
}
|
||||
|
||||
@@ -109,7 +107,7 @@ class NativeCallSpec extends Specification {
|
||||
|
||||
when:
|
||||
def resp = nativeCall.executeOnRemote(call).block(Duration.ofSeconds(1))
|
||||
def act = objectMapper.readValue(resp.payload, Object)
|
||||
def act = objectMapper.readValue(resp.result, Object)
|
||||
then:
|
||||
act == "foo"
|
||||
}
|
||||
@@ -131,7 +129,10 @@ class NativeCallSpec extends Specification {
|
||||
def resp = nativeCall.executeOnRemote(call)
|
||||
then:
|
||||
StepVerifier.create(resp)
|
||||
.expectErrorMatches({ t -> t instanceof NativeCall.CallFailure && t.id == 1 })
|
||||
.expectNextMatches { result ->
|
||||
result.isError()
|
||||
}
|
||||
.expectComplete()
|
||||
.verify(Duration.ofSeconds(1))
|
||||
}
|
||||
|
||||
@@ -176,7 +177,7 @@ class NativeCallSpec extends Specification {
|
||||
|
||||
when:
|
||||
def resp = nativeCall.buildResponse(
|
||||
new NativeCall.CallContext<byte[]>(1561, TestingCommons.multistream(TestingCommons.api()), Selector.empty, new AlwaysQuorum(), objectMapper.writeValueAsBytes(json))
|
||||
new NativeCall.CallResult(1561, objectMapper.writeValueAsBytes(json), null)
|
||||
)
|
||||
then:
|
||||
resp.id == 1561
|
||||
|
||||
Reference in New Issue
Block a user