Skip to content

Commit 1534761

Browse files
authored
GH-601: Introduce SentPayable Table (#611)
* GH-601: introduce sent_payable table * GH-601: test that table with certain columns were created during migration * GH-601: resuse code to test fields of table * GH-601: migrate utils code * GH-601: trigger actions * GH-601: fix test constants_have_correct_values * GH-601: review changes * GH-601: move constant to database/test_utils.rs
1 parent f2a2470 commit 1534761

File tree

9 files changed

+216
-28
lines changed

9 files changed

+216
-28
lines changed

masq_lib/src/constants.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::data_version::DataVersion;
55
use const_format::concatcp;
66

77
pub const DEFAULT_CHAIN: Chain = Chain::PolyMainnet;
8-
pub const CURRENT_SCHEMA_VERSION: usize = 10;
8+
pub const CURRENT_SCHEMA_VERSION: usize = 11;
99

1010
pub const HIGHEST_RANDOM_CLANDESTINE_PORT: u16 = 9999;
1111
pub const HTTP_PORT: u16 = 80;

node/src/database/db_initializer.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ impl DbInitializerReal {
135135
Self::create_config_table(conn);
136136
Self::initialize_config(conn, external_params);
137137
Self::create_payable_table(conn);
138+
Self::create_sent_payable_table(conn);
138139
Self::create_pending_payable_table(conn);
139140
Self::create_receivable_table(conn);
140141
Self::create_banned_table(conn);
@@ -258,6 +259,31 @@ impl DbInitializerReal {
258259
Self::set_config_value(conn, "max_block_count", None, false, "maximum block count");
259260
}
260261

262+
pub fn create_sent_payable_table(conn: &Connection) {
263+
conn.execute(
264+
"create table if not exists sent_payable (
265+
rowid integer primary key,
266+
tx_hash text not null,
267+
receiver_address text not null,
268+
amount_high_b integer not null,
269+
amount_low_b integer not null,
270+
timestamp integer not null,
271+
gas_price_wei integer not null,
272+
nonce integer not null,
273+
status text not null,
274+
retried integer not null
275+
)",
276+
[],
277+
)
278+
.expect("Can't create sent_payable table");
279+
280+
conn.execute(
281+
"CREATE UNIQUE INDEX sent_payable_tx_hash_idx ON sent_payable (tx_hash)",
282+
[],
283+
)
284+
.expect("Can't create transaction hash index in sent payments");
285+
}
286+
261287
pub fn create_pending_payable_table(conn: &Connection) {
262288
conn.execute(
263289
"create table if not exists pending_payable (
@@ -621,6 +647,7 @@ impl Debug for DbInitializationConfig {
621647
mod tests {
622648
use super::*;
623649
use crate::database::db_initializer::InitializationError::SqliteError;
650+
use crate::database::test_utils::SQL_ATTRIBUTES_FOR_CREATING_SENT_PAYABLE;
624651
use crate::db_config::config_dao::{ConfigDao, ConfigDaoReal};
625652
use crate::test_utils::database_utils::{
626653
assert_create_table_stm_contains_all_parts,
@@ -652,7 +679,7 @@ mod tests {
652679
#[test]
653680
fn constants_have_correct_values() {
654681
assert_eq!(DATABASE_FILE, "node-data.db");
655-
assert_eq!(CURRENT_SCHEMA_VERSION, 10);
682+
assert_eq!(CURRENT_SCHEMA_VERSION, 11);
656683
}
657684

658685
#[test]
@@ -713,6 +740,34 @@ mod tests {
713740
)
714741
}
715742

743+
#[test]
744+
fn db_initialize_creates_sent_payable_table() {
745+
let home_dir = ensure_node_home_directory_does_not_exist(
746+
"db_initializer",
747+
"db_initialize_creates_sent_payable_table",
748+
);
749+
let subject = DbInitializerReal::default();
750+
751+
let conn = subject
752+
.initialize(&home_dir, DbInitializationConfig::test_default())
753+
.unwrap();
754+
755+
let mut stmt = conn.prepare("select rowid, tx_hash, receiver_address, amount_high_b, amount_low_b, timestamp, gas_price_wei, nonce, status, retried from sent_payable").unwrap();
756+
let mut sent_payable_contents = stmt.query_map([], |_| Ok(42)).unwrap();
757+
assert!(sent_payable_contents.next().is_none());
758+
assert_create_table_stm_contains_all_parts(
759+
&*conn,
760+
"sent_payable",
761+
SQL_ATTRIBUTES_FOR_CREATING_SENT_PAYABLE,
762+
);
763+
let expected_key_words: &[&[&str]] = &[&["tx_hash"]];
764+
assert_index_stm_is_coupled_with_right_parameter(
765+
conn.as_ref(),
766+
"sent_payable_tx_hash_idx",
767+
expected_key_words,
768+
)
769+
}
770+
716771
#[test]
717772
fn db_initialize_creates_payable_table() {
718773
let home_dir = ensure_node_home_directory_does_not_exist(

node/src/database/db_migrations/db_migrator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use crate::database::db_initializer::ExternalData;
44
use crate::database::db_migrations::migrations::migration_0_to_1::Migrate_0_to_1;
5+
use crate::database::db_migrations::migrations::migration_10_to_11::Migrate_10_to_11;
56
use crate::database::db_migrations::migrations::migration_1_to_2::Migrate_1_to_2;
67
use crate::database::db_migrations::migrations::migration_2_to_3::Migrate_2_to_3;
78
use crate::database::db_migrations::migrations::migration_3_to_4::Migrate_3_to_4;
@@ -80,6 +81,7 @@ impl DbMigratorReal {
8081
&Migrate_7_to_8,
8182
&Migrate_8_to_9,
8283
&Migrate_9_to_10,
84+
&Migrate_10_to_11,
8385
]
8486
}
8587

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use crate::database::db_migrations::db_migrator::DatabaseMigration;
2+
use crate::database::db_migrations::migrator_utils::DBMigDeclarator;
3+
4+
#[allow(non_camel_case_types)]
5+
pub struct Migrate_10_to_11;
6+
7+
impl DatabaseMigration for Migrate_10_to_11 {
8+
fn migrate<'a>(
9+
&self,
10+
declaration_utils: Box<dyn DBMigDeclarator + 'a>,
11+
) -> rusqlite::Result<()> {
12+
let sql_statement = "create table if not exists sent_payable (
13+
rowid integer primary key,
14+
tx_hash text not null,
15+
receiver_address text not null,
16+
amount_high_b integer not null,
17+
amount_low_b integer not null,
18+
timestamp integer not null,
19+
gas_price_wei integer not null,
20+
nonce integer not null,
21+
status text not null,
22+
retried integer not null
23+
)";
24+
25+
declaration_utils.execute_upon_transaction(&[&sql_statement])
26+
}
27+
28+
fn old_version(&self) -> usize {
29+
10
30+
}
31+
}
32+
33+
#[cfg(test)]
34+
mod tests {
35+
use crate::database::db_initializer::{
36+
DbInitializationConfig, DbInitializer, DbInitializerReal, DATABASE_FILE,
37+
};
38+
use crate::database::test_utils::SQL_ATTRIBUTES_FOR_CREATING_SENT_PAYABLE;
39+
use crate::test_utils::database_utils::{
40+
assert_create_table_stm_contains_all_parts, assert_table_exists,
41+
bring_db_0_back_to_life_and_return_connection, make_external_data,
42+
};
43+
use masq_lib::test_utils::logging::{init_test_logging, TestLogHandler};
44+
use masq_lib::test_utils::utils::ensure_node_home_directory_exists;
45+
use std::fs::create_dir_all;
46+
47+
#[test]
48+
fn migration_from_10_to_11_is_applied_correctly() {
49+
init_test_logging();
50+
let dir_path = ensure_node_home_directory_exists(
51+
"db_migrations",
52+
"migration_from_10_to_11_is_properly_set",
53+
);
54+
create_dir_all(&dir_path).unwrap();
55+
let db_path = dir_path.join(DATABASE_FILE);
56+
let _ = bring_db_0_back_to_life_and_return_connection(&db_path);
57+
let subject = DbInitializerReal::default();
58+
59+
let _prev_connection = subject
60+
.initialize_to_version(
61+
&dir_path,
62+
10,
63+
DbInitializationConfig::create_or_migrate(make_external_data()),
64+
)
65+
.unwrap();
66+
67+
let connection = subject
68+
.initialize_to_version(
69+
&dir_path,
70+
11,
71+
DbInitializationConfig::create_or_migrate(make_external_data()),
72+
)
73+
.unwrap();
74+
75+
assert_table_exists(connection.as_ref(), "sent_payable");
76+
assert_create_table_stm_contains_all_parts(
77+
&*connection,
78+
"sent_payable",
79+
SQL_ATTRIBUTES_FOR_CREATING_SENT_PAYABLE,
80+
);
81+
TestLogHandler::new().assert_logs_contain_in_order(vec![
82+
"DbMigrator: Database successfully migrated from version 10 to 11",
83+
]);
84+
}
85+
}

node/src/database/db_migrations/migrations/migration_8_to_9.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,22 @@ mod tests {
4343
let _ = bring_db_0_back_to_life_and_return_connection(&db_path);
4444
let subject = DbInitializerReal::default();
4545

46-
let result = subject.initialize_to_version(
47-
&dir_path,
48-
8,
49-
DbInitializationConfig::create_or_migrate(make_external_data()),
50-
);
51-
52-
assert!(result.is_ok());
46+
let _prev_connection = subject
47+
.initialize_to_version(
48+
&dir_path,
49+
8,
50+
DbInitializationConfig::create_or_migrate(make_external_data()),
51+
)
52+
.unwrap();
5353

54-
let result = subject.initialize_to_version(
55-
&dir_path,
56-
9,
57-
DbInitializationConfig::create_or_migrate(make_external_data()),
58-
);
54+
let connection = subject
55+
.initialize_to_version(
56+
&dir_path,
57+
9,
58+
DbInitializationConfig::create_or_migrate(make_external_data()),
59+
)
60+
.unwrap();
5961

60-
let connection = result.unwrap();
6162
let (mp_value, mp_encrypted) = retrieve_config_row(connection.as_ref(), "max_block_count");
6263
let (cs_value, cs_encrypted) = retrieve_config_row(connection.as_ref(), "schema_version");
6364
assert_eq!(mp_value, None);

node/src/database/db_migrations/migrations/migration_9_to_10.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,22 @@ mod tests {
4343
let _ = bring_db_0_back_to_life_and_return_connection(&db_path);
4444
let subject = DbInitializerReal::default();
4545

46-
let result = subject.initialize_to_version(
47-
&dir_path,
48-
9,
49-
DbInitializationConfig::create_or_migrate(make_external_data()),
50-
);
51-
52-
assert!(result.is_ok());
46+
let _prev_connection = subject
47+
.initialize_to_version(
48+
&dir_path,
49+
9,
50+
DbInitializationConfig::create_or_migrate(make_external_data()),
51+
)
52+
.unwrap();
5353

54-
let result = subject.initialize_to_version(
55-
&dir_path,
56-
10,
57-
DbInitializationConfig::create_or_migrate(make_external_data()),
58-
);
54+
let connection = subject
55+
.initialize_to_version(
56+
&dir_path,
57+
10,
58+
DbInitializationConfig::create_or_migrate(make_external_data()),
59+
)
60+
.unwrap();
5961

60-
let connection = result.unwrap();
6162
let (mp_value, mp_encrypted) = retrieve_config_row(connection.as_ref(), "max_block_count");
6263
let (cs_value, cs_encrypted) = retrieve_config_row(connection.as_ref(), "schema_version");
6364
assert_eq!(mp_value, Some(100_000u64.to_string()));

node/src/database/db_migrations/migrations/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ pub mod migration_6_to_7;
1010
pub mod migration_7_to_8;
1111
pub mod migration_8_to_9;
1212
pub mod migration_9_to_10;
13+
#[rustfmt::skip]
14+
pub mod migration_10_to_11;

node/src/database/test_utils/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ use std::fmt::Debug;
1212
use std::path::{Path, PathBuf};
1313
use std::sync::{Arc, Mutex};
1414

15+
pub const SQL_ATTRIBUTES_FOR_CREATING_SENT_PAYABLE: &[&[&str]] = &[
16+
&["rowid", "integer", "primary", "key"],
17+
&["tx_hash", "text", "not", "null"],
18+
&["receiver_address", "text", "not", "null"],
19+
&["amount_high_b", "integer", "not", "null"],
20+
&["amount_low_b", "integer", "not", "null"],
21+
&["timestamp", "integer", "not", "null"],
22+
&["gas_price_wei", "integer", "not", "null"],
23+
&["nonce", "integer", "not", "null"],
24+
&["status", "text", "not", "null"],
25+
&["retried", "integer", "not", "null"],
26+
];
27+
1528
#[derive(Debug, Default)]
1629
pub struct ConnectionWrapperMock<'conn> {
1730
prepare_params: Arc<Mutex<Vec<String>>>,
@@ -114,3 +127,27 @@ impl DbInitializerMock {
114127
self
115128
}
116129
}
130+
131+
#[cfg(test)]
132+
mod tests {
133+
use crate::database::test_utils::SQL_ATTRIBUTES_FOR_CREATING_SENT_PAYABLE;
134+
135+
#[test]
136+
fn constants_have_correct_values() {
137+
assert_eq!(
138+
SQL_ATTRIBUTES_FOR_CREATING_SENT_PAYABLE,
139+
&[
140+
&["rowid", "integer", "primary", "key"],
141+
&["tx_hash", "text", "not", "null"],
142+
&["receiver_address", "text", "not", "null"],
143+
&["amount_high_b", "integer", "not", "null"],
144+
&["amount_low_b", "integer", "not", "null"],
145+
&["timestamp", "integer", "not", "null"],
146+
&["gas_price_wei", "integer", "not", "null"],
147+
&["nonce", "integer", "not", "null"],
148+
&["status", "text", "not", "null"],
149+
&["retried", "integer", "not", "null"]
150+
]
151+
);
152+
}
153+
}

node/src/test_utils/database_utils.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ pub fn retrieve_config_row(conn: &dyn ConnectionWrapper, name: &str) -> (Option<
103103
})
104104
}
105105

106+
pub fn assert_table_exists(conn: &dyn ConnectionWrapper, table_name: &str) {
107+
let result = conn.prepare(&format!("select * from {}", table_name));
108+
assert!(result.is_ok(), "Table {} should exist", table_name);
109+
}
110+
106111
pub fn assert_table_does_not_exist(conn: &dyn ConnectionWrapper, table_name: &str) {
107112
let error_stm = conn
108113
.prepare(&format!("select * from {}", table_name))

0 commit comments

Comments
 (0)