change(tests): adds RPC request client for condensing shared code (#5619)
* Adds RPCRequestClient * uses RPCRequestClient in the rest of the rpc calls * removes duplicate expect call * fixed mistaken "get_info" method call with "getinfo" Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
816d845d94
commit
61af406d35
|
@ -161,6 +161,8 @@ use common::{
|
||||||
test_type::TestType::{self, *},
|
test_type::TestType::{self, *},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::common::rpc_client::RPCRequestClient;
|
||||||
|
|
||||||
/// The maximum amount of time that we allow the creation of a future to block the `tokio` executor.
|
/// The maximum amount of time that we allow the creation of a future to block the `tokio` executor.
|
||||||
///
|
///
|
||||||
/// This should be larger than the amount of time between thread time slices on a busy test VM.
|
/// This should be larger than the amount of time between thread time slices on a busy test VM.
|
||||||
|
@ -1320,7 +1322,6 @@ async fn rpc_endpoint_parallel_threads() -> Result<()> {
|
||||||
/// Set `parallel_cpu_threads` to true to auto-configure based on the number of CPU cores.
|
/// Set `parallel_cpu_threads` to true to auto-configure based on the number of CPU cores.
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
async fn rpc_endpoint(parallel_cpu_threads: bool) -> Result<()> {
|
async fn rpc_endpoint(parallel_cpu_threads: bool) -> Result<()> {
|
||||||
use hyper::{body::to_bytes, Body, Client, Method, Request};
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
let _init_guard = zebra_test::init();
|
let _init_guard = zebra_test::init();
|
||||||
|
@ -1331,7 +1332,6 @@ async fn rpc_endpoint(parallel_cpu_threads: bool) -> Result<()> {
|
||||||
// Write a configuration that has RPC listen_addr set
|
// Write a configuration that has RPC listen_addr set
|
||||||
// [Note on port conflict](#Note on port conflict)
|
// [Note on port conflict](#Note on port conflict)
|
||||||
let mut config = random_known_rpc_port_config(parallel_cpu_threads)?;
|
let mut config = random_known_rpc_port_config(parallel_cpu_threads)?;
|
||||||
let url = format!("http://{}", config.rpc.listen_addr.unwrap());
|
|
||||||
|
|
||||||
let dir = testdir()?.with_config(&mut config)?;
|
let dir = testdir()?.with_config(&mut config)?;
|
||||||
let mut child = dir.spawn_child(args!["start"])?;
|
let mut child = dir.spawn_child(args!["start"])?;
|
||||||
|
@ -1342,24 +1342,15 @@ async fn rpc_endpoint(parallel_cpu_threads: bool) -> Result<()> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Create an http client
|
// Create an http client
|
||||||
let client = Client::new();
|
let client = RPCRequestClient::new(config.rpc.listen_addr.unwrap());
|
||||||
|
|
||||||
// Create a request to call `getinfo` RPC method
|
// Make the call to the `getinfo` RPC method
|
||||||
let req = Request::builder()
|
let res = client.call("getinfo", "[]".to_string()).await?;
|
||||||
.method(Method::POST)
|
|
||||||
.uri(url)
|
|
||||||
.header("content-type", "application/json")
|
|
||||||
.body(Body::from(
|
|
||||||
r#"{"jsonrpc":"1.0","method":"getinfo","params":[],"id":123}"#,
|
|
||||||
))?;
|
|
||||||
|
|
||||||
// Make the call to the RPC endpoint
|
|
||||||
let res = client.request(req).await?;
|
|
||||||
|
|
||||||
// Test rpc endpoint response
|
// Test rpc endpoint response
|
||||||
assert!(res.status().is_success());
|
assert!(res.status().is_success());
|
||||||
|
|
||||||
let body = to_bytes(res).await;
|
let body = res.bytes().await;
|
||||||
let (body, mut child) = child.kill_on_error(body)?;
|
let (body, mut child) = child.kill_on_error(body)?;
|
||||||
|
|
||||||
let parsed: Value = serde_json::from_slice(&body)?;
|
let parsed: Value = serde_json::from_slice(&body)?;
|
||||||
|
@ -1419,17 +1410,12 @@ fn non_blocking_logger() -> Result<()> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Create an http client
|
// Create an http client
|
||||||
let client = reqwest::Client::new();
|
let client = RPCRequestClient::new(zebra_rpc_address);
|
||||||
|
|
||||||
// Most of Zebra's lines are 100-200 characters long, so 500 requests should print enough to fill the unix pipe,
|
// Most of Zebra's lines are 100-200 characters long, so 500 requests should print enough to fill the unix pipe,
|
||||||
// fill the channel that tracing logs are queued onto, and drop logs rather than block execution.
|
// fill the channel that tracing logs are queued onto, and drop logs rather than block execution.
|
||||||
for _ in 0..500 {
|
for _ in 0..500 {
|
||||||
let res = client
|
let res = client.call("getinfo", "[]".to_string()).await?;
|
||||||
.post(format!("http://{}", &zebra_rpc_address))
|
|
||||||
.body(r#"{"jsonrpc":"1.0","method":"getinfo","params":[],"id":123}"#)
|
|
||||||
.header("Content-Type", "application/json")
|
|
||||||
.send()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Test that zebrad rpc endpoint is still responding to requests
|
// Test that zebrad rpc endpoint is still responding to requests
|
||||||
assert!(res.status().is_success());
|
assert!(res.status().is_success());
|
||||||
|
@ -2042,28 +2028,17 @@ async fn fully_synced_rpc_test() -> Result<()> {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
zebrad.expect_stdout_line_matches(&format!(
|
let zebra_rpc_address = zebra_rpc_address.expect("lightwalletd test must have RPC port");
|
||||||
"Opened RPC endpoint at {}",
|
|
||||||
zebra_rpc_address.expect("lightwalletd test must have RPC port"),
|
zebrad.expect_stdout_line_matches(&format!("Opened RPC endpoint at {zebra_rpc_address}"))?;
|
||||||
))?;
|
|
||||||
|
let client = RPCRequestClient::new(zebra_rpc_address);
|
||||||
|
|
||||||
// Make a getblock test that works only on synced node (high block number).
|
// Make a getblock test that works only on synced node (high block number).
|
||||||
// The block is before the mandatory checkpoint, so the checkpoint cached state can be used
|
// The block is before the mandatory checkpoint, so the checkpoint cached state can be used
|
||||||
// if desired.
|
// if desired.
|
||||||
let client = reqwest::Client::new();
|
|
||||||
let res = client
|
let res = client
|
||||||
.post(format!(
|
.text_from_call("getblock", r#"["1180900", 0]"#.to_string())
|
||||||
"http://{}",
|
|
||||||
&zebra_rpc_address
|
|
||||||
.expect("lightwalletd test must have RPC port")
|
|
||||||
.to_string()
|
|
||||||
))
|
|
||||||
// Manually constructed request to avoid encoding it, for simplicity
|
|
||||||
.body(r#"{"jsonrpc": "2.0", "method": "getblock", "params": ["1180900", 0], "id":123 }"#)
|
|
||||||
.header("Content-Type", "application/json")
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.text()
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Simple textual check to avoid fully parsing the response, for simplicity
|
// Simple textual check to avoid fully parsing the response, for simplicity
|
||||||
|
|
|
@ -9,8 +9,6 @@ use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use reqwest::Client;
|
|
||||||
|
|
||||||
use color_eyre::eyre::{eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
@ -26,6 +24,7 @@ use zebra_chain::{
|
||||||
use zebra_state::{ChainTipChange, LatestChainTip};
|
use zebra_state::{ChainTipChange, LatestChainTip};
|
||||||
|
|
||||||
use crate::common::config::testdir;
|
use crate::common::config::testdir;
|
||||||
|
use crate::common::rpc_client::RPCRequestClient;
|
||||||
|
|
||||||
use zebra_state::MAX_BLOCK_REORG_HEIGHT;
|
use zebra_state::MAX_BLOCK_REORG_HEIGHT;
|
||||||
|
|
||||||
|
@ -231,22 +230,11 @@ pub async fn get_raw_future_blocks(
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Create an http client
|
// Create an http client
|
||||||
let client = Client::new();
|
let rpc_client = RPCRequestClient::new(rpc_address);
|
||||||
|
|
||||||
let send_rpc_request = |method, params| {
|
|
||||||
client
|
|
||||||
.post(format!("http://{}", &rpc_address))
|
|
||||||
.body(format!(
|
|
||||||
r#"{{"jsonrpc": "2.0", "method": "{method}", "params": {params}, "id":123 }}"#
|
|
||||||
))
|
|
||||||
.header("Content-Type", "application/json")
|
|
||||||
.send()
|
|
||||||
};
|
|
||||||
|
|
||||||
let blockchain_info: serde_json::Value = serde_json::from_str(
|
let blockchain_info: serde_json::Value = serde_json::from_str(
|
||||||
&send_rpc_request("getblockchaininfo", "[]".to_string())
|
&rpc_client
|
||||||
.await?
|
.text_from_call("getblockchaininfo", "[]".to_string())
|
||||||
.text()
|
|
||||||
.await?,
|
.await?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -266,9 +254,8 @@ pub async fn get_raw_future_blocks(
|
||||||
|
|
||||||
for block_height in (0..max_num_blocks).map(|idx| idx + estimated_finalized_tip_height) {
|
for block_height in (0..max_num_blocks).map(|idx| idx + estimated_finalized_tip_height) {
|
||||||
let raw_block: serde_json::Value = serde_json::from_str(
|
let raw_block: serde_json::Value = serde_json::from_str(
|
||||||
&send_rpc_request("getblock", format!(r#"["{block_height}", 0]"#))
|
&rpc_client
|
||||||
.await?
|
.text_from_call("getblock", format!(r#"["{block_height}", 0]"#))
|
||||||
.text()
|
|
||||||
.await?,
|
.await?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
|
|
||||||
use color_eyre::eyre::{Context, Result};
|
use color_eyre::eyre::{Context, Result};
|
||||||
|
|
||||||
use reqwest::Client;
|
|
||||||
use zebra_chain::parameters::Network;
|
use zebra_chain::parameters::Network;
|
||||||
|
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
cached_state::get_raw_future_blocks,
|
cached_state::get_raw_future_blocks,
|
||||||
launch::{can_spawn_zebrad_for_rpc, spawn_zebrad_for_rpc},
|
launch::{can_spawn_zebrad_for_rpc, spawn_zebrad_for_rpc},
|
||||||
|
rpc_client::RPCRequestClient,
|
||||||
test_type::TestType,
|
test_type::TestType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,16 +65,11 @@ pub(crate) async fn run() -> Result<()> {
|
||||||
tracing::info!(?rpc_address, "zebrad opened its RPC port",);
|
tracing::info!(?rpc_address, "zebrad opened its RPC port",);
|
||||||
|
|
||||||
// Create an http client
|
// Create an http client
|
||||||
let client = Client::new();
|
let client = RPCRequestClient::new(rpc_address);
|
||||||
|
|
||||||
for raw_block in raw_blocks {
|
for raw_block in raw_blocks {
|
||||||
let res = client
|
let res = client
|
||||||
.post(format!("http://{}", &rpc_address))
|
.call("submitblock", format!(r#"["{raw_block}"]"#))
|
||||||
.body(format!(
|
|
||||||
r#"{{"jsonrpc": "2.0", "method": "submitblock", "params": ["{raw_block}"], "id":123 }}"#
|
|
||||||
))
|
|
||||||
.header("Content-Type", "application/json")
|
|
||||||
.send()
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
assert!(res.status().is_success());
|
assert!(res.status().is_success());
|
||||||
|
|
|
@ -13,6 +13,7 @@ use zebra_test::prelude::*;
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
launch::ZebradTestDirExt,
|
launch::ZebradTestDirExt,
|
||||||
lightwalletd::wallet_grpc::{connect_to_lightwalletd, ChainSpec},
|
lightwalletd::wallet_grpc::{connect_to_lightwalletd, ChainSpec},
|
||||||
|
rpc_client::RPCRequestClient,
|
||||||
test_type::TestType,
|
test_type::TestType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,14 +183,9 @@ pub fn are_zebrad_and_lightwalletd_tips_synced(
|
||||||
let lightwalletd_tip_height = lightwalletd_tip_block.height;
|
let lightwalletd_tip_height = lightwalletd_tip_block.height;
|
||||||
|
|
||||||
// Get the block tip from zebrad
|
// Get the block tip from zebrad
|
||||||
let zebrad_json_rpc_client = reqwest::Client::new();
|
let client = RPCRequestClient::new(zebra_rpc_address);
|
||||||
let zebrad_blockchain_info = zebrad_json_rpc_client
|
let zebrad_blockchain_info = client
|
||||||
.post(format!("http://{}", &zebra_rpc_address.to_string()))
|
.text_from_call("getblockchaininfo", "[]".to_string())
|
||||||
.body(r#"{"jsonrpc": "2.0", "method": "getblockchaininfo", "params": [], "id":123 }"#)
|
|
||||||
.header("Content-Type", "application/json")
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.text()
|
|
||||||
.await?;
|
.await?;
|
||||||
let zebrad_blockchain_info: serde_json::Value =
|
let zebrad_blockchain_info: serde_json::Value =
|
||||||
serde_json::from_str(&zebrad_blockchain_info)?;
|
serde_json::from_str(&zebrad_blockchain_info)?;
|
||||||
|
|
|
@ -17,5 +17,6 @@ pub mod failure_messages;
|
||||||
pub mod get_block_template_rpcs;
|
pub mod get_block_template_rpcs;
|
||||||
pub mod launch;
|
pub mod launch;
|
||||||
pub mod lightwalletd;
|
pub mod lightwalletd;
|
||||||
|
pub mod rpc_client;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
pub mod test_type;
|
pub mod test_type;
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
//! A client for calling Zebra's Json-RPC methods
|
||||||
|
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
use reqwest::Client;
|
||||||
|
|
||||||
|
/// An http client for making Json-RPC requests
|
||||||
|
pub struct RPCRequestClient {
|
||||||
|
client: Client,
|
||||||
|
rpc_address: SocketAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RPCRequestClient {
|
||||||
|
/// Creates new RPCRequestSender
|
||||||
|
pub fn new(rpc_address: SocketAddr) -> Self {
|
||||||
|
Self {
|
||||||
|
client: Client::new(),
|
||||||
|
rpc_address,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds rpc request
|
||||||
|
pub async fn call(
|
||||||
|
&self,
|
||||||
|
method: &'static str,
|
||||||
|
params: impl Into<String>,
|
||||||
|
) -> reqwest::Result<reqwest::Response> {
|
||||||
|
let params = params.into();
|
||||||
|
self.client
|
||||||
|
.post(format!("http://{}", &self.rpc_address))
|
||||||
|
.body(format!(
|
||||||
|
r#"{{"jsonrpc": "2.0", "method": "{method}", "params": {params}, "id":123 }}"#
|
||||||
|
))
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds rpc request and gets text from response
|
||||||
|
pub async fn text_from_call(
|
||||||
|
&self,
|
||||||
|
method: &'static str,
|
||||||
|
params: impl Into<String>,
|
||||||
|
) -> reqwest::Result<String> {
|
||||||
|
self.call(method, params).await?.text().await
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue