Skip to content

Commit f2388bc

Browse files
Add summaries to test files and create common module for shared code
Co-Authored-By: Ian Clarke <[email protected]>
1 parent ac56e9a commit f2388bc

8 files changed

+289
-0
lines changed
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
2+
use std::{
3+
collections::HashSet,
4+
net::{Ipv4Addr, SocketAddr, TcpListener},
5+
path::PathBuf,
6+
time::Duration,
7+
};
8+
9+
use anyhow::{anyhow, Context, Result};
10+
use freenet::{
11+
config::{ConfigArgs, InlineGwConfig, NetworkArgs, SecretArgs, WebsocketApiArgs},
12+
dev_tool::TransportKeypair,
13+
local_node::NodeConfig,
14+
server::serve_gateway,
15+
};
16+
use freenet_ping_types::{Ping, PingContractOptions};
17+
use freenet_stdlib::{
18+
client_api::{ClientRequest, ContractRequest, ContractResponse, HostResponse, WebApi},
19+
prelude::*,
20+
};
21+
use futures::{future::BoxFuture, FutureExt};
22+
use rand::{Rng, SeedableRng};
23+
use tokio::{select, time::sleep};
24+
use tracing::{info, span, Instrument, Level};
25+
26+
pub fn base_node_test_config(
27+
data_dir: PathBuf,
28+
ws_api_port: u16,
29+
network_port: u16,
30+
blocked_peers: Vec<PeerId>,
31+
) -> NodeConfig {
32+
let mut rng = rand::rngs::StdRng::from_entropy();
33+
let seed: [u8; 32] = rng.gen();
34+
35+
let mut config = NodeConfig::new(data_dir, seed);
36+
37+
config.network.ws_api_port = ws_api_port;
38+
config.network.port = network_port;
39+
config.network.blocked_peers = blocked_peers;
40+
41+
config.network.connect_timeout = Duration::from_secs(5);
42+
config.network.operation_timeout = Duration::from_secs(10);
43+
44+
config
45+
}
46+
47+
pub fn gw_config(data_dir: PathBuf, ws_api_port: u16, network_port: u16) -> NodeConfig {
48+
base_node_test_config(data_dir, ws_api_port, network_port, vec![])
49+
}
50+
51+
pub fn ping_states_equal(a: &Ping, b: &Ping) -> bool {
52+
let a_set: HashSet<_> = a.get_all().into_iter().collect();
53+
let b_set: HashSet<_> = b.get_all().into_iter().collect();
54+
a_set == b_set
55+
}
56+
57+
pub async fn get_all_states(
58+
client_gw: &mut WebApi,
59+
client_node1: &mut WebApi,
60+
client_node2: &mut WebApi,
61+
key: ContractKey,
62+
) -> Result<(Ping, Ping, Ping)> {
63+
info!("Querying all nodes for current state...");
64+
65+
let response = client_gw
66+
.request(ClientRequest::Contract(ContractRequest::Get { key }))
67+
.await
68+
.context("Failed to get gateway state")?;
69+
70+
let state_gw = if let ContractResponse::State { state, .. } = response {
71+
serde_json::from_slice(&state).context("Failed to deserialize gateway state")?
72+
} else {
73+
anyhow::bail!("Unexpected response from gateway");
74+
};
75+
76+
let response = client_node1
77+
.request(ClientRequest::Contract(ContractRequest::Get { key }))
78+
.await
79+
.context("Failed to get node 1 state")?;
80+
81+
let state_node1 = if let ContractResponse::State { state, .. } = response {
82+
serde_json::from_slice(&state).context("Failed to deserialize node 1 state")?
83+
} else {
84+
anyhow::bail!("Unexpected response from node 1");
85+
};
86+
87+
let response = client_node2
88+
.request(ClientRequest::Contract(ContractRequest::Get { key }))
89+
.await
90+
.context("Failed to get node 2 state")?;
91+
92+
let state_node2 = if let ContractResponse::State { state, .. } = response {
93+
serde_json::from_slice(&state).context("Failed to deserialize node 2 state")?
94+
} else {
95+
anyhow::bail!("Unexpected response from node 2");
96+
};
97+
98+
Ok((state_gw, state_node1, state_node2))
99+
}
100+
101+
pub async fn setup_test_network(
102+
temp_dir: &std::path::Path,
103+
) -> Result<(
104+
BoxFuture<'static, ()>,
105+
BoxFuture<'static, ()>,
106+
BoxFuture<'static, ()>,
107+
PeerId,
108+
PeerId,
109+
PeerId,
110+
)> {
111+
let gw_dir = temp_dir.join("gateway");
112+
let node1_dir = temp_dir.join("node1");
113+
let node2_dir = temp_dir.join("node2");
114+
115+
std::fs::create_dir_all(&gw_dir)?;
116+
std::fs::create_dir_all(&node1_dir)?;
117+
std::fs::create_dir_all(&node2_dir)?;
118+
119+
let gw_ws_port = 50510;
120+
let gw_network_port = 50511;
121+
let node1_ws_port = 50512;
122+
let node1_network_port = 50513;
123+
let node2_ws_port = 50514;
124+
let node2_network_port = 50515;
125+
126+
let gw_config = gw_config(gw_dir.clone(), gw_ws_port, gw_network_port);
127+
let gateway_peer_id = gw_config.identity.peer_id();
128+
129+
let node1_config = base_node_test_config(node1_dir.clone(), node1_ws_port, node1_network_port, vec![]);
130+
let node1_peer_id = node1_config.identity.peer_id();
131+
132+
let node2_config = base_node_test_config(node2_dir.clone(), node2_ws_port, node2_network_port, vec![]);
133+
let node2_peer_id = node2_config.identity.peer_id();
134+
135+
let gateway_node = {
136+
let config = gw_config;
137+
let node = Node::new(config);
138+
info!("Starting gateway node");
139+
node.run().await
140+
}
141+
.boxed_local();
142+
143+
let node1 = {
144+
let config = base_node_test_config(
145+
node1_dir,
146+
node1_ws_port,
147+
node1_network_port,
148+
vec![node2_peer_id],
149+
);
150+
151+
let node = Node::new(config);
152+
info!("Starting node 1");
153+
node.run().await
154+
}
155+
.boxed_local();
156+
157+
let node2 = {
158+
let config = base_node_test_config(
159+
node2_dir,
160+
node2_ws_port,
161+
node2_network_port,
162+
vec![node1_peer_id],
163+
);
164+
165+
let node = Node::new(config);
166+
info!("Starting node 2");
167+
node.run().await
168+
}
169+
.boxed_local();
170+
171+
Ok((
172+
gateway_node,
173+
node1,
174+
node2,
175+
gateway_peer_id,
176+
node1_peer_id,
177+
node2_peer_id,
178+
))
179+
}
180+
181+
pub async fn connect_to_nodes(
182+
gw_ws_port: u16,
183+
node1_ws_port: u16,
184+
node2_ws_port: u16,
185+
) -> Result<(WebApi, WebApi, WebApi)> {
186+
let uri_gw = format!("ws://127.0.0.1:{}", gw_ws_port);
187+
let uri_node1 = format!("ws://127.0.0.1:{}", node1_ws_port);
188+
let uri_node2 = format!("ws://127.0.0.1:{}", node2_ws_port);
189+
190+
let client_gw = WebApi::connect(&uri_gw).await?;
191+
let client_node1 = WebApi::connect(&uri_node1).await?;
192+
let client_node2 = WebApi::connect(&uri_node2).await?;
193+
194+
info!("Connected to all nodes");
195+
196+
Ok((client_gw, client_node1, client_node2))
197+
}
198+
199+
pub async fn deploy_ping_contract(
200+
client_gw: &mut WebApi,
201+
code: Vec<u8>,
202+
ping_options: PingOptions,
203+
initial_state: Ping,
204+
) -> Result<ContractKey> {
205+
info!("Deploying ping contract on gateway...");
206+
207+
let response = client_gw
208+
.request(ClientRequest::Contract(ContractRequest::Deploy {
209+
code,
210+
state: serde_json::to_vec(&initial_state)?,
211+
options: serde_json::to_vec(&ping_options)?,
212+
}))
213+
.await?;
214+
215+
let key = if let ContractResponse::Deployed { key } = response {
216+
key
217+
} else {
218+
anyhow::bail!("Failed to deploy contract");
219+
};
220+
221+
info!("Contract deployed with key: {}", key);
222+
Ok(key)
223+
}
224+
225+
pub async fn subscribe_to_contract(
226+
client: &mut WebApi,
227+
key: ContractKey,
228+
node_name: &str,
229+
) -> Result<Ping> {
230+
info!("{} subscribing to contract...", node_name);
231+
let response = client
232+
.request(ClientRequest::Contract(ContractRequest::Subscribe { key }))
233+
.await?;
234+
235+
let state = if let ContractResponse::Subscribed { state, .. } = response {
236+
let ping: Ping = serde_json::from_slice(&state)?;
237+
ping
238+
} else {
239+
anyhow::bail!("Failed to subscribe {} to contract", node_name);
240+
};
241+
242+
info!("{} subscribed to contract", node_name);
243+
Ok(state)
244+
}
245+
246+
pub async fn send_update(
247+
client: &mut WebApi,
248+
key: ContractKey,
249+
ping: Ping,
250+
node_name: &str,
251+
) -> Result<()> {
252+
info!("Sending update from {}...", node_name);
253+
254+
client
255+
.request(ClientRequest::Contract(ContractRequest::Update {
256+
key,
257+
data: UpdateData::Delta(StateDelta::from(serde_json::to_vec(&ping)?)),
258+
}))
259+
.await?;
260+
261+
info!("Update sent from {}", node_name);
262+
Ok(())
263+
}

