Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tests/integration/common/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ impl fmt::Display for RpcError {
write!(f, "{self:?}")
}
}

impl std::error::Error for RpcError {}
6 changes: 3 additions & 3 deletions tests/integration/common/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ pub async fn assert_tx_succeeded_accepted<T: Provider>(

match receipt.execution_result() {
ExecutionResult::Succeeded => (),
other => anyhow::bail!("Should have succeeded; got: {other:?}"),
other => anyhow::bail!("Tx {tx_hash:#x} should have succeeded; got: {other:?}"),
}

match receipt.finality_status() {
starknet_rs_core::types::TransactionFinalityStatus::AcceptedOnL2 => Ok(()),
other => anyhow::bail!("Should have been accepted on L2; got: {other:?}"),
other => anyhow::bail!("Tx {tx_hash:#x} should have been accepted on L2; got: {other:?}"),
}
}

Expand Down Expand Up @@ -435,7 +435,7 @@ pub async fn deploy_argent_account(

let account_address = deployment.address();
devnet.mint(account_address, u128::MAX).await;
let deployment_result = deployment.send().await.map_err(|e| anyhow::anyhow!("{e:?}"))?;
let deployment_result = deployment.send().await?;

Ok((deployment_result, signer))
}
Expand Down
20 changes: 11 additions & 9 deletions tests/integration/test_accepting_blocks_on_l1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,30 @@ async fn assert_accepted_on_l1(
for block_hash in block_hashes {
match devnet.json_rpc_client.get_block_with_tx_hashes(BlockId::Hash(*block_hash)).await {
Ok(MaybePreConfirmedBlockWithTxHashes::Block(block)) => {
assert_eq!(block.status, BlockStatus::AcceptedOnL1)
anyhow::ensure!(block.status == BlockStatus::AcceptedOnL1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Problem

I was not aware that anyhow::ensure only accepts a boolean argument. This reduces the information in the reported error. assert_eq nicely reports the failure telling us the left and the right argument which don't match, but the stack trace is messy. With anyhow::ensure we get a nice stack trace, but lose the mismatched content.

Suggestion

The best would be to have a custom equality assertion function that would only be used in these helper functions (basically the places where you've now configured anyhow::ensure). The function would accept two arguments implementing the Debug trait, return Ok(()) if equal, or return an Err containing info on left and right, but propagating it. Though there might be issues when the two arguments are not of the same type, meaning it would require something like this:

fn assert_eq_propagated<T, U>(a: T, b: U) -> Result<(), anyhow::Error>
where
    T: Into<U> + Debug,  // T can be converted into U
    U: From<T> + Debug,   // U can be constructed from T
{

Let me know if you think this is too much of hassle and if it's even feasible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ensure!(user == 0, "only user 0 is allowed"); takes in an optional error message argument, we could use that, but if it don't report as much info as needed, I'd look into implementing your suggestion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FabijanC what do you think about this?

fn take_abi_from_json(value: &mut serde_json::Value) -> Result<serde_json::Value, anyhow::Error> {
    let abi_jsonified = value["abi"].take();
    let json_null = serde_json::json!(null);
    anyhow::ensure!(
        abi_jsonified != json_null,
        format!("assertion `left == right` failed, left: {abi_jsonified}, right: {json_null}")
    );
    Ok(serde_json::from_str(abi_jsonified.as_str().unwrap())?)
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Situations where we assert non-equality (i.e. x != y) or "greater-than" relation (i.e. x > y) are less problematic. Personally, I'd rather we kept using assert_eq than anyhow::ensure and now I regret recommending it in the first place. The ideal solution would be to have a macro or a custom function that I proposed above, but I will understand if you don't want to implement one of those.

So: let me know if you will just revert the anyhow::ensure changes or also implement a custom asserter. Sorry once again for the double work on your side.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, It's fine, my bad, I went with providing custom error messages, I'd implement the custom assert, and push.

}
other => anyhow::bail!("Unexpected block: {other:?}"),
}
}

for tx_hash in tx_hashes {
let tx_status = devnet.json_rpc_client.get_transaction_status(tx_hash).await.unwrap();
assert_eq!(tx_status.finality_status(), SequencerTransactionStatus::AcceptedOnL1);
anyhow::ensure!(tx_status.finality_status() == SequencerTransactionStatus::AcceptedOnL1);
}

Ok(())
}

async fn assert_latest_accepted_on_l2(devnet: &BackgroundDevnet) {
let latest_block = devnet.get_latest_block_with_tx_hashes().await.unwrap();
assert_eq!(latest_block.status, BlockStatus::AcceptedOnL2,);
async fn assert_latest_accepted_on_l2(devnet: &BackgroundDevnet) -> Result<(), anyhow::Error> {
let latest_block = devnet.get_latest_block_with_tx_hashes().await?;
anyhow::ensure!(latest_block.status == BlockStatus::AcceptedOnL2,);

for tx_hash in latest_block.transactions {
let tx_status = devnet.json_rpc_client.get_transaction_status(tx_hash).await.unwrap();
assert_eq!(tx_status.finality_status(), SequencerTransactionStatus::AcceptedOnL2)
let tx_status = devnet.json_rpc_client.get_transaction_status(tx_hash).await?;
anyhow::ensure!(tx_status.finality_status() == SequencerTransactionStatus::AcceptedOnL2)
}

Ok(())
}

#[tokio::test]
Expand Down Expand Up @@ -110,7 +112,7 @@ async fn should_convert_accepted_on_l2_with_numeric_id() {
assert_eq!(accepted_block_hashes, block_hashes);

assert_accepted_on_l1(&devnet, &block_hashes, &[tx_hash]).await.unwrap();
assert_latest_accepted_on_l2(&devnet).await;
assert_latest_accepted_on_l2(&devnet).await.unwrap();
}

#[tokio::test]
Expand All @@ -133,7 +135,7 @@ async fn should_convert_accepted_on_l2_with_hash_id() {
assert_eq!(accepted_block_hashes, block_hashes);

assert_accepted_on_l1(&devnet, &block_hashes, &[tx_hash]).await.unwrap();
assert_latest_accepted_on_l2(&devnet).await;
assert_latest_accepted_on_l2(&devnet).await.unwrap();
}

#[tokio::test]
Expand Down
23 changes: 14 additions & 9 deletions tests/integration/test_account_selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,33 +42,38 @@ async fn spawnable_with_custom_account_cairo_1() {
}

/// Common body for tests defined below
async fn correct_artifact_test_body(devnet_args: &[&str], expected_hash_hex: &str) {
let devnet = BackgroundDevnet::spawn_with_additional_args(devnet_args).await.unwrap();
async fn correct_artifact_test_body(
devnet_args: &[&str],
expected_hash_hex: &str,
) -> Result<(), anyhow::Error> {
let devnet = BackgroundDevnet::spawn_with_additional_args(devnet_args).await?;

let (_, account_address) = devnet.get_first_predeployed_account().await;
let retrieved_class_hash = devnet
.json_rpc_client
.get_class_hash_at(BlockId::Tag(BlockTag::Latest), account_address)
.await
.unwrap();
.await?;
let expected_hash = Felt::from_hex_unchecked(expected_hash_hex);
assert_eq!(retrieved_class_hash, expected_hash);
anyhow::ensure!(retrieved_class_hash == expected_hash);

let config = devnet.get_config().await;
let config_class_hash_hex = config["account_contract_class_hash"].as_str().unwrap();
assert_eq!(Felt::from_hex_unchecked(config_class_hash_hex), expected_hash);
let config_class_hash_hex = config["account_contract_class_hash"]
.as_str()
.ok_or(anyhow::anyhow!("contract class hash not found"))?;
anyhow::ensure!(Felt::from_hex_unchecked(config_class_hash_hex) == expected_hash);
Ok(())
}

#[tokio::test]
async fn correct_cairo1_artifact() {
let cli_args = ["--account-class", "cairo1"];
correct_artifact_test_body(&cli_args, CAIRO_1_ACCOUNT_CONTRACT_SIERRA_HASH).await;
correct_artifact_test_body(&cli_args, CAIRO_1_ACCOUNT_CONTRACT_SIERRA_HASH).await.unwrap();
}

#[tokio::test]
async fn correct_custom_artifact() {
let cli_args = ["--account-class-custom", CAIRO_1_ACCOUNT_CONTRACT_SIERRA_PATH];
correct_artifact_test_body(&cli_args, CAIRO_1_ACCOUNT_CONTRACT_SIERRA_HASH).await;
correct_artifact_test_body(&cli_args, CAIRO_1_ACCOUNT_CONTRACT_SIERRA_HASH).await.unwrap();
}

#[tokio::test]
Expand Down
Loading