Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: introduce libp2p-swarm-test #2888

Merged
merged 82 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
c814911
Initialise `libp2p-swarm-test` with bits of rendezvous' test-harness
thomaseizinger Sep 12, 2022
7c7cd69
Introduce `SwarmExt::next_within`
thomaseizinger Sep 12, 2022
f00d954
Rewrite libp2p-ping tests using new test framework
thomaseizinger Sep 12, 2022
9ac8c8a
Merge branch 'master' into swarm-test
thomaseizinger Sep 16, 2022
ae33efc
Only use yamux
thomaseizinger Sep 16, 2022
909de35
Introduce `SwarmExt::new_ephemeral`
thomaseizinger Sep 16, 2022
246d10c
Add missing features
thomaseizinger Sep 16, 2022
0a679cd
Re-write first test of libp2p-ping with `SwarmExt::new_ephemeral`
thomaseizinger Sep 16, 2022
3ec9ab3
Rename connect function
thomaseizinger Sep 19, 2022
ba91fc8
Fix typo
thomaseizinger Sep 19, 2022
099eec3
Default transport in `new_ephemeral` to `MemoryTransport`
thomaseizinger Sep 19, 2022
aeb7224
Update docs
thomaseizinger Sep 19, 2022
96ebbf2
Make ping tests pass by fully converting to test harness
thomaseizinger Sep 19, 2022
82ede8f
Remove unused imports
thomaseizinger Sep 19, 2022
2aa7f5e
Apply clippy suggestion
thomaseizinger Sep 19, 2022
3c0ac6a
Remove extern crate statement
thomaseizinger Sep 19, 2022
973a66f
Remove duplication in test
thomaseizinger Sep 19, 2022
ac30260
Update swarm-test/src/lib.rs
thomaseizinger Sep 22, 2022
2bc39ff
Merge branch 'master' into swarm-test
thomaseizinger Sep 22, 2022
61ed59c
Merge branch 'swarm-test' of github.com:libp2p/rust-libp2p into swarm…
thomaseizinger Sep 22, 2022
85a1ab9
Fix imports
thomaseizinger Sep 22, 2022
39ab0f5
Fix compile error
thomaseizinger Sep 22, 2022
10e49ae
Merge branch 'master' into swarm-test
thomaseizinger Sep 23, 2022
67b9afb
Remove configurable timeout from `next_within`
thomaseizinger Sep 23, 2022
a091254
Use all external addresses of swarm for dialling
thomaseizinger Sep 23, 2022
d93825e
Add `SwarmExt::next_behaviour_event`
thomaseizinger Sep 23, 2022
7f24bbc
Merge branch 'master' into swarm-test
thomaseizinger Sep 30, 2022
df6bd24
Add license
thomaseizinger Sep 30, 2022
3ae3482
Fix build error
thomaseizinger Sep 30, 2022
c6b670d
Reduce fn arguments of `new_ephemeral` to `Keypair`
thomaseizinger Sep 30, 2022
6d48fe1
Port tests of `request-response` protocol
thomaseizinger Sep 30, 2022
358b4b8
Merge branch 'master' into swarm-test
thomaseizinger Oct 27, 2022
6ab68be
Shorten to `listen`
thomaseizinger Oct 27, 2022
5925500
Simplify combinators
thomaseizinger Oct 27, 2022
c58e752
MemoryTransport can now handle `/p2p`
thomaseizinger Oct 27, 2022
383583a
Don't track address if we don't use it
thomaseizinger Oct 27, 2022
5ef37b7
Use `SelectAll`
thomaseizinger Oct 27, 2022
2106ad8
Make `wait_for` an async fn
thomaseizinger Oct 27, 2022
e67b760
Simplify `drain_poll`
thomaseizinger Oct 27, 2022
d73fd19
Migrate to `libp2p-swarm-test`
thomaseizinger Oct 27, 2022
76fe529
Switch `libp2p-swarm-test` to `PlaintextConfig`
thomaseizinger Oct 27, 2022
d387d56
Autogenerate event
thomaseizinger Oct 27, 2022
e76ce57
Migrate from `LocalPool` to `async` test
thomaseizinger Oct 27, 2022
913cded
Inline variable
thomaseizinger Oct 27, 2022
077a7bf
Don't use select! macro
thomaseizinger Oct 27, 2022
d699f1e
Use time-gated function for dialing
thomaseizinger Oct 27, 2022
1365f01
Add `dial_and_wait`
thomaseizinger Oct 27, 2022
91d4c5c
Add `SwarmExt::wait`
thomaseizinger Oct 27, 2022
539d159
Migrate dcutr to `libp2p-swarm-test`
thomaseizinger Oct 27, 2022
972766a
Fix clippy lints
thomaseizinger Oct 27, 2022
2f76d9a
Merge branch 'master' into swarm-test
thomaseizinger Feb 28, 2023
9bbf18f
Address compile errors
thomaseizinger Feb 28, 2023
86f2d70
Don't depend on root crate in `swarm-test`
thomaseizinger Feb 28, 2023
951998a
Rewrite autonat client tests using swarm-test
thomaseizinger Feb 28, 2023
0affe0f
Rewrite autonat server tests using swarm-test
thomaseizinger Feb 28, 2023
7add311
Minor dcutr tweaks
thomaseizinger Feb 28, 2023
e5729da
Remove harness in autonat
thomaseizinger Feb 28, 2023
df4d48a
Write mdns async-std tests using swarm-test
thomaseizinger Feb 28, 2023
7a6d256
Rewrite tokio tests
thomaseizinger Feb 28, 2023
a74a058
Don't depend on async-std executor of swarm
thomaseizinger Feb 28, 2023
f4122d8
Make gossipsub tests compile
thomaseizinger Feb 28, 2023
4f7eb04
Fix formatting
thomaseizinger Mar 1, 2023
81ca805
Fix dcutr tests
thomaseizinger Mar 1, 2023
70d8d14
Fix gossipsub doc tests
thomaseizinger Mar 1, 2023
ee295af
Fix ping tests
thomaseizinger Mar 1, 2023
7029868
Make autonat test more resilient
thomaseizinger Mar 1, 2023
e4203e6
Fix req-res test
thomaseizinger Mar 1, 2023
3183125
Fix test
thomaseizinger Mar 2, 2023
e8600f0
Rename `next_or_timeout` to `next_swarm_event`
thomaseizinger Mar 2, 2023
e942586
Get rid of rendezvous harness
thomaseizinger Mar 2, 2023
0e83a95
Use defaults of derive macro
thomaseizinger Mar 2, 2023
09e34c5
Merge branch 'master' into swarm-test
thomaseizinger Mar 2, 2023
8aad527
Introduce `swarm_test::drive` to avoid starvation in rendezvous protocol
thomaseizinger Mar 2, 2023
e47dbf7
Further improve drive
thomaseizinger Mar 2, 2023
2f0f200
Fix clippy and docs
thomaseizinger Mar 2, 2023
cd93320
Fix clippy
thomaseizinger Mar 2, 2023
9f8015d
Use `drive` in ping test
thomaseizinger Mar 2, 2023
20ccbcb
Lazily compute vec length
thomaseizinger Mar 2, 2023
3ba7eb0
Update swarm-test/src/lib.rs
thomaseizinger Mar 8, 2023
96fd331
Add license header
thomaseizinger Mar 8, 2023
9f5f280
Fix docs
thomaseizinger Mar 8, 2023
56ea5e1
Merge branch 'master' into swarm-test
mergify[bot] Mar 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ members = [
"protocols/request-response",
"swarm",
"swarm-derive",
"swarm-test",
"transports/deflate",
"transports/dns",
"transports/noise",
Expand Down
1 change: 1 addition & 0 deletions protocols/ping/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ libp2p-noise = { path = "../../transports/noise" }
libp2p-yamux = { path = "../../muxers/yamux" }
libp2p-mplex = { path = "../../muxers/mplex" }
quickcheck = "0.9.0"
libp2p-swarm-test = { path = "../../swarm-test" }
176 changes: 61 additions & 115 deletions protocols/ping/tests/ping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,20 @@

//! Integration tests for the `Ping` network behaviour.

use futures::{channel::mpsc, prelude::*};
extern crate core;

use futures::prelude::*;
use libp2p_core::{
identity,
muxing::StreamMuxerBox,
transport::{self, Transport},
upgrade, Multiaddr, PeerId,
upgrade, PeerId,
};
use libp2p_mplex as mplex;
use libp2p_noise as noise;
use libp2p_ping as ping;
use libp2p_swarm::{DummyBehaviour, KeepAlive, Swarm, SwarmEvent};
use libp2p_swarm_test::SwarmExt;
use libp2p_tcp::{GenTcpConfig, TcpTransport};
use libp2p_yamux as yamux;
use quickcheck::*;
Expand All @@ -50,63 +53,35 @@ fn ping_pong() {
let (peer2_id, trans) = mk_transport(muxer);
let mut swarm2 = Swarm::new(trans, ping::Behaviour::new(cfg), peer2_id.clone());

let (mut tx, mut rx) = mpsc::channel::<Multiaddr>(1);
async_std::task::block_on(async {
swarm1.listen_on_random_localhost_tcp_port().await;
swarm2.block_on_connection(&mut swarm1).await;

let pid1 = peer1_id.clone();
let addr = "/ip4/127.0.0.1/tcp/0".parse().unwrap();
swarm1.listen_on(addr).unwrap();
for _ in 0..count.get() {
let (e1, e2) =
futures::future::join(swarm1.next_within(5), swarm2.next_within(5)).await;

let mut count1 = count.get();
let mut count2 = count.get();
let e1 = e1.try_into_behaviour_event().unwrap();
let e2 = e2.try_into_behaviour_event().unwrap();

let peer1 = async move {
loop {
match swarm1.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => tx.send(address).await.unwrap(),
SwarmEvent::Behaviour(ping::Event {
peer,
result: Ok(ping::Success::Ping { rtt }),
}) => {
count1 -= 1;
if count1 == 0 {
return (pid1.clone(), peer, rtt);
}
}
SwarmEvent::Behaviour(ping::Event { result: Err(e), .. }) => {
panic!("Ping failure: {:?}", e)
}
_ => {}
}
}
};
assert_eq!(e1.peer, peer2_id);
assert_eq!(e2.peer, peer1_id);

let pid2 = peer2_id.clone();
let peer2 = async move {
swarm2.dial(rx.next().await.unwrap()).unwrap();
let e1 = e1.result.expect("ping failure");
let e2 = e2.result.expect("ping failure");

loop {
match swarm2.select_next_some().await {
SwarmEvent::Behaviour(ping::Event {
peer,
result: Ok(ping::Success::Ping { rtt }),
}) => {
count2 -= 1;
if count2 == 0 {
return (pid2.clone(), peer, rtt);
}
}
SwarmEvent::Behaviour(ping::Event { result: Err(e), .. }) => {
panic!("Ping failure: {:?}", e)
match (e1, e2) {
(
ping::Success::Ping { rtt: peer1_rtt },
ping::Success::Ping { rtt: peer2_rtt },
) => {
assert!(peer1_rtt < Duration::from_millis(50));
assert!(peer2_rtt < Duration::from_millis(50));
}
_ => {}
}
}
};

let result = future::select(Box::pin(peer1), Box::pin(peer2));
let ((p1, p2, rtt), _) = async_std::task::block_on(result).factor_first();
assert!(p1 == peer1_id && p2 == peer2_id || p1 == peer2_id && p2 == peer1_id);
assert!(rtt < Duration::from_millis(50));
});
}

QuickCheck::new().tests(10).quickcheck(prop as fn(_, _))
Expand All @@ -129,62 +104,46 @@ fn max_failures() {
let (peer2_id, trans) = mk_transport(muxer);
let mut swarm2 = Swarm::new(trans, ping::Behaviour::new(cfg), peer2_id.clone());

let (mut tx, mut rx) = mpsc::channel::<Multiaddr>(1);

let addr = "/ip4/127.0.0.1/tcp/0".parse().unwrap();
swarm1.listen_on(addr).unwrap();

let peer1 = async move {
let mut count1: u8 = 0;
async_std::task::block_on(async {
swarm1.listen_on_random_localhost_tcp_port().await;
swarm2.block_on_connection(&mut swarm1).await;
});

loop {
match swarm1.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => tx.send(address).await.unwrap(),
SwarmEvent::Behaviour(ping::Event {
result: Ok(ping::Success::Ping { .. }),
..
}) => {
count1 = 0; // there may be an occasional success
}
SwarmEvent::Behaviour(ping::Event { result: Err(_), .. }) => {
count1 += 1;
}
SwarmEvent::ConnectionClosed { .. } => return count1,
_ => {}
}
}
};

let peer2 = async move {
swarm2.dial(rx.next().await.unwrap()).unwrap();

let mut count2: u8 = 0;

loop {
match swarm2.select_next_some().await {
SwarmEvent::Behaviour(ping::Event {
result: Ok(ping::Success::Ping { .. }),
..
}) => {
count2 = 0; // there may be an occasional success
}
SwarmEvent::Behaviour(ping::Event { result: Err(_), .. }) => {
count2 += 1;
}
SwarmEvent::ConnectionClosed { .. } => return count2,
_ => {}
}
}
};

let future = future::join(peer1, peer2);
let future = future::join(
count_consecutive_ping_failures_until_connection_closed(swarm1),
count_consecutive_ping_failures_until_connection_closed(swarm2),
);
let (count1, count2) = async_std::task::block_on(future);
assert_eq!(u8::max(count1, count2), max_failures.get() - 1);
}

QuickCheck::new().tests(10).quickcheck(prop as fn(_, _))
}

async fn count_consecutive_ping_failures_until_connection_closed(
mut swarm: Swarm<ping::Behaviour>,
) -> u8 {
let mut failure_count = 0;

loop {
match swarm.next_within(5).await {
SwarmEvent::Behaviour(ping::Event {
result: Ok(ping::Success::Ping { .. }),
..
}) => {
failure_count = 0; // there may be an occasional success
}
SwarmEvent::Behaviour(ping::Event { result: Err(_), .. }) => {
failure_count += 1;
}
SwarmEvent::ConnectionClosed { .. } => {
return failure_count;
}
_ => {}
}
}
}

#[test]
fn unsupported_doesnt_fail() {
let (peer1_id, trans) = mk_transport(MuxerChoice::Mplex);
Expand All @@ -201,25 +160,12 @@ fn unsupported_doesnt_fail() {
peer2_id.clone(),
);

let (mut tx, mut rx) = mpsc::channel::<Multiaddr>(1);

let addr = "/ip4/127.0.0.1/tcp/0".parse().unwrap();
swarm1.listen_on(addr).unwrap();

async_std::task::spawn(async move {
loop {
match swarm1.select_next_some().await {
SwarmEvent::NewListenAddr { address, .. } => tx.send(address).await.unwrap(),
_ => {}
}
}
});

let result = async_std::task::block_on(async move {
swarm2.dial(rx.next().await.unwrap()).unwrap();
let result = async_std::task::block_on(async {
swarm1.listen_on_random_localhost_tcp_port().await;
swarm2.block_on_connection(&mut swarm1).await;

loop {
match swarm2.select_next_some().await {
match swarm2.next_within(5).await {
SwarmEvent::Behaviour(ping::Event {
result: Err(ping::Failure::Unsupported),
..
Expand Down
1 change: 1 addition & 0 deletions protocols/rendezvous/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ env_logger = "0.8"
libp2p = { path = "../..", default-features = false, features = ["ping", "identify", "tcp-async-io", "dns-async-std", "websocket", "noise", "mplex", "yamux", "rendezvous"] }
rand = "0.8"
tokio = { version = "1.15", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] }
libp2p-swarm-test = { path = "../../swarm-test" }

[build-dependencies]
prost-build = "0.11"