From 88aee1966d49351557b36a548f8e64c55c3806f6 Mon Sep 17 00:00:00 2001 From: Lorenzo Tucci Date: Wed, 14 Dec 2022 17:17:43 +0100 Subject: [PATCH] adding new unfinished RPC tests --- Cargo.lock | 127 ++++++++++++---------- swap/Cargo.toml | 3 +- swap/src/api/request.rs | 8 +- swap/src/rpc.rs | 4 +- swap/src/rpc/methods.rs | 39 +++---- swap/tests/rpc.rs | 232 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 325 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 491fe8b7..a9615656 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,6 +124,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "async-lock" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" +dependencies = [ + "event-listener", + "futures-lite", +] + [[package]] name = "async-trait" version = "0.1.59" @@ -1308,6 +1318,21 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite 0.2.9", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.25" @@ -1658,12 +1683,9 @@ checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ "http", "hyper", - "log", "rustls 0.20.2", - "rustls-native-certs 0.6.2", "tokio", "tokio-rustls 0.23.1", - "webpki-roots 0.22.2", ] [[package]] @@ -1817,28 +1839,31 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" dependencies = [ - "jsonrpsee-core 0.16.2", + "jsonrpsee-core", "jsonrpsee-server", - "jsonrpsee-types 0.16.2", + "jsonrpsee-types", + "jsonrpsee-ws-client", ] [[package]] -name = "jsonrpsee-core" -version = "0.15.1" +name = "jsonrpsee-client-transport" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3dc3e9cf2ba50b7b1d7d76a667619f82846caa39e8e8daa8a4962d74acaddca" +checksum = "965de52763f2004bc91ac5bcec504192440f0b568a5d621c59d9dbd6f886c3fb" dependencies = [ - "anyhow", - "async-trait", - "beef", - "futures-channel", "futures-util", - "hyper", - "jsonrpsee-types 0.15.1", - "serde", - "serde_json", + "http", + "jsonrpsee-core", + "jsonrpsee-types", + "pin-project 1.0.5", + "rustls-native-certs 0.6.2", + "soketto", "thiserror", + "tokio", + "tokio-rustls 0.23.1", + "tokio-util 0.7.3", "tracing", + "webpki-roots 0.22.2", ] [[package]] @@ -1849,13 +1874,15 @@ checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" dependencies = [ "anyhow", "arrayvec 0.7.2", + "async-lock", "async-trait", "beef", "futures-channel", + "futures-timer", "futures-util", "globset", "hyper", - "jsonrpsee-types 0.16.2", + "jsonrpsee-types", "parking_lot 0.12.0", "rand 0.8.3", "rustc-hash", @@ -1867,26 +1894,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "jsonrpsee-http-client" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f7c0e2333ab2115c302eeb4f137c8a4af5ab609762df68bbda8f06496677c9" -dependencies = [ - "async-trait", - "hyper", - "hyper-rustls", - "jsonrpsee-core 0.15.1", - "jsonrpsee-types 0.15.1", - "rustc-hash", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "tracing-futures", -] - [[package]] name = "jsonrpsee-server" version = "0.16.2" @@ -1897,8 +1904,8 @@ dependencies = [ "futures-util", "http", "hyper", - "jsonrpsee-core 0.16.2", - "jsonrpsee-types 0.16.2", + "jsonrpsee-core", + "jsonrpsee-types", "serde", "serde_json", "soketto", @@ -1909,20 +1916,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "jsonrpsee-types" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e290bba767401b646812f608c099b922d8142603c9e73a50fb192d3ac86f4a0d" -dependencies = [ - "anyhow", - "beef", - "serde", - "serde_json", - "thiserror", - "tracing", -] - [[package]] name = "jsonrpsee-types" version = "0.16.2" @@ -1937,6 +1930,18 @@ dependencies = [ "tracing", ] +[[package]] +name = "jsonrpsee-ws-client" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b83daeecfc6517cfe210df24e570fb06213533dfb990318fae781f4c7119dd9" +dependencies = [ + "http", + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-types", +] + [[package]] name = "keccak" version = "0.1.0" @@ -2743,6 +2748,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "parking" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" + [[package]] name = "parking_lot" version = "0.11.2" @@ -4210,8 +4221,8 @@ dependencies = [ "hyper", "itertools", "jsonrpsee", - "jsonrpsee-core 0.16.2", - "jsonrpsee-http-client", + "jsonrpsee-core", + "jsonrpsee-types", "libp2p", "monero", "monero-harness", @@ -4996,6 +5007,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "want" version = "0.3.0" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 94938cdd..84b4691c 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -80,8 +80,9 @@ bitcoin-harness = "0.2.2" get-port = "3" hyper = "0.14" monero-harness = { path = "../monero-harness" } +jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] } +jsonrpsee-types = { version = "0.16.2" } port_check = "0.1" -jsonrpsee-http-client = "0.15.1" proptest = "1" serde_cbor = "0.11" spectral = "0.6" diff --git a/swap/src/api/request.rs b/swap/src/api/request.rs index ac7daea1..6e0d3486 100644 --- a/swap/src/api/request.rs +++ b/swap/src/api/request.rs @@ -222,10 +222,10 @@ impl Request { }) } Method::GetSeller => { - let swap_id = self.params.swap_id.unwrap(); - let peerId = context.db.get_peer_id(swap_id).await?; + let swap_id = self.params.swap_id.with_context(|| "A swap_id is needed")?; + let peerId = context.db.get_peer_id(swap_id).await.with_context(|| "Could not get PeerID")?; - let addresses = context.db.get_addresses(peerId).await?; + let addresses = context.db.get_addresses(peerId).await.with_context(|| "Could not get addressess")?; json!({ "peerId": peerId.to_base58(), @@ -233,7 +233,7 @@ impl Request { }) } Method::SwapStartDate => { - let swap_id = self.params.swap_id.unwrap(); + let swap_id = self.params.swap_id.with_context(|| "A swap_id is needed")?; let start_date = context .db diff --git a/swap/src/rpc.rs b/swap/src/rpc.rs index f926059e..eb308536 100644 --- a/swap/src/rpc.rs +++ b/swap/src/rpc.rs @@ -8,8 +8,8 @@ pub mod methods; #[derive(Debug, Error)] pub enum Error { - #[error("example")] - ExampleError, + #[error("Could not parse key value from params")] + ParseError, } pub async fn run_server( diff --git a/swap/src/rpc/methods.rs b/swap/src/rpc/methods.rs index 4cfb670f..1769fdef 100644 --- a/swap/src/rpc/methods.rs +++ b/swap/src/rpc/methods.rs @@ -1,6 +1,5 @@ use crate::api::{Context}; use crate::api::request::{Params, Request, Method, Shutdown}; -//use crate::rpc::Error; use anyhow::Result; use crate::{bitcoin, monero}; use crate::{bitcoin::bitcoin_address, monero::monero_address}; @@ -10,6 +9,7 @@ use std::collections::HashMap; use std::str::FromStr; use std::sync::Arc; use uuid::Uuid; +use crate::rpc::Error; pub fn register_modules(context: Arc) -> RpcModule> { let mut module = RpcModule::new(context); @@ -30,38 +30,35 @@ pub fn register_modules(context: Arc) -> RpcModule> { .unwrap(); module .register_async_method("get_seller", |params, context| async move { - let params: HashMap = params.parse()?; + let params: HashMap = params.parse()?; - let swap_id = Uuid::from_str(params.get("swap_id").ok_or_else(|| { + let swap_id = params.get("swap_id").ok_or_else(|| { jsonrpsee_core::Error::Custom("Does not contain swap_id".to_string()) - })?) - .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; + })?; - get_seller(swap_id, &context).await + get_seller(*swap_id, &context).await }) .unwrap(); module .register_async_method("get_swap_start_date", |params, context| async move { - let params: HashMap = params.parse()?; + let params: HashMap = params.parse()?; - let swap_id = Uuid::from_str(params.get("swap_id").ok_or_else(|| { + let swap_id = params.get("swap_id").ok_or_else(|| { jsonrpsee_core::Error::Custom("Does not contain swap_id".to_string()) - })?) - .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; + })?; - get_swap_start_date(swap_id, &context).await + get_swap_start_date(*swap_id, &context).await }) .unwrap(); module .register_async_method("resume_swap", |params, context| async move { - let params: HashMap = params.parse()?; + let params: HashMap = params.parse()?; - let swap_id = Uuid::from_str(params.get("swap_id").ok_or_else(|| { + let swap_id = params.get("swap_id").ok_or_else(|| { jsonrpsee_core::Error::Custom("Does not contain swap_id".to_string()) - })?) - .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; + })?; - resume_swap(swap_id, &context).await + resume_swap(*swap_id, &context).await }) .unwrap(); module @@ -130,14 +127,12 @@ pub fn register_modules(context: Arc) -> RpcModule> { .unwrap(); module .register_async_method("list_sellers", |params, context| async move { - let params: HashMap = params.parse()?; - let rendezvous_point = - Multiaddr::from_str(params.get("rendezvous_point").ok_or_else(|| { + let params: HashMap = params.parse()?; + let rendezvous_point = params.get("rendezvous_point").ok_or_else(|| { jsonrpsee_core::Error::Custom("Does not contain rendezvous_point".to_string()) - })?) - .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; + })?; - list_sellers(rendezvous_point, &context).await + list_sellers(rendezvous_point.clone(), &context).await }) .unwrap(); module diff --git a/swap/tests/rpc.rs b/swap/tests/rpc.rs index bdb26bf9..6fb1b43b 100644 --- a/swap/tests/rpc.rs +++ b/swap/tests/rpc.rs @@ -7,17 +7,36 @@ use swap::api::request::{Request, Params, Method, Shutdown}; use std::sync::Arc; use tokio::time::{interval, timeout}; use std::time::Duration; -pub use jsonrpsee_http_client as http_client; +use jsonrpsee::ws_client::WsClientBuilder; +use jsonrpsee_core::{client::ClientT, params::ObjectParams}; +use jsonrpsee::{rpc_params, RpcModule}; +use jsonrpsee_types::error::CallError; use tokio::sync::broadcast; +use swap::cli::command::{Bitcoin, Monero}; +use std::collections::HashMap; +use uuid::Uuid; +use serde_json::{json, Value}; +use sequential_test::sequential; #[cfg(test)] +const SERVER_ADDRESS: &str = "127.0.0.1:1234"; + pub async fn initialize_context() -> (Arc, Request) { let (is_testnet, debug, json) = (true, false, false); //let data_dir = data::data_dir_from(None, is_testnet).unwrap(); let server_address = None; let (tx, _) = broadcast::channel(1); + let bitcoin = Bitcoin { + bitcoin_electrum_rpc_url: None, + bitcoin_target_block: None, + }; + + let monero = Monero { + monero_daemon_address: None, + }; + let mut request = Request { params: Params::default(), cmd: Method::StartDaemon, @@ -25,7 +44,7 @@ pub async fn initialize_context() -> (Arc, Request) { }; let context = Context::build( - None, + Some(bitcoin), None, None, None, @@ -41,7 +60,8 @@ pub async fn initialize_context() -> (Arc, Request) { #[tokio::test] -pub async fn start_server() { +#[sequential] +pub async fn can_start_server() { let (ctx, mut request) = initialize_context().await; let move_ctx = Arc::clone(&ctx); tokio::spawn(async move { @@ -49,8 +69,212 @@ pub async fn start_server() { }); tokio::time::sleep(Duration::from_secs(3)).await; ctx.shutdown.send(()); - tokio::time::sleep(Duration::from_secs(3)).await; assert!(true); } +#[tokio::test] +#[sequential] +pub async fn get_bitcoin_balance() { + let (ctx, mut request) = initialize_context().await; + let move_ctx = Arc::clone(&ctx); + tokio::spawn(async move { + request.call(Arc::clone(&move_ctx)).await; + }); + let url = format!("ws://{}", SERVER_ADDRESS); + tokio::time::sleep(Duration::from_secs(3)).await; + + let client = WsClientBuilder::default().build(&url).await.unwrap(); + let response: HashMap = client.request("get_bitcoin_balance", rpc_params!["id"]).await.unwrap(); + + assert_eq!(response, HashMap::from([("balance".to_string(), 0)])); + ctx.shutdown.send(()); +} + +#[tokio::test] +#[sequential] +pub async fn get_history() { + let (ctx, mut request) = initialize_context().await; + let move_ctx = Arc::clone(&ctx); + tokio::spawn(async move { + request.call(Arc::clone(&move_ctx)).await; + }); + + let url = format!("ws://{}", SERVER_ADDRESS); + tokio::time::sleep(Duration::from_secs(3)).await; + + let client = WsClientBuilder::default().build(&url).await.unwrap(); + let mut params = ObjectParams::new(); + + let response: HashMap> = client.request("get_history", params).await.unwrap(); + let swaps: Vec<(Uuid, String)> = Vec::new(); + + assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)])); + ctx.shutdown.send(()); +} + +#[tokio::test] +#[sequential] +pub async fn get_raw_history() { + let (ctx, mut request) = initialize_context().await; + let move_ctx = Arc::clone(&ctx); + tokio::spawn(async move { + request.call(Arc::clone(&move_ctx)).await; + }); + + let url = format!("ws://{}", SERVER_ADDRESS); + tokio::time::sleep(Duration::from_secs(3)).await; + + let client = WsClientBuilder::default().build(&url).await.unwrap(); + let mut params = ObjectParams::new(); + let raw_history: HashMap = HashMap::new(); + + let response: HashMap> = client.request("get_raw_history", params).await.unwrap(); + + assert_eq!(response, HashMap::from([("raw_history".to_string(), raw_history)])); + ctx.shutdown.send(()); +} + +#[tokio::test] +#[sequential] +pub async fn get_seller() { + let (ctx, mut request) = initialize_context().await; + let move_ctx = Arc::clone(&ctx); + tokio::spawn(async move { + request.call(Arc::clone(&move_ctx)).await; + }); + + let url = format!("ws://{}", SERVER_ADDRESS); + tokio::time::sleep(Duration::from_secs(3)).await; + + let client = WsClientBuilder::default().build(&url).await.unwrap(); + let mut params = ObjectParams::new(); + + let response: Result, _> = client.request("get_seller", params).await; + + // We should ideally match the expected error and panic if it's different one, but the request returns a custom error (to investigate) + // Err(jsonrpsee_core::Error::Call(CallError::InvalidParams(e))) => (), + // Err(e) => panic!("ErrorType was not ParseError but {e:?}"), + + match response { + Err(e) => (), + _ => panic!("Expected an error when swap_id is missing"), + } + + let mut params = ObjectParams::new(); + params.insert("swap_id", "invalid_swap_000"); + + let response: Result, _> = client.request("get_seller", params).await; + + match response { + Err(e) => (), + _ => panic!("Expected an error swap_id is malformed"), + } + + let mut params = ObjectParams::new(); + params.insert("swap_id", "existing_swap"); + + let response: Result, _> = client.request("get_seller", params).await; + + match response { + Ok(hash) => (), + Err(e) => panic!("Expected a HashMap with correct params, got an error: {}", e), + } + ctx.shutdown.send(()); +} + +#[tokio::test] +#[sequential] +pub async fn get_swap_start_date() { + let (ctx, mut request) = initialize_context().await; + let move_ctx = Arc::clone(&ctx); + tokio::spawn(async move { + request.call(Arc::clone(&move_ctx)).await; + }); + + let url = format!("ws://{}", SERVER_ADDRESS); + tokio::time::sleep(Duration::from_secs(3)).await; + + let client = WsClientBuilder::default().build(&url).await.unwrap(); + let mut params = ObjectParams::new(); + + let response: Result, _> = client.request("get_swap_start_date", params).await; + + // We should ideally match the expected error and panic if it's different one, but the request returns a custom error (to investigate) + // Err(jsonrpsee_core::Error::Call(CallError::InvalidParams(e))) => (), + // Err(e) => panic!("ErrorType was not ParseError but {e:?}"), + + match response { + Err(e) => (), + _ => panic!("Expected an error when swap_id is missing"), + } + + let mut params = ObjectParams::new(); + params.insert("swap_id", "invalid_swap_000"); + + let response: Result, _> = client.request("get_swap_start_date", params).await; + + match response { + Err(e) => (), + _ => panic!("Expected an error when swap_id is malformed"), + } + + let mut params = ObjectParams::new(); + params.insert("swap_id", "existing_swap"); + + let response: Result, _> = client.request("get_swap_start_date", params).await; + + match response { + Ok(hash) => (), + Err(e) => panic!("Expected a HashMap, got an error: {}", e), + } + ctx.shutdown.send(()); +} + +#[tokio::test] +#[sequential] +pub async fn resume_swap() { + let (ctx, mut request) = initialize_context().await; + let move_ctx = Arc::clone(&ctx); + tokio::spawn(async move { + request.call(Arc::clone(&move_ctx)).await; + }); + + let url = format!("ws://{}", SERVER_ADDRESS); + tokio::time::sleep(Duration::from_secs(3)).await; + + let client = WsClientBuilder::default().build(&url).await.unwrap(); + let mut params = ObjectParams::new(); + + let response: Result, _> = client.request("get_swap_start_date", params).await; + + // We should ideally match the expected error and panic if it's different one, but the request returns a custom error (to investigate) + // Err(jsonrpsee_core::Error::Call(CallError::InvalidParams(e))) => (), + // Err(e) => panic!("ErrorType was not ParseError but {e:?}"), + + match response { + Err(e) => (), + _ => panic!("Expected an error when swap_id is missing"), + } + + let mut params = ObjectParams::new(); + params.insert("swap_id", "invalid_swap_000"); + + let response: Result, _> = client.request("get_swap_start_date", params).await; + + match response { + Err(e) => (), + _ => panic!("Expected an error when swap_id is malformed"), + } + + let mut params = ObjectParams::new(); + params.insert("swap_id", "existing_swap"); + + let response: Result, _> = client.request("get_swap_start_date", params).await; + + match response { + Ok(hash) => (), + Err(e) => panic!("Expected a HashMap, got an error: {}", e), + } + ctx.shutdown.send(()); +}