apps/freenet-ping/app/tests/run_app_blocked_peers.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
//
2+
//
3+
4+
15
use std::{
26
net::{Ipv4Addr, SocketAddr, TcpListener},
37
path::PathBuf,

apps/freenet-ping/app/tests/run_app_blocked_peers_debug.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//
2+
//
3+
14
use std::{
25
net::{Ipv4Addr, SocketAddr, TcpListener},
36
path::PathBuf,

apps/freenet-ping/app/tests/run_app_blocked_peers_improved.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
//
2+
//
3+
4+
15
use std::{
26
net::{Ipv4Addr, SocketAddr, TcpListener},
37
path::PathBuf,

apps/freenet-ping/app/tests/run_app_blocked_peers_optimized.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//
2+
//
3+
14
use std::{
25
net::{Ipv4Addr, SocketAddr, TcpListener},
36
path::PathBuf,

apps/freenet-ping/app/tests/run_app_blocked_peers_reliable.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
//
2+
//
3+
4+
15
use std::{
26
net::{Ipv4Addr, SocketAddr, TcpListener},
37
path::PathBuf,

apps/freenet-ping/app/tests/run_app_blocked_peers_simple.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//
2+
//
3+
14
use std::{collections::HashSet, path::PathBuf, time::Duration};
25

36
use anyhow::Context;

apps/freenet-ping/app/tests/run_app_blocked_peers_solution.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
//
2+
//
3+
//
4+
5+
16
use std::{
27
net::{Ipv4Addr, SocketAddr, TcpListener},
38
path::PathBuf,

0 commit comments

Comments
 (0)