-
Notifications
You must be signed in to change notification settings - Fork 174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ws client]: add tests #134
Changes from 13 commits
d958818
70fa3d5
089f9ef
009fcc7
7e035cb
157122f
0a0a377
44518c2
e310dc4
e0126cd
420da5f
f06c0d0
e4fefed
dd3997b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,125 @@ | ||
#![cfg(test)] | ||
|
||
use crate::client::{WsClient, WsConfig, WsSubscription}; | ||
use crate::types::error::Error; | ||
use crate::types::jsonrpc; | ||
|
||
use jsonrpsee_test_utils::helpers::*; | ||
use jsonrpsee_test_utils::types::{Id, WebSocketTestServer}; | ||
|
||
fn assert_error_response(response: Result<jsonrpc::JsonValue, Error>, code: jsonrpc::ErrorCode, message: String) { | ||
let expected = jsonrpc::Error { code, message, data: None }; | ||
match response { | ||
Err(Error::Request(err)) => { | ||
assert_eq!(err, expected); | ||
} | ||
e @ _ => panic!("Expected error: \"{}\", got: {:?}", expected, e), | ||
}; | ||
} | ||
|
||
#[tokio::test] | ||
async fn method_call_works() { | ||
let server = WebSocketTestServer::with_hardcoded_response( | ||
"127.0.0.1:0".parse().unwrap(), | ||
ok_response("hello".into(), Id::Num(0_u64)), | ||
) | ||
.await; | ||
let uri = to_ws_uri_string(server.local_addr()); | ||
let client = WsClient::new(&uri, WsConfig::default()).await.unwrap(); | ||
let response: jsonrpc::JsonValue = client.request("say_hello", jsonrpc::Params::None).await.unwrap(); | ||
let exp = jsonrpc::JsonValue::String("hello".to_string()); | ||
assert_eq!(response, exp); | ||
} | ||
|
||
#[tokio::test] | ||
async fn notif_works() { | ||
// this empty string shouldn't be read because the server shouldn't respond to notifications. | ||
let server = WebSocketTestServer::with_hardcoded_response("127.0.0.1:0".parse().unwrap(), String::new()).await; | ||
let uri = to_ws_uri_string(server.local_addr()); | ||
let client = WsClient::new(&uri, WsConfig::default()).await.unwrap(); | ||
assert!(client.notification("notif", jsonrpc::Params::None).await.is_ok()); | ||
} | ||
|
||
#[tokio::test] | ||
async fn method_not_found_works() { | ||
let server = | ||
WebSocketTestServer::with_hardcoded_response("127.0.0.1:0".parse().unwrap(), method_not_found(Id::Num(0_u64))) | ||
.await; | ||
let uri = to_ws_uri_string(server.local_addr()); | ||
let client = WsClient::new(&uri, WsConfig::default()).await.unwrap(); | ||
let response: Result<jsonrpc::JsonValue, Error> = client.request("say_hello", jsonrpc::Params::None).await; | ||
assert_error_response(response, jsonrpc::ErrorCode::MethodNotFound, METHOD_NOT_FOUND.into()); | ||
} | ||
|
||
#[tokio::test] | ||
async fn parse_error_works() { | ||
let server = | ||
WebSocketTestServer::with_hardcoded_response("127.0.0.1:0".parse().unwrap(), parse_error(Id::Num(0_u64))).await; | ||
let uri = to_ws_uri_string(server.local_addr()); | ||
let client = WsClient::new(&uri, WsConfig::default()).await.unwrap(); | ||
let response: Result<jsonrpc::JsonValue, Error> = client.request("say_hello", jsonrpc::Params::None).await; | ||
assert_error_response(response, jsonrpc::ErrorCode::ParseError, PARSE_ERROR.into()); | ||
} | ||
|
||
#[tokio::test] | ||
async fn invalid_request_works() { | ||
let server = | ||
WebSocketTestServer::with_hardcoded_response("127.0.0.1:0".parse().unwrap(), invalid_request(Id::Num(0_u64))) | ||
.await; | ||
let uri = to_ws_uri_string(server.local_addr()); | ||
let client = WsClient::new(&uri, WsConfig::default()).await.unwrap(); | ||
let response: Result<jsonrpc::JsonValue, Error> = client.request("say_hello", jsonrpc::Params::None).await; | ||
assert_error_response(response, jsonrpc::ErrorCode::InvalidRequest, INVALID_REQUEST.into()); | ||
} | ||
|
||
#[tokio::test] | ||
async fn invalid_params_works() { | ||
let server = | ||
WebSocketTestServer::with_hardcoded_response("127.0.0.1:0".parse().unwrap(), invalid_params(Id::Num(0_u64))) | ||
.await; | ||
let uri = to_ws_uri_string(server.local_addr()); | ||
let client = WsClient::new(&uri, WsConfig::default()).await.unwrap(); | ||
let response: Result<jsonrpc::JsonValue, Error> = client.request("say_hello", jsonrpc::Params::None).await; | ||
assert_error_response(response, jsonrpc::ErrorCode::InvalidParams, INVALID_PARAMS.into()); | ||
} | ||
|
||
#[tokio::test] | ||
async fn internal_error_works() { | ||
let server = | ||
WebSocketTestServer::with_hardcoded_response("127.0.0.1:0".parse().unwrap(), internal_error(Id::Num(0_u64))) | ||
.await; | ||
let uri = to_ws_uri_string(server.local_addr()); | ||
let client = WsClient::new(&uri, WsConfig::default()).await.unwrap(); | ||
let response: Result<jsonrpc::JsonValue, Error> = client.request("say_hello", jsonrpc::Params::None).await; | ||
assert_error_response(response, jsonrpc::ErrorCode::InternalError, INTERNAL_ERROR.into()); | ||
} | ||
|
||
#[tokio::test] | ||
async fn subscription_works() { | ||
let server = WebSocketTestServer::with_hardcoded_subscription( | ||
"127.0.0.1:0".parse().unwrap(), | ||
server_subscription_id_response(Id::Num(0)), | ||
server_subscription_response(jsonrpc::JsonValue::String("hello my friend".to_owned())), | ||
) | ||
.await; | ||
let uri = to_ws_uri_string(server.local_addr()); | ||
let client = WsClient::new(&uri, WsConfig::default()).await.unwrap(); | ||
{ | ||
let mut sub: WsSubscription<String> = | ||
client.subscribe("subscribe_hello", jsonrpc::Params::None, "unsubscribe_hello").await.unwrap(); | ||
let response: String = sub.next().await.unwrap().into(); | ||
assert_eq!("hello my friend".to_owned(), response); | ||
} | ||
} | ||
|
||
#[tokio::test] | ||
async fn response_with_wrong_id() { | ||
env_logger::init(); | ||
let server = | ||
WebSocketTestServer::with_hardcoded_response("127.0.0.1:0".parse().unwrap(), internal_error(Id::Num(99_u64))) | ||
.await; | ||
let uri = to_ws_uri_string(server.local_addr()); | ||
let client = WsClient::new(&uri, WsConfig::default()).await.unwrap(); | ||
let err: Result<jsonrpc::JsonValue, Error> = client.request("say_hello", jsonrpc::Params::None).await; | ||
assert!(matches!(err, Err(Error::TransportError(e)) if e.to_string().contains("background task closed"))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is error is quite bad, we just terminate the background thread and the frontend will receive https://docs.rs/futures/0.3.8/futures/channel/oneshot/struct.Canceled.html. We could introduce another |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,6 +64,24 @@ pub fn internal_error(id: Id) -> String { | |
) | ||
} | ||
|
||
/// Hardcoded server response when a client initiates a new subscription. | ||
/// | ||
/// NOTE: works only for one subscription because the subscription ID is hardcoded. | ||
pub fn server_subscription_id_response(id: Id) -> String { | ||
format!( | ||
r#"{{"jsonrpc":"2.0","result":"D3wwzU6vvoUUYehv4qoFzq42DZnLoAETeFzeyk8swH4o","id":{}}}"#, | ||
serde_json::to_string(&id).unwrap() | ||
) | ||
} | ||
|
||
/// Server response to a hardcoded pending subscription | ||
pub fn server_subscription_response(result: Value) -> String { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can these functions be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://docs.serde.rs/serde_json/fn.to_string.html is not const and I think |
||
format!( | ||
r#"{{"jsonrpc":"2.0","method":"bar","params":{{"subscription":"D3wwzU6vvoUUYehv4qoFzq42DZnLoAETeFzeyk8swH4o","result":{}}}}}"#, | ||
serde_json::to_string(&result).unwrap() | ||
) | ||
} | ||
|
||
pub async fn http_request(body: Body, uri: Uri) -> Result<HttpResponse, String> { | ||
let client = hyper::Client::new(); | ||
let r = hyper::Request::post(uri) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
//! Shared test helpers for JSONRPC v2. | ||
|
||
#![recursion_limit = "256"] | ||
|
||
pub mod helpers; | ||
pub mod types; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE, this doesn't test that subscription is unsubscribed when the subscription is dropped.
The
MockedServer
needs then parse the responses and maintain the requests so I prefer to have theMockedServer
as simple as possible for now.