#distributed-applications #distributed-systems #virtual #namespaces #linux #parallel #synchronization

bin+lib testnet

A library that helps you test your distributed applications using a virtual network via Linux namespaces

1 unstable release

0.1.0 Sep 15, 2024

#428 in Testing

Download history 141/week @ 2024-09-10 32/week @ 2024-09-17 12/week @ 2024-09-24 18/week @ 2024-10-01

96 downloads per month

MIT license

62KB
1.5K SLoC

testnet

Crates.io Version Docs dependency status

A library that helps you test your distributed applications using a virtual network via Linux namespaces.

Introduction

Certain distributed applications (VPNs, distributed key-value stores, blockchains etc.) require a pre-configured network to run on. Running on a loopback (127.0.0.0/8) is of course an option, but is it really enough? More often than not you need to synchronize parallel processes to verify that the system is in a valid expected state. Doing so over loopback network requires some sort of a middleware that runs on top. Testnet is such a middleware, and it also sets up a virtual network for you.

Testnet provides simple broadcast commands to synchronize parallel processes running on different network nodes and optionally share some data between all the nodes (e.g. the endpoints and ports that are used by the applications, public and private keys that are needed by the test etc.).

Examples

Hello world

use testnet::testnet;
use testnet::NetConfig;
let config = NetConfig {
    main: |context| {
        let i = context.current_node_index();
        let node = context.current_node();
        eprintln!("hello from node {} name {:?}", i, node.name);
        Ok(())
    },
    nodes: vec!["node1", "node2"],
};
// will print
// 
// hello from node 0 name "node1"
// hello from node 1 name "node2"
testnet(config).unwrap();

Ping between two nodes

use testnet::testnet;
use testnet::NetConfig;
use std::process::Command;
let config = NetConfig {
    main: |context| {
        let other = match context.current_node_name() {
            "node1" => "node2",
            "node2" => "node1",
            _ => unreachable!(),
        };
        Command::new("ping").args(["-c", "1", other]).status()?;
        Ok(())
    },
    nodes: vec!["node1", "node2"],
};
testnet(config).unwrap();

Docker

To run this inside Docker you need to allow clone(2) system call. The easiest way of doing this is to specify --security-opt seccomp=unconfined option on the Docker command line. Please, note that on Github runner you might need full-blown --privileged for this crate to work.

Dependencies

~6–16MB
~231K SLoC