Skip to content

Commit

Permalink
[api] Add view function testing to the API tester (#9658)
Browse files Browse the repository at this point in the history
This commit adds a new test which tests a simple view function.
  • Loading branch information
ngkuru committed Aug 22, 2023
1 parent 39ae118 commit 16cb6ac
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 24 deletions.
9 changes: 9 additions & 0 deletions crates/aptos-api-tester/src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
// Copyright © Aptos Foundation

use crate::utils::NetworkName;
use once_cell::sync::Lazy;
use std::{env, time::Duration};
use url::Url;

// Node and faucet constants

// TODO: consider making this a CLI argument
pub static NETWORK_NAME: Lazy<NetworkName> = Lazy::new(|| {
env::var("NETWORK_NAME")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(NetworkName::Devnet)
});

pub static DEVNET_NODE_URL: Lazy<Url> =
Lazy::new(|| Url::parse("https://fullnode.devnet.aptoslabs.com").unwrap());

Expand Down
13 changes: 9 additions & 4 deletions crates/aptos-api-tester/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::utils::{NetworkName, TestName};
use anyhow::Result;
use aptos_logger::{info, Level, Logger};
use aptos_push_metrics::MetricsPusher;
use consts::{NUM_THREADS, STACK_SIZE};
use consts::{NETWORK_NAME, NUM_THREADS, STACK_SIZE};
use futures::future::join_all;
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::runtime::{Builder, Runtime};
Expand Down Expand Up @@ -59,11 +59,18 @@ async fn test_flows(runtime: &Runtime, network_name: NetworkName) -> Result<()>
TestName::PublishModule.run(network_name, &test_time).await;
});

// Flow 5: View function
let test_time = run_id.clone();
let handle_viewfunction = runtime.spawn(async move {
TestName::ViewFunction.run(network_name, &test_time).await;
});

