From 286f863dc2679312a687fa59d9294c2257aa76eb Mon Sep 17 00:00:00 2001 From: michael1011 Date: Tue, 20 Aug 2024 16:27:30 +0200 Subject: [PATCH] test: add basic unit tests --- .github/workflows/ci.yml | 3 + src/database/model.rs | 118 +++++++++++++++++++-------------------- src/grpc/tls.rs | 94 +++++++++++++++++++++++++++++++ src/grpc/transformers.rs | 4 +- 4 files changed, 158 insertions(+), 61 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 907506b..29c2ddb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,3 +35,6 @@ jobs: - name: Clippy run: cargo clippy + + - name: Unit tests + run: cargo test diff --git a/src/database/model.rs b/src/database/model.rs index 99f2c2d..b1d09ff 100644 --- a/src/database/model.rs +++ b/src/database/model.rs @@ -3,6 +3,59 @@ use diesel::{AsChangeset, Associations, Identifiable, Insertable, Queryable, Sel use serde::Serialize; use std::fmt::{Display, Formatter}; +#[derive(Queryable, Identifiable, Selectable, AsChangeset, Serialize, Debug, PartialEq, Clone)] +#[diesel(table_name = crate::database::schema::invoices)] +pub struct Invoice { + pub id: i64, + pub payment_hash: Vec, + pub preimage: Option>, + pub bolt11: String, + pub state: String, + pub created_at: chrono::NaiveDateTime, +} + +#[derive(Insertable, Debug, PartialEq, Clone)] +#[diesel(table_name = crate::database::schema::invoices)] +pub struct InvoiceInsertable { + pub payment_hash: Vec, + pub bolt11: String, + pub state: String, +} + +#[derive( + Queryable, + Identifiable, + Selectable, + Associations, + Insertable, + AsChangeset, + Serialize, + Debug, + PartialEq, + Clone, +)] +#[diesel(belongs_to(Invoice))] +#[diesel(table_name = crate::database::schema::htlcs)] +pub struct Htlc { + pub id: i64, + pub invoice_id: i64, + pub state: String, + pub scid: String, + pub channel_id: i64, + pub msat: i64, + pub created_at: chrono::NaiveDateTime, +} + +#[derive(Insertable, Debug, PartialEq, Clone)] +#[diesel(table_name = crate::database::schema::htlcs)] +pub struct HtlcInsertable { + pub invoice_id: i64, + pub state: String, + pub scid: String, + pub channel_id: i64, + pub msat: i64, +} + #[derive(Debug, PartialEq, Clone, Copy)] pub enum InvoiceState { Paid = 0, @@ -17,12 +70,6 @@ impl Display for InvoiceState { } } -impl InvoiceState { - pub fn is_final(&self) -> bool { - *self == InvoiceState::Paid || *self == InvoiceState::Cancelled - } -} - impl From for String { fn from(value: InvoiceState) -> Self { match value { @@ -49,6 +96,12 @@ impl TryFrom<&str> for InvoiceState { } } +impl InvoiceState { + pub fn is_final(&self) -> bool { + *self == InvoiceState::Paid || *self == InvoiceState::Cancelled + } +} + #[derive(Serialize, Clone, Debug)] pub struct HoldInvoice { pub invoice: Invoice, @@ -78,56 +131,3 @@ impl HoldInvoice { .any(|htlc| htlc.scid == scid && htlc.channel_id == id as i64) } } - -#[derive(Queryable, Identifiable, Selectable, AsChangeset, Serialize, Debug, PartialEq, Clone)] -#[diesel(table_name = crate::database::schema::invoices)] -pub struct Invoice { - pub id: i64, - pub payment_hash: Vec, - pub preimage: Option>, - pub bolt11: String, - pub state: String, - pub created_at: chrono::NaiveDateTime, -} - -#[derive(Insertable, Debug, PartialEq, Clone)] -#[diesel(table_name = crate::database::schema::invoices)] -pub struct InvoiceInsertable { - pub payment_hash: Vec, - pub bolt11: String, - pub state: String, -} - -#[derive( - Queryable, - Identifiable, - Selectable, - Associations, - Insertable, - AsChangeset, - Serialize, - Debug, - PartialEq, - Clone, -)] -#[diesel(belongs_to(Invoice))] -#[diesel(table_name = crate::database::schema::htlcs)] -pub struct Htlc { - pub id: i64, - pub invoice_id: i64, - pub state: String, - pub scid: String, - pub channel_id: i64, - pub msat: i64, - pub created_at: chrono::NaiveDateTime, -} - -#[derive(Insertable, Debug, PartialEq, Clone)] -#[diesel(table_name = crate::database::schema::htlcs)] -pub struct HtlcInsertable { - pub invoice_id: i64, - pub state: String, - pub scid: String, - pub channel_id: i64, - pub msat: i64, -} diff --git a/src/grpc/tls.rs b/src/grpc/tls.rs index cd2b5d0..628e329 100644 --- a/src/grpc/tls.rs +++ b/src/grpc/tls.rs @@ -95,3 +95,97 @@ fn generate_certificate( Vec::from(cert.pem().as_bytes()), )) } + +#[cfg(test)] +mod test { + use crate::grpc::tls::{generate_certificate, generate_or_load_certificate, load_certificates}; + use rcgen::{CertificateParams, KeyPair}; + use std::fs; + use std::path::Path; + + #[test] + fn test_load_certificates() { + let certs_dir = "test-certs-all"; + assert_eq!(Path::new(certs_dir).exists(), false); + + let (_, cert) = load_certificates(certs_dir.into()).unwrap(); + assert_eq!(Path::new(certs_dir).exists(), true); + + for file in vec!["ca", "client", "server"] + .iter() + .flat_map(|entry| vec![format!("{}.pem", entry), format!("{}-key.pem", entry)]) + { + assert_eq!(Path::new(certs_dir).join(file).exists(), true); + } + + let (_, cert_loaded) = load_certificates(certs_dir.into()).unwrap(); + assert_eq!(cert.into_inner(), cert_loaded.into_inner()); + + fs::remove_dir_all(certs_dir).unwrap(); + } + + #[test] + fn test_generate_or_load_certificate() { + let certs_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("test-certs-load".to_string()); + fs::create_dir(certs_dir.clone()).unwrap(); + + let (created_key, created_cert) = + generate_or_load_certificate("test", Path::new(&certs_dir), "ca", None).unwrap(); + let (loaded_key, loaded_cert) = + generate_or_load_certificate("test", Path::new(&certs_dir), "ca", None).unwrap(); + + assert_eq!(created_key, loaded_key); + assert_eq!(created_cert, loaded_cert); + + fs::remove_dir_all(certs_dir).unwrap(); + } + + #[test] + fn test_generate_certificate_ca() { + let certs_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("test-certs1".to_string()); + fs::create_dir(certs_dir.clone()).unwrap(); + + let key_path = certs_dir.clone().join("key.pem"); + let cert_path = certs_dir.clone().join("cert.pem"); + let (key, cert) = + generate_certificate("test", key_path.clone(), cert_path.clone(), None).unwrap(); + + assert_eq!(key, fs::read(key_path).unwrap()); + assert_eq!(cert, fs::read(cert_path).unwrap()); + + fs::remove_dir_all(certs_dir).unwrap(); + } + + #[test] + fn test_generate_certificate() { + let certs_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("test-certs2".to_string()); + fs::create_dir(certs_dir.clone()).unwrap(); + + let (ca_key, ca_cert) = generate_certificate( + "test", + certs_dir.clone().join("ca-key.pem"), + certs_dir.clone().join("ca.pem"), + None, + ) + .unwrap(); + + let ca_keypair = KeyPair::from_pem(&String::from_utf8_lossy(&ca_key)).unwrap(); + let ca = ( + &ca_keypair, + &CertificateParams::from_ca_cert_pem(&String::from_utf8_lossy(&ca_cert.clone())) + .unwrap() + .self_signed(&ca_keypair) + .unwrap(), + ); + + let key_path = certs_dir.clone().join("client-key.pem"); + let cert_path = certs_dir.clone().join("client.pem"); + let (client_key, client_cert) = + generate_certificate("test", key_path.clone(), cert_path.clone(), Some(ca)).unwrap(); + + assert_eq!(client_key, fs::read(key_path).unwrap()); + assert_eq!(client_cert, fs::read(cert_path).unwrap()); + + fs::remove_dir_all(certs_dir).unwrap(); + } +} diff --git a/src/grpc/transformers.rs b/src/grpc/transformers.rs index f277712..23c06ec 100644 --- a/src/grpc/transformers.rs +++ b/src/grpc/transformers.rs @@ -20,9 +20,9 @@ impl From for hold::Invoice { fn from(value: HoldInvoice) -> Self { hold::Invoice { id: value.invoice.id, - payment_hash: vec![], - preimage: value.invoice.preimage, bolt11: value.invoice.bolt11, + preimage: value.invoice.preimage, + payment_hash: value.invoice.payment_hash, state: transform_invoice_state( InvoiceState::try_from(value.invoice.state.as_str()).unwrap(), ),