@@ -62,7 +62,7 @@ class ProxyServerSpec extends Specification {
|
||||
def act = server.execute(Common.ChainRef.CHAIN_ETHEREUM, call)
|
||||
|
||||
then:
|
||||
1 * nativeCall.nativeCall(_) >> Flux.just(BlockchainOuterClass.NativeCallReplyItem.newBuilder().build())
|
||||
1 * nativeCall.nativeCallResult(_) >> Flux.just(new NativeCall.CallResult(1, "".bytes, null))
|
||||
StepVerifier.create(act)
|
||||
.expectNext("hello")
|
||||
.expectComplete()
|
||||
|
||||
@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.proxy
|
||||
|
||||
import com.google.protobuf.ByteString
|
||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||
import io.emeraldpay.dshackle.rpc.NativeCall
|
||||
import io.emeraldpay.dshackle.test.TestingCommons
|
||||
import reactor.core.publisher.Flux
|
||||
import spock.lang.Specification
|
||||
@@ -86,11 +87,7 @@ class WriteRpcJsonSpec extends Specification {
|
||||
def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
|
||||
call.ids[1] = 105
|
||||
def data = [
|
||||
BlockchainOuterClass.NativeCallReplyItem.newBuilder()
|
||||
.setId(1)
|
||||
.setSucceed(true)
|
||||
.setPayload(ByteString.copyFrom('"0x98dbb1"', 'UTF-8'))
|
||||
.build()
|
||||
new NativeCall.CallResult(1, '"0x98dbb1"'.bytes, null)
|
||||
]
|
||||
when:
|
||||
def act = writer.toJson(call, data[0])
|
||||
@@ -103,11 +100,7 @@ class WriteRpcJsonSpec extends Specification {
|
||||
def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
|
||||
call.ids[1] = 1
|
||||
def data = [
|
||||
BlockchainOuterClass.NativeCallReplyItem.newBuilder()
|
||||
.setId(1)
|
||||
.setSucceed(false)
|
||||
.setErrorMessage("Internal Error")
|
||||
.build()
|
||||
new NativeCall.CallResult(1, null, new NativeCall.CallError(1, "Internal Error", null))
|
||||
]
|
||||
when:
|
||||
def act = writer.toJson(call, data[0])
|
||||
@@ -120,11 +113,7 @@ class WriteRpcJsonSpec extends Specification {
|
||||
def call = new ProxyCall(ProxyCall.RpcType.SINGLE)
|
||||
call.ids[1] = "aaa"
|
||||
def data = [
|
||||
BlockchainOuterClass.NativeCallReplyItem.newBuilder()
|
||||
.setId(1)
|
||||
.setSucceed(true)
|
||||
.setPayload(ByteString.copyFrom('"0x98dbb1"', 'UTF-8'))
|
||||
.build()
|
||||
new NativeCall.CallResult(1, '"0x98dbb1"'.bytes, null)
|
||||
]
|
||||
when:
|
||||
def act = writer.toJson(call, data[0])
|
||||
@@ -139,21 +128,9 @@ class WriteRpcJsonSpec extends Specification {
|
||||
call.ids[2] = 11
|
||||
call.ids[3] = 15
|
||||
def data = [
|
||||
BlockchainOuterClass.NativeCallReplyItem.newBuilder()
|
||||
.setId(1)
|
||||
.setSucceed(true)
|
||||
.setPayload(ByteString.copyFrom('"0x98dbb1"', 'UTF-8'))
|
||||
.build(),
|
||||
BlockchainOuterClass.NativeCallReplyItem.newBuilder()
|
||||
.setId(2)
|
||||
.setSucceed(false)
|
||||
.setErrorMessage("oops")
|
||||
.build(),
|
||||
BlockchainOuterClass.NativeCallReplyItem.newBuilder()
|
||||
.setId(3)
|
||||
.setSucceed(true)
|
||||
.setPayload(ByteString.copyFrom('{"hash": "0x2484f459dc"}', 'UTF-8'))
|
||||
.build(),
|
||||
new NativeCall.CallResult(1, '"0x98dbb1"'.bytes, null),
|
||||
new NativeCall.CallResult(2, null, new NativeCall.CallError(2, "oops", null)),
|
||||
new NativeCall.CallResult(3, '{"hash": "0x2484f459dc"}'.bytes, null),
|
||||
]
|
||||
when:
|
||||
def act = Flux.fromIterable(data)
|
||||
|
||||
@@ -22,6 +22,7 @@ import io.emeraldpay.dshackle.test.TestingCommons
|
||||
import io.emeraldpay.dshackle.upstream.Head
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.quorum.BroadcastQuorum
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
|
||||
import io.infinitape.etherjar.rpc.RpcException
|
||||
import spock.lang.Specification
|
||||
|
||||
@@ -54,7 +55,7 @@ class BroadcastQuorumSpec extends Specification {
|
||||
1 * q.recordValue(_, "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c", _)
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Nonce too low"), upstream3)
|
||||
q.record(new JsonRpcException(1, "Nonce too low"), upstream3)
|
||||
then:
|
||||
1 * q.recordError(_, _, _)
|
||||
q.isResolved()
|
||||
@@ -74,7 +75,7 @@ class BroadcastQuorumSpec extends Specification {
|
||||
!q.isResolved()
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Internal error"), upstream1)
|
||||
q.record(new JsonRpcException(1, "Internal error"), upstream1)
|
||||
then:
|
||||
!q.isResolved()
|
||||
1 * q.recordError(_, _, _)
|
||||
@@ -86,7 +87,7 @@ class BroadcastQuorumSpec extends Specification {
|
||||
1 * q.recordValue(_, "0xeaa972c0d8d1ecd3e34fbbef6d34e06670e745c788bdba31c4234a1762f0378c", _)
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Nonce too low"), upstream3)
|
||||
q.record(new JsonRpcException(1, "Nonce too low"), upstream3)
|
||||
then:
|
||||
1 * q.recordError(_, _, _)
|
||||
q.isResolved()
|
||||
|
||||
@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.quorum
|
||||
import io.emeraldpay.dshackle.test.TestingCommons
|
||||
import io.emeraldpay.dshackle.upstream.Head
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
|
||||
import io.infinitape.etherjar.rpc.RpcException
|
||||
import spock.lang.Specification
|
||||
|
||||
@@ -37,19 +38,19 @@ class NonEmptyQuorumSpec extends Specification {
|
||||
!q.isFailed()
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Internal"), upstream1)
|
||||
q.record(new JsonRpcException(1, "Internal"), upstream1)
|
||||
then:
|
||||
!q.isResolved()
|
||||
!q.isFailed()
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Internal"), upstream2)
|
||||
q.record(new JsonRpcException(1, "Internal"), upstream2)
|
||||
then:
|
||||
!q.isResolved()
|
||||
!q.isFailed()
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Internal"), upstream3)
|
||||
q.record(new JsonRpcException(1, "Internal"), upstream3)
|
||||
then:
|
||||
q.isFailed()
|
||||
!q.isResolved()
|
||||
@@ -89,7 +90,7 @@ class NonEmptyQuorumSpec extends Specification {
|
||||
!q.isFailed()
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Internal"), upstream1)
|
||||
q.record(new JsonRpcException(1, "Internal"), upstream1)
|
||||
then:
|
||||
!q.isFailed()
|
||||
!q.isResolved()
|
||||
|
||||
@@ -22,6 +22,7 @@ import io.emeraldpay.dshackle.test.TestingCommons
|
||||
import io.emeraldpay.dshackle.upstream.Head
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.quorum.NonceQuorum
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
|
||||
import io.infinitape.etherjar.rpc.RpcException
|
||||
import spock.lang.Specification
|
||||
|
||||
@@ -74,7 +75,7 @@ class NonceQuorumSpec extends Specification {
|
||||
!q.isResolved()
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Internal"), upstream1)
|
||||
q.record(new JsonRpcException(1, "Internal"), upstream1)
|
||||
then:
|
||||
!q.isResolved()
|
||||
1 * q.recordError(_, _, _)
|
||||
@@ -113,21 +114,23 @@ class NonceQuorumSpec extends Specification {
|
||||
!q.isFailed()
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Internal"), upstream1)
|
||||
q.record(new JsonRpcException(1, "Internal"), upstream1)
|
||||
then:
|
||||
!q.isResolved()
|
||||
!q.isFailed()
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Internal"), upstream2)
|
||||
q.record(new JsonRpcException(1, "Internal"), upstream2)
|
||||
then:
|
||||
!q.isResolved()
|
||||
!q.isFailed()
|
||||
|
||||
when:
|
||||
q.record(new RpcException(1, "Internal"), upstream3)
|
||||
q.record(new JsonRpcException(1, "Internal"), upstream3)
|
||||
then:
|
||||
q.isFailed()
|
||||
!q.isResolved()
|
||||
q.getError() != null
|
||||
q.getError().message == "Internal"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package io.emeraldpay.dshackle.quorum
|
||||
|
||||
import io.emeraldpay.dshackle.upstream.Upstream
|
||||
import io.emeraldpay.dshackle.quorum.NotLaggingQuorum
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcException
|
||||
import io.infinitape.etherjar.rpc.RpcException
|
||||
import spock.lang.Specification
|
||||
|
||||
@@ -74,7 +75,7 @@ class NotLaggingQuorumSpec extends Specification {
|
||||
def quorum = new NotLaggingQuorum(1)
|
||||
|
||||
when:
|
||||
quorum.record(new RpcException(-100, "test error"), up)
|
||||
quorum.record(new JsonRpcException(-100, "test error"), up)
|
||||
then:
|
||||
1 * up.getLag() >> 1
|
||||
!quorum.isResolved()
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.google.protobuf.ByteString
|
||||
import io.emeraldpay.api.proto.BlockchainOuterClass
|
||||
import io.emeraldpay.dshackle.Global
|
||||
import io.emeraldpay.dshackle.reader.Reader
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcError
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcRequest
|
||||
import io.emeraldpay.dshackle.upstream.rpcclient.JsonRpcResponse
|
||||
import io.grpc.stub.StreamObserver
|
||||
@@ -60,7 +61,7 @@ class EthereumApiMock implements Reader<JsonRpcRequest, JsonRpcResponse> {
|
||||
Callable<JsonRpcResponse> call = {
|
||||
def predefined = predefined.find { it.isSame(request.method, request.params) }
|
||||
byte[] result = null
|
||||
JsonRpcResponse.ResponseError error = null
|
||||
JsonRpcError error = null
|
||||
if (predefined != null) {
|
||||
if (predefined.exception != null) {
|
||||
predefined.onCalled()
|
||||
@@ -69,7 +70,7 @@ class EthereumApiMock implements Reader<JsonRpcRequest, JsonRpcResponse> {
|
||||
}
|
||||
if (predefined.result instanceof RpcResponseError) {
|
||||
((RpcResponseError) predefined.result).with { err ->
|
||||
error = new JsonRpcResponse.ResponseError(err.code, err.message)
|
||||
error = new JsonRpcError(err.code, err.message)
|
||||
}
|
||||
} else {
|
||||
// ResponseJson json = new ResponseJson<Object, Integer>(id: 1, result: predefined.result)
|
||||
@@ -79,7 +80,7 @@ class EthereumApiMock implements Reader<JsonRpcRequest, JsonRpcResponse> {
|
||||
predefined.print()
|
||||
} else {
|
||||
log.error("Method ${request.method} with ${request.params} is not mocked")
|
||||
error = new JsonRpcResponse.ResponseError(-32601, "Method ${request.method} with ${request.params} is not mocked")
|
||||
error = new JsonRpcError(-32601, "Method ${request.method} with ${request.params} is not mocked")
|
||||
}
|
||||
return new JsonRpcResponse(result, error)
|
||||
} as Callable<JsonRpcResponse>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package io.emeraldpay.dshackle.upstream.rpcclient
|
||||
|
||||
import io.infinitape.etherjar.rpc.RpcException
|
||||
import nl.jqno.equalsverifier.EqualsVerifier
|
||||
import nl.jqno.equalsverifier.Warning
|
||||
import spock.lang.Specification
|
||||
|
||||
class JsonRpcErrorSpec extends Specification {
|
||||
|
||||
def "Build from RpcException"() {
|
||||
when:
|
||||
def act = JsonRpcError.from(new RpcException(-32123, "test test"))
|
||||
then:
|
||||
act.code == -32123
|
||||
act.message == "test test"
|
||||
act.details == null
|
||||
}
|
||||
|
||||
def "Build from RpcException with details"() {
|
||||
when:
|
||||
def act = JsonRpcError.from(new RpcException(-32123, "test test", "foo bar"))
|
||||
then:
|
||||
act.code == -32123
|
||||
act.message == "test test"
|
||||
act.details == "foo bar"
|
||||
}
|
||||
|
||||
def "Equals"() {
|
||||
when:
|
||||
def v = EqualsVerifier.forClass(JsonRpcError)
|
||||
then:
|
||||
v.verify()
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ class JsonRpcHttpClientSpec extends Specification {
|
||||
then:
|
||||
StepVerifier.create(act)
|
||||
.expectErrorMatches { t ->
|
||||
t instanceof RpcException && t.code == RpcResponseError.CODE_UPSTREAM_INVALID_RESPONSE
|
||||
t instanceof JsonRpcException && t.error.code == RpcResponseError.CODE_UPSTREAM_INVALID_RESPONSE
|
||||
}
|
||||
.verify(Duration.ofSeconds(1))
|
||||
}
|
||||
|
||||
@@ -178,6 +178,36 @@ class JsonRpcParserSpec extends Specification {
|
||||
!act.hasResult()
|
||||
}
|
||||
|
||||
def "Parse error with data"() {
|
||||
setup:
|
||||
// 0 8 16 32
|
||||
def json = '{"jsonrpc": "2.0", "id": 1, "result": null, "error": {"code": -1111, "message": "test", "data": "just data"}}'
|
||||
when:
|
||||
def act = parser.parse(json.getBytes())
|
||||
then:
|
||||
act.error != null
|
||||
act.error.code == -1111
|
||||
act.error.message == "test"
|
||||
act.error.details == "just data"
|
||||
act.hasError()
|
||||
!act.hasResult()
|
||||
}
|
||||
|
||||
def "Parse error with data struct"() {
|
||||
setup:
|
||||
// 0 8 16 32
|
||||
def json = '{"jsonrpc": "2.0", "id": 1, "result": null, "error": {"code": -1111, "message": "test", "data": {"foo": "just data", "bar": 1}}}'
|
||||
when:
|
||||
def act = parser.parse(json.getBytes())
|
||||
then:
|
||||
act.error != null
|
||||
act.error.code == -1111
|
||||
act.error.message == "test"
|
||||
act.error.details == [foo: "just data", bar: 1]
|
||||
act.hasError()
|
||||
!act.hasResult()
|
||||
}
|
||||
|
||||
def "Handle non-json with producing an error response"() {
|
||||
setup:
|
||||
def json = 'NOT JSON'
|
||||
|
||||
@@ -90,7 +90,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
|
||||
def "Serialize int id and error"() {
|
||||
setup:
|
||||
def json = new JsonRpcResponse(null, new JsonRpcResponse.ResponseError(-32041, "Oooops"), new JsonRpcResponse.IntId(101))
|
||||
def json = new JsonRpcResponse(null, new JsonRpcError(-32041, "Oooops"), new JsonRpcResponse.IntId(101))
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
then:
|
||||
@@ -127,7 +127,7 @@ class JsonRpcResponseSpec extends Specification {
|
||||
def "Serialize string id and error"() {
|
||||
setup:
|
||||
def json = new JsonRpcResponse(null,
|
||||
new JsonRpcResponse.ResponseError(-32041, "Oooops"),
|
||||
new JsonRpcError(-32041, "Oooops"),
|
||||
new JsonRpcResponse.StringId("9kbo29gkaasf"))
|
||||
when:
|
||||
def act = objectMapper.writeValueAsString(json)
|
||||
|
||||
Reference in New Issue
Block a user