join_all(vec![
handle_newaccount,
handle_cointransfer,
handle_nfttransfer,
handle_publishmodule,
handle_viewfunction,
])
.await;
Ok(())
Expand All @@ -82,10 +89,8 @@ fn main() -> Result<()> {
let _mp = MetricsPusher::start_for_local_run("api-tester");

// run tests
// TODO: separate the running of the two networks
runtime.block_on(async {
let _ = test_flows(&runtime, NetworkName::Testnet).await;
let _ = test_flows(&runtime, NetworkName::Devnet).await;
let _ = test_flows(&runtime, *NETWORK_NAME).await;
});

Ok(())
Expand Down
4 changes: 4 additions & 0 deletions crates/aptos-api-tester/src/strings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub const FAIL_WRONG_TOKEN_DATA: &str = "wrong token data";

// Error messages

pub const ERROR_BAD_BALANCE_STRING: &str = "bad balance string";
pub const ERROR_COULD_NOT_BUILD_PACKAGE: &str = "failed to build package";
pub const ERROR_COULD_NOT_CHECK: &str = "persistency check never started";
pub const ERROR_COULD_NOT_CREATE_ACCOUNT: &str = "failed to create account";
Expand All @@ -21,8 +22,10 @@ pub const ERROR_COULD_NOT_CREATE_AND_SUBMIT_TRANSACTION: &str =
pub const ERROR_COULD_NOT_FINISH_TRANSACTION: &str = "failed to finish transaction";
pub const ERROR_COULD_NOT_FUND_ACCOUNT: &str = "failed to fund account";
pub const ERROR_COULD_NOT_SERIALIZE: &str = "failed to serialize";
pub const ERROR_COULD_NOT_VIEW: &str = "view function failed";
pub const ERROR_NO_ACCOUNT_DATA: &str = "can't find account data";
pub const ERROR_NO_BALANCE: &str = "can't find account balance";
pub const ERROR_NO_BALANCE_STRING: &str = "the API did not return a balance string";
pub const ERROR_NO_BYTECODE: &str = "can't find bytecode";
pub const ERROR_NO_COLLECTION_DATA: &str = "can't find collection data";
pub const ERROR_NO_MESSAGE: &str = "can't find message";
Expand Down Expand Up @@ -53,3 +56,4 @@ pub const PUBLISH_MODULE: &str = "publish_module";
pub const CHECK_MODULE_DATA: &str = "check_module_data";
pub const SET_MESSAGE: &str = "set_message";
pub const CHECK_MESSAGE: &str = "check_message";
pub const CHECK_VIEW_ACCOUNT_BALANCE: &str = "check_view_account_balance";
1 change: 1 addition & 0 deletions crates/aptos-api-tester/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pub mod coin_transfer;
pub mod new_account;
pub mod publish_module;
pub mod tokenv1_transfer;
pub mod view_function;
6 changes: 3 additions & 3 deletions crates/aptos-api-tester/src/tests/publish_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use move_core_types::{ident_str, language_storage::ModuleId};
use std::{collections::BTreeMap, path::PathBuf};

static MODULE_NAME: &str = "message";
static MESSAGE: &str = "test message";
static TEST_MESSAGE: &str = "test message";

/// Tests module publishing and interaction. Checks that:
/// - can publish module
Expand Down Expand Up @@ -293,7 +293,7 @@ async fn check_module_data(

async fn set_message(client: &Client, account: &mut LocalAccount) -> Result<(), TestFailure> {
// set up message
let message = match bcs::to_bytes(MESSAGE) {
let message = match bcs::to_bytes(TEST_MESSAGE) {
Ok(data) => data,
Err(e) => {
error!(
Expand Down Expand Up @@ -341,7 +341,7 @@ async fn set_message(client: &Client, account: &mut LocalAccount) -> Result<(),

async fn check_message(client: &Client, address: AccountAddress) -> Result<(), TestFailure> {
// expected
let expected = MESSAGE.to_string();
let expected = TEST_MESSAGE.to_string();

// actual
let actual = match get_message(client, address).await {
Expand Down
177 changes: 177 additions & 0 deletions crates/aptos-api-tester/src/tests/view_function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// Copyright © Aptos Foundation

use crate::{
consts::FUND_AMOUNT,
persistent_check,
strings::{
CHECK_ACCOUNT_DATA, CHECK_VIEW_ACCOUNT_BALANCE, ERROR_BAD_BALANCE_STRING,
ERROR_COULD_NOT_FUND_ACCOUNT, ERROR_COULD_NOT_VIEW, ERROR_NO_BALANCE_STRING,
FAIL_WRONG_BALANCE, SETUP,
},
time_fn,
utils::{
check_balance, create_and_fund_account, emit_step_metrics, NetworkName, TestFailure,
TestName,
},
};
use anyhow::anyhow;
use aptos_api_types::{ViewRequest, U64};
use aptos_logger::error;
use aptos_rest_client::Client;
use aptos_sdk::types::LocalAccount;
use aptos_types::account_address::AccountAddress;

/// Tests view function use. Checks that:
/// - view function returns correct value
pub async fn test(network_name: NetworkName, run_id: &str) -> Result<(), TestFailure> {
// setup
let (client, account) = emit_step_metrics(
time_fn!(setup, network_name),
TestName::ViewFunction,
SETUP,
network_name,
run_id,
)?;

// check account data persistently
emit_step_metrics(
time_fn!(
persistent_check::address,
CHECK_ACCOUNT_DATA,
check_account_data,
&client,
account.address()
),
TestName::ViewFunction,
CHECK_ACCOUNT_DATA,
network_name,
run_id,
)?;

// check account balance from view function persistently
emit_step_metrics(
time_fn!(
persistent_check::address,
CHECK_VIEW_ACCOUNT_BALANCE,
check_view_account_balance,
&client,
account.address()
),
TestName::ViewFunction,
CHECK_VIEW_ACCOUNT_BALANCE,
network_name,
run_id,
)?;

Ok(())
}

// Steps

async fn setup(network_name: NetworkName) -> Result<(Client, LocalAccount), TestFailure> {
// spin up clients
let client = network_name.get_client();
let faucet_client = network_name.get_faucet_client();

// create account
let account = match create_and_fund_account(&faucet_client, TestName::ViewFunction).await {
Ok(account) => account,
Err(e) => {
error!(
"test: {} part: {} ERROR: {}, with error {:?}",
TestName::ViewFunction.to_string(),
SETUP,
ERROR_COULD_NOT_FUND_ACCOUNT,
e
);
return Err(e.into());
},
};

Ok((client, account))
}

async fn check_account_data(client: &Client, account: AccountAddress) -> Result<(), TestFailure> {
check_balance(TestName::ViewFunction, client, account, U64(FUND_AMOUNT)).await?;

Ok(())
}

async fn check_view_account_balance(
client: &Client,
address: AccountAddress,
) -> Result<(), TestFailure> {
// expected
let expected = U64(FUND_AMOUNT);

// actual

// get client response
let response = match client
.view(
&ViewRequest {
function: "0x1::coin::balance".parse()?,
type_arguments: vec!["0x1::aptos_coin::AptosCoin".parse()?],
arguments: vec![serde_json::Value::String(address.to_hex_literal())],
},
None,
)
.await
{
Ok(response) => response,
Err(e) => {
error!(
"test: {} part: {} ERROR: {}, with error {:?}",
TestName::ViewFunction.to_string(),
CHECK_VIEW_ACCOUNT_BALANCE,
ERROR_COULD_NOT_VIEW,
e
);
return Err(e.into());
},
};

// get the string value from the serde_json value
let value = match response.inner()[0].as_str() {
Some(value) => value,
None => {
error!(
"test: {} part: {} ERROR: {}, with error {:?}",
TestName::ViewFunction.to_string(),
CHECK_VIEW_ACCOUNT_BALANCE,
ERROR_NO_BALANCE_STRING,
response.inner()
);
return Err(anyhow!(ERROR_NO_BALANCE_STRING).into());
},
};

// parse the string into a U64
let actual = match value.parse::<u64>() {
Ok(value) => U64(value),
Err(e) => {
error!(
"test: {} part: {} ERROR: {}, with error {:?}",
TestName::ViewFunction.to_string(),
CHECK_VIEW_ACCOUNT_BALANCE,
ERROR_BAD_BALANCE_STRING,
e
);
return Err(e.into());
},
};

// compare
if expected != actual {
error!(
"test: {} part: {} FAIL: {}, expected {:?}, got {:?}",
TestName::ViewFunction.to_string(),
CHECK_VIEW_ACCOUNT_BALANCE,
FAIL_WRONG_BALANCE,
expected,
actual
);
}

Ok(())
}
Loading

0 comments on commit 16cb6ac

Please sign in to comment.