Skip to content

Commit 856d243

Browse files
musitdevl-monningermzabaluev
authored
feature: Update Load and Soak test to pre execute code before test so that test can be run with one local faucet. (#1116)
Co-authored-by: Liam Monninger <[email protected]> Co-authored-by: Mikhail Zabaluev <[email protected]>
1 parent 1326df2 commit 856d243

File tree

10 files changed

+308
-101
lines changed

10 files changed

+308
-101
lines changed

networks/movement/movement-client/Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ name = "demo_scenario"
1515
path = "src/bin/e2e/demo_scenario.rs"
1616

1717
[[bin]]
18-
name = "movement-tests-e2e-basic-alice-bob"
19-
path = "src/bin/e2e/basic_alice_bob.rs"
18+
name = "movement-tests-e2e-load-alice-bob"
19+
path = "src/bin/e2e/load_alice_bob.rs"
20+
21+
[[bin]]
22+
name = "movement-tests-e2e-soak-alice-bob"
23+
path = "src/bin/e2e/soak_alice_bob.rs"
2024

2125
[[bin]]
2226
name = "bardock-tests-load-soak-basic"

networks/movement/movement-client/src/bin/e2e/bardock_alice_bob.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static FAUCET_URL: Lazy<Url> = Lazy::new(|| {
8484

8585
#[async_trait::async_trait]
8686
impl Scenario for BasicScenario {
87-
async fn run(self: Box<Self>) -> Result<()> {
87+
async fn run(&mut self) -> Result<()> {
8888
// Sleep for 7 seconds before each Scenario run to not get Rate Limited
8989
sleep(Duration::from_secs(5)).await;
9090

networks/movement/movement-client/src/bin/e2e/demo_scenario.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl ScenarioDemo {
4545

4646
#[async_trait::async_trait]
4747
impl Scenario for ScenarioDemo {
48-
async fn run(self: Box<Self>) -> Result<()> {
48+
async fn run(&mut self) -> Result<()> {
4949
// Trace in the log file and stdout.
5050
tracing::info!("Scenarios:{} start", self.id);
5151
let _ = tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;

networks/movement/movement-client/src/bin/e2e/basic_alice_bob.rs renamed to networks/movement/movement-client/src/bin/e2e/load_alice_bob.rs

Lines changed: 36 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,18 @@ fn main() {
2626

2727
// Scenario constructor function use by the Test runtime to create new scenarios.
2828
fn create_scenario(id: usize) -> Box<dyn Scenario> {
29-
Box::new(BasicScenario { id })
29+
Box::new(BasicScenario::new(id))
3030
}
3131

3232
pub struct BasicScenario {
3333
id: usize,
34+
alice: Option<LocalAccount>,
35+
bob: Option<LocalAccount>,
3436
}
3537

3638
impl BasicScenario {
3739
pub fn new(id: usize) -> Self {
38-
BasicScenario { id }
40+
BasicScenario { id, alice: None, bob: None }
3941
}
4042
}
4143

@@ -86,7 +88,7 @@ static FAUCET_URL: Lazy<Url> = Lazy::new(|| {
8688

8789
#[async_trait::async_trait]
8890
impl Scenario for BasicScenario {
89-
async fn run(self: Box<Self>) -> Result<()> {
91+
async fn prepare(&mut self) -> Result<(), anyhow::Error> {
9092
let rest_client = Client::new(NODE_URL.clone());
9193
let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone());
9294
let coin_client = CoinClient::new(&rest_client);
@@ -97,96 +99,60 @@ impl Scenario for BasicScenario {
9799

98100
// Print account addresses.
99101
tracing::info!(
100-
"Scenario:{}\n=== Addresses ===\nAlice: {}\nBob: {}",
102+
"Scenario:{} prepare \n=== Addresses ===\nAlice: {}\nBob: {}",
101103
self.id,
102104
alice.address().to_hex_literal(),
103105
bob.address().to_hex_literal()
104106
);
105107

106-
tracing::info!("{} Before alice fund", self.id);
107-
self.log_exec_info(&format!("{} Before alice fund", self.id));
108108
// Create the accounts on chain, but only fund Alice.
109-
faucet_client.fund(alice.address(), 100_000_000).await?;
110-
tracing::info!("{} Before Bod create_account", self.id);
111-
self.log_exec_info(&format!("{} Before Bod create_account", self.id));
109+
faucet_client.fund(alice.address(), 100_000_000_000).await?;
112110
faucet_client.create_account(bob.address()).await?;
113-
tracing::info!("{} After Bod create_account", self.id);
114-
self.log_exec_info(&format!("{} After Bod create_account", self.id));
115-
116-
// Print initial balances.
117-
tracing::info!(
118-
"Scenario:{}\n=== Initial Balances ===\nAlice: {:?}\nBob: {:?}",
119-
self.id,
120-
coin_client
121-
.get_account_balance(&alice.address())
122-
.await
123-
.context("Failed to get Alice's account balance")?,
124-
coin_client
125-
.get_account_balance(&bob.address())
126-
.await
127-
.context("Failed to get Bob's account balance")?
128-
);
129111

130112
// Have Alice send Bob some coins.
131113
let txn_hash = coin_client
132-
.transfer(&mut alice, bob.address(), 1_000, None)
114+
.transfer(&mut alice, bob.address(), 1_000_000, None)
133115
.await
134116
.context("Failed to submit transaction to transfer coins")?;
135117
rest_client
136118
.wait_for_transaction(&txn_hash)
137119
.await
138120
.context("Failed when waiting for the transfer transaction")?;
121+
tracing::info!("Scenario:{} prepare done. account created and founded", self.id,);
139122

140-
// Print intermediate balances.
141-
tracing::info!(
142-
"Scenario:{}\n=== Intermediate Balances ===\nAlice: {:?}\nBob: {:?}",
143-
self.id,
144-
coin_client
145-
.get_account_balance(&alice.address())
146-
.await
147-
.context("Failed to get Alice's account balance the second time")?,
148-
coin_client
149-
.get_account_balance(&bob.address())
150-
.await
151-
.context("Failed to get Bob's account balance the second time")?
152-
);
123+
self.alice = Some(alice);
124+
self.bob = Some(bob);
125+
Ok(())
126+
}
153127

154-
self.log_exec_info(&format!("Scenario:{} ended", self.id));
128+
async fn run(&mut self) -> Result<()> {
129+
let rest_client = Client::new(NODE_URL.clone());
130+
let coin_client = CoinClient::new(&rest_client); // Print initial balances.
155131

156-
// Have Alice send Bob some coins.
157-
let txn_hash = coin_client
158-
.transfer(&mut alice, bob.address(), 1_000, None)
159-
.await
160-
.context("Failed to submit transaction to transfer coins")?;
161-
rest_client
162-
.wait_for_transaction(&txn_hash)
163-
.await
164-
.context("Failed when waiting for the transfer transaction")?;
132+
let alice = self.alice.as_mut().unwrap();
133+
let bob = self.bob.as_mut().unwrap();
165134

166-
// Print intermediate balances.
167-
tracing::info!(
168-
"Scenario:{}\n=== Intermediate Balances ===\n Alice: {:?}\n Bob: {:?}",
169-
self.id,
170-
coin_client
171-
.get_account_balance(&alice.address())
135+
for _ in 0..2 {
136+
// Have Bob send Alice some coins.
137+
let txn_hash = coin_client
138+
.transfer(bob, alice.address(), 10, None)
172139
.await
173-
.context("Failed to get Alice's account balance the second time")?,
174-
coin_client
175-
.get_account_balance(&bob.address())
140+
.context("Failed to submit transaction to transfer coins")?;
141+
rest_client
142+
.wait_for_transaction(&txn_hash)
176143
.await
177-
.context("Failed to get Bob's account balance the second time")?
178-
);
144+
.context("Failed when waiting for the transfer transaction")?;
179145

180-
// Have Alice send Bob some more coins.
181-
let txn_hash = coin_client
182-
.transfer(&mut alice, bob.address(), 1_000, None)
183-
.await
184-
.context("Failed to submit transaction to transfer coins")?; // <:!:section_5
185-
// :!:>section_6
186-
rest_client
187-
.wait_for_transaction(&txn_hash)
188-
.await
189-
.context("Failed when waiting for the transfer transaction")?; // <:!:section_6
146+
// Have Alice send Bob some more coins.
147+
let txn_hash = coin_client
148+
.transfer(alice, bob.address(), 10, None)
149+
.await
150+
.context("Failed to submit transaction to transfer coins")?;
151+
rest_client
152+
.wait_for_transaction(&txn_hash)
153+
.await
154+
.context("Failed when waiting for the transfer transaction")?;
155+
}
190156

191157
// Print final balances.
192158
tracing::info!(
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
use anyhow::{Context, Result};
2+
use aptos_sdk::{
3+
coin_client::CoinClient,
4+
rest_client::{Client, FaucetClient},
5+
types::LocalAccount,
6+
};
7+
use movement_client::load_soak_testing::TestKind;
8+
use movement_client::load_soak_testing::{execute_test, init_test, ExecutionConfig, Scenario};
9+
use once_cell::sync::Lazy;
10+
use std::str::FromStr;
11+
use std::sync::Arc;
12+
use url::Url;
13+
14+
fn main() {
15+
// Define the Test config. Use the default parameters.
16+
let mut config = ExecutionConfig::default();
17+
18+
// Set some params for the load test, drive some requests
19+
config.kind = TestKind::Soak {
20+
min_scenarios: 20,
21+
max_scenarios: 20,
22+
duration: std::time::Duration::from_secs(600), // 10 minutes
23+
number_cycle: 1,
24+
};
25+
26+
// 2 Clients and 10 Requests per client
27+
config.number_scenario_per_client = 10;
28+
29+
// Init the Test before execution
30+
if let Err(err) = init_test(&config) {
31+
println!("Test init fail ; {err}",);
32+
}
33+
34+
// Execute the test.
35+
let result = execute_test(config, Arc::new(create_scenario));
36+
tracing::info!("End Test with result {result:?}",);
37+
}
38+
39+
// Scenario constructor function use by the Test runtime to create new scenarios.
40+
fn create_scenario(id: usize) -> Box<dyn Scenario> {
41+
Box::new(BasicScenario::new(id))
42+
}
43+
44+
pub struct BasicScenario {
45+
id: usize,
46+
alice: Option<LocalAccount>,
47+
bob: Option<LocalAccount>,
48+
}
49+
50+
impl BasicScenario {
51+
pub fn new(id: usize) -> Self {
52+
BasicScenario { id, alice: None, bob: None }
53+
}
54+
}
55+
56+
static SUZUKA_CONFIG: Lazy<movement_config::Config> = Lazy::new(|| {
57+
let dot_movement = dot_movement::DotMovement::try_from_env().unwrap();
58+
let config = dot_movement.try_get_config_from_json::<movement_config::Config>().unwrap();
59+
config
60+
});
61+
62+
static NODE_URL: Lazy<Url> = Lazy::new(|| {
63+
let node_connection_address = SUZUKA_CONFIG
64+
.execution_config
65+
.maptos_config
66+
.client
67+
.maptos_rest_connection_hostname
68+
.clone();
69+
let node_connection_port = SUZUKA_CONFIG
70+
.execution_config
71+
.maptos_config
72+
.client
73+
.maptos_rest_connection_port
74+
.clone();
75+
76+
let node_connection_url =
77+
format!("http://{}:{}", node_connection_address, node_connection_port);
78+
79+
Url::from_str(node_connection_url.as_str()).unwrap()
80+
});
81+
82+
static FAUCET_URL: Lazy<Url> = Lazy::new(|| {
83+
let faucet_listen_address = SUZUKA_CONFIG
84+
.execution_config
85+
.maptos_config
86+
.client
87+
.maptos_faucet_rest_connection_hostname
88+
.clone();
89+
let faucet_listen_port = SUZUKA_CONFIG
90+
.execution_config
91+
.maptos_config
92+
.client
93+
.maptos_faucet_rest_connection_port
94+
.clone();
95+
96+
let faucet_listen_url = format!("http://{}:{}", faucet_listen_address, faucet_listen_port);
97+
98+
Url::from_str(faucet_listen_url.as_str()).unwrap()
99+
});
100+
101+
#[async_trait::async_trait]
102+
impl Scenario for BasicScenario {
103+
async fn prepare(&mut self) -> Result<(), anyhow::Error> {
104+
let rest_client = Client::new(NODE_URL.clone());
105+
let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone());
106+
let coin_client = CoinClient::new(&rest_client); // Print initial balances.
107+
108+
// Create two accounts locally, Alice and Bob.
109+
let mut alice = LocalAccount::generate(&mut rand::rngs::OsRng);
110+
let bob = LocalAccount::generate(&mut rand::rngs::OsRng); // <:!:section_2
111+
112+
// Print account addresses.
113+
tracing::info!(
114+
"Scenario:{} prepare \n=== Addresses ===\nAlice: {}\nBob: {}",
115+
self.id,
116+
alice.address().to_hex_literal(),
117+
bob.address().to_hex_literal()
118+
);
119+
120+
// Create the accounts on chain, but only fund Alice.
121+
faucet_client.fund(alice.address(), 100_000_000_000).await?;
122+
faucet_client.create_account(bob.address()).await?;
123+
124+
// Have Alice send Bob some coins.
125+
let txn_hash = coin_client
126+
.transfer(&mut alice, bob.address(), 1_000_000, None)
127+
.await
128+
.context("Failed to submit transaction to transfer coins")?;
129+
rest_client
130+
.wait_for_transaction(&txn_hash)
131+
.await
132+
.context("Failed when waiting for the transfer transaction")?;
133+
tracing::info!("Scenario:{} prepare done. account created and founded", self.id,);
134+
135+
self.alice = Some(alice);
136+
self.bob = Some(bob);
137+
Ok(())
138+
}
139+
140+
async fn run(&mut self) -> Result<()> {
141+
let rest_client = Client::new(NODE_URL.clone());
142+
let coin_client = CoinClient::new(&rest_client); // Print initial balances.
143+
144+
let alice = self.alice.as_mut().unwrap();
145+
let bob = self.bob.as_mut().unwrap();
146+
147+
for _ in 0..2 {
148+
// Have Bod send Alice some coins.
149+
let txn_hash = coin_client
150+
.transfer(bob, alice.address(), 10, None)
151+
.await
152+
.context("Failed to submit transaction to transfer coins")?;
153+
rest_client
154+
.wait_for_transaction(&txn_hash)
155+
.await
156+
.context("Failed when waiting for the transfer transaction")?;
157+
158+
// Have Alice send Bob some more coins.
159+
let txn_hash = coin_client
160+
.transfer(alice, bob.address(), 10, None)
161+
.await
162+
.context("Failed to submit transaction to transfer coins")?;
163+
rest_client
164+
.wait_for_transaction(&txn_hash)
165+
.await
166+
.context("Failed when waiting for the transfer transaction")?;
167+
}
168+
169+
// Print final balances.
170+
tracing::info!(
171+
"Scenario:{}\n=== Final Balances ===\n Alice: {:?}\n Bob: {:?}",
172+
self.id,
173+
coin_client
174+
.get_account_balance(&alice.address())
175+
.await
176+
.context("Failed to get Alice's account balance the second time")?,
177+
coin_client
178+
.get_account_balance(&bob.address())
179+
.await
180+
.context("Failed to get Bob's account balance the second time")?
181+
);
182+
183+
Ok(())
184+
}
185+
}

0 commit comments

Comments
 (0)