Skip to content

Commit abd7bca

Browse files
committed
refactor: [#1231] tests to use database mock in KeysHandler
tests that require the `Database` trait.
1 parent e3ba1e1 commit abd7bca

3 files changed

Lines changed: 96 additions & 64 deletions

File tree

packages/tracker-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ bittorrent-http-protocol = { version = "3.0.0-develop", path = "../http-protocol
2020
bittorrent-primitives = "0.1.0"
2121
chrono = { version = "0", default-features = false, features = ["clock"] }
2222
derive_more = { version = "1", features = ["as_ref", "constructor", "from"] }
23+
mockall = "0"
2324
r2d2 = "0"
2425
r2d2_mysql = "25"
2526
r2d2_sqlite = { version = "0", features = ["bundled"] }

packages/tracker-core/src/authentication/handler.rs

Lines changed: 93 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -55,68 +55,81 @@ impl KeysHandler {
5555
/// - The provided pre-generated key is invalid.
5656
/// - The key could not been persisted due to database issues.
5757
pub async fn add_peer_key(&self, add_key_req: AddKeyRequest) -> Result<PeerKey, PeerKeyError> {
58-
match add_key_req.opt_key {
59-
Some(pre_existing_key) => {
60-
// Upload pre-generated key
61-
62-
if let Some(seconds_valid) = add_key_req.opt_seconds_valid {
63-
// Expiring key
64-
let Some(valid_until) = CurrentClock::now_add(&Duration::from_secs(seconds_valid)) else {
65-
return Err(PeerKeyError::DurationOverflow { seconds_valid });
66-
};
58+
println!("add_peer_key: {add_key_req:?}");
59+
60+
if let Some(pre_existing_key) = add_key_req.opt_key {
61+
// Upload pre-generated key
62+
println!("pre-generated key: {pre_existing_key:?}");
63+
64+
if let Some(seconds_valid) = add_key_req.opt_seconds_valid {
65+
// Expiring key
66+
let Some(valid_until) = CurrentClock::now_add(&Duration::from_secs(seconds_valid)) else {
67+
return Err(PeerKeyError::DurationOverflow { seconds_valid });
68+
};
6769

68-
let key = pre_existing_key.parse::<Key>();
69-
70-
match key {
71-
Ok(key) => match self.add_expiring_peer_key(key, Some(valid_until)).await {
72-
Ok(auth_key) => Ok(auth_key),
73-
Err(err) => Err(PeerKeyError::DatabaseError {
74-
source: Located(err).into(),
75-
}),
76-
},
77-
Err(err) => Err(PeerKeyError::InvalidKey {
78-
key: pre_existing_key,
70+
println!("pre-generated expiring key, valid until: {valid_until:?}");
71+
72+
let key = pre_existing_key.parse::<Key>();
73+
74+
match key {
75+
Ok(key) => match self.add_expiring_peer_key(key, Some(valid_until)).await {
76+
Ok(auth_key) => Ok(auth_key),
77+
Err(err) => Err(PeerKeyError::DatabaseError {
7978
source: Located(err).into(),
8079
}),
81-
}
82-
} else {
83-
// Permanent key
84-
let key = pre_existing_key.parse::<Key>();
85-
86-
match key {
87-
Ok(key) => match self.add_permanent_peer_key(key).await {
88-
Ok(auth_key) => Ok(auth_key),
89-
Err(err) => Err(PeerKeyError::DatabaseError {
90-
source: Located(err).into(),
91-
}),
92-
},
93-
Err(err) => Err(PeerKeyError::InvalidKey {
94-
key: pre_existing_key,
80+
},
81+
Err(err) => Err(PeerKeyError::InvalidKey {
82+
key: pre_existing_key,
83+
source: Located(err).into(),
84+
}),
85+
}
86+
} else {
87+
// Permanent key
88+
println!("pre-generated permanent key");
89+
90+
let key = pre_existing_key.parse::<Key>();
91+
92+
match key {
93+
Ok(key) => match self.add_permanent_peer_key(key).await {
94+
Ok(auth_key) => Ok(auth_key),
95+
Err(err) => Err(PeerKeyError::DatabaseError {
9596
source: Located(err).into(),
9697
}),
97-
}
98+
},
99+
Err(err) => Err(PeerKeyError::InvalidKey {
100+
key: pre_existing_key,
101+
source: Located(err).into(),
102+
}),
98103
}
99104
}
100-
None => match add_key_req.opt_seconds_valid {
101-
// Generate a new random key
102-
Some(seconds_valid) => match self
105+
} else {
106+
// Generate a new random key
107+
println!("random key");
108+
109+
if let Some(seconds_valid) = add_key_req.opt_seconds_valid {
110+
// Expiring key
111+
println!("random expiring key, seconds valid: {seconds_valid:?}");
112+
113+
match self
103114
.generate_expiring_peer_key(Some(Duration::from_secs(seconds_valid)))
104115
.await
105116
{
106-
// Expiring key
107117
Ok(auth_key) => Ok(auth_key),
108118
Err(err) => Err(PeerKeyError::DatabaseError {
109119
source: Located(err).into(),
110120
}),
111-
},
112-
None => match self.generate_permanent_peer_key().await {
113-
// Permanent key
121+
}
122+
} else {
123+
// Permanent key
124+
println!("random permanent key");
125+
126+
match self.generate_permanent_peer_key().await {
114127
Ok(auth_key) => Ok(auth_key),
115128
Err(err) => Err(PeerKeyError::DatabaseError {
116129
source: Located(err).into(),
117130
}),
118-
},
119-
},
131+
}
132+
}
120133
}
121134
}
122135

@@ -331,18 +344,22 @@ mod tests {
331344
}
332345

333346
mod pre_generated {
347+
use std::panic::Location;
334348
use std::sync::Arc;
335349
use std::time::Duration;
336350

337-
use torrust_tracker_clock::clock::Time;
351+
use mockall::predicate;
352+
use torrust_tracker_clock::clock::stopped::Stopped;
353+
use torrust_tracker_clock::clock::{self, Time};
338354
use torrust_tracker_test_helpers::configuration;
339355

340356
use crate::authentication::handler::tests::the_keys_handler_when_the_tracker_is_configured_as_private::instantiate_keys_handler;
341357
use crate::authentication::handler::{AddKeyRequest, KeysHandler};
342358
use crate::authentication::key::repository::in_memory::InMemoryKeyRepository;
343359
use crate::authentication::key::repository::persisted::DatabaseKeyRepository;
344360
use crate::authentication::{Key, PeerKey};
345-
use crate::databases::setup::initialize_database;
361+
use crate::databases::driver::Driver;
362+
use crate::databases::{self, Database, MockDatabase};
346363
use crate::error::PeerKeyError;
347364
use crate::CurrentClock;
348365

@@ -383,23 +400,38 @@ mod tests {
383400

384401
#[tokio::test]
385402
async fn it_should_fail_adding_a_pre_generated_key_when_there_is_a_database_error() {
386-
let config = configuration::ephemeral_private();
387-
let database = initialize_database(&config.core);
388-
let db_key_repository = Arc::new(DatabaseKeyRepository::new(&database));
389-
let in_memory_key_repository = Arc::new(InMemoryKeyRepository::default());
403+
let _config = configuration::ephemeral_private();
390404

391-
// Force database error.
392-
// todo: extract trait for DatabaseKeyRepository to be able
393-
// to mock it. Test should be faster if we don't have to
394-
// create a new database.
395-
let _unused = database.drop_database_tables();
405+
clock::Stopped::local_set(&Duration::from_secs(0));
406+
407+
let expected_valid_until = clock::Stopped::now_add(&Duration::from_secs(60)).unwrap();
408+
let expected_peer_key = PeerKey {
409+
key: Key::new("YZSl4lMZupRuOpSRC3krIKR5BPB14nrJ").unwrap(),
410+
valid_until: Some(expected_valid_until),
411+
};
412+
413+
let mut database_mock = MockDatabase::default();
414+
database_mock
415+
.expect_add_key_to_keys()
416+
.with(predicate::eq(expected_peer_key))
417+
.times(1)
418+
.returning(|_peer_key| {
419+
Err(databases::error::Error::InsertFailed {
420+
location: Location::caller(),
421+
driver: Driver::Sqlite3,
422+
})
423+
});
424+
let database_mock: Arc<Box<dyn Database>> = Arc::new(Box::new(database_mock));
425+
426+
let db_key_repository = Arc::new(DatabaseKeyRepository::new(&database_mock));
427+
let in_memory_key_repository = Arc::new(InMemoryKeyRepository::default());
396428

397429
let keys_handler = KeysHandler::new(&db_key_repository, &in_memory_key_repository);
398430

399431
let result = keys_handler
400432
.add_peer_key(AddKeyRequest {
401433
opt_key: Some(Key::new("YZSl4lMZupRuOpSRC3krIKR5BPB14nrJ").unwrap().to_string()),
402-
opt_seconds_valid: Some(100),
434+
opt_seconds_valid: Some(60),
403435
})
404436
.await;
405437

@@ -446,16 +478,9 @@ mod tests {
446478

447479
mod pre_generated_keys {
448480

449-
use std::sync::Arc;
450-
451-
use torrust_tracker_test_helpers::configuration;
452-
453481
use crate::authentication::handler::tests::the_keys_handler_when_the_tracker_is_configured_as_private::instantiate_keys_handler;
454-
use crate::authentication::handler::{AddKeyRequest, KeysHandler};
455-
use crate::authentication::key::repository::in_memory::InMemoryKeyRepository;
456-
use crate::authentication::key::repository::persisted::DatabaseKeyRepository;
482+
use crate::authentication::handler::AddKeyRequest;
457483
use crate::authentication::{Key, PeerKey};
458-
use crate::databases::setup::initialize_database;
459484
use crate::error::PeerKeyError;
460485

461486
#[tokio::test]
@@ -493,6 +518,8 @@ mod tests {
493518
assert!(matches!(result.unwrap_err(), PeerKeyError::InvalidKey { .. }));
494519
}
495520

521+
/*
522+
496523
#[tokio::test]
497524
async fn it_should_fail_adding_a_pre_generated_key_when_there_is_a_database_error() {
498525
let config = configuration::ephemeral_private();
@@ -517,6 +544,8 @@ mod tests {
517544
518545
assert!(matches!(result.unwrap_err(), PeerKeyError::DatabaseError { .. }));
519546
}
547+
548+
*/
520549
}
521550
}
522551
}

packages/tracker-core/src/databases/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub mod sqlite;
5252
use std::marker::PhantomData;
5353

5454
use bittorrent_primitives::info_hash::InfoHash;
55+
use mockall::automock;
5556
use torrust_tracker_primitives::PersistentTorrents;
5657

5758
use self::error::Error;
@@ -79,6 +80,7 @@ where
7980
}
8081

8182
/// The persistence trait. It contains all the methods to interact with the database.
83+
#[automock]
8284
pub trait Database: Sync + Send {
8385
/// It instantiates a new database driver.
8486
///

0 commit comments

Comments
 (0)