Allow running integration tests given a SUBXT_TEST_URL=ws://foo:port (#1640)

* Allow running integration tests given a SUBXT_TEST_URL=ws://foo:port

* update comment

* fmt

* Fix lightclient get_url usage

* fix light client

* fix lightclient tests take 2
This commit is contained in:
James Wilson
2024-06-24 14:29:08 +01:00
committed by GitHub
parent d408da1636
commit 4a07b64c27
@@ -11,10 +11,32 @@ use subxt::{
Config, OnlineClient,
};
// The URL that we'll connect to for our tests comes from SUBXT_TEXT_HOST env var,
// defaulting to localhost if not provided. If the env var is set, we won't spawn
// a binary. Note though that some tests expect and modify a fresh state, and so will
// fail. Fo a similar reason wyou should also use `--test-threads 1` when running tests
// to reduce the number of conflicts between state altering tests.
const URL_ENV_VAR: &str = "SUBXT_TEST_URL";
fn is_url_provided() -> bool {
std::env::var(URL_ENV_VAR).is_ok()
}
fn get_url(port: Option<u16>) -> String {
match (std::env::var(URL_ENV_VAR).ok(), port) {
(Some(host), None) => host,
(None, Some(port)) => format!("ws://127.0.0.1:{port}"),
(Some(_), Some(_)) => {
panic!("{URL_ENV_VAR} and port provided: only one or the other should exist")
}
(None, None) => {
panic!("No {URL_ENV_VAR} or port was provided, so we don't know where to connect to")
}
}
}
/// Spawn a local substrate node for testing subxt.
pub struct TestNodeProcess<R: Config> {
// Keep a handle to the node; once it's dropped the node is killed.
proc: SubstrateNode,
proc: Option<SubstrateNode>,
// Lazily construct these when asked for.
unstable_client: RefCell<Option<OnlineClient<R>>>,
@@ -50,7 +72,7 @@ where
/// Hand back an RPC client connected to the test node.
pub async fn rpc_client(&self) -> rpc::RpcClient {
let url = format!("ws://127.0.0.1:{}", self.proc.ws_port());
let url = get_url(self.proc.as_ref().map(|p| p.ws_port()));
rpc::RpcClient::from_url(url)
.await
.expect("Unable to connect RPC client to test node")
@@ -124,17 +146,21 @@ impl TestNodeProcessBuilder {
where
R: Config,
{
let mut node_builder = SubstrateNode::builder();
// Only spawn a process if a URL to target wasn't provided as an env var.
let proc = if !is_url_provided() {
let mut node_builder = SubstrateNode::builder();
node_builder.binary_paths(&self.node_paths);
node_builder.binary_paths(&self.node_paths);
if let Some(authority) = &self.authority {
node_builder.arg(authority.to_lowercase());
}
if let Some(authority) = &self.authority {
node_builder.arg(authority.to_lowercase());
}
Some(node_builder.spawn().map_err(|e| e.to_string())?)
} else {
None
};
// Spawn the node and retrieve a URL to it:
let proc = node_builder.spawn().map_err(|e| e.to_string())?;
let ws_url = format!("ws://127.0.0.1:{}", proc.ws_port());
let ws_url = get_url(proc.as_ref().map(|p| p.ws_port()));
let rpc_client = build_rpc_client(&ws_url)
.await
.map_err(|e| format!("Failed to connect to node at {ws_url}: {e}"))?;
@@ -173,7 +199,7 @@ impl TestNodeProcessBuilder {
}
async fn build_rpc_client(ws_url: &str) -> Result<rpc::RpcClient, String> {
let rpc_client = rpc::RpcClient::from_url(ws_url)
let rpc_client = rpc::RpcClient::from_insecure_url(ws_url)
.await
.map_err(|e| format!("Cannot construct RPC client: {e}"))?;
@@ -217,10 +243,18 @@ async fn build_unstable_client<T: Config>(
}
#[cfg(lightclient)]
async fn build_light_client<T: Config>(proc: &SubstrateNode) -> Result<OnlineClient<T>, String> {
async fn build_light_client<T: Config>(
maybe_proc: &Option<SubstrateNode>,
) -> Result<OnlineClient<T>, String> {
use subxt::lightclient::{ChainConfig, LightClient};
// RPC endpoint.
let proc = if let Some(proc) = maybe_proc {
proc
} else {
return Err("Cannot build light client: no substrate node is running (you can't start a light client when pointing to an external node)".into());
};
// RPC endpoint. Only localhost works.
let ws_url = format!("ws://127.0.0.1:{}", proc.ws_port());
// Wait for a few blocks to be produced using the subxt client.