Skip to content

Commit

Permalink
feat(tests): introducing tests framework
Browse files Browse the repository at this point in the history
Signed-off-by: Vincenzo Palazzo <[email protected]>
  • Loading branch information
vincenzopalazzo committed Jun 21, 2023
1 parent 48dd734 commit 89b28f1
Show file tree
Hide file tree
Showing 17 changed files with 1,153 additions and 58 deletions.
649 changes: 612 additions & 37 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ members = [
"coffee_cmd",
"coffee_httpd",
"coffee_plugin",
"coffee_testing",
]
resolver = "2"
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CC=cargo
FMT=fmt

OPTIONS=
ARGS="--all"

default: fmt
$(CC) build
Expand All @@ -14,7 +14,7 @@ fmt:
$(CC) fmt --all

check:
$(CC) test --all
$(CC) test $(ARGS)

example:
@echo "No example for the moment"
Expand All @@ -30,3 +30,6 @@ dev-book:

install:
$(CC) install --locked --path ./coffee_cmd

integration:
cd tests; $(CC) test $(ARGS)
2 changes: 1 addition & 1 deletion coffee_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ coffee_storage = { path = "../coffee_storage" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
clightningrpc-conf = "0.0.3"
clightningrpc-common = "0.3.0-beta.3"
clightningrpc-common = "0.3.0-beta.4"
9 changes: 4 additions & 5 deletions coffee_core/src/coffee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ impl PluginManager for CoffeeManager {
if let Some(mut plugin) = repo.get_plugin_by_name(plugin) {
log::trace!("{:#?}", plugin);
let result = plugin.configure(verbose).await;
log::debug!("result from plugin configure: {:?}", result);
match result {
Ok(path) => {
log::debug!("runnable plugin path {path}");
Expand All @@ -238,11 +239,9 @@ impl PluginManager for CoffeeManager {
}
}
}
let err = CoffeeError::new(
1,
&format!("plugin `{plugin}` are not present inside the repositories"),
);
Err(err)
Err(error!(
"plugin `{plugin}` are not present inside the repositories"
))
}

async fn remove(&mut self, plugin: &str) -> Result<CoffeeRemove, CoffeeError> {
Expand Down
14 changes: 14 additions & 0 deletions coffee_lib/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ impl CoffeeError {
}
}

impl std::error::Error for CoffeeError {
fn cause(&self) -> Option<&dyn std::error::Error> {
Some(self)
}

fn description(&self) -> &str {
&self.msg
}

fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(self)
}
}

impl fmt::Display for CoffeeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "code: {}, msg: {}", self.code, self.msg)
Expand Down
9 changes: 5 additions & 4 deletions coffee_lib/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ macro_rules! sh {
};

if !command.status.success() {
return Err(CoffeeError::new(
2,
&String::from_utf8(command.stderr).unwrap(),
));
let mut content = String::from_utf8(command.stderr).unwrap();
if content.trim().is_empty() {
content = String::from_utf8(command.stdout).unwrap();
}
return Err(CoffeeError::new(2, &content));
}
}
};
Expand Down
16 changes: 8 additions & 8 deletions coffee_lib/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,46 @@ use serde::{Deserialize, Serialize};

use crate::plugin::Plugin;

#[derive(Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct CoffeeRemove {
pub plugin: Plugin,
}

#[derive(Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct CoffeeList {
pub plugins: Vec<Plugin>,
}

#[derive(Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct CoffeeRemote {
pub remotes: Option<Vec<CoffeeListRemote>>,
}

#[derive(Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct CoffeeListRemote {
pub local_name: String,
pub url: String,
pub plugins: Vec<Plugin>,
}

#[derive(Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub enum NurseStatus {
Corrupted,
Sane,
}

#[derive(Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct CoffeeNurse {
pub status: NurseStatus,
}

#[derive(Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub enum UpgradeStatus {
UpToDate,
Updated,
}

