From d8f502660f30327f5ffe1ef6a961641bdfad539e Mon Sep 17 00:00:00 2001 From: Vladimir Fomene Date: Wed, 7 Sep 2022 20:45:22 +0300 Subject: [PATCH] Add more test to the database module This PR aims to add more test to database code so that we can catch bugs as soon as they occur. Contributing to fixing issue #699. --- src/database/keyvalue.rs | 40 ++++++++ src/database/memory.rs | 40 ++++++++ src/database/mod.rs | 196 ++++++++++++++++++++++++++++++++++++++- src/database/sqlite.rs | 40 ++++++++ 4 files changed, 314 insertions(+), 2 deletions(-) diff --git a/src/database/keyvalue.rs b/src/database/keyvalue.rs index e10ada1fa4..f586ebeba8 100644 --- a/src/database/keyvalue.rs +++ b/src/database/keyvalue.rs @@ -492,4 +492,44 @@ mod test { fn test_sync_time() { crate::database::test::test_sync_time(get_tree()); } + + #[test] + fn test_iter_raw_txs() { + crate::database::test::test_iter_raw_txs(get_tree()); + } + + #[test] + fn test_del_path_from_script_pubkey() { + crate::database::test::test_del_path_from_script_pubkey(get_tree()); + } + + #[test] + fn test_iter_script_pubkeys() { + crate::database::test::test_iter_script_pubkeys(get_tree()); + } + + #[test] + fn test_del_utxo() { + crate::database::test::test_del_utxo(get_tree()); + } + + #[test] + fn test_del_raw_tx() { + crate::database::test::test_del_raw_tx(get_tree()); + } + + #[test] + fn test_del_tx() { + crate::database::test::test_del_tx(get_tree()); + } + + #[test] + fn test_del_last_index() { + crate::database::test::test_del_last_index(get_tree()); + } + + #[test] + fn test_check_descriptor_checksum() { + crate::database::test::test_check_descriptor_checksum(get_tree()); + } } diff --git a/src/database/memory.rs b/src/database/memory.rs index eff5ecf148..691e7eb16b 100644 --- a/src/database/memory.rs +++ b/src/database/memory.rs @@ -647,4 +647,44 @@ mod test { fn test_sync_time() { crate::database::test::test_sync_time(get_tree()); } + + #[test] + fn test_iter_raw_txs() { + crate::database::test::test_iter_raw_txs(get_tree()); + } + + #[test] + fn test_del_path_from_script_pubkey() { + crate::database::test::test_del_path_from_script_pubkey(get_tree()); + } + + #[test] + fn test_iter_script_pubkeys() { + crate::database::test::test_iter_script_pubkeys(get_tree()); + } + + #[test] + fn test_del_utxo() { + crate::database::test::test_del_utxo(get_tree()); + } + + #[test] + fn test_del_raw_tx() { + crate::database::test::test_del_raw_tx(get_tree()); + } + + #[test] + fn test_del_tx() { + crate::database::test::test_del_tx(get_tree()); + } + + #[test] + fn test_del_last_index() { + crate::database::test::test_del_last_index(get_tree()); + } + + #[test] + fn test_check_descriptor_checksum() { + crate::database::test::test_check_descriptor_checksum(get_tree()); + } } diff --git a/src/database/mod.rs b/src/database/mod.rs index c7ff17951f..f2c1a5fdff 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -217,6 +217,7 @@ pub mod test { use std::str::FromStr; use bitcoin::consensus::encode::deserialize; + use bitcoin::consensus::serialize; use bitcoin::hashes::hex::*; use bitcoin::*; @@ -322,8 +323,24 @@ pub mod test { } pub fn test_raw_tx(mut tree: D) { - let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); - let tx: Transaction = deserialize(&hex_tx).unwrap(); + let hex_tx = Vec::::from_hex("02000000000101f58c18a90d7a76b30c7e47d4e817adfdd79a6a589a615ef36e360f913adce2cd0000000000feffffff0210270000000000001600145c9a1816d38db5cbdd4b067b689dc19eb7d930e2cf70aa2b080000001600140f48b63160043047f4f60f7f8f551f80458f693f024730440220413f42b7bc979945489a38f5221e5527d4b8e3aa63eae2099e01945896ad6c10022024ceec492d685c31d8adb64e935a06933877c5ae0e21f32efe029850914c5bad012102361caae96f0e9f3a453d354bb37a5c3244422fb22819bf0166c0647a38de39f21fca2300").unwrap(); + let mut tx: Transaction = deserialize(&hex_tx).unwrap(); + + tree.set_raw_tx(&tx).unwrap(); + + let txid = tx.txid(); + + assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx.clone())); + + // mutate transaction's witnesses + for tx_in in tx.input.iter_mut() { + tx_in.witness = Witness::new(); + } + + let updated_hex_tx = serialize(&tx); + + // verify that mutation was successful + assert_ne!(hex_tx, updated_hex_tx); tree.set_raw_tx(&tx).unwrap(); @@ -441,5 +458,180 @@ pub mod test { assert!(tree.get_sync_time().unwrap().is_none()); } + pub fn test_iter_raw_txs(mut db: D) { + let txs = db.iter_raw_txs().unwrap(); + assert!(txs.is_empty()); + + let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let first_tx: Transaction = deserialize(&hex_tx).unwrap(); + + let hex_tx = Vec::::from_hex("02000000000101f58c18a90d7a76b30c7e47d4e817adfdd79a6a589a615ef36e360f913adce2cd0000000000feffffff0210270000000000001600145c9a1816d38db5cbdd4b067b689dc19eb7d930e2cf70aa2b080000001600140f48b63160043047f4f60f7f8f551f80458f693f024730440220413f42b7bc979945489a38f5221e5527d4b8e3aa63eae2099e01945896ad6c10022024ceec492d685c31d8adb64e935a06933877c5ae0e21f32efe029850914c5bad012102361caae96f0e9f3a453d354bb37a5c3244422fb22819bf0166c0647a38de39f21fca2300").unwrap(); + let second_tx: Transaction = deserialize(&hex_tx).unwrap(); + + db.set_raw_tx(&first_tx).unwrap(); + db.set_raw_tx(&second_tx).unwrap(); + + let txs = db.iter_raw_txs().unwrap(); + + assert!(txs.contains(&first_tx)); + assert!(txs.contains(&second_tx)); + assert_eq!(txs.len(), 2); + } + + pub fn test_del_path_from_script_pubkey(mut db: D) { + let keychain = KeychainKind::External; + + let script = Script::from( + Vec::::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(), + ); + let path = 42; + + let res = db.del_path_from_script_pubkey(&script).unwrap(); + + assert!(res.is_none()); + + let _res = db.set_script_pubkey(&script, keychain, path); + let (chain, child) = db.del_path_from_script_pubkey(&script).unwrap().unwrap(); + + assert_eq!(chain, keychain); + assert_eq!(path, child); + } + + pub fn test_iter_script_pubkeys(mut db: D) { + let keychain = KeychainKind::External; + let scripts = db.iter_script_pubkeys(Some(keychain)).unwrap(); + assert!(scripts.is_empty()); + + let first_script = Script::from( + Vec::::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(), + ); + let path = 42; + + db.set_script_pubkey(&first_script, keychain, path).unwrap(); + + let second_script = Script::from( + Vec::::from_hex("00145c9a1816d38db5cbdd4b067b689dc19eb7d930e2").unwrap(), + ); + let path = 57; + + db.set_script_pubkey(&second_script, keychain, path) + .unwrap(); + let scripts = db.iter_script_pubkeys(Some(keychain)).unwrap(); + + assert!(scripts.contains(&first_script)); + assert!(scripts.contains(&second_script)); + assert_eq!(scripts.len(), 2); + } + + pub fn test_del_utxo(mut db: D) { + let outpoint = OutPoint::from_str( + "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0", + ) + .unwrap(); + let script = Script::from( + Vec::::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(), + ); + let txout = TxOut { + value: 133742, + script_pubkey: script, + }; + let utxo = LocalUtxo { + txout, + outpoint, + keychain: KeychainKind::External, + is_spent: true, + }; + + let res = db.del_utxo(&outpoint).unwrap(); + assert!(res.is_none()); + + db.set_utxo(&utxo).unwrap(); + + let res = db.del_utxo(&outpoint).unwrap(); + + assert_eq!(res.unwrap(), utxo); + } + + pub fn test_del_raw_tx(mut db: D) { + let hex_tx = Vec::::from_hex("02000000000101f58c18a90d7a76b30c7e47d4e817adfdd79a6a589a615ef36e360f913adce2cd0000000000feffffff0210270000000000001600145c9a1816d38db5cbdd4b067b689dc19eb7d930e2cf70aa2b080000001600140f48b63160043047f4f60f7f8f551f80458f693f024730440220413f42b7bc979945489a38f5221e5527d4b8e3aa63eae2099e01945896ad6c10022024ceec492d685c31d8adb64e935a06933877c5ae0e21f32efe029850914c5bad012102361caae96f0e9f3a453d354bb37a5c3244422fb22819bf0166c0647a38de39f21fca2300").unwrap(); + let tx: Transaction = deserialize(&hex_tx).unwrap(); + + let res = db.del_raw_tx(&tx.txid()).unwrap(); + + assert!(res.is_none()); + + db.set_raw_tx(&tx).unwrap(); + + let res = db.del_raw_tx(&tx.txid()).unwrap(); + + assert_eq!(res.unwrap(), tx); + } + + pub fn test_del_tx(mut db: D) { + let hex_tx = Vec::::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap(); + let tx: Transaction = deserialize(&hex_tx).unwrap(); + let txid = tx.txid(); + let mut tx_details = TransactionDetails { + transaction: Some(tx.clone()), + txid, + received: 1337, + sent: 420420, + fee: Some(140), + confirmation_time: Some(BlockTime { + timestamp: 123456, + height: 1000, + }), + }; + + let res = db.del_tx(&tx.txid(), true).unwrap(); + + assert!(res.is_none()); + + db.set_tx(&tx_details).unwrap(); + + let res = db.del_tx(&tx.txid(), false).unwrap(); + tx_details.transaction = None; + assert_eq!(res.unwrap(), tx_details); + + let res = db.get_raw_tx(&tx.txid()).unwrap(); + assert_eq!(res.unwrap(), tx); + + db.set_tx(&tx_details).unwrap(); + let res = db.del_tx(&tx.txid(), true).unwrap(); + tx_details.transaction = Some(tx.clone()); + assert_eq!(res.unwrap(), tx_details); + + let res = db.get_raw_tx(&tx.txid()).unwrap(); + assert!(res.is_none()); + } + + pub fn test_del_last_index(mut db: D) { + let keychain = KeychainKind::External; + + let _res = db.increment_last_index(keychain); + + let res = db.get_last_index(keychain).unwrap().unwrap(); + + assert_eq!(res, 0); + + let _res = db.increment_last_index(keychain); + + let res = db.del_last_index(keychain).unwrap().unwrap(); + + assert_eq!(res, 1); + } + + pub fn test_check_descriptor_checksum(mut db: D) { + let checksum = "1cead456".as_bytes(); + let keychain = KeychainKind::External; + let _res = db.check_descriptor_checksum(keychain, checksum); + + let checksum = "1cead454".as_bytes(); + let keychain = KeychainKind::External; + let res = db.check_descriptor_checksum(keychain, checksum); + + assert!(res.is_err()); + } + // TODO: more tests... } diff --git a/src/database/sqlite.rs b/src/database/sqlite.rs index dc35b856ce..562c93497d 100644 --- a/src/database/sqlite.rs +++ b/src/database/sqlite.rs @@ -1036,4 +1036,44 @@ pub mod test { fn test_txs() { crate::database::test::test_list_transaction(get_database()); } + + #[test] + fn test_iter_raw_txs() { + crate::database::test::test_iter_raw_txs(get_database()); + } + + #[test] + fn test_del_path_from_script_pubkey() { + crate::database::test::test_del_path_from_script_pubkey(get_database()); + } + + #[test] + fn test_iter_script_pubkeys() { + crate::database::test::test_iter_script_pubkeys(get_database()); + } + + #[test] + fn test_del_utxo() { + crate::database::test::test_del_utxo(get_database()); + } + + #[test] + fn test_del_raw_tx() { + crate::database::test::test_del_raw_tx(get_database()); + } + + #[test] + fn test_del_tx() { + crate::database::test::test_del_tx(get_database()); + } + + #[test] + fn test_del_last_index() { + crate::database::test::test_del_last_index(get_database()); + } + + #[test] + fn test_check_descriptor_checksum() { + crate::database::test::test_check_descriptor_checksum(get_database()); + } }