From 6657adae5d2664abb63602a70a5b5e46492dcb00 Mon Sep 17 00:00:00 2001 From: librelois <c@elo.tf> Date: Wed, 2 Dec 2020 01:25:03 +0100 Subject: [PATCH] [tests] mock db read ops & test some gva queries --- Cargo.lock | 29 ++++++- Cargo.toml | 1 + rust-libs/duniter-dbs-read-ops/src/lib.rs | 47 +++++++++--- rust-libs/duniter-dbs-write-ops/Cargo.toml | 1 + .../duniter-dbs-write-ops/src/apply_block.rs | 8 +- rust-libs/duniter-dbs-write-ops/src/lib.rs | 6 +- rust-libs/duniter-dbs/src/lib.rs | 21 +++--- rust-libs/duniter-dbs/src/open_dbs.rs | 18 ++--- rust-libs/duniter-module/src/lib.rs | 10 +-- rust-libs/duniter-server/Cargo.toml | 3 - rust-libs/duniter-server/src/lib.rs | 56 ++------------ rust-libs/modules/duniter-gva/Cargo.toml | 2 + rust-libs/modules/duniter-gva/src/lib.rs | 71 +++++++++++++++++- .../src/queries/account_balance.rs | 47 ++++++++++-- .../modules/duniter-gva/src/queries/gen_tx.rs | 10 +-- .../modules/duniter-gva/src/queries/uds.rs | 36 ++++++++- .../modules/duniter-gva/src/queries/utxos.rs | 5 +- rust-libs/modules/duniter-gva/src/schema.rs | 16 +++- .../duniter-integration-tests/Cargo.toml | 24 ++++++ .../duniter-integration-tests/src/lib.rs | 75 +++++++++++++++++++ 20 files changed, 359 insertions(+), 127 deletions(-) create mode 100644 rust-libs/tests/duniter-integration-tests/Cargo.toml create mode 100644 rust-libs/tests/duniter-integration-tests/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 38a5c45f3..7da721dbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1147,14 +1147,38 @@ dependencies = [ "futures", "http", "log", + "mockall", "resiter", "serde", + "serde_json", "serde_urlencoded 0.7.0", "tokio", "unwrap", "warp", ] +[[package]] +name = "duniter-integration-tests" +version = "0.1.0" +dependencies = [ + "anyhow", + "dubp", + "duniter-conf", + "duniter-dbs", + "duniter-dbs-read-ops", + "duniter-dbs-write-ops", + "duniter-gva", + "duniter-mempools", + "duniter-module", + "duniter-server", + "fast-threadpool", + "flume", + "log", + "paste", + "resiter", + "tokio", +] + [[package]] name = "duniter-launcher" version = "1.8.1" @@ -1218,7 +1242,6 @@ dependencies = [ "paste", "resiter", "tokio", - "unwrap", ] [[package]] @@ -2420,9 +2443,9 @@ checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693" [[package]] name = "once_cell" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" [[package]] name = "oorandom" diff --git a/Cargo.toml b/Cargo.toml index c671f85a1..09974e444 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,7 @@ members = [ "rust-libs/duniter-module", "rust-libs/duniter-server", "rust-libs/modules/duniter-gva", + "rust-libs/tests/duniter-integration-tests", "rust-libs/tools/kv_typed" ] diff --git a/rust-libs/duniter-dbs-read-ops/src/lib.rs b/rust-libs/duniter-dbs-read-ops/src/lib.rs index 45d94cb20..26ca21089 100644 --- a/rust-libs/duniter-dbs-read-ops/src/lib.rs +++ b/rust-libs/duniter-dbs-read-ops/src/lib.rs @@ -34,25 +34,50 @@ use crate::pagination::{has_next_page, has_previous_page}; use dubp::common::crypto::hashs::Hash; use dubp::common::crypto::keys::ed25519::PublicKey; use dubp::documents::transaction::TransactionDocumentV10; -use dubp::{common::prelude::BlockNumber, wallet::prelude::SourceAmount}; +use dubp::{common::prelude::BlockNumber, wallet::prelude::*}; use duniter_dbs::bc_v2::BcV2DbReadable; use duniter_dbs::{ - kv_typed::prelude::*, BlockMetaV2, GvaV1DbReadable, HashKeyV2, PubKeyKeyV2, TxDbV2, - TxsMpV2DbReadable, UtxoIdDbV2, + kv_typed::prelude::*, BlockMetaV2, GvaV1DbReadable, HashKeyV2, PubKeyKeyV2, SourceAmountValV2, + TxDbV2, TxsMpV2DbReadable, UtxoIdDbV2, }; use resiter::filter::Filter; use resiter::filter_map::FilterMap; use resiter::map::Map; use std::collections::BTreeSet; -pub fn get_current_block_meta<BcDb: BcV2DbReadable>(bc_db: &BcDb) -> KvResult<Option<BlockMetaV2>> { - bc_db - .blocks_meta() - .iter(.., |it| it.reverse().values().next_res()) +#[derive(Clone, Copy, Debug)] +pub struct DbsReader; + +pub fn create_dbs_reader() -> DbsReader { + DbsReader } -pub fn get_current_ud<BcDb: BcV2DbReadable>(bc_db: &BcDb) -> KvResult<Option<SourceAmount>> { - bc_db - .uds_reval() - .iter(.., |it| it.reverse().values().map_ok(|v| v.0).next_res()) +impl DbsReader { + pub fn get_account_balance<GvaDb: GvaV1DbReadable>( + &self, + gva_db: &GvaDb, + account_script: &WalletScriptV10, + ) -> KvResult<Option<SourceAmountValV2>> { + gva_db + .balances() + .get(duniter_dbs::WalletConditionsV2::from_ref(account_script)) + } + + pub fn get_current_block_meta<BcDb: BcV2DbReadable>( + &self, + bc_db: &BcDb, + ) -> KvResult<Option<BlockMetaV2>> { + bc_db + .blocks_meta() + .iter(.., |it| it.reverse().values().next_res()) + } + + pub fn get_current_ud<BcDb: BcV2DbReadable>( + &self, + bc_db: &BcDb, + ) -> KvResult<Option<SourceAmount>> { + bc_db + .uds_reval() + .iter(.., |it| it.reverse().values().map_ok(|v| v.0).next_res()) + } } diff --git a/rust-libs/duniter-dbs-write-ops/Cargo.toml b/rust-libs/duniter-dbs-write-ops/Cargo.toml index acc4a8ffd..f2eba28e3 100644 --- a/rust-libs/duniter-dbs-write-ops/Cargo.toml +++ b/rust-libs/duniter-dbs-write-ops/Cargo.toml @@ -21,6 +21,7 @@ resiter = "0.4.0" [dev-dependencies] anyhow = "1.0.34" +duniter-dbs = { path = "../duniter-dbs", features = ["mem"] } serde_json = "1.0.53" [features] diff --git a/rust-libs/duniter-dbs-write-ops/src/apply_block.rs b/rust-libs/duniter-dbs-write-ops/src/apply_block.rs index 9e78303c8..fea9f164b 100644 --- a/rust-libs/duniter-dbs-write-ops/src/apply_block.rs +++ b/rust-libs/duniter-dbs-write-ops/src/apply_block.rs @@ -18,7 +18,7 @@ use crate::*; pub fn apply_block( block: DubpBlockV10, current_opt: Option<BlockMetaV2>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, gva: bool, throw_chainability: bool, ) -> KvResult<BlockMetaV2> { @@ -49,7 +49,7 @@ pub fn apply_block( #[inline(always)] pub fn apply_chunk( current_opt: Option<BlockMetaV2>, - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, blocks: Vec<DubpBlockV10>, gva: bool, ) -> KvResult<BlockMetaV2> { @@ -102,7 +102,7 @@ fn verify_chunk_chainability( } fn apply_block_inner( - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, block: Arc<DubpBlockV10>, gva: bool, ) -> KvResult<BlockMetaV2> { @@ -134,7 +134,7 @@ fn apply_block_inner( } fn apply_chunk_inner( - dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs>, + dbs_pool: &fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, blocks: Arc<Vec<DubpBlockV10>>, gva: bool, ) -> KvResult<BlockMetaV2> { diff --git a/rust-libs/duniter-dbs-write-ops/src/lib.rs b/rust-libs/duniter-dbs-write-ops/src/lib.rs index d9d74a921..58a0a1066 100644 --- a/rust-libs/duniter-dbs-write-ops/src/lib.rs +++ b/rust-libs/duniter-dbs-write-ops/src/lib.rs @@ -39,9 +39,9 @@ use dubp::documents::{ use dubp::wallet::prelude::*; use duniter_dbs::gva_v1::{TxsByIssuerEvent, TxsByRecipientEvent, TxsEvent}; use duniter_dbs::{ - kv_typed::prelude::*, BlockMetaV2, DuniterDbs, GvaV1Db, GvaV1DbReadable, GvaV1DbWritable, - HashKeyV2, PendingTxDbV2, PubKeyKeyV2, PubKeyValV2, SourceAmountValV2, TxDbV2, TxsMpV2Db, - TxsMpV2DbReadable, TxsMpV2DbWritable, UtxoValV2, WalletConditionsV2, + kv_typed::prelude::*, BlockMetaV2, DuniterDbs, FileBackend, GvaV1Db, GvaV1DbReadable, + GvaV1DbWritable, HashKeyV2, PendingTxDbV2, PubKeyKeyV2, PubKeyValV2, SourceAmountValV2, TxDbV2, + TxsMpV2Db, TxsMpV2DbReadable, TxsMpV2DbWritable, UtxoValV2, WalletConditionsV2, }; use resiter::filter::Filter; use resiter::filter_map::FilterMap; diff --git a/rust-libs/duniter-dbs/src/lib.rs b/rust-libs/duniter-dbs/src/lib.rs index 862425f5c..550b9d63c 100644 --- a/rust-libs/duniter-dbs/src/lib.rs +++ b/rust-libs/duniter-dbs/src/lib.rs @@ -44,7 +44,7 @@ pub use kv_typed; // Prelude pub mod prelude { - pub use crate::{DbsBackend, DuniterDbs}; + pub use crate::DuniterDbs; #[cfg(feature = "explorer")] pub use kv_typed::explorer::{ DbExplorable, EntryFound, ExplorerAction, ExplorerActionResponse, ValueCaptures, @@ -114,21 +114,20 @@ pub trait ToDumpString { fn to_dump_string(&self) -> String; } -#[cfg(feature = "mem")] -pub type DbsBackend = kv_typed::backend::memory::Mem; -#[cfg(not(feature = "mem"))] -pub type DbsBackend = Sled; +#[cfg(all(not(feature = "mem"), not(test)))] +pub type FileBackend = kv_typed::backend::sled::Sled; +#[cfg(any(feature = "mem", test))] +pub type FileBackend = kv_typed::backend::memory::Mem; #[derive(Clone, Debug)] -pub struct DuniterDbs { - pub bc_db: bc_v2::BcV2Db<DbsBackend>, +pub struct DuniterDbs<B: Backend> { + pub bc_db: bc_v2::BcV2Db<B>, pub cm_db: cm_v1::CmV1Db<MemSingleton>, - pub gva_db: GvaV1Db<DbsBackend>, - pub txs_mp_db: TxsMpV2Db<DbsBackend>, + pub gva_db: GvaV1Db<B>, + pub txs_mp_db: TxsMpV2Db<B>, } -#[cfg(feature = "mem")] -impl DuniterDbs { +impl DuniterDbs<Mem> { pub fn mem() -> KvResult<Self> { use bc_v2::BcV2DbWritable as _; use cm_v1::CmV1DbWritable as _; diff --git a/rust-libs/duniter-dbs/src/open_dbs.rs b/rust-libs/duniter-dbs/src/open_dbs.rs index 0f99368b5..8a01ae550 100644 --- a/rust-libs/duniter-dbs/src/open_dbs.rs +++ b/rust-libs/duniter-dbs/src/open_dbs.rs @@ -17,22 +17,16 @@ use crate::bc_v2::BcV2DbWritable as _; use crate::cm_v1::CmV1DbWritable as _; use crate::*; -pub fn open_dbs(home_path_opt: Option<&Path>) -> DuniterDbs { +pub fn open_dbs<B: BackendConf>(home_path_opt: Option<&Path>) -> DuniterDbs<B> { DuniterDbs { - bc_db: crate::bc_v2::BcV2Db::<DbsBackend>::open(DbsBackend::gen_backend_conf( - "bc_v2", - home_path_opt, - )) - .expect("fail to open BcV2 DB"), + bc_db: crate::bc_v2::BcV2Db::<B>::open(B::gen_backend_conf("bc_v2", home_path_opt)) + .expect("fail to open BcV2 DB"), cm_db: crate::cm_v1::CmV1Db::<MemSingleton>::open(MemSingletonConf::default()) .expect("fail to open CmV1 DB"), - gva_db: GvaV1Db::<DbsBackend>::open(DbsBackend::gen_backend_conf("gva_v1", home_path_opt)) + gva_db: GvaV1Db::<B>::open(B::gen_backend_conf("gva_v1", home_path_opt)) .expect("fail to open Gva DB"), - txs_mp_db: TxsMpV2Db::<DbsBackend>::open(DbsBackend::gen_backend_conf( - "txs_mp_v2", - home_path_opt, - )) - .expect("fail to open TxsMp DB"), + txs_mp_db: TxsMpV2Db::<B>::open(B::gen_backend_conf("txs_mp_v2", home_path_opt)) + .expect("fail to open TxsMp DB"), } } diff --git a/rust-libs/duniter-module/src/lib.rs b/rust-libs/duniter-module/src/lib.rs index 28f49c53b..d9e3d1ca4 100644 --- a/rust-libs/duniter-module/src/lib.rs +++ b/rust-libs/duniter-module/src/lib.rs @@ -23,7 +23,7 @@ )] use duniter_conf::DuniterConf; -use duniter_dbs::DuniterDbs; +use duniter_dbs::{DuniterDbs, FileBackend}; use duniter_mempools::Mempools; use std::path::Path; @@ -34,7 +34,7 @@ pub trait DuniterModule: 'static + Sized { fn init( conf: &DuniterConf, currency: &str, - dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, + dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, mempools: Mempools, profile_path_opt: Option<&Path>, software_version: &'static str, @@ -51,7 +51,7 @@ macro_rules! plug_duniter_modules { async fn start_duniter_modules( conf: &DuniterConf, currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, + dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, mempools: duniter_mempools::Mempools, profile_path_opt: Option<std::path::PathBuf>, software_version: &'static str, @@ -105,7 +105,7 @@ mod tests { fn init( _conf: &DuniterConf, _currency: &str, - _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, + _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, _mempools: Mempools, profile_path_opt: Option<&Path>, _software_version: &'static str, @@ -128,7 +128,7 @@ mod tests { fn init( _conf: &DuniterConf, _currency: &str, - _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, + _dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, _mempools: Mempools, _profile_path_opt: Option<&Path>, _software_version: &'static str, diff --git a/rust-libs/duniter-server/Cargo.toml b/rust-libs/duniter-server/Cargo.toml index 770ec868b..0818892ff 100644 --- a/rust-libs/duniter-server/Cargo.toml +++ b/rust-libs/duniter-server/Cargo.toml @@ -21,6 +21,3 @@ log = "0.4.11" paste = "1.0.2" resiter = "0.4.0" tokio = { version = "0.2.22", features = ["io-util", "rt-threaded"] } - -[dev-dependencies] -unwrap = "1.2.1" diff --git a/rust-libs/duniter-server/src/lib.rs b/rust-libs/duniter-server/src/lib.rs index c1cf343d7..85e5e525d 100644 --- a/rust-libs/duniter-server/src/lib.rs +++ b/rust-libs/duniter-server/src/lib.rs @@ -37,7 +37,7 @@ use duniter_dbs::cm_v1::{CmV1DbReadable, CmV1DbWritable}; use duniter_dbs::{ kv_typed::prelude::*, GvaV1DbReadable, HashKeyV2, PendingTxDbV2, TxsMpV2DbReadable, }; -use duniter_dbs::{prelude::*, BlockMetaV2}; +use duniter_dbs::{prelude::*, BlockMetaV2, FileBackend}; use duniter_dbs_read_ops::txs_history::TxsHistory; use duniter_mempools::{Mempools, TxMpError, TxsMempool}; use duniter_module::{plug_duniter_modules, DuniterModule as _, Endpoint}; @@ -54,7 +54,7 @@ pub enum DuniterCommand { pub struct DuniterServer { conf: DuniterConf, current: Option<BlockMetaV2>, - dbs_pool: fast_threadpool::ThreadPoolSyncHandler<DuniterDbs>, + dbs_pool: fast_threadpool::ThreadPoolSyncHandler<DuniterDbs<FileBackend>>, pending_txs_subscriber: flume::Receiver<Arc<Events<duniter_dbs::txs_mp_v2::TxsEvent>>>, txs_mempool: TxsMempool, } @@ -74,12 +74,14 @@ impl DuniterServer { _ => DuniterCommand::Start, }; + let dbs_reader = duniter_dbs_read_ops::create_dbs_reader(); let txs_mempool = TxsMempool::new(conf.txs_mempool_size); log::info!("open duniter databases..."); let dbs = duniter_dbs::open_dbs(home_path_opt); log::info!("Databases successfully opened."); - let current = duniter_dbs_read_ops::get_current_block_meta(&dbs.bc_db) + let current = dbs_reader + .get_current_block_meta(&dbs.bc_db) .context("Fail to get current")?; if let Some(current) = current { log::info!("Current block: #{}-{}", current.number, current.hash); @@ -333,51 +335,3 @@ impl DuniterServer { .expect("dbs pool disconnected") } } - -#[cfg(test)] -mod tests { - use super::*; - use dubp::documents::transaction::TransactionDocumentV10Builder; - use dubp::{crypto::keys::ed25519::Ed25519KeyPair, documents::smallvec::smallvec}; - - #[test] - fn test_txs_history() -> anyhow::Result<()> { - let server = DuniterServer::start( - None, - DuniterConf { - gva: None, - self_key_pair: Ed25519KeyPair::generate_random() - .expect("fail to gen random keypair"), - txs_mempool_size: 200, - }, - "currency_test".to_owned(), - None, - "test", - )?; - - let tx = TransactionDocumentV10Builder { - currency: "duniter_unit_test_currency", - blockstamp: Blockstamp::default(), - locktime: 0, - issuers: smallvec![PublicKey::default()], - inputs: &[], - unlocks: &[], - outputs: smallvec![], - comment: "test", - hash: None, - } - .build_with_signature(smallvec![]); - server.add_pending_tx_force(tx.clone())?; - - let txs_history = server.get_transactions_history(PublicKey::default())?; - - tx.get_hash(); - assert_eq!(txs_history.sending, vec![tx]); - - server.remove_all_pending_txs()?; - - assert_eq!(server.get_pending_txs(0, 0)?.len(), 0); - - Ok(()) - } -} diff --git a/rust-libs/modules/duniter-gva/Cargo.toml b/rust-libs/modules/duniter-gva/Cargo.toml index 0c0ee93ab..b918aae35 100644 --- a/rust-libs/modules/duniter-gva/Cargo.toml +++ b/rust-libs/modules/duniter-gva/Cargo.toml @@ -29,5 +29,7 @@ warp = "0.2" [dev-dependencies] duniter-dbs = { path = "../../duniter-dbs", features = ["mem"] } +mockall = "0.8.0" +serde_json = "1.0.53" tokio = { version = "0.2.22", features = ["macros", "rt-threaded"] } unwrap = "1.2.1" diff --git a/rust-libs/modules/duniter-gva/src/lib.rs b/rust-libs/modules/duniter-gva/src/lib.rs index 24b282bfc..82756eeed 100644 --- a/rust-libs/modules/duniter-gva/src/lib.rs +++ b/rust-libs/modules/duniter-gva/src/lib.rs @@ -43,6 +43,10 @@ use crate::inputs::{TxIssuer, TxRecipient, UdsFilter}; use crate::inputs_validators::TxCommentValidator; use crate::pagination::{PaginationWithIntCursor, PaginationWithStrCursor}; use crate::schema::{GraphQlSchema, SchemaData}; +#[cfg(test)] +use crate::tests::create_dbs_reader; +#[cfg(test)] +use crate::tests::DbsReader; use async_graphql::http::GraphQLPlaygroundConfig; use async_graphql::validators::{IntGreaterThan, ListMinLength, StringMaxLength, StringMinLength}; use dubp::common::crypto::keys::{ed25519::PublicKey, KeyPair as _, PublicKey as _}; @@ -52,7 +56,11 @@ use dubp::documents::transaction::{TransactionDocumentTrait, TransactionDocument use dubp::documents_parser::prelude::*; use dubp::wallet::prelude::*; use duniter_dbs::prelude::*; -use duniter_dbs::{kv_typed::prelude::*, TxDbV2, TxsMpV2DbReadable}; +use duniter_dbs::{kv_typed::prelude::*, FileBackend, TxDbV2, TxsMpV2DbReadable}; +#[cfg(not(test))] +use duniter_dbs_read_ops::create_dbs_reader; +#[cfg(not(test))] +use duniter_dbs_read_ops::DbsReader; use duniter_mempools::{Mempools, TxsMempool}; use futures::{StreamExt, TryStreamExt}; use resiter::map::Map; @@ -66,7 +74,7 @@ use warp::{http::Response as HttpResponse, Filter as _, Rejection, Stream}; pub struct GvaModule { conf: Option<GvaConf>, currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, + dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, mempools: Mempools, self_pubkey: PublicKey, software_version: &'static str, @@ -77,7 +85,7 @@ impl duniter_module::DuniterModule for GvaModule { fn init( conf: &duniter_conf::DuniterConf, currency: &str, - dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, + dbs_pool: &fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, mempools: Mempools, _profile_path_opt: Option<&std::path::Path>, software_version: &'static str, @@ -150,7 +158,7 @@ impl GvaModule { async fn start_inner( conf: GvaConf, currency: String, - dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, + dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, mempools: Mempools, self_pubkey: PublicKey, software_version: &'static str, @@ -163,6 +171,7 @@ impl GvaModule { ) .data(schema::SchemaData { dbs_pool, + dbs_reader: create_dbs_reader(), server_meta_data: ServerMetaData { currency, self_pubkey, @@ -278,11 +287,65 @@ impl From<duniter_dbs::PeerCardDbV1> for PeerCardStringified { mod tests { use super::*; use duniter_conf::DuniterConf; + use duniter_dbs::bc_v2::BcV2DbReadable; + use duniter_dbs::gva_v1::GvaV1DbReadable; + use duniter_dbs::{BlockMetaV2, SourceAmountValV2}; use duniter_mempools::Mempools; use duniter_module::DuniterModule; use fast_threadpool::ThreadPoolConfig; use unwrap::unwrap; + mockall::mock! { + pub DbsReader { + fn get_account_balance<GvaDb: 'static + GvaV1DbReadable>( + &self, + gva_db: &GvaDb, + account_script: &WalletScriptV10, + ) -> KvResult<Option<SourceAmountValV2>>; + fn get_current_block_meta<BcDb: 'static + BcV2DbReadable>( + &self, + bc_db: &BcDb, + ) -> KvResult<Option<BlockMetaV2>>; + fn get_current_ud<BcDb: 'static + BcV2DbReadable>( + &self, + bc_db: &BcDb, + ) -> KvResult<Option<SourceAmount>>; + } + } + pub type DbsReader = duniter_dbs::kv_typed::prelude::Arc<MockDbsReader>; + pub fn create_dbs_reader() -> DbsReader { + Arc::new(MockDbsReader::new()) + } + + pub(crate) fn create_schema(dbs_ops: MockDbsReader) -> KvResult<GraphQlSchema> { + let dbs = DuniterDbs::mem()?; + let threadpool = fast_threadpool::ThreadPool::start(ThreadPoolConfig::default(), dbs); + Ok(async_graphql::Schema::build( + queries::QueryRoot::default(), + mutations::MutationRoot::default(), + subscriptions::SubscriptionRoot::default(), + ) + .data(schema::SchemaData { + dbs_pool: threadpool.into_async_handler(), + dbs_reader: Arc::new(dbs_ops), + server_meta_data: ServerMetaData { + currency: "test_currency".to_owned(), + self_pubkey: PublicKey::default(), + software_version: "test", + }, + txs_mempool: TxsMempool::new(10), + }) + .extension(async_graphql::extensions::Logger) + .finish()) + } + + pub(crate) async fn exec_graphql_request( + schema: &GraphQlSchema, + request: &str, + ) -> anyhow::Result<serde_json::Value> { + Ok(serde_json::to_value(schema.execute(request).await)?) + } + #[tokio::test] #[ignore] async fn launch_mem_gva() -> anyhow::Result<()> { diff --git a/rust-libs/modules/duniter-gva/src/queries/account_balance.rs b/rust-libs/modules/duniter-gva/src/queries/account_balance.rs index 5afc02a5a..d8814d6af 100644 --- a/rust-libs/modules/duniter-gva/src/queries/account_balance.rs +++ b/rust-libs/modules/duniter-gva/src/queries/account_balance.rs @@ -14,7 +14,6 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. use crate::*; -use duniter_dbs::{GvaV1DbReadable, WalletConditionsV2}; #[derive(Default)] pub(crate) struct AccountBalanceQuery; @@ -33,14 +32,11 @@ impl AccountBalanceQuery { }; let data = ctx.data::<SchemaData>()?; + let dbs_reader = data.dbs_reader(); let balance = data .dbs_pool - .execute(move |dbs| { - dbs.gva_db - .balances() - .get(&WalletConditionsV2(account_script)) - }) + .execute(move |dbs| dbs_reader.get_account_balance(&dbs.gva_db, &account_script)) .await?? .unwrap_or_default() .0; @@ -51,3 +47,42 @@ impl AccountBalanceQuery { }) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::*; + use duniter_dbs::SourceAmountValV2; + + #[tokio::test] + async fn query_balance() -> anyhow::Result<()> { + let mut dbs_reader = MockDbsReader::new(); + use duniter_dbs::gva_v1::GvaV1Db; + dbs_reader + .expect_get_account_balance::<GvaV1Db<FileBackend>>() + .withf(|_, s| { + s == &WalletScriptV10::single_sig( + PublicKey::from_base58("DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP") + .expect("wrong pubkey"), + ) + }) + .times(1) + .returning(|_, _| Ok(Some(SourceAmountValV2(SourceAmount::with_base0(38))))); + let schema = create_schema(dbs_reader)?; + assert_eq!( + exec_graphql_request( + &schema, + r#"{ balance(script: "DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP") {amount} }"# + ) + .await?, + serde_json::json!({ + "data": { + "balance": { + "amount": 38 + } + } + }) + ); + Ok(()) + } +} diff --git a/rust-libs/modules/duniter-gva/src/queries/gen_tx.rs b/rust-libs/modules/duniter-gva/src/queries/gen_tx.rs index b3f43ed93..ff9df7e2c 100644 --- a/rust-libs/modules/duniter-gva/src/queries/gen_tx.rs +++ b/rust-libs/modules/duniter-gva/src/queries/gen_tx.rs @@ -112,14 +112,13 @@ impl GenTxsQuery { let recipient = PublicKey::from_base58(&recipient)?; let data = ctx.data::<SchemaData>()?; + let dbs_reader = data.dbs_reader(); let currency = data.server_meta_data.currency.clone(); let (current_block, (inputs, inputs_sum)) = data .dbs_pool .execute(move |dbs| { - if let Some(current_block) = - duniter_dbs_read_ops::get_current_block_meta(&dbs.bc_db)? - { + if let Some(current_block) = dbs_reader.get_current_block_meta(&dbs.bc_db)? { Ok(( current_block, duniter_dbs_read_ops::find_inputs::find_inputs( @@ -187,14 +186,13 @@ impl GenTxsQuery { } let data = ctx.data::<SchemaData>()?; + let dbs_reader = data.dbs_reader(); let currency = data.server_meta_data.currency.clone(); let (current_block, issuers_inputs_with_sum) = data .dbs_pool .execute(move |dbs| { - if let Some(current_block) = - duniter_dbs_read_ops::get_current_block_meta(&dbs.bc_db)? - { + if let Some(current_block) = dbs_reader.get_current_block_meta(&dbs.bc_db)? { let mut issuers_inputs_with_sum = Vec::new(); for issuer in issuers { issuers_inputs_with_sum.push(( diff --git a/rust-libs/modules/duniter-gva/src/queries/uds.rs b/rust-libs/modules/duniter-gva/src/queries/uds.rs index 4867a37ce..a04fd2fb2 100644 --- a/rust-libs/modules/duniter-gva/src/queries/uds.rs +++ b/rust-libs/modules/duniter-gva/src/queries/uds.rs @@ -28,10 +28,11 @@ impl UdsQuery { ctx: &async_graphql::Context<'_>, ) -> async_graphql::Result<Option<CurrentUdGva>> { let data = ctx.data::<SchemaData>()?; + let dbs_reader = data.dbs_reader(); Ok(data .dbs_pool - .execute(move |dbs| duniter_dbs_read_ops::get_current_ud(&dbs.bc_db)) + .execute(move |dbs| dbs_reader.get_current_ud(&dbs.bc_db)) .await?? .map(|sa| CurrentUdGva { amount: sa.amount(), @@ -53,6 +54,7 @@ impl UdsQuery { let pubkey = PublicKey::from_base58(&pubkey)?; let data = ctx.data::<SchemaData>()?; + let dbs_reader = data.dbs_reader(); let ( PagedData { @@ -64,9 +66,7 @@ impl UdsQuery { ) = data .dbs_pool .execute(move |dbs| { - if let Some(current_block) = - duniter_dbs_read_ops::get_current_block_meta(&dbs.bc_db)? - { + if let Some(current_block) = dbs_reader.get_current_block_meta(&dbs.bc_db)? { let paged_data = match filter { UdsFilter::All => duniter_dbs_read_ops::uds_of_pubkey::all_uds_of_pubkey( &dbs.bc_db, @@ -156,3 +156,31 @@ impl UdsQuery { .await??) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::*; + + #[tokio::test] + async fn query_current_ud() -> anyhow::Result<()> { + let mut dbs_reader = MockDbsReader::new(); + use duniter_dbs::bc_v2::BcV2Db; + dbs_reader + .expect_get_current_ud::<BcV2Db<FileBackend>>() + .times(1) + .returning(|_| Ok(Some(SourceAmount::with_base0(100)))); + let schema = create_schema(dbs_reader)?; + assert_eq!( + exec_graphql_request(&schema, r#"{ currentUd {amount} }"#).await?, + serde_json::json!({ + "data": { + "currentUd": { + "amount": 100 + } + } + }) + ); + Ok(()) + } +} diff --git a/rust-libs/modules/duniter-gva/src/queries/utxos.rs b/rust-libs/modules/duniter-gva/src/queries/utxos.rs index 90bdc3d94..e184e1bd4 100644 --- a/rust-libs/modules/duniter-gva/src/queries/utxos.rs +++ b/rust-libs/modules/duniter-gva/src/queries/utxos.rs @@ -38,6 +38,7 @@ impl UtxosQuery { let script = dubp::documents_parser::wallet_script_from_str(&script)?; let data = ctx.data::<SchemaData>()?; + let dbs_reader = data.dbs_reader(); let ( PagedData { @@ -49,9 +50,7 @@ impl UtxosQuery { ) = data .dbs_pool .execute(move |dbs| { - if let Some(current_block) = - duniter_dbs_read_ops::get_current_block_meta(&dbs.bc_db)? - { + if let Some(current_block) = dbs_reader.get_current_block_meta(&dbs.bc_db)? { let paged_data = duniter_dbs_read_ops::utxos::find_script_utxos( &dbs.gva_db, &dbs.txs_mp_db, diff --git a/rust-libs/modules/duniter-gva/src/schema.rs b/rust-libs/modules/duniter-gva/src/schema.rs index c830bb85b..c4540e7bb 100644 --- a/rust-libs/modules/duniter-gva/src/schema.rs +++ b/rust-libs/modules/duniter-gva/src/schema.rs @@ -21,7 +21,21 @@ pub(crate) type GraphQlSchema = async_graphql::Schema< crate::subscriptions::SubscriptionRoot, >; pub(crate) struct SchemaData { - pub(crate) dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs>, + pub(crate) dbs_pool: fast_threadpool::ThreadPoolAsyncHandler<DuniterDbs<FileBackend>>, + pub(crate) dbs_reader: DbsReader, pub(crate) server_meta_data: ServerMetaData, pub(crate) txs_mempool: TxsMempool, } + +#[cfg(not(test))] +impl SchemaData { + pub fn dbs_reader(&self) -> DbsReader { + self.dbs_reader + } +} +#[cfg(test)] +impl SchemaData { + pub fn dbs_reader(&self) -> DbsReader { + self.dbs_reader.clone() + } +} diff --git a/rust-libs/tests/duniter-integration-tests/Cargo.toml b/rust-libs/tests/duniter-integration-tests/Cargo.toml new file mode 100644 index 000000000..275321cf6 --- /dev/null +++ b/rust-libs/tests/duniter-integration-tests/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "duniter-integration-tests" +version = "0.1.0" +authors = ["librelois <elois@duniter.org>"] +license = "AGPL-3.0" +edition = "2018" + +[dependencies] +anyhow = "1.0.34" +dubp = { version = "0.32.2" } +duniter-conf = { path = "../../duniter-conf" } +duniter-dbs = { path = "../../duniter-dbs" } +duniter-dbs-read-ops = { path = "../../duniter-dbs-read-ops" } +duniter-dbs-write-ops = { path = "../../duniter-dbs-write-ops" } +duniter-gva = { path = "../../modules/duniter-gva" } +duniter-mempools = { path = "../../duniter-mempools" } +duniter-module = { path = "../../duniter-module" } +duniter-server = { path = "../../duniter-server" } +fast-threadpool = "0.2.1" +flume = "0.9.1" +log = "0.4.11" +paste = "1.0.2" +resiter = "0.4.0" +tokio = { version = "0.2.22", features = ["io-util", "rt-threaded"] } diff --git a/rust-libs/tests/duniter-integration-tests/src/lib.rs b/rust-libs/tests/duniter-integration-tests/src/lib.rs new file mode 100644 index 000000000..4260a8b61 --- /dev/null +++ b/rust-libs/tests/duniter-integration-tests/src/lib.rs @@ -0,0 +1,75 @@ +// Copyright (C) 2020 Éloïs SANCHEZ. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#![deny( + missing_copy_implementations, + trivial_casts, + trivial_numeric_casts, + unstable_features, + unused_import_braces +)] + +#[cfg(test)] +mod tests { + use dubp::documents::transaction::TransactionDocumentV10Builder; + use dubp::{ + common::prelude::*, + crypto::keys::ed25519::{Ed25519KeyPair, PublicKey}, + documents::prelude::*, + documents::smallvec::smallvec, + }; + use duniter_server::*; + + #[test] + fn test_txs_history() -> anyhow::Result<()> { + let server = DuniterServer::start( + None, + DuniterConf { + gva: None, + self_key_pair: Ed25519KeyPair::generate_random() + .expect("fail to gen random keypair"), + txs_mempool_size: 200, + }, + "currency_test".to_owned(), + None, + "test", + )?; + + let tx = TransactionDocumentV10Builder { + currency: "duniter_unit_test_currency", + blockstamp: Blockstamp::default(), + locktime: 0, + issuers: smallvec![PublicKey::default()], + inputs: &[], + unlocks: &[], + outputs: smallvec![], + comment: "test", + hash: None, + } + .build_with_signature(smallvec![]); + server.add_pending_tx_force(tx.clone())?; + + let txs_history = server.get_transactions_history(PublicKey::default())?; + + tx.get_hash(); + assert_eq!(txs_history.sending, vec![tx]); + + server.remove_all_pending_txs()?; + + assert_eq!(server.get_pending_txs(0, 0)?.len(), 0); + + Ok(()) + } +} -- GitLab