Skip to content

Commit

Permalink
[pallet-revive] breakdown integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pgherveou committed Nov 12, 2024
1 parent 9f8656b commit 7c7939a
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 38 deletions.
6 changes: 6 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,9 @@ serial-integration = { max-threads = 1 }
[[profile.default.overrides]]
filter = 'test(/(^ui$|_ui|ui_)/)'
test-group = 'serial-integration'

# Running eth-rpc tests sequentially
# As they rely on a shared resource (the RPC and Node) and could run into race conditions with the nonces
[[profile.default.overrides]]
filter = 'package(pallet-revive-eth-rpc) and test(/^tests::/)'
test-group = 'serial-integration'
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions substrate/frame/revive/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ ethabi = { version = "18.0.0" }
example = ["hex-literal", "rlp", "secp256k1", "subxt-signer"]

[dev-dependencies]
static_init = { workspace = true }
hex-literal = { workspace = true }
pallet-revive-fixtures = { workspace = true }
substrate-cli-test-utils = { workspace = true }
Expand Down
139 changes: 101 additions & 38 deletions substrate/frame/revive/rpc/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use pallet_revive::{
create1,
evm::{Account, BlockTag, U256},
};
use static_init::dynamic;
use std::thread;
use substrate_cli_test_utils::*;

Expand Down Expand Up @@ -60,6 +61,52 @@ fn get_contract(name: &str) -> anyhow::Result<(Vec<u8>, ethabi::Contract)> {
Ok((bytecode, contract))
}

struct SharedResources {
_node_handle: std::thread::JoinHandle<()>,
_rpc_handle: std::thread::JoinHandle<()>,
}

impl SharedResources {
fn start() -> Self {
// Start the node.
let _node_handle = thread::spawn(move || {
if let Err(e) = start_node_inline(vec![
"--dev",
"--rpc-port=45789",
"--no-telemetry",
"--no-prometheus",
"-lerror,evm=debug,sc_rpc_server=info,runtime::revive=trace",
]) {
panic!("Node exited with error: {e:?}");
}
});

// Start the rpc server.
let args = CliCommand::parse_from([
"--dev",
"--rpc-port=45788",
"--node-rpc-url=ws://localhost:45789",
"--no-prometheus",
"-linfo,eth-rpc=debug",
]);

let _rpc_handle = thread::spawn(move || {
if let Err(e) = cli::run(args) {
panic!("eth-rpc exited with error: {e:?}");
}
});

Self { _node_handle, _rpc_handle }
}

async fn client() -> WsClient {
ws_client_with_retry("ws://localhost:45788").await
}
}

#[dynamic(lazy)]
static mut SHARED_RESOURCES: SharedResources = SharedResources::start();

macro_rules! unwrap_call_err(
($err:expr) => {
match $err.downcast_ref::<jsonrpsee::core::client::Error>().unwrap() {
Expand All @@ -70,41 +117,42 @@ macro_rules! unwrap_call_err(
);

#[tokio::test]
async fn test_jsonrpsee_server() -> anyhow::Result<()> {
// Start the node.
let _ = thread::spawn(move || {
if let Err(e) = start_node_inline(vec![
"--dev",
"--rpc-port=45789",
"--no-telemetry",
"--no-prometheus",
"-lerror,evm=debug,sc_rpc_server=info,runtime::revive=trace",
]) {
panic!("Node exited with error: {e:?}");
}
});

// Start the rpc server.
let args = CliCommand::parse_from([
"--dev",
"--rpc-port=45788",
"--node-rpc-url=ws://localhost:45789",
"--no-prometheus",
"-linfo,eth-rpc=debug",
]);
let _ = thread::spawn(move || {
if let Err(e) = cli::run(args) {
panic!("eth-rpc exited with error: {e:?}");
}
});
async fn transfer() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;

let client = ws_client_with_retry("ws://localhost:45788").await;
let ethan = Account::from(subxt_signer::eth::dev::ethan());
let initial_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;

let value = 1_000_000_000_000_000_000_000u128.into();
let hash = TransactionBuilder::default()
.value(value)
.to(ethan.address())
.send(&client)
.await?;

let receipt = wait_for_successful_receipt(&client, hash).await?;
assert_eq!(
Some(ethan.address()),
receipt.to,
"Receipt should have the correct contract address."
);

let increase =
client.get_balance(ethan.address(), BlockTag::Latest.into()).await? - initial_balance;
assert_eq!(value, increase);
Ok(())
}

#[tokio::test]
async fn deploy_and_call() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;
let account = Account::default();

// Balance transfer
let ethan = Account::from(subxt_signer::eth::dev::ethan());
let ethan_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;
assert_eq!(U256::zero(), ethan_balance);
let initial_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;

let value = 1_000_000_000_000_000_000_000u128.into();
let hash = TransactionBuilder::default()
Expand All @@ -120,8 +168,8 @@ async fn test_jsonrpsee_server() -> anyhow::Result<()> {
"Receipt should have the correct contract address."
);

let ethan_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;
assert_eq!(value, ethan_balance, "ethan's balance should be the same as the value sent.");
let updated_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;
assert_eq!(value, updated_balance - initial_balance);

// Deploy contract
let data = b"hello world".to_vec();
Expand Down Expand Up @@ -169,15 +217,19 @@ async fn test_jsonrpsee_server() -> anyhow::Result<()> {
wait_for_successful_receipt(&client, hash).await?;
let increase = client.get_balance(contract_address, BlockTag::Latest.into()).await? - balance;
assert_eq!(value, increase, "contract's balance should have increased by the value sent.");
Ok(())
}

// Deploy revert
#[tokio::test]
async fn revert_call() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;
let (bytecode, contract) = get_contract("revert")?;
let receipt = TransactionBuilder::default()
.input(contract.constructor.clone().unwrap().encode_input(bytecode, &[]).unwrap())
.send_and_wait_for_receipt(&client)
.await?;

// Call doRevert
let err = TransactionBuilder::default()
.to(receipt.contract_address.unwrap())
.input(contract.function("doRevert")?.encode_input(&[])?.to_vec())
Expand All @@ -187,25 +239,36 @@ async fn test_jsonrpsee_server() -> anyhow::Result<()> {

let call_err = unwrap_call_err!(err.source().unwrap());
assert_eq!(call_err.message(), "Execution reverted: revert message");
Ok(())
}

// Deploy event
#[tokio::test]
async fn event_logs() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;
let (bytecode, contract) = get_contract("event")?;
let receipt = TransactionBuilder::default()
.input(bytecode)
.send_and_wait_for_receipt(&client)
.await?;

// Call triggerEvent
let receipt = TransactionBuilder::default()
.to(receipt.contract_address.unwrap())
.input(contract.function("triggerEvent")?.encode_input(&[])?.to_vec())
.send_and_wait_for_receipt(&client)
.await?;
assert_eq!(receipt.logs.len(), 1, "There should be one log.");
Ok(())
}

#[tokio::test]
async fn invalid_transaction() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;
let ethan = Account::from(subxt_signer::eth::dev::ethan());

// Invalid transaction
let err = TransactionBuilder::default()
.value(value)
.value(U256::from(1_000_000_000_000u128))
.to(ethan.address())
.mutate(|tx| tx.chain_id = Some(42u32.into()))
.send(&client)
Expand Down

0 comments on commit 7c7939a

Please sign in to comment.