#[derive(Serialize, Deserialize)]
#[derive(Debug, Serialize, Deserialize)]
pub struct CoffeeUpgrade {
pub repo: String,
pub status: UpgradeStatus,
Expand Down
2 changes: 1 addition & 1 deletion coffee_plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ edition = "2021"
[dependencies]
tokio = { version = "1.22.0", features = ["rt"] }
clightningrpc-common = "0.3.0-beta.3"
clightningrpc-plugin = "0.3.0-beta.7"
clightningrpc-plugin = "0.3.0-beta.8"
coffee_core = { path = "../coffee_core" }
serde_json = "1"
16 changes: 16 additions & 0 deletions coffee_testing/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "coffee_testing"
version = "0.1.0"
edition = "2021"

[dependencies]
clightningrpc = "0.3.0-beta.6"
bitcoincore-rpc = "0.17.0"
log = "0.4.19"
cln-test = { git = "https://github.com/laanwj/cln4rust.git", branch = "macros/test-framework" }
cln-btc-test = { git = "https://github.com/laanwj/cln4rust.git", branch = "macros/test-framework" }
coffee_core = { path = "../coffee_core" }
tempfile = "3.6.0"
port-selector = "0.1.6"
anyhow = "1.0.71"
tokio = { version = "1.22.0", features = ["process", "time"] }
103 changes: 103 additions & 0 deletions coffee_testing/src/btc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//! Bitcoin Testing framework.
use bitcoincore_rpc::{Auth, Client, RpcApi};
use port::Port;
use port_selector as port;
use tempfile::TempDir;

pub mod macros {
#[macro_export]
macro_rules! bitcoind {
($dir:expr, $port:expr, $opt_args:expr) => {
async {
use std::process::Stdio;

use log;
use tokio::process::Command;

let opt_args = format!($opt_args);
let args = opt_args.trim();
let args_tok: Vec<&str> = args.split(" ").collect();
log::debug!("additional args: {:?}", args_tok);
let mut command = Command::new("bitcoind");
command
.args(&args_tok)
.arg(format!("-port={}", $port + 1))
.arg(format!("-rpcport={}", $port))
.arg(format!("-datadir={}", $dir.path().to_str().unwrap()))
.stdout(Stdio::null())
.spawn()
}
.await
};
($dir:expr, $port:expr) => {
$crate::bitcoind!($dir, $port, "")
};
}

pub use bitcoind;
}

pub struct BtcNode {
inner: Client,
pub user: String,
pub pass: String,
pub port: Port,
root_path: TempDir,
process: Vec<tokio::process::Child>,
}

impl Drop for BtcNode {
fn drop(&mut self) {
for process in self.process.iter() {
let child = process.id().unwrap();
let mut kill = std::process::Command::new("kill")
.args(["-s", "SIGKILL", &child.to_string()])
.spawn()
.unwrap();
kill.wait().unwrap();
}
std::fs::remove_dir_all(self.root_path.path()).unwrap();
}
}

impl BtcNode {
pub async fn tmp() -> anyhow::Result<Self> {
let dir = tempfile::tempdir()?;
let user = "crab".to_owned();
let pass = "crab".to_owned();
let port = port::random_free_port().unwrap();
let process = macros::bitcoind!(
dir,
port,
"-server -regtest -rpcuser={user} -rpcpassword={pass}"
)?;
let rpc = Client::new(
&format!("http://localhost:{port}"),
Auth::UserPass(user.clone(), pass.clone()),
)?;
let bg_process = vec![process];
Ok(Self {
inner: rpc,
root_path: dir,
user,
pass,
port,
process: bg_process,
})
}

pub fn rpc(&self) -> &Client {
&self.inner
}

pub async fn stop(&mut self) -> anyhow::Result<()> {
log::info!("stop bitcoin node");
self.inner.stop()?;
for process in self.process.iter_mut() {
process.kill().await?;
let _ = process.wait().await?;
log::debug!("process killed");
}
Ok(())
}
}
106 changes: 106 additions & 0 deletions coffee_testing/src/cln.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//! Integration testing library for core lightning
use clightningrpc::LightningRPC;
use port_selector as port;
use tempfile::TempDir;

use crate::btc::BtcNode;
use crate::prelude::*;

pub mod macros {
#[macro_export]
macro_rules! lightningd {
($dir:expr, $port:expr, $($opt_args:tt)*) => {
async {
use std::process::Stdio;

use tokio::process::Command;

let opt_args = format!($($opt_args)*);
let args = opt_args.trim();
let args_tok: Vec<&str> = args.split(" ").collect();

let mut command = Command::new("lightningd");
command
.args(&args_tok)
.arg(format!("--addr=127.0.0.1:{}", $port))
.arg(format!("--bind-addr=127.0.0.1:{}", $port))
.arg(format!("--lightning-dir={}", $dir.path().to_str().unwrap()))
.arg("--dev-fast-gossip")
.arg("--funding-confirms=1")
.stdout(Stdio::null())
.spawn()
}.await
};
($dir:expr, $port:expr) => {
$crate::lightningd!($dir, $port, "")
};
}

pub use lightningd;
}

pub struct Node {
inner: LightningRPC,
root_path: TempDir,
bitcoin: BtcNode,
process: Vec<tokio::process::Child>,
}

impl Drop for Node {
fn drop(&mut self) {
for process in self.process.iter() {
let child = process.id().unwrap();
let mut kill = std::process::Command::new("kill")
.args(["-s", "SIGKILL", &child.to_string()])
.spawn()
.unwrap();
kill.wait().unwrap();
}

std::fs::remove_dir_all(self.root_path.path()).unwrap();
}
}

impl Node {
pub async fn tmp() -> anyhow::Result<Self> {
let btc = BtcNode::tmp().await?;

let dir = tempfile::tempdir()?;
let process = macros::lightningd!(
dir,
port::random_free_port().unwrap(),
"--network=regtest --bitcoin-rpcuser={} --bitcoin-rpcpassword={} --bitcoin-rpcport={}",
btc.user,
btc.pass,
btc.port,
)?;

let rpc = LightningRPC::new(dir.path().join("regtest").join("lightning-rpc"));

wait_for!(async { rpc.getinfo() });

Ok(Self {
inner: rpc,
root_path: dir,
bitcoin: btc,
process: vec![process],
})
}

pub fn rpc(&self) -> &LightningRPC {
&self.inner
}

pub async fn stop(&mut self) -> anyhow::Result<()> {
log::info!("stop lightning node");
self.inner.stop()?;
for process in self.process.iter_mut() {
process.kill().await?;
let _ = process.wait().await?;
log::debug!("killing process");
}
self.bitcoin.stop().await?;
Ok(())
}
}
Loading

0 comments on commit 89b28f1

Please sign in to